From 8d284bebe3c2392680949c06bbd17253960ce0f8 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Wed, 1 Aug 2012 05:54:33 +0000 Subject: git-svn-id: http://svn.miranda-ng.org/main/trunk@1295 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Clist_nicer/src/CLCButton.cpp | 552 +++ plugins/Clist_nicer/src/CLUIFrames/cluiframes.cpp | 3584 ++++++++++++++++++++ plugins/Clist_nicer/src/CLUIFrames/cluiframes.h | 105 + plugins/Clist_nicer/src/CLUIFrames/framesmenu.cpp | 228 ++ plugins/Clist_nicer/src/CLUIFrames/groupmenu.cpp | 704 ++++ plugins/Clist_nicer/src/CLUIFrames/movetogroup.cpp | 60 + plugins/Clist_nicer/src/Coolsb/coolsb_internal.h | 95 + plugins/Clist_nicer/src/Coolsb/coolsblib.cpp | 1003 ++++++ plugins/Clist_nicer/src/Coolsb/coolsblib.h | 41 + plugins/Clist_nicer/src/Coolsb/coolscroll.cpp | 3206 +++++++++++++++++ plugins/Clist_nicer/src/Coolsb/coolscroll.h | 232 ++ plugins/Clist_nicer/src/Coolsb/userdefs.h | 79 + plugins/Clist_nicer/src/Docking.cpp | 286 ++ plugins/Clist_nicer/src/Include/alphablend.h | 30 + plugins/Clist_nicer/src/Include/clc.h | 632 ++++ plugins/Clist_nicer/src/Include/clist.h | 48 + plugins/Clist_nicer/src/Include/commonheaders.h | 223 ++ plugins/Clist_nicer/src/Include/config.h | 209 ++ plugins/Clist_nicer/src/Include/extBackg.h | 97 + plugins/Clist_nicer/src/Include/m_cln_skinedit.h | 174 + plugins/Clist_nicer/src/Include/resource.h | 416 +++ plugins/Clist_nicer/src/Include/rowheight_funcs.h | 85 + plugins/Clist_nicer/src/Include/vsstyle.h | 1606 +++++++++ plugins/Clist_nicer/src/Include/vssym32.h | 712 ++++ plugins/Clist_nicer/src/alphablend.cpp | 545 +++ plugins/Clist_nicer/src/clc.cpp | 806 +++++ plugins/Clist_nicer/src/clcidents.cpp | 102 + plugins/Clist_nicer/src/clcitems.cpp | 659 ++++ plugins/Clist_nicer/src/clcmsgs.cpp | 221 ++ plugins/Clist_nicer/src/clcopts.cpp | 1620 +++++++++ plugins/Clist_nicer/src/clcpaint.cpp | 1674 +++++++++ plugins/Clist_nicer/src/clcutils.cpp | 624 ++++ plugins/Clist_nicer/src/clistevents.cpp | 397 +++ plugins/Clist_nicer/src/clistmenus.cpp | 493 +++ plugins/Clist_nicer/src/clistmod.cpp | 258 ++ plugins/Clist_nicer/src/clistopts.cpp | 220 ++ plugins/Clist_nicer/src/clistsettings.cpp | 33 + plugins/Clist_nicer/src/clisttray.cpp | 171 + plugins/Clist_nicer/src/clnplus.cpp | 40 + plugins/Clist_nicer/src/clui.cpp | 2191 ++++++++++++ plugins/Clist_nicer/src/cluiopts.cpp | 476 +++ plugins/Clist_nicer/src/cluiservices.cpp | 261 ++ plugins/Clist_nicer/src/commonheaders.cpp | 1 + plugins/Clist_nicer/src/config.cpp | 482 +++ plugins/Clist_nicer/src/contact.cpp | 333 ++ plugins/Clist_nicer/src/extBackg.cpp | 1859 ++++++++++ plugins/Clist_nicer/src/init.cpp | 386 +++ plugins/Clist_nicer/src/rowheight_funcs.cpp | 287 ++ plugins/Clist_nicer/src/statusbar.cpp | 197 ++ plugins/Clist_nicer/src/statusfloater.cpp | 1240 +++++++ plugins/Clist_nicer/src/viewmodes.cpp | 1249 +++++++ plugins/Clist_nicer/src/wallpaper.cpp | 56 + 52 files changed, 31288 insertions(+) create mode 100644 plugins/Clist_nicer/src/CLCButton.cpp create mode 100644 plugins/Clist_nicer/src/CLUIFrames/cluiframes.cpp create mode 100644 plugins/Clist_nicer/src/CLUIFrames/cluiframes.h create mode 100644 plugins/Clist_nicer/src/CLUIFrames/framesmenu.cpp create mode 100644 plugins/Clist_nicer/src/CLUIFrames/groupmenu.cpp create mode 100644 plugins/Clist_nicer/src/CLUIFrames/movetogroup.cpp create mode 100644 plugins/Clist_nicer/src/Coolsb/coolsb_internal.h create mode 100644 plugins/Clist_nicer/src/Coolsb/coolsblib.cpp create mode 100644 plugins/Clist_nicer/src/Coolsb/coolsblib.h create mode 100644 plugins/Clist_nicer/src/Coolsb/coolscroll.cpp create mode 100644 plugins/Clist_nicer/src/Coolsb/coolscroll.h create mode 100644 plugins/Clist_nicer/src/Coolsb/userdefs.h create mode 100644 plugins/Clist_nicer/src/Docking.cpp create mode 100644 plugins/Clist_nicer/src/Include/alphablend.h create mode 100644 plugins/Clist_nicer/src/Include/clc.h create mode 100644 plugins/Clist_nicer/src/Include/clist.h create mode 100644 plugins/Clist_nicer/src/Include/commonheaders.h create mode 100644 plugins/Clist_nicer/src/Include/config.h create mode 100644 plugins/Clist_nicer/src/Include/extBackg.h create mode 100644 plugins/Clist_nicer/src/Include/m_cln_skinedit.h create mode 100644 plugins/Clist_nicer/src/Include/resource.h create mode 100644 plugins/Clist_nicer/src/Include/rowheight_funcs.h create mode 100644 plugins/Clist_nicer/src/Include/vsstyle.h create mode 100644 plugins/Clist_nicer/src/Include/vssym32.h create mode 100644 plugins/Clist_nicer/src/alphablend.cpp create mode 100644 plugins/Clist_nicer/src/clc.cpp create mode 100644 plugins/Clist_nicer/src/clcidents.cpp create mode 100644 plugins/Clist_nicer/src/clcitems.cpp create mode 100644 plugins/Clist_nicer/src/clcmsgs.cpp create mode 100644 plugins/Clist_nicer/src/clcopts.cpp create mode 100644 plugins/Clist_nicer/src/clcpaint.cpp create mode 100644 plugins/Clist_nicer/src/clcutils.cpp create mode 100644 plugins/Clist_nicer/src/clistevents.cpp create mode 100644 plugins/Clist_nicer/src/clistmenus.cpp create mode 100644 plugins/Clist_nicer/src/clistmod.cpp create mode 100644 plugins/Clist_nicer/src/clistopts.cpp create mode 100644 plugins/Clist_nicer/src/clistsettings.cpp create mode 100644 plugins/Clist_nicer/src/clisttray.cpp create mode 100644 plugins/Clist_nicer/src/clnplus.cpp create mode 100644 plugins/Clist_nicer/src/clui.cpp create mode 100644 plugins/Clist_nicer/src/cluiopts.cpp create mode 100644 plugins/Clist_nicer/src/cluiservices.cpp create mode 100644 plugins/Clist_nicer/src/commonheaders.cpp create mode 100644 plugins/Clist_nicer/src/config.cpp create mode 100644 plugins/Clist_nicer/src/contact.cpp create mode 100644 plugins/Clist_nicer/src/extBackg.cpp create mode 100644 plugins/Clist_nicer/src/init.cpp create mode 100644 plugins/Clist_nicer/src/rowheight_funcs.cpp create mode 100644 plugins/Clist_nicer/src/statusbar.cpp create mode 100644 plugins/Clist_nicer/src/statusfloater.cpp create mode 100644 plugins/Clist_nicer/src/viewmodes.cpp create mode 100644 plugins/Clist_nicer/src/wallpaper.cpp (limited to 'plugins/Clist_nicer/src') diff --git a/plugins/Clist_nicer/src/CLCButton.cpp b/plugins/Clist_nicer/src/CLCButton.cpp new file mode 100644 index 0000000000..2f01b7d3db --- /dev/null +++ b/plugins/Clist_nicer/src/CLCButton.cpp @@ -0,0 +1,552 @@ +/* +Miranda IM +Copyright (C) 2002 Robert Rainwater + +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 "commonheaders.h" + +#include +#include + +struct +{ + int ctrlid; + char *pszButtonID, *pszButtonDn, *pszButtonName; + int isPush, isVis, isAction; + HANDLE hButton; +} +static BTNS[] = +{ + { IDC_TBTOPMENU, "CLN_topmenu", NULL, LPGEN("Show menu"), 1, 1, 1 }, + { IDC_TBHIDEOFFLINE, "CLN_online", NULL, LPGEN("Show / hide offline contacts"), 0, 1, 0 }, + { IDC_TBHIDEGROUPS, "CLN_groups", NULL, LPGEN("Toggle group mode"), 0, 1, 0 }, + { IDC_TBFINDANDADD, "CLN_findadd", NULL, LPGEN("Find and add contacts"), 1, 1, 0 }, + { IDC_TBACCOUNTS, "CLN_accounts", NULL, LPGEN("Accounts"), 1, 1, 0 }, + { IDC_TBOPTIONS, "CLN_options", NULL, LPGEN("Open preferences"), 1, 1, 0 }, + { IDC_TBSOUND, "CLN_sound", "CLN_soundsoff", LPGEN("Toggle sounds"), 0, 1, 0 }, + { IDC_TBMINIMIZE, "CLN_minimize", NULL, LPGEN("Minimize contact list"), 1, 0, 0 }, + { IDC_TBTOPSTATUS, "CLN_topstatus", NULL, LPGEN("Status menu"), 1, 0, 1 }, + { IDC_TABSRMMSLIST, "CLN_slist", NULL, LPGEN("tabSRMM session list"), 1, 0, 1 }, + { IDC_TABSRMMMENU, "CLN_menu", NULL, LPGEN("tabSRMM Menu"), 1, 0, 1 }, + + { IDC_TBSELECTVIEWMODE, "CLN_CLVM_select", NULL, LPGEN("Select view mode"), 1, 0, 1 }, + { IDC_TBCONFIGUREVIEWMODE,"CLN_CLVM_options", NULL, LPGEN("Setup view modes"), 1, 0, 0 }, + { IDC_TBCLEARVIEWMODE, "CLN_CLVM_reset", NULL, LPGEN("Clear view mode"), 1, 0, 0 } +}; + +static int g_index = -1; + +static int getButtonIndex(HANDLE hButton) +{ + // nasty clutch. during the initial customization + // hButton isn't assigned into BNTS yet + if (g_index != -1) + return g_index; + + for (int i=0; i < SIZEOF(BTNS); i++) + if (BTNS[i].hButton == hButton) + return i; + + return -1; +} + +static int InitDefaultButtons(WPARAM, LPARAM) +{ + for (int i=0; i < SIZEOF(BTNS); i++ ) { + TTBButton tbb = { 0 }; + tbb.cbSize = sizeof(tbb); + + g_index = i; + if (BTNS[i].pszButtonID) { + if ( !BTNS[i].isPush) + tbb.dwFlags |= TTBBF_ASPUSHBUTTON; + + tbb.pszTooltipUp = tbb.name = LPGEN(BTNS[i].pszButtonName); + tbb.hIconHandleUp = Skin_GetIconHandle(BTNS[i].pszButtonID); + if (BTNS[i].pszButtonDn) + tbb.hIconHandleUp = Skin_GetIconHandle(BTNS[i].pszButtonDn); + } + else tbb.dwFlags |= TTBBF_ISSEPARATOR; + + tbb.dwFlags |= (BTNS[i].isVis ? TTBBF_VISIBLE : 0 ); + BTNS[i].hButton = TopToolbar_AddButton(&tbb); + } + g_index = -1; + + ClcSetButtonState(IDC_TBHIDEOFFLINE, db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT)); + ClcSetButtonState(IDC_TBHIDEGROUPS, db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT)); + ClcSetButtonState(IDC_TBSOUND, db_get_b(NULL, "Skin", "UseSound", 1)); + return 1; +} + +void ClcSetButtonState(int ctrlid, int status) +{ + for (int i=0; i < SIZEOF(BTNS); i++) + if (BTNS[i].ctrlid == ctrlid) { + CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)BTNS[i].hButton, status ? TTBST_PUSHED : TTBST_RELEASED); + break; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +struct MButtonExtension : public MButtonCtrl +{ + HICON hIconPrivate; + TCHAR szText[128]; + SIZE sLabel; + HIMAGELIST hIml; + int iIcon, iCtrlID; + BOOL bSendOnDown; + ButtonItem *buttonItem; + LONG lastGlyphMetrics[4]; +}; + +// Used for our own cheap TrackMouseEvent +#define BUTTON_POLLID 100 +#define BUTTON_POLLDELAY 50 + +static int TBStateConvert2Flat(int state) +{ + switch (state) { + case PBS_NORMAL: + return TS_NORMAL; + case PBS_HOT: + return TS_HOT; + case PBS_PRESSED: + return TS_PRESSED; + case PBS_DISABLED: + return TS_DISABLED; + case PBS_DEFAULTED: + return TS_NORMAL; + } + return TS_NORMAL; +} + +static void PaintWorker(MButtonExtension *ctl, HDC hdcPaint) +{ + if (hdcPaint) { + HDC hdcMem; + HBITMAP hbmMem; + HBITMAP hbmOld = 0; + RECT rcClient; + HFONT hOldFont = 0; + int xOffset = 0; + + GetClientRect(ctl->hwnd, &rcClient); + hdcMem = CreateCompatibleDC(hdcPaint); + hbmMem = CreateCompatibleBitmap(hdcPaint, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); + hbmOld = reinterpret_cast(SelectObject(hdcMem, hbmMem)); + + hOldFont = reinterpret_cast(SelectObject(hdcMem, ctl->hFont)); + // If its a push button, check to see if it should stay pressed + if (ctl->bIsPushBtn && ctl->bIsPushed) + ctl->stateId = PBS_PRESSED; + + // Draw the flat button + if (ctl->bIsFlat) { + if (ctl->hThemeToolbar && ctl->bIsThemed) { + RECT rc = rcClient; + int state = IsWindowEnabled(ctl->hwnd) ? (ctl->stateId == PBS_NORMAL && ctl->bIsDefault ? PBS_DEFAULTED : ctl->stateId) : PBS_DISABLED; + SkinDrawBg(ctl->hwnd, hdcMem); + if (API::pfnIsThemeBackgroundPartiallyTransparent(ctl->hThemeToolbar, TP_BUTTON, TBStateConvert2Flat(state))) { + API::pfnDrawThemeParentBackground(ctl->hwnd, hdcMem, &rc); + } + API::pfnDrawThemeBackground(ctl->hThemeToolbar, hdcMem, TP_BUTTON, TBStateConvert2Flat(state), &rc, &rc); + } else { + HBRUSH hbr; + RECT rc = rcClient; + + if(ctl->buttonItem) { + RECT rcParent; + POINT pt; + HWND hwndParent = pcli->hwndContactList; + ImageItem *imgItem = ctl->stateId == PBS_HOT ? ctl->buttonItem->imgHover : (ctl->stateId == PBS_PRESSED ? ctl->buttonItem->imgPressed : ctl->buttonItem->imgNormal); + LONG *glyphMetrics = ctl->stateId == PBS_HOT ? ctl->buttonItem->hoverGlyphMetrics : (ctl->stateId == PBS_PRESSED ? ctl->buttonItem->pressedGlyphMetrics : ctl->buttonItem->normalGlyphMetrics); + + GetWindowRect(ctl->hwnd, &rcParent); + pt.x = rcParent.left; + pt.y = rcParent.top; + + ScreenToClient(pcli->hwndContactList, &pt); + + BitBlt(hdcMem, 0, 0, rc.right, rc.bottom, cfg::dat.hdcBg, pt.x, pt.y, SRCCOPY); + if(imgItem) + DrawAlpha(hdcMem, &rc, 0, 0, 0, 0, 0, 0, 0, imgItem); + if(g_glyphItem) { + API::pfnAlphaBlend(hdcMem, (rc.right - glyphMetrics[2]) / 2, (rc.bottom - glyphMetrics[3]) / 2, + glyphMetrics[2], glyphMetrics[3], g_glyphItem->hdc, + glyphMetrics[0], glyphMetrics[1], glyphMetrics[2], + glyphMetrics[3], g_glyphItem->bf); + } + } + else if(ctl->bIsSkinned) { // skinned + RECT rcParent; + POINT pt; + HWND hwndParent = pcli->hwndContactList; + StatusItems_t *item; + int item_id; + + GetWindowRect(ctl->hwnd, &rcParent); + pt.x = rcParent.left; + pt.y = rcParent.top; + + ScreenToClient(pcli->hwndContactList, &pt); + + if(HIWORD(ctl->bIsSkinned)) + item_id = ctl->stateId == PBS_HOT ? ID_EXTBKTBBUTTONMOUSEOVER : (ctl->stateId == PBS_PRESSED ? ID_EXTBKTBBUTTONSPRESSED : ID_EXTBKTBBUTTONSNPRESSED); + else + item_id = ctl->stateId == PBS_HOT ? ID_EXTBKBUTTONSMOUSEOVER : (ctl->stateId == PBS_PRESSED ? ID_EXTBKBUTTONSPRESSED : ID_EXTBKBUTTONSNPRESSED); + item = &StatusItems[item_id - ID_STATUS_OFFLINE]; + + SetTextColor(hdcMem, item->TEXTCOLOR); + if(item->IGNORED) { + if(pt.y < 10 || cfg::dat.bWallpaperMode) + BitBlt(hdcMem, 0, 0, rc.right, rc.bottom, cfg::dat.hdcBg, pt.x, pt.y, SRCCOPY); + else + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_3DFACE)); + } + else { + if(pt.y < 10 || cfg::dat.bWallpaperMode) + BitBlt(hdcMem, 0, 0, rc.right, rc.bottom, cfg::dat.hdcBg, pt.x, pt.y, SRCCOPY); + else + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_3DFACE)); + rc.top += item->MARGIN_TOP; rc.bottom -= item->MARGIN_BOTTOM; + rc.left += item->MARGIN_LEFT; rc.right -= item->MARGIN_RIGHT; + DrawAlpha(hdcMem, &rc, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, item->GRADIENT, + item->CORNER, item->BORDERSTYLE, item->imageItem); + } + } + else { + if (ctl->stateId == PBS_PRESSED || ctl->stateId == PBS_HOT) + hbr = GetSysColorBrush(COLOR_3DFACE); + else { + HDC dc; + HWND hwndParent; + + hwndParent = GetParent(ctl->hwnd); + dc = GetDC(hwndParent); + hbr = (HBRUSH) SendMessage(hwndParent, WM_CTLCOLORDLG, (WPARAM) dc, (LPARAM) hwndParent); + ReleaseDC(hwndParent, dc); + } + if (hbr) { + FillRect(hdcMem, &rc, hbr); + DeleteObject(hbr); + } + } + if(!ctl->bIsSkinned && ctl->buttonItem == 0) { + if (ctl->stateId == PBS_HOT || ctl->focus) { + if (ctl->bIsPushed) + DrawEdge(hdcMem, &rc, EDGE_ETCHED, BF_RECT | BF_SOFT); + else + DrawEdge(hdcMem, &rc, BDR_RAISEDOUTER, BF_RECT | BF_SOFT); + } else if (ctl->stateId == PBS_PRESSED) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT | BF_SOFT); + } + } + } else { + // Draw background/border + if (ctl->hThemeButton && ctl->bIsThemed) { + int state = IsWindowEnabled(ctl->hwnd) ? (ctl->stateId == PBS_NORMAL && ctl->bIsDefault ? PBS_DEFAULTED : ctl->stateId) : PBS_DISABLED; + POINT pt; + RECT rcParent; + + GetWindowRect(ctl->hwnd, &rcParent); + pt.x = rcParent.left; + pt.y = rcParent.top; + ScreenToClient(pcli->hwndContactList, &pt); + BitBlt(hdcMem, 0, 0, rcClient.right, rcClient.bottom, cfg::dat.hdcBg, pt.x, pt.y, SRCCOPY); + + if (API::pfnIsThemeBackgroundPartiallyTransparent(ctl->hThemeButton, BP_PUSHBUTTON, state)) { + API::pfnDrawThemeParentBackground(ctl->hwnd, hdcMem, &rcClient); + } + API::pfnDrawThemeBackground(ctl->hThemeButton, hdcMem, BP_PUSHBUTTON, state, &rcClient, &rcClient); + } else { + UINT uState = DFCS_BUTTONPUSH | ((ctl->stateId == PBS_HOT) ? DFCS_HOT : 0) | ((ctl->stateId == PBS_PRESSED) ? DFCS_PUSHED : 0); + if (ctl->bIsDefault && ctl->stateId == PBS_NORMAL) + uState |= DLGC_DEFPUSHBUTTON; + DrawFrameControl(hdcMem, &rcClient, DFC_BUTTON, uState); + } + + // Draw focus rectangle if button has focus + if (ctl->focus) { + RECT focusRect = rcClient; + InflateRect(&focusRect, -3, -3); + DrawFocusRect(hdcMem, &focusRect); + } + } + + // If we have an icon or a bitmap, ignore text and only draw the image on the button + if (ctl->hIcon || ctl->hIconPrivate || ctl->iIcon) { + int ix = (rcClient.right - rcClient.left) / 2 - (g_cxsmIcon / 2); + int iy = (rcClient.bottom - rcClient.top) / 2 - (g_cxsmIcon / 2); + HICON hIconNew = ctl->hIconPrivate != 0 ? ctl->hIconPrivate : ctl->hIcon; + if (lstrlen(ctl->szText) == 0) { + if (ctl->iIcon) + ImageList_DrawEx(ctl->hIml, ctl->iIcon, hdcMem, ix, iy, g_cxsmIcon, g_cysmIcon, CLR_NONE, CLR_NONE, ILD_NORMAL); + else + DrawState(hdcMem, NULL, NULL, (LPARAM) hIconNew, 0, ix, iy, g_cxsmIcon, g_cysmIcon, IsWindowEnabled(ctl->hwnd) ? DST_ICON | DSS_NORMAL : DST_ICON | DSS_DISABLED); + ctl->sLabel.cx = ctl->sLabel.cy = 0; + } else { + GetTextExtentPoint32(hdcMem, ctl->szText, lstrlen(ctl->szText), &ctl->sLabel); + + if(g_cxsmIcon + ctl->sLabel.cx + 8 > rcClient.right - rcClient.left) + ctl->sLabel.cx = (rcClient.right - rcClient.left) - g_cxsmIcon - 8; + else + ctl->sLabel.cx += 4; + + ix = (rcClient.right - rcClient.left) / 2 - ((g_cxsmIcon + ctl->sLabel.cx) / 2); + if (ctl->iIcon) + ImageList_DrawEx(ctl->hIml, ctl->iIcon, hdcMem, ix, iy, g_cxsmIcon, g_cysmIcon, CLR_NONE, CLR_NONE, ILD_NORMAL); + else + DrawState(hdcMem, NULL, NULL, (LPARAM) hIconNew, 0, ix, iy, g_cxsmIcon, g_cysmIcon, IsWindowEnabled(ctl->hwnd) ? DST_ICON | DSS_NORMAL : DST_ICON | DSS_DISABLED); + xOffset = ix + g_cxsmIcon + 4; + } + } else if (ctl->hBitmap) { + BITMAP bminfo; + int ix, iy; + + GetObject(ctl->hBitmap, sizeof(bminfo), &bminfo); + ix = (rcClient.right - rcClient.left) / 2 - (bminfo.bmWidth / 2); + iy = (rcClient.bottom - rcClient.top) / 2 - (bminfo.bmHeight / 2); + if (ctl->stateId == PBS_PRESSED) { + ix++; + iy++; + } + DrawState(hdcMem, NULL, NULL, (LPARAM) ctl->hBitmap, 0, ix, iy, bminfo.bmWidth, bminfo.bmHeight, IsWindowEnabled(ctl->hwnd) ? DST_BITMAP : DST_BITMAP | DSS_DISABLED); + } + if (GetWindowTextLength(ctl->hwnd)) { + // Draw the text and optinally the arrow + RECT rcText; + + CopyRect(&rcText, &rcClient); + SetBkMode(hdcMem, TRANSPARENT); + // XP w/themes doesn't used the glossy disabled text. Is it always using COLOR_GRAYTEXT? Seems so. + if(!ctl->bIsSkinned) + SetTextColor(hdcMem, IsWindowEnabled(ctl->hwnd) || !ctl->hThemeButton ? GetSysColor(COLOR_BTNTEXT) : GetSysColor(COLOR_GRAYTEXT)); + if (ctl->arrow) + DrawState(hdcMem, NULL, NULL, (LPARAM) ctl->arrow, 0, rcClient.right - rcClient.left - 5 - g_cxsmIcon + (!ctl->hThemeButton && ctl->stateId == PBS_PRESSED ? 1 : 0), (rcClient.bottom - rcClient.top) / 2 - g_cysmIcon / 2 + (!ctl->hThemeButton && ctl->stateId == PBS_PRESSED ? 1 : 0), g_cxsmIcon, g_cysmIcon, IsWindowEnabled(ctl->hwnd) ? DST_ICON : DST_ICON | DSS_DISABLED); + DrawState(hdcMem, NULL, NULL, (LPARAM) ctl->szText, 0, xOffset + (!ctl->hThemeButton && ctl->stateId == PBS_PRESSED ? 1 : 0), ctl->hThemeButton ? (rcText.bottom - rcText.top - ctl->sLabel.cy) / 2 + 1 : (rcText.bottom - rcText.top - ctl->sLabel.cy) / 2 + (ctl->stateId == PBS_PRESSED ? 1 : 0), ctl->sLabel.cx, ctl->sLabel.cy, IsWindowEnabled(ctl->hwnd) || ctl->hThemeButton ? DST_PREFIXTEXT | DSS_NORMAL : DST_PREFIXTEXT | DSS_DISABLED); + } + if (hOldFont) + SelectObject(hdcMem, hOldFont); + BitBlt(hdcPaint, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hbmOld); + DeleteObject(hbmMem); + DeleteDC(hdcMem); + DeleteObject(hbmOld); + } +} + +static LRESULT CALLBACK TSButtonWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + MButtonExtension *bct = (MButtonExtension*) GetWindowLongPtr(hwnd, 0); + + switch (msg) { + case WM_DESTROY: + if (bct && bct->hIconPrivate) + DestroyIcon(bct->hIconPrivate); + break; + + case WM_SETTEXT: + lstrcpyn(bct->szText, (TCHAR *)lParam, 127); + bct->szText[127] = 0; + break; + + case WM_SYSKEYUP: + if (bct->stateId != PBS_DISABLED && bct->cHot && bct->cHot == tolower((int) wParam)) { + if (!bct->bSendOnDown) + SendMessage(pcli->hwndContactList, WM_COMMAND, MAKELONG(bct->iCtrlID, BN_CLICKED), (LPARAM) hwnd); + bct->lResult = 0; + return 1; + } + break; + + case BM_GETIMAGE: + if (wParam == IMAGE_ICON) { + bct->lResult = (LRESULT)(bct->hIconPrivate ? bct->hIconPrivate : bct->hIcon); + return 1; + } + break; + + case BM_SETIMAGE: + if(!lParam) + break; + + bct->hIml = 0; + bct->iIcon = 0; + if (wParam == IMAGE_ICON) { + ICONINFO ii = {0}; + BITMAP bm = {0}; + + if (bct->hIconPrivate) { + DestroyIcon(bct->hIconPrivate); + bct->hIconPrivate = 0; + } + + GetIconInfo((HICON) lParam, &ii); + GetObject(ii.hbmColor, sizeof(bm), &bm); + if (bm.bmWidth > g_cxsmIcon || bm.bmHeight > g_cysmIcon) { + HIMAGELIST hImageList; + hImageList = ImageList_Create(g_cxsmIcon, g_cysmIcon, IsWinVerXPPlus() ? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, 1, 0); + ImageList_AddIcon(hImageList, (HICON) lParam); + bct->hIconPrivate = ImageList_GetIcon(hImageList, 0, ILD_NORMAL); + ImageList_RemoveAll(hImageList); + ImageList_Destroy(hImageList); + bct->hIcon = 0; + } else { + bct->hIcon = (HICON) lParam; + bct->hIconPrivate = 0; + } + + DeleteObject(ii.hbmMask); + DeleteObject(ii.hbmColor); + bct->hBitmap = NULL; + InvalidateRect(bct->hwnd, NULL, TRUE); + } + else if (wParam == IMAGE_BITMAP) { + bct->hBitmap = (HBITMAP) lParam; + if (bct->hIconPrivate) + DestroyIcon(bct->hIconPrivate); + bct->hIcon = bct->hIconPrivate = NULL; + InvalidateRect(bct->hwnd, NULL, TRUE); + } + return 1; + + case BUTTONSETIMLICON: + if (bct->hIconPrivate) + DestroyIcon(bct->hIconPrivate); + bct->hIml = (HIMAGELIST) wParam; + bct->iIcon = (int) lParam; + bct->hIcon = bct->hIconPrivate = 0; + InvalidateRect(bct->hwnd, NULL, TRUE); + break; + + case BUTTONSETSKINNED: + bct->bIsSkinned = lParam != 0; + bct->bIsThemed = bct->bIsSkinned ? FALSE : bct->bIsThemed; + InvalidateRect(bct->hwnd, NULL, TRUE); + break; + + case BUTTONSETBTNITEM: + bct->buttonItem = (ButtonItem *)lParam; + break; + + case BUTTONSETASMENUACTION: + bct->bSendOnDown = wParam ? TRUE : FALSE; + break; + + case WM_LBUTTONDOWN: + if (!bct->iCtrlID) return 0; + if (bct->stateId != PBS_DISABLED && bct->stateId != PBS_PRESSED) { + bct->stateId = PBS_PRESSED; + InvalidateRect(bct->hwnd, NULL, TRUE); + if (bct->bSendOnDown) { + SendMessage( GetParent(hwnd), WM_COMMAND, MAKELONG(bct->iCtrlID, BN_CLICKED), (LPARAM) hwnd); + bct->stateId = PBS_NORMAL; + InvalidateRect(bct->hwnd, NULL, TRUE); + } + } + return 1; + + case WM_LBUTTONUP: + if (!bct->iCtrlID) return 0; + if (bct->bIsPushBtn) + bct->bIsPushed = !bct->bIsPushed; + + if (bct->stateId != PBS_DISABLED) { + // don't change states if disabled + bct->stateId = PBS_HOT; + InvalidateRect(bct->hwnd, NULL, TRUE); + } + if ( !bct->bSendOnDown) + SendMessage( GetParent(hwnd), WM_COMMAND, MAKELONG(bct->iCtrlID, BN_CLICKED), (LPARAM) hwnd); + return 1; + + case WM_NCHITTEST: + switch( SendMessage(pcli->hwndContactList, WM_NCHITTEST, wParam, lParam)) { + case HTLEFT: case HTRIGHT: case HTBOTTOM: case HTTOP: + case HTTOPLEFT: case HTTOPRIGHT: case HTBOTTOMLEFT: case HTBOTTOMRIGHT: + bct->lResult = HTTRANSPARENT; + return 1; + } + } + return 0; +} + +static void SetButtonAsCustom(HWND hWnd) +{ + MButtonCustomize Custom; + Custom.cbLen = sizeof(MButtonExtension); + Custom.fnPainter = (pfnPainterFunc)PaintWorker; + Custom.fnWindowProc = TSButtonWndProc; + SendMessage(hWnd, BUTTONSETCUSTOM, 0, (LPARAM)&Custom); +} + +static LRESULT CALLBACK ToolbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED) + SendMessage(pcli->hwndContactList, msg, wParam, lParam); + + return 0; +} + +static void CustomizeToolbar(HANDLE hButton, HWND hWnd, LPARAM) +{ + // we don't customize the toolbar window, only buttons + if (hButton == TTB_WINDOW_HANDLE) { + TTBCtrlCustomize custData = { sizeof(TTBCtrl), ToolbarWndProc }; + SendMessage(hWnd, TTB_SETCUSTOM, 0, (LPARAM)&custData); + return; + } + + SetButtonAsCustom(hWnd); + + MButtonExtension *bct = (MButtonExtension*) GetWindowLongPtr(hWnd, 0); + int idx = getButtonIndex(hButton); + if (idx != -1) { // adding built-in button + bct->iCtrlID = BTNS[idx].ctrlid; + if (BTNS[idx].isAction) + bct->bSendOnDown = TRUE; + if (!BTNS[idx].isPush) + bct->bIsPushBtn = TRUE; + } +} + +void CustomizeButton(HWND hWnd, bool bIsSkinned, bool bIsThemed, bool bIsFlat) +{ + SetButtonAsCustom(hWnd); + + MButtonExtension *bct = (MButtonExtension*) GetWindowLongPtr(hWnd, 0); + if (bct) + bct->iCtrlID = GetDlgCtrlID(hWnd); + + SendMessage(hWnd, BUTTONSETSKINNED, bIsSkinned, 0); + SendMessage(hWnd, BUTTONSETASTHEMEDBTN, bIsThemed, 0); + SendMessage(hWnd, BUTTONSETASFLATBTN, bIsFlat, 0); +} + +static int Nicer_CustomizeToolbar(WPARAM, LPARAM) +{ + HookEvent(ME_TTB_INITBUTTONS, InitDefaultButtons); + TopToolbar_SetCustomProc(CustomizeToolbar, 0); + return 0; +} + +void LoadButtonModule() +{ + HookEvent(ME_SYSTEM_MODULESLOADED, Nicer_CustomizeToolbar); +} diff --git a/plugins/Clist_nicer/src/CLUIFrames/cluiframes.cpp b/plugins/Clist_nicer/src/CLUIFrames/cluiframes.cpp new file mode 100644 index 0000000000..8fbaa547e6 --- /dev/null +++ b/plugins/Clist_nicer/src/CLUIFrames/cluiframes.cpp @@ -0,0 +1,3584 @@ +/* +astyle --force-indent=tab=4 --brackets=linux --indent-switches + --pad=oper --one-line=keep-blocks --unpad=paren + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 +#include "cluiframes.h" +HFONT __fastcall ChangeToFont(HDC hdc, struct ClcData *dat, int id, int *fontHeight); + +extern HIMAGELIST himlExtraImages; +extern HWND g_hwndViewModeFrame, g_hwndEventArea; +extern StatusItems_t *StatusItems; +extern int mf_updatethread_running; + +extern DWORD WINAPI MF_UpdateThread(LPVOID p); +extern HANDLE hThreadMFUpdate;; + +HANDLE hExtraImageListRebuilding, hExtraImageApplying; +HANDLE hStatusBarShowToolTipEvent, hStatusBarHideToolTipEvent; +HANDLE g_hEventThread = 0; + +//not needed,now use MS_CLIST_FRAMEMENUNOTIFY service +//HANDLE hPreBuildFrameMenuEvent;//external event from clistmenus + +LOGFONT TitleBarLogFont = {0}; + +extern HINSTANCE g_hInst; + +//we use dynamic frame list, +//but who wants so huge number of frames ?? +#define MAX_FRAMES 40 + +#define UNCOLLAPSED_FRAME_SIZE 0 + +//legacy menu support +#define frame_menu_lock 1 +#define frame_menu_visible 2 +#define frame_menu_showtitlebar 3 +#define frame_menu_floating 4 +#define frame_menu_skinned 5 + +extern INT_PTR ModifyMenuItemProxy(WPARAM wParam, LPARAM lParam); +static int UpdateTBToolTip(int framepos); +INT_PTR CLUIFrameSetFloat(WPARAM wParam, LPARAM lParam); +int CLUIFrameResizeFloatingFrame(int framepos); +extern int ProcessCommandProxy(WPARAM wParam, LPARAM lParam); +extern int InitFramesMenus(void); +extern int UnitFramesMenu(); +static int CLUIFramesReSort(); + +boolean FramesSysNotStarted = TRUE; +HPEN g_hPenCLUIFrames = 0; + +typedef struct { + int order; + int realpos; +} SortData; + +static SortData g_sd[MAX_FRAMES]; + +static HHOOK g_hFrameHook = 0; + +static int sortfunc(const void *a, const void *b) +{ + SortData *sd1, *sd2; + sd1 = (SortData *)a; + sd2 = (SortData *)b; + if (sd1->order > sd2->order) + return(1); + if (sd1->order < sd2->order) + return(-1); + return(0); +} + +#define CLUIFRAMESSETALIGN "CLUIFramesSetAlign" +#define CLUIFRAMESSETALIGNALTOP "CLUIFramesSetAlignalTop" +#define CLUIFRAMESSETALIGNALCLIENT "CLUIFramesSetAlignalClient" +#define CLUIFRAMESSETALIGNALBOTTOM "CLUIFramesSetAlignalBottom" +#define CLUIFRAMESMOVEUP "CLUIFramesMoveUp" +#define CLUIFRAMESMOVEDOWN "CLUIFramesMoveDown" + +static wndFrame *Frames = NULL; + +wndFrame *wndFrameCLC = NULL, *wndFrameEventArea = NULL, *wndFrameViewMode = NULL; + +static int nFramescount = 0; +static int alclientFrame = -1;//for fast access to frame with alclient properties +static int NextFrameId = 100; + +static int TitleBarH = DEFAULT_TITLEBAR_HEIGHT; +static boolean resizing = FALSE; + +// menus +static HANDLE contMIVisible, contMITitle, contMITBVisible, contMILock, contMIColl, contMIFloating; +static HANDLE contMIAlignRoot; +static HANDLE contMIAlignTop, contMIAlignClient, contMIAlignBottom; +static HANDLE contMIBorder, contMISkinned; +static HANDLE MainMIRoot = (HANDLE) - 1; + +// others +static int ContactListHeight; +static int LastStoreTick = 0; + +static int lbypos = -1; +static int oldframeheight = -1; +static int curdragbar = -1; +static CRITICAL_SECTION csFrameHook; + +static BOOLEAN CLUIFramesFitInSize(void); +HWND hWndExplorerToolBar; +static int GapBetweenFrames = 1; + +static int RemoveItemFromList(int pos, wndFrame **lpFrames, int *FrameItemCount) +{ + memcpy(&((*lpFrames)[pos]), &((*lpFrames)[pos+1]), sizeof(wndFrame)*(*FrameItemCount - pos - 1)); + (*FrameItemCount)--; + return 0; +} + +static int id2pos(int id) +{ + int i; + + if (FramesSysNotStarted) + return -1; + + for (i = 0;i < nFramescount;i++) { + if (Frames[i].id == id) + return(i); + } + return(-1); +} + +int __forceinline btoint(BOOLEAN b) +{ + return(b ? 1 : 0); +} + +void __forceinline lockfrm() +{ + if (FramesSysNotStarted == FALSE) + EnterCriticalSection(&csFrameHook); +} + +void __forceinline ulockfrm() +{ + LeaveCriticalSection(&csFrameHook); +} + +static wndFrame* FindFrameByWnd(HWND hwnd) +{ + BOOL bFound = FALSE; + int i; + + if (hwnd == NULL) + return(NULL); + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].floating) && (Frames[i].ContainerWnd == hwnd)) + return(&Frames[i]); + } + return(NULL); +} + + +static void DockThumbs(wndFrame *pThumbLeft, wndFrame *pThumbRight, BOOL bMoveLeft) +{ + if ((pThumbRight->dockOpt.hwndLeft == NULL) && (pThumbLeft->dockOpt.hwndRight == NULL)) { + pThumbRight->dockOpt.hwndLeft = pThumbLeft->ContainerWnd; + pThumbLeft->dockOpt.hwndRight = pThumbRight->ContainerWnd; + } +} + + +static void UndockThumbs(wndFrame *pThumb1, wndFrame *pThumb2) +{ + if ((pThumb1 == NULL) || (pThumb2 == NULL)) + return; + + if (pThumb1->dockOpt.hwndRight == pThumb2->ContainerWnd) + pThumb1->dockOpt.hwndRight = NULL; + + if (pThumb1->dockOpt.hwndLeft == pThumb2->ContainerWnd) + pThumb1->dockOpt.hwndLeft = NULL; + + if (pThumb2->dockOpt.hwndRight == pThumb1->ContainerWnd) + pThumb2->dockOpt.hwndRight = NULL; + + if (pThumb2->dockOpt.hwndLeft == pThumb1->ContainerWnd) + pThumb2->dockOpt.hwndLeft = NULL; +} + +BOOLEAN bMoveTogether; + +static void PositionThumb(wndFrame *pThumb, short nX, short nY) +{ + wndFrame *pCurThumb = &Frames[0]; + wndFrame *pDockThumb = pThumb; + wndFrame fakeMainWindow; + wndFrame fakeTaskBarWindow; + RECT rc; + RECT rcThumb; + RECT rcOld; + SIZE sizeScreen; + int nNewX; + int nNewY; + int nOffs = 10; + int nWidth; + int nHeight; + POINT pt; + RECT rcLeft; + RECT rcTop; + RECT rcRight; + RECT rcBottom; + BOOL bDocked; + BOOL bDockedLeft; + BOOL bDockedRight; + BOOL bLeading; + int frmidx = 0; + + if (pThumb == NULL) + return; + + sizeScreen.cx = GetSystemMetrics(SM_CXSCREEN); + sizeScreen.cy = GetSystemMetrics(SM_CYSCREEN); + + // Get thumb dimnsions + GetWindowRect(pThumb->ContainerWnd, &rcThumb); + nWidth = rcThumb.right - rcThumb.left; + nHeight = rcThumb.bottom - rcThumb.top; + + // Docking to the edges of the screen + nNewX = nX < nOffs ? 0 : nX; + nNewX = nNewX > (sizeScreen.cx - nWidth - nOffs) ? (sizeScreen.cx - nWidth) : nNewX; + nNewY = nY < nOffs ? 0 : nY; + nNewY = nNewY > (sizeScreen.cy - nHeight - nOffs) ? (sizeScreen.cy - nHeight) : nNewY; + + bLeading = pThumb->dockOpt.hwndRight != NULL; + + if (bMoveTogether) { + UndockThumbs(pThumb, FindFrameByWnd(pThumb->dockOpt.hwndLeft)); + GetWindowRect(pThumb->ContainerWnd, &rcOld); + } + + memset(&fakeMainWindow, 0, sizeof(fakeMainWindow)); + fakeMainWindow.ContainerWnd = pcli->hwndContactList; + fakeMainWindow.floating = TRUE; + + memset(&fakeTaskBarWindow, 0, sizeof(fakeTaskBarWindow)); + fakeTaskBarWindow.ContainerWnd = hWndExplorerToolBar; + fakeTaskBarWindow.floating = TRUE; + + + while (pCurThumb != NULL) { + if (pCurThumb->floating) { + + if (pCurThumb != pThumb) { + GetWindowRect(pThumb->ContainerWnd, &rcThumb); + OffsetRect(&rcThumb, nX - rcThumb.left, nY - rcThumb.top); + + GetWindowRect(pCurThumb->ContainerWnd, &rc); + + rcLeft.left = rc.left - nOffs; + rcLeft.top = rc.top - nOffs; + rcLeft.right = rc.left + nOffs; + rcLeft.bottom = rc.bottom + nOffs; + + rcTop.left = rc.left - nOffs; + rcTop.top = rc.top - nOffs; + rcTop.right = rc.right + nOffs; + rcTop.bottom = rc.top + nOffs; + + rcRight.left = rc.right - nOffs; + rcRight.top = rc.top - nOffs; + rcRight.right = rc.right + nOffs; + rcRight.bottom = rc.bottom + nOffs; + + rcBottom.left = rc.left - nOffs; + rcBottom.top = rc.bottom - nOffs; + rcBottom.right = rc.right + nOffs; + rcBottom.bottom = rc.bottom + nOffs; + + + bDockedLeft = FALSE; + bDockedRight = FALSE; + + // Upper-left + pt.x = rcThumb.left; + pt.y = rcThumb.top; + bDocked = FALSE; + + if (PtInRect(&rcRight, pt)) { + nNewX = rc.right; + bDocked = TRUE; + } + + if (PtInRect(&rcBottom, pt)) { + nNewY = rc.bottom; + + if (PtInRect(&rcLeft, pt)) + nNewX = rc.left; + } + + if (PtInRect(&rcTop, pt)) { + nNewY = rc.top; + bDockedLeft = bDocked; + } + + // Upper-right + pt.x = rcThumb.right; + pt.y = rcThumb.top; + bDocked = FALSE; + + if (!bLeading && PtInRect(&rcLeft, pt)) { + if (!bDockedLeft) { + nNewX = rc.left - nWidth; + bDocked = TRUE; + } else if (rc.right == rcThumb.left) + bDocked = TRUE; + } + + + if (PtInRect(&rcBottom, pt)) { + nNewY = rc.bottom; + + if (PtInRect(&rcRight, pt)) + nNewX = rc.right - nWidth; + } + + if (!bLeading && PtInRect(&rcTop, pt)) { + nNewY = rc.top; + bDockedRight = bDocked; + } + + if (bMoveTogether) { + if (bDockedRight) { + DockThumbs(pThumb, pCurThumb, TRUE); + } + + if (bDockedLeft) { + DockThumbs(pCurThumb, pThumb, FALSE); + } + } + + // Lower-left + pt.x = rcThumb.left; + pt.y = rcThumb.bottom; + + if (PtInRect(&rcRight, pt)) { + nNewX = rc.right; + } + + if (PtInRect(&rcTop, pt)) { + nNewY = rc.top - nHeight; + + if (PtInRect(&rcLeft, pt)) { + nNewX = rc.left; + } + } + + + // Lower-right + pt.x = rcThumb.right; + pt.y = rcThumb.bottom; + + if (!bLeading && PtInRect(&rcLeft, pt)) { + nNewX = rc.left - nWidth; + } + + if (!bLeading && PtInRect(&rcTop, pt)) { + nNewY = rc.top - nHeight; + + if (PtInRect(&rcRight, pt)) { + nNewX = rc.right - nWidth; + } + } + } + + }; + frmidx++; + if (pCurThumb->ContainerWnd == fakeTaskBarWindow.ContainerWnd) + break; + if (pCurThumb->ContainerWnd == fakeMainWindow.ContainerWnd) { + pCurThumb = &fakeTaskBarWindow; + continue; + } + if (frmidx == nFramescount) { + pCurThumb = &fakeMainWindow; + continue; + } + pCurThumb = &Frames[frmidx]; + } + + // Adjust coords once again + nNewX = nNewX < nOffs ? 0 : nNewX; + nNewX = nNewX > (sizeScreen.cx - nWidth - nOffs) ? (sizeScreen.cx - nWidth) : nNewX; + nNewY = nNewY < nOffs ? 0 : nNewY; + nNewY = nNewY > (sizeScreen.cy - nHeight - nOffs) ? (sizeScreen.cy - nHeight) : nNewY; + + SetWindowPos(pThumb->ContainerWnd, + 0, + nNewX, + nNewY, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + + + // OK, move all docked thumbs + if (bMoveTogether) { + pDockThumb = FindFrameByWnd(pDockThumb->dockOpt.hwndRight); + + PositionThumb(pDockThumb, (short)(nNewX + nWidth), (short)nNewY); + } +} + +void GetBorderSize(HWND hwnd, RECT *rect) +{ + RECT wr, cr; + POINT pt1, pt2; + + GetWindowRect(hwnd, &wr); + GetClientRect(hwnd, &cr); + pt1.y = cr.top; + pt1.x = cr.left; + pt2.y = cr.bottom; + pt2.x = cr.right; + + ClientToScreen(hwnd, &pt1); + ClientToScreen(hwnd, &pt2); + + cr.top = pt1.y; + cr.left = pt1.x; + cr.bottom = pt2.y; + cr.right = pt2.x; + + rect->top = cr.top - wr.top; + rect->left = cr.left - wr.left; + rect->right = wr.right - cr.right; + rect->bottom = wr.bottom - cr.bottom; +} + +//append string +char __forceinline *AS(char *str, const char *setting, char *addstr) +{ + if (str != NULL) { + strcpy(str, setting); + strcat(str, addstr); + } + return str; +} + +int DBLoadFrameSettingsAtPos(int pos, int Frameid) +{ + char sadd[15]; + char buf[255]; + + _itoa(pos, sadd, 10); + + Frames[Frameid].collapsed = cfg::getByte(CLUIFrameModule, AS(buf, "Collapse", sadd), Frames[Frameid].collapsed); + + Frames[Frameid].Locked = cfg::getByte(CLUIFrameModule, AS(buf, "Locked", sadd), Frames[Frameid].Locked); + Frames[Frameid].visible = cfg::getByte(CLUIFrameModule, AS(buf, "Visible", sadd), Frames[Frameid].visible); + Frames[Frameid].TitleBar.ShowTitleBar = cfg::getByte(CLUIFrameModule, AS(buf, "TBVisile", sadd), Frames[Frameid].TitleBar.ShowTitleBar); + + Frames[Frameid].height = cfg::getWord(CLUIFrameModule, AS(buf, "Height", sadd), Frames[Frameid].height); + Frames[Frameid].HeightWhenCollapsed = cfg::getWord(CLUIFrameModule, AS(buf, "HeightCollapsed", sadd), 0); + Frames[Frameid].align = cfg::getWord(CLUIFrameModule, AS(buf, "Align", sadd), Frames[Frameid].align); + + Frames[Frameid].FloatingPos.x = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatX", sadd), 100, 0, 1024); + Frames[Frameid].FloatingPos.y = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatY", sadd), 100, 0, 1024); + Frames[Frameid].FloatingSize.x = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatW", sadd), 100, 0, 1024); + Frames[Frameid].FloatingSize.y = DBGetContactSettingRangedWord(0, CLUIFrameModule, AS(buf, "FloatH", sadd), 100, 0, 1024); + + Frames[Frameid].floating = cfg::getByte(CLUIFrameModule, AS(buf, "Floating", sadd), 0); + Frames[Frameid].order = cfg::getWord(CLUIFrameModule, AS(buf, "Order", sadd), 0); + + Frames[Frameid].UseBorder = cfg::getByte(CLUIFrameModule, AS(buf, "UseBorder", sadd), Frames[Frameid].UseBorder); + Frames[Frameid].Skinned = cfg::getByte(CLUIFrameModule, AS(buf, "Skinned", sadd), Frames[Frameid].Skinned); + return 0; +} + +int DBStoreFrameSettingsAtPos(int pos, int Frameid) +{ + char sadd[16]; + char buf[255]; + + _itoa(pos, sadd, 10); + + cfg::writeTString(0, CLUIFrameModule, AS(buf, "Name", sadd), Frames[Frameid].name); + //boolean + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Collapse", sadd), (BYTE)btoint(Frames[Frameid].collapsed)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Locked", sadd), (BYTE)btoint(Frames[Frameid].Locked)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Visible", sadd), (BYTE)btoint(Frames[Frameid].visible)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "TBVisile", sadd), (BYTE)btoint(Frames[Frameid].TitleBar.ShowTitleBar)); + + cfg::writeWord(CLUIFrameModule, AS(buf, "Height", sadd), (WORD)Frames[Frameid].height); + cfg::writeWord(CLUIFrameModule, AS(buf, "HeightCollapsed", sadd), (WORD)Frames[Frameid].HeightWhenCollapsed); + cfg::writeWord(CLUIFrameModule, AS(buf, "Align", sadd), (WORD)Frames[Frameid].align); + //FloatingPos + cfg::writeWord(CLUIFrameModule, AS(buf, "FloatX", sadd), (WORD)Frames[Frameid].FloatingPos.x); + cfg::writeWord(CLUIFrameModule, AS(buf, "FloatY", sadd), (WORD)Frames[Frameid].FloatingPos.y); + cfg::writeWord(CLUIFrameModule, AS(buf, "FloatW", sadd), (WORD)Frames[Frameid].FloatingSize.x); + cfg::writeWord(0, CLUIFrameModule, AS(buf, "FloatH", sadd), (WORD)Frames[Frameid].FloatingSize.y); + + cfg::writeByte(0, CLUIFrameModule, AS(buf, "Floating", sadd), (BYTE)btoint(Frames[Frameid].floating)); + cfg::writeByte(0, CLUIFrameModule, AS(buf, "UseBorder", sadd), (BYTE)btoint(Frames[Frameid].UseBorder)); + cfg::writeWord(0, CLUIFrameModule, AS(buf, "Order", sadd), (WORD)Frames[Frameid].order); + + cfg::writeByte(CLUIFrameModule, AS(buf, "Skinned", sadd), Frames[Frameid].Skinned); + return 0; +} + +int LocateStorePosition(int Frameid, int maxstored) +{ + int i; + LPTSTR frmname; + char settingname[255]; + if (Frames[Frameid].name == NULL) return -1; + + for (i = 0;i < maxstored;i++) { + mir_snprintf(settingname, sizeof(settingname), "Name%d", i); + frmname = DBGetStringT(0, CLUIFrameModule, settingname); + if (frmname == NULL) continue; + if (lstrcmpi(frmname, Frames[Frameid].name) == 0) { + mir_free(frmname); + return i; + } + mir_free(frmname); + } + return -1; +} + +int CLUIFramesLoadFrameSettings(int Frameid) +{ + int storpos, maxstored; + + if (FramesSysNotStarted) return -1; + + if (Frameid < 0 || Frameid >= nFramescount) + return -1; + + maxstored = cfg::getWord(CLUIFrameModule, "StoredFrames", -1); + if (maxstored == -1) + return 0; + + storpos = LocateStorePosition(Frameid, maxstored); + if (storpos == -1) + return 0; + + DBLoadFrameSettingsAtPos(storpos, Frameid); + return 0; +} + +int CLUIFramesStoreFrameSettings(int Frameid) +{ + int maxstored, storpos; + + if (FramesSysNotStarted) + return -1; + + if (Frameid < 0 || Frameid >= nFramescount) + return -1; + + maxstored = cfg::getWord(CLUIFrameModule, "StoredFrames", -1); + if (maxstored == -1) + maxstored = 0; + + storpos = LocateStorePosition(Frameid, maxstored); + if (storpos == -1) { + storpos = maxstored; + maxstored++; + } + + DBStoreFrameSettingsAtPos(storpos, Frameid); + cfg::writeWord(CLUIFrameModule, "StoredFrames", (WORD)maxstored); + return 0; +} + +int CLUIFramesStoreAllFrames() +{ + int i; + + if (FramesSysNotStarted) + return -1; + + if (cfg::shutDown) + return -1; + + lockfrm(); + for (i = 0;i < nFramescount;i++) + CLUIFramesStoreFrameSettings(i); + ulockfrm(); + return 0; +} + +// Get client frame +int CLUIFramesGetalClientFrame(void) +{ + int i; + if (FramesSysNotStarted) + return -1; + + if (alclientFrame != -1) + return alclientFrame; + + if (alclientFrame != -1) { + /* this value could become invalid if RemoveItemFromList was called, + * so we double-check */ + if (alclientFrame < nFramescount) { + if (Frames[alclientFrame].align == alClient) { + return alclientFrame; + } + } + } + + for (i = 0;i < nFramescount;i++) + if (Frames[i].align == alClient) { + alclientFrame = i; + return i; + } + return -1; +} + +HMENU CLUIFramesCreateMenuForFrame(int frameid, int root, int popuppos, HGENMENU (*pfnAdd )( CLISTMENUITEM* )) +{ + CLISTMENUITEM mi; + //TMO_MenuItem tmi; + HANDLE menuid; + int framepos = id2pos(frameid); + + if (FramesSysNotStarted) return NULL; + + ZeroMemory(&mi, sizeof(mi)); + + mi.cbSize = sizeof(mi); + mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA); //LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_MIRANDA)); + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&FrameTitle"); + mi.flags = CMIF_CHILDPOPUP | CMIF_GRAYED | CMIF_ICONFROMICOLIB; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMITitle = menuid; + else Frames[framepos].MenuHandles.MITitle = menuid; + + popuppos += 100000; + mi.hIcon = NULL; + mi.cbSize = sizeof(mi); + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Visible"); + mi.flags = CMIF_CHILDPOPUP | CMIF_CHECKED; + mi.pszContactOwner = (char *)0; + mi.pszService = MS_CLIST_FRAMES_SHFRAME; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIVisible = menuid; + else Frames[framepos].MenuHandles.MIVisible = menuid; + + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Show TitleBar"); + mi.flags = CMIF_CHILDPOPUP | CMIF_CHECKED; + mi.pszService = MS_CLIST_FRAMES_SHFRAMETITLEBAR; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMITBVisible = menuid; + else Frames[framepos].MenuHandles.MITBVisible = menuid; + + + popuppos += 100000; + + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Locked"); + mi.flags = CMIF_CHILDPOPUP | CMIF_CHECKED; + mi.pszService = MS_CLIST_FRAMES_ULFRAME; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMILock = menuid; + else Frames[framepos].MenuHandles.MILock = menuid; + + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Collapsed"); + mi.flags = CMIF_CHILDPOPUP | CMIF_CHECKED; + mi.pszService = MS_CLIST_FRAMES_UCOLLFRAME; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIColl = menuid; + else Frames[framepos].MenuHandles.MIColl = menuid; + + //floating + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Floating Mode"); + mi.flags = CMIF_CHILDPOPUP; + mi.pszService = "Set_Floating"; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIFloating = menuid; + else Frames[framepos].MenuHandles.MIFloating = menuid; + + + popuppos += 100000; + + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Border"); + mi.flags = CMIF_CHILDPOPUP | CMIF_CHECKED; + mi.pszService = MS_CLIST_FRAMES_SETUNBORDER; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIBorder = menuid; + else Frames[framepos].MenuHandles.MIBorder = menuid; + + popuppos += 100000; + + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Skinned frame"); + mi.flags = CMIF_CHILDPOPUP | CMIF_CHECKED; + mi.pszService = MS_CLIST_FRAMES_SETSKINNED; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMISkinned = menuid; + else Frames[framepos].MenuHandles.MISkinned = menuid; + + popuppos += 100000; + + { + //alignment root + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Align"); + mi.flags = CMIF_CHILDPOPUP | CMIF_ROOTPOPUP; + mi.pszService = ""; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIAlignRoot = menuid; + else Frames[framepos].MenuHandles.MIAlignRoot = menuid; + + mi.flags = CMIF_CHILDPOPUP; + //align top + mi.pszPopupName = (char *)menuid; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Top"); + mi.pszService = CLUIFRAMESSETALIGNALTOP; + mi.pszContactOwner = (char *)alTop; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIAlignTop = menuid; + else Frames[framepos].MenuHandles.MIAlignTop = menuid; + + + //align client + mi.position = popuppos++; + mi.pszName = LPGEN("&Client"); + mi.pszService = CLUIFRAMESSETALIGNALCLIENT; + mi.pszContactOwner = (char *)alClient; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIAlignClient = menuid; + else Frames[framepos].MenuHandles.MIAlignClient = menuid; + + //align bottom + mi.position = popuppos++; + mi.pszName = LPGEN("&Bottom"); + mi.pszService = CLUIFRAMESSETALIGNALBOTTOM; + mi.pszContactOwner = (char *)alBottom; + menuid = pfnAdd(&mi); + if (frameid == -1) contMIAlignBottom = menuid; + else Frames[framepos].MenuHandles.MIAlignBottom = menuid; + + } + + { //position + //position root + mi.pszPopupName = (char *)root; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Position"); + mi.flags = CMIF_CHILDPOPUP | CMIF_ROOTPOPUP; + mi.pszService = ""; + mi.pszContactOwner = (char *)0; + menuid = pfnAdd(&mi); + + mi.pszPopupName = (char *)menuid; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Up"); + mi.flags = CMIF_CHILDPOPUP; + mi.pszService = CLUIFRAMESMOVEUP; + mi.pszContactOwner = (char *)1; + pfnAdd(&mi); + + mi.pszPopupName = (char *)menuid; + mi.popupPosition = frameid; + mi.position = popuppos++; + mi.pszName = LPGEN("&Down"); + mi.flags = CMIF_CHILDPOPUP; + mi.pszService = CLUIFRAMESMOVEDOWN; + mi.pszContactOwner = (char *) - 1; + pfnAdd(&mi); + } + + return 0; +} + +int ModifyMItem(WPARAM wParam, LPARAM lParam) +{ + return ModifyMenuItemProxy(wParam, lParam); +}; + + +static int CLUIFramesModifyContextMenuForFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + CLISTMENUITEM mi; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + + if (pos >= 0 && pos < nFramescount) { + memset(&mi, 0, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_NAME | CMIF_CHILDPOPUP | CMIF_TCHAR; + mi.ptszName = Frames[pos].TitleBar.tbname ? Frames[pos].TitleBar.tbname : Frames[pos].name; + ModifyMItem((WPARAM)contMITitle, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].visible) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMIVisible, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].Locked) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMILock, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].TitleBar.ShowTitleBar) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMITBVisible, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].floating) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMIFloating, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if ((Frames[pos].UseBorder)) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMIBorder, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if ((Frames[pos].Skinned)) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMISkinned, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].align&alTop) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMIAlignTop, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].align&alClient) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMIAlignClient, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].align&alBottom) mi.flags |= CMIF_CHECKED; + ModifyMItem((WPARAM)contMIAlignBottom, (LPARAM)&mi); + + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (!Frames[pos].collapsed) mi.flags |= CMIF_CHECKED; + if ((!Frames[pos].visible) || (Frames[pos].Locked) || (pos == CLUIFramesGetalClientFrame())) mi.flags |= CMIF_GRAYED; + ModifyMItem((WPARAM)contMIColl, (LPARAM)&mi); + } + ulockfrm(); + return 0; +} + +INT_PTR CLUIFramesModifyMainMenuItems(WPARAM wParam, LPARAM lParam) +{ + int pos; + CLISTMENUITEM mi; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + + if (pos >= 0 && pos < nFramescount) { + memset(&mi, 0, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_NAME | CMIF_CHILDPOPUP | CMIF_TCHAR; + mi.ptszName = Frames[pos].TitleBar.tbname ? Frames[pos].TitleBar.tbname : Frames[pos].name; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MITitle, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].visible) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MIVisible, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].Locked) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MILock, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].TitleBar.ShowTitleBar) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MITBVisible, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].floating) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MIFloating, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if ((Frames[pos].UseBorder)) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MIBorder, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if ((Frames[pos].Skinned)) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MISkinned, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP | ((Frames[pos].align & alClient) ? CMIF_GRAYED : 0); + if (Frames[pos].align&alTop) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MIAlignTop, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (Frames[pos].align&alClient) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MIAlignClient, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP | ((Frames[pos].align & alClient) ? CMIF_GRAYED : 0); + if (Frames[pos].align&alBottom) mi.flags |= CMIF_CHECKED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MIAlignBottom, (LPARAM)&mi); + + mi.flags = CMIM_FLAGS | CMIF_CHILDPOPUP; + if (!Frames[pos].collapsed) mi.flags |= CMIF_CHECKED; + if ((!Frames[pos].visible) || Frames[pos].Locked || (pos == CLUIFramesGetalClientFrame())) mi.flags |= CMIF_GRAYED; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)Frames[pos].MenuHandles.MIColl, (LPARAM)&mi); + } + ulockfrm(); + return 0; +} + +INT_PTR CLUIFramesGetFrameOptions(WPARAM wParam, LPARAM lParam) +{ + int pos; + INT_PTR retval; + + if (FramesSysNotStarted) return -1; + + lockfrm(); + pos = id2pos(HIWORD(wParam)); + if (pos < 0 || pos >= nFramescount) { + ulockfrm(); + return -1; + } + + switch (LOWORD(wParam)) { + case FO_FLAGS: + retval = 0; + if (Frames[pos].visible) retval |= F_VISIBLE; + if (!Frames[pos].collapsed) retval |= F_UNCOLLAPSED; + if (Frames[pos].Locked) retval |= F_LOCKED; + if (Frames[pos].TitleBar.ShowTitleBar) retval |= F_SHOWTB; + if (Frames[pos].TitleBar.ShowTitleBarTip) retval |= F_SHOWTBTIP; + if (Frames[pos].Skinned) retval |= F_SKINNED; + if (!(GetWindowLongPtr(Frames[pos].hWnd, GWL_STYLE)&WS_BORDER)) retval |= F_NOBORDER; + break; + + case FO_NAME: + retval = (INT_PTR)Frames[pos].name; + break; + + case FO_TBNAME: + retval = (INT_PTR)Frames[pos].TitleBar.tbname; + break; + + case FO_TBTIPNAME: + retval = (INT_PTR)Frames[pos].TitleBar.tooltip; + break; + + case FO_TBSTYLE: + retval = GetWindowLongPtr(Frames[pos].TitleBar.hwnd, GWL_STYLE); + break; + + case FO_TBEXSTYLE: + retval = GetWindowLongPtr(Frames[pos].TitleBar.hwnd, GWL_EXSTYLE); + break; + + case FO_ICON: + retval = (INT_PTR)Frames[pos].TitleBar.hicon; + break; + + case FO_HEIGHT: + retval = (INT_PTR)Frames[pos].height; + break; + + case FO_ALIGN: + retval = (INT_PTR)Frames[pos].align; + break; + case FO_FLOATING: + retval = (int)Frames[pos].floating; + break; + default: + retval = -1; + break; + } + ulockfrm(); + return retval; +} + +INT_PTR CLUIFramesSetFrameOptions(WPARAM wParam, LPARAM lParam) +{ + int pos; + int retval; // value to be returned + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos(HIWORD(wParam)); + if (pos < 0 || pos >= nFramescount) { + ulockfrm(); + return -1; + } + + switch (LOWORD(wParam) & ~FO_UNICODETEXT) { + case FO_FLAGS: { + int flag = lParam; + int style; + + Frames[pos].dwFlags = flag; + Frames[pos].visible = FALSE; + if (flag&F_VISIBLE) Frames[pos].visible = TRUE; + + Frames[pos].collapsed = TRUE; + if (flag&F_UNCOLLAPSED) Frames[pos].collapsed = FALSE; + + Frames[pos].Locked = FALSE; + if (flag&F_LOCKED) Frames[pos].Locked = TRUE; + + Frames[pos].UseBorder = TRUE; + if (flag&F_NOBORDER) Frames[pos].UseBorder = FALSE; + + Frames[pos].TitleBar.ShowTitleBar = FALSE; + if (flag&F_SHOWTB) Frames[pos].TitleBar.ShowTitleBar = TRUE; + + Frames[pos].TitleBar.ShowTitleBarTip = FALSE; + if (flag&F_SHOWTBTIP) Frames[pos].TitleBar.ShowTitleBarTip = TRUE; + + SendMessage(Frames[pos].TitleBar.hwndTip, TTM_ACTIVATE, (WPARAM)Frames[pos].TitleBar.ShowTitleBarTip, 0); + + style = (int)GetWindowLongPtr(Frames[pos].hWnd, GWL_STYLE); + style |= WS_BORDER; + style |= CLS_SKINNEDFRAME; + + if (flag&F_NOBORDER) + style &= (~WS_BORDER); + + Frames[pos].Skinned = FALSE; + if (flag & F_SKINNED) + Frames[pos].Skinned = TRUE; + + if (!(flag & F_SKINNED)) + style &= ~CLS_SKINNEDFRAME; + + SetWindowLongPtr(Frames[pos].hWnd, GWL_STYLE, (LONG)style); + SetWindowLongPtr(Frames[pos].TitleBar.hwnd, GWL_STYLE, (LONG)style & ~(WS_VSCROLL | WS_HSCROLL)); + + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + SetWindowPos(Frames[pos].TitleBar.hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + return 0; + } + + case FO_NAME: + if (lParam == (LPARAM)NULL) { + ulockfrm(); + return -1; + } + mir_free(Frames[pos].name); + Frames[pos].name = (wParam & FO_UNICODETEXT) ? mir_u2t((LPWSTR)lParam) : mir_a2t((LPSTR)lParam); + ulockfrm(); + return 0; + + case FO_TBNAME: + if (lParam == (LPARAM)NULL) { + ulockfrm(); + return(-1); + } + mir_free(Frames[pos].TitleBar.tbname); + Frames[pos].TitleBar.tbname = (wParam & FO_UNICODETEXT) ? mir_u2t((LPWSTR)lParam) : mir_a2t((LPSTR)lParam); + ulockfrm(); + if (Frames[pos].floating && (Frames[pos].TitleBar.tbname != NULL)) + SetWindowText(Frames[pos].ContainerWnd, Frames[pos].TitleBar.tbname); + return 0; + + case FO_TBTIPNAME: + if (lParam == (LPARAM)NULL) { + ulockfrm(); + return(-1); + } + mir_free(Frames[pos].TitleBar.tooltip); + Frames[pos].TitleBar.tooltip = (wParam & FO_UNICODETEXT) ? mir_u2t((LPWSTR)lParam) : mir_a2t((LPSTR)lParam); + UpdateTBToolTip(pos); + ulockfrm(); + return 0; + + case FO_TBSTYLE: + SetWindowLongPtr(Frames[pos].TitleBar.hwnd, GWL_STYLE, lParam); + ulockfrm(); + return 0; + + case FO_TBEXSTYLE: + SetWindowLongPtr(Frames[pos].TitleBar.hwnd, GWL_EXSTYLE, lParam); + ulockfrm(); + return 0; + + case FO_ICON: + Frames[pos].TitleBar.hicon = (HICON)lParam; + ulockfrm(); + return 0; + + case FO_HEIGHT: + { + if (lParam < 0) { + ulockfrm(); + return -1; + } + if(Frames[pos].Skinned) { + int uID = (Frames[pos].TitleBar.ShowTitleBar ? ID_EXTBKOWNEDFRAMEBORDERTB - ID_STATUS_OFFLINE : ID_EXTBKOWNEDFRAMEBORDER - ID_STATUS_OFFLINE); + lParam += (StatusItems[uID].MARGIN_BOTTOM + StatusItems[uID].MARGIN_TOP); + } + if (Frames[pos].collapsed) { + int oldHeight = Frames[pos].height; + retval = Frames[pos].height; + Frames[pos].height = lParam; + if (!CLUIFramesFitInSize()) + Frames[pos].height = retval; + retval = Frames[pos].height; + + if (Frames[pos].height != oldHeight) { + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0); + if(Frames[pos].Skinned) + RedrawWindow(Frames[pos].hWnd, 0, 0, RDW_FRAME|RDW_UPDATENOW|RDW_INVALIDATE); + } + } + else { + retval = Frames[pos].HeightWhenCollapsed; + Frames[pos].HeightWhenCollapsed = lParam; + if (!CLUIFramesFitInSize()) + Frames[pos].HeightWhenCollapsed = retval; + retval = Frames[pos].HeightWhenCollapsed; + } + ulockfrm(); + return(retval); + } + + case FO_FLOATING: + if (lParam < 0) { + ulockfrm(); + return -1; + } + { + int id = Frames[pos].id; + Frames[pos].floating = !(lParam); + ulockfrm(); + + CLUIFrameSetFloat(id, 1);//lparam=1 use stored width and height + return(wParam); + } + case FO_ALIGN: + if (!(lParam&alTop || lParam&alBottom || lParam&alClient)) { + ulockfrm(); + return(-1); + } + if ((lParam&alClient) && (CLUIFramesGetalClientFrame() >= 0)) { //only one alClient frame possible + alclientFrame = -1;//recalc it + ulockfrm(); + return -1; + } + Frames[pos].align = lParam; + ulockfrm(); + return(0); + } + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + return -1; +} + +static INT_PTR CLUIFramesShowAll(WPARAM wParam, LPARAM lParam) +{ + int i; + + if (FramesSysNotStarted) return -1; + + for (i = 0;i < nFramescount;i++) + Frames[i].visible = TRUE; + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + return 0; +} + +INT_PTR CLUIFramesShowAllTitleBars(WPARAM wParam, LPARAM lParam) +{ + int i; + + if (FramesSysNotStarted) return -1; + + for (i = 0;i < nFramescount;i++) { + Frames[i].TitleBar.ShowTitleBar = TRUE; + SetWindowPos(Frames[i].hWnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + } + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return 0; +} + +//wparam=lparam=0 +INT_PTR CLUIFramesHideAllTitleBars(WPARAM wParam, LPARAM lParam) +{ + int i; + + if (FramesSysNotStarted) return -1; + + for (i = 0;i < nFramescount;i++) { + Frames[i].TitleBar.ShowTitleBar = FALSE; + SetWindowPos(Frames[i].hWnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + } + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return 0; +} + +//wparam=frameid +INT_PTR CLUIFramesShowHideFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && !lstrcmp(Frames[pos].name, _T("My Contacts"))) + Frames[pos].visible = 1; + else { + if (pos >= 0 && (int)pos < nFramescount) + Frames[pos].visible = !Frames[pos].visible; + if (Frames[pos].floating) + CLUIFrameResizeFloatingFrame(pos); + } + ulockfrm(); + if (!Frames[pos].floating) + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return 0; +} + +//wparam=frameid +INT_PTR CLUIFramesShowHideFrameTitleBar(WPARAM wParam, LPARAM lParam) +{ + int pos; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && (int)pos < nFramescount) { + Frames[pos].TitleBar.ShowTitleBar = !Frames[pos].TitleBar.ShowTitleBar; + SetWindowPos(Frames[pos].hWnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + } + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return 0; +} + + +//wparam=frameid +//lparam=-1 up ,1 down +INT_PTR CLUIFramesMoveUpDown(WPARAM wParam, LPARAM lParam) +{ + int pos, i, curpos, curalign, v, tmpval; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && (int)pos < nFramescount) { + curpos = Frames[pos].order; + curalign = Frames[pos].align; + v = 0; + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + for (i = 0;i < nFramescount;i++) { + if (Frames[i].floating || (!Frames[i].visible) || (Frames[i].align != curalign)) + continue; + g_sd[v].order = Frames[i].order; + g_sd[v].realpos = i; + v++; + } + if (v == 0) { + ulockfrm(); + return(0); + } + qsort(g_sd, v, sizeof(SortData), sortfunc); + for (i = 0;i < v;i++) { + if (g_sd[i].realpos == pos) { + if (lParam == -1) { + if (i < 1) break; + tmpval = Frames[g_sd[i-1].realpos].order; + Frames[g_sd[i-1].realpos].order = Frames[pos].order; + Frames[pos].order = tmpval; + break; + } + if (lParam == 1) { + if (i > v - 1) break; + tmpval = Frames[g_sd[i+1].realpos].order; + Frames[g_sd[i+1].realpos].order = Frames[pos].order; + Frames[pos].order = tmpval; + break; + } + } + } + ulockfrm(); + CLUIFramesReSort(); + //CLUIFramesStoreAllFrames(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + } + return(0); +} + +static INT_PTR CLUIFramesMoveUp(WPARAM wParam, LPARAM lParam) +{ + return(CLUIFramesMoveUpDown(wParam, -1)); +} + +static INT_PTR CLUIFramesMoveDown(WPARAM wParam, LPARAM lParam) +{ + return(CLUIFramesMoveUpDown(wParam, 1)); +} + + +//wparam=frameid +//lparam=alignment +INT_PTR CLUIFramesSetAlign(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) return -1; + + CLUIFramesSetFrameOptions(MAKEWPARAM(FO_ALIGN, wParam), lParam); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return(0); +} +INT_PTR CLUIFramesSetAlignalTop(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) return -1; + + return CLUIFramesSetAlign(wParam, alTop); +} +INT_PTR CLUIFramesSetAlignalBottom(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) return -1; + + return CLUIFramesSetAlign(wParam, alBottom); +} +INT_PTR CLUIFramesSetAlignalClient(WPARAM wParam, LPARAM lParam) +{ + if (FramesSysNotStarted) return -1; + + return CLUIFramesSetAlign(wParam, alClient); +} + + +//wparam=frameid +INT_PTR CLUIFramesLockUnlockFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos >= 0 && (int)pos < nFramescount) { + Frames[pos].Locked = !Frames[pos].Locked; + CLUIFramesStoreFrameSettings(pos); + } + ulockfrm(); + return 0; +} + +//wparam=frameid +INT_PTR CLUIFramesSetUnSetBorder(WPARAM wParam, LPARAM lParam) +{ + RECT rc; + int FrameId, oldflags; + HWND hw; + boolean flt; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + FrameId = id2pos((INT_PTR)wParam); + if (FrameId == -1) { + ulockfrm(); + return(-1); + } + flt = oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, wParam), 0); + + if (oldflags&F_NOBORDER) + oldflags &= (~F_NOBORDER); + else + oldflags |= F_NOBORDER; + + hw = Frames[FrameId].hWnd; + GetWindowRect(hw, &rc); + ulockfrm(); + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, wParam), oldflags); + SetWindowPos(hw, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_NOZORDER); + return(0); +} + +//wparam=frameid +INT_PTR CLUIFramesSetUnSetSkinned(WPARAM wParam, LPARAM lParam) +{ + RECT rc; + int FrameId, oldflags; + HWND hw; + boolean flt; + + if (FramesSysNotStarted) + return -1; + + lockfrm(); + FrameId = id2pos((INT_PTR)wParam); + if (FrameId == -1) { + ulockfrm(); + return(-1); + } + flt = oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, wParam), 0); + + if (oldflags & F_SKINNED) + oldflags &= ~F_SKINNED; + else + oldflags |= F_SKINNED; + + hw = Frames[FrameId].hWnd; + GetWindowRect(hw, &rc); + ulockfrm(); + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, wParam), oldflags); + SetWindowPos(hw, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_NOZORDER); + return(0); +} + +//wparam=frameid +INT_PTR CLUIFramesCollapseUnCollapseFrame(WPARAM wParam, LPARAM lParam) +{ + int FrameId; + + if (FramesSysNotStarted) + return -1; + + TitleBarH = cfg::dat.titleBarHeight; + lockfrm(); + FrameId = id2pos((INT_PTR)wParam); + if (FrameId >= 0 && FrameId < nFramescount) { + int oldHeight; + + // do not collapse/uncollapse client/locked/invisible frames + if (Frames[FrameId].align == alClient && !(Frames[FrameId].Locked || (!Frames[FrameId].visible) || Frames[FrameId].floating)) { + RECT rc; + if (CallService(MS_CLIST_DOCKINGISDOCKED, 0, 0)) { + ulockfrm(); + return 0; + } + if (cfg::getByte("CLUI", "AutoSize", 0)) { + ulockfrm(); + return 0; + } + GetWindowRect(pcli->hwndContactList, &rc); + + if (Frames[FrameId].collapsed == TRUE) { + rc.bottom -= rc.top; + rc.bottom -= Frames[FrameId].height; + Frames[FrameId].HeightWhenCollapsed = Frames[FrameId].height; + Frames[FrameId].collapsed = FALSE; + } else { + rc.bottom -= rc.top; + rc.bottom += Frames[FrameId].HeightWhenCollapsed; + Frames[FrameId].collapsed = TRUE; + } + + SetWindowPos(pcli->hwndContactList, NULL, 0, 0, rc.right - rc.left, rc.bottom, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); + + CLUIFramesStoreAllFrames(); + ulockfrm(); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return 0; + + } + if (Frames[FrameId].Locked || (!Frames[FrameId].visible)) { + ulockfrm(); + return 0; + } + + oldHeight = Frames[FrameId].height; + + // if collapsed, uncollapse + if (Frames[FrameId].collapsed == TRUE) { + Frames[FrameId].HeightWhenCollapsed = Frames[FrameId].height; + Frames[FrameId].height = UNCOLLAPSED_FRAME_SIZE; + Frames[FrameId].collapsed = FALSE; + } + // if uncollapsed, collapse + else { + Frames[FrameId].height = Frames[FrameId].HeightWhenCollapsed; + Frames[FrameId].collapsed = TRUE; + } + + if (!Frames[FrameId].floating) { + + if (!CLUIFramesFitInSize()) { + //cant collapse,we can resize only for height 2*UNCOLLAPSED_FRAME_SIZE) { + oldHeight = Frames[alfrm].height - UNCOLLAPSED_FRAME_SIZE; + Frames[FrameId].collapsed = TRUE; + } + } else { + int i, sumheight = 0; + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].align != alClient) && (!Frames[i].floating) && (Frames[i].visible) && (!Frames[i].needhide)) { + sumheight += (Frames[i].height) + (TitleBarH * btoint(Frames[i].TitleBar.ShowTitleBar)) + 2; + ulockfrm(); + return FALSE; + } + if (sumheight > ContactListHeight - 0 - 2) + Frames[FrameId].height = (ContactListHeight - 0 - 2) - sumheight; + } + } + Frames[FrameId].height = oldHeight; + if (Frames[FrameId].collapsed == FALSE) { + if (Frames[FrameId].floating) + SetWindowPos(Frames[FrameId].ContainerWnd, HWND_TOP, 0, 0, Frames[FrameId].wndSize.right - Frames[FrameId].wndSize.left + 6, Frames[FrameId].height + DEFAULT_TITLEBAR_HEIGHT + 4, SWP_SHOWWINDOW | SWP_NOMOVE); + ulockfrm(); + return -1; + } + } + } + ulockfrm(); + if (!Frames[FrameId].floating) + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + else { + RECT contwnd; + GetWindowRect(Frames[FrameId].ContainerWnd, &contwnd); + contwnd.top = contwnd.bottom - contwnd.top;//height + contwnd.left = contwnd.right - contwnd.left;//width + + contwnd.top -= (oldHeight - Frames[FrameId].height);//newheight + SetWindowPos(Frames[FrameId].ContainerWnd, HWND_TOP, 0, 0, contwnd.left, contwnd.top, SWP_SHOWWINDOW | SWP_NOMOVE); + } + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + CLUIFramesStoreAllFrames(); + return(0); + } else { + ulockfrm(); + return -1; + } + ulockfrm(); + return 0; +} + +static int CLUIFramesLoadMainMenu() +{ + CLISTMENUITEM mi; + int i, separator; + + if (FramesSysNotStarted) + return -1; + + if (MainMIRoot != (HANDLE) - 1) { + CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)MainMIRoot, 0); + MainMIRoot = (HANDLE) - 1; + } + + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + + // create root menu + mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA); //LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_MIRANDA)); + mi.flags = CMIF_ROOTPOPUP | CMIF_ICONFROMICOLIB; + mi.position = (int)3000090000; + mi.pszPopupName = (char*) - 1; + mi.pszName = LPGEN("Frames"); + mi.pszService = 0; + MainMIRoot = Menu_AddMainMenuItem(&mi); + + // create frames menu + separator = (int)3000200000; + for (i = 0;i < nFramescount;i++) { + mi.hIcon = Frames[i].TitleBar.hicon; + mi.flags = CMIF_CHILDPOPUP | CMIF_ROOTPOPUP | CMIF_TCHAR; + mi.position = separator; + mi.pszPopupName = (char*)MainMIRoot; + mi.ptszName = Frames[i].TitleBar.tbname ? Frames[i].TitleBar.tbname : Frames[i].name; + mi.pszService = 0; + Frames[i].MenuHandles.MainMenuItem = Menu_AddMainMenuItem(&mi); + CLUIFramesCreateMenuForFrame(Frames[i].id, (int)Frames[i].MenuHandles.MainMenuItem, separator, Menu_AddMainMenuItem); + CLUIFramesModifyMainMenuItems(Frames[i].id, 0); + //NotifyEventHooks(hPreBuildFrameMenuEvent,i,(LPARAM)Frames[i].MenuHandles.MainMenuItem); + CallService(MS_CLIST_FRAMEMENUNOTIFY, (WPARAM)Frames[i].id, (LPARAM)Frames[i].MenuHandles.MainMenuItem); + separator++; + } + + separator += 100000; + + // create "show all frames" menu + mi.hIcon = NULL;//LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_MIRANDA)); + mi.flags = CMIF_CHILDPOPUP; + mi.position = separator++; + mi.pszPopupName = (char*)MainMIRoot; + mi.pszName = LPGEN("Show All Frames"); + mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMES; + Menu_AddMainMenuItem(&mi); + + // create "show all titlebars" menu + mi.hIcon = NULL;//LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_HELP)); + mi.position = separator++; + mi.pszPopupName = (char*)MainMIRoot; + mi.flags = CMIF_CHILDPOPUP; + mi.pszName = LPGEN("Show All Titlebars"); + mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMESTB; + Menu_AddMainMenuItem(&mi); + + // create "hide all titlebars" menu + mi.hIcon = NULL;//LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_HELP)); + mi.position = separator++; + mi.pszPopupName = (char*)MainMIRoot; + mi.flags = CMIF_CHILDPOPUP; + mi.pszName = LPGEN("Hide All Titlebars"); + mi.pszService = MS_CLIST_FRAMES_HIDEALLFRAMESTB; + Menu_AddMainMenuItem(&mi); + + return 0; +} + +static HFONT CLUILoadTitleBarFont() +{ + char facename[] = "MS Shell Dlg"; + HFONT hfont; + LOGFONT logfont; + memset(&logfont, 0, sizeof(logfont)); + memcpy(logfont.lfFaceName, facename, sizeof(facename)); + logfont.lfWeight = FW_NORMAL; + logfont.lfHeight = -10; + hfont = CreateFontIndirect(&logfont); + return hfont; +} + +static int UpdateTBToolTip(int framepos) +{ + { + TOOLINFO ti; + + ZeroMemory(&ti, sizeof(ti)); + ti.cbSize = sizeof(ti); + ti.lpszText = Frames[framepos].TitleBar.tooltip; + ti.hinst = g_hInst; + ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS ; + ti.uId = (UINT_PTR)Frames[framepos].TitleBar.hwnd; + + return(SendMessage(Frames[framepos].TitleBar.hwndTip, TTM_UPDATETIPTEXT, (WPARAM)0, (LPARAM)&ti)); + } + +}; + +int FrameNCPaint(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar) +{ + HDC hdc; + RECT rcWindow, rc; + HWND hwndParent = GetParent(hwnd); + LRESULT result; + + if (hwndParent != pcli->hwndContactList || !cfg::dat.bSkinnedScrollbar) + result = CallWindowProc(oldWndProc, hwnd, WM_NCPAINT, wParam, lParam); + else + result = 0; + + if (pcli && pcli->hwndContactList && GetParent(hwnd) == pcli->hwndContactList) { + if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SKINNEDFRAME) { + StatusItems_t *item = StatusItems ? (hasTitleBar ? &StatusItems[ID_EXTBKOWNEDFRAMEBORDERTB - ID_STATUS_OFFLINE] : &StatusItems[ID_EXTBKOWNEDFRAMEBORDER - ID_STATUS_OFFLINE]) : 0; + HDC realDC; + HBITMAP hbmDraw, hbmOld; + + if (item == 0) + return 0; + + GetWindowRect(hwnd, &rcWindow); + rc.left = rc.top = 0; + rc.right = rcWindow.right - rcWindow.left; + rc.bottom = rcWindow.bottom - rcWindow.top; + + hdc = realDC = GetWindowDC(hwnd); + if (hwnd == pcli->hwndContactTree) { + realDC = CreateCompatibleDC(hdc); + hbmDraw = CreateCompatibleBitmap(hdc, rc.right, rc.bottom); + hbmOld = reinterpret_cast(SelectObject(realDC, hbmDraw)); + } + + ExcludeClipRect(realDC, item->MARGIN_LEFT, item->MARGIN_TOP, rc.right - item->MARGIN_RIGHT, rc.bottom - item->MARGIN_BOTTOM); + + BitBlt(realDC, 0, 0, rc.right - rc.left, rc.bottom - rc.top, cfg::dat.hdcBg, rcWindow.left - cfg::dat.ptW.x, rcWindow.top - cfg::dat.ptW.y, SRCCOPY); + + DrawAlpha(realDC, &rc, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, item->GRADIENT, + item->CORNER, item->BORDERSTYLE, item->imageItem); + if (hwnd == pcli->hwndContactTree) { + ExcludeClipRect(hdc, item->MARGIN_LEFT, item->MARGIN_TOP, rc.right - item->MARGIN_RIGHT, rc.bottom - item->MARGIN_BOTTOM); + BitBlt(hdc, 0, 0, rc.right, rc.bottom, realDC, 0, 0, SRCCOPY); + SelectObject(realDC, hbmOld); + DeleteObject(hbmDraw); + DeleteDC(realDC); + } + ReleaseDC(hwnd, hdc); + return 0; + } else if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_BORDER) { + HPEN hPenOld; + HBRUSH brold; + + hdc = GetWindowDC(hwnd); + hPenOld = reinterpret_cast(SelectObject(hdc, g_hPenCLUIFrames)); + GetWindowRect(hwnd, &rcWindow); + rc.left = rc.top = 0; + rc.right = rcWindow.right - rcWindow.left; + rc.bottom = rcWindow.bottom - rcWindow.top; + brold = reinterpret_cast(SelectObject(hdc, GetStockObject(HOLLOW_BRUSH))); + Rectangle(hdc, 0, 0, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top); + SelectObject(hdc, hPenOld); + SelectObject(hdc, brold); + ReleaseDC(hwnd, hdc); + return 0; + } + } + return result; +} + +int FrameNCCalcSize(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar) +{ + StatusItems_t *item = StatusItems ? (hasTitleBar ? &StatusItems[ID_EXTBKOWNEDFRAMEBORDERTB - ID_STATUS_OFFLINE] : &StatusItems[ID_EXTBKOWNEDFRAMEBORDER - ID_STATUS_OFFLINE]) : 0; + LRESULT orig = oldWndProc ? CallWindowProc(oldWndProc, hwnd, WM_NCCALCSIZE, wParam, lParam) : 0; + NCCALCSIZE_PARAMS *nccp = (NCCALCSIZE_PARAMS *)lParam; + DWORD dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + + if (item == 0 || pcli == 0) + return orig; + + if (item->IGNORED || !(dwStyle & CLS_SKINNEDFRAME) || GetParent(hwnd) != pcli->hwndContactList) + return orig; + + nccp->rgrc[0].left += item->MARGIN_LEFT; + nccp->rgrc[0].right -= item->MARGIN_RIGHT; + nccp->rgrc[0].bottom -= item->MARGIN_BOTTOM; + nccp->rgrc[0].top += item->MARGIN_TOP; + return WVR_REDRAW; +} + +static LRESULT CALLBACK FramesSubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int i; + + WNDPROC oldWndProc = 0; + BOOL hasTitleBar = FALSE; + + for (i = 0; i < nFramescount; i++) { + if (Frames[i].hWnd == hwnd) { + oldWndProc = Frames[i].wndProc; + hasTitleBar = Frames[i].TitleBar.ShowTitleBar; + } + } + switch (msg) { + case WM_NCPAINT: { + return FrameNCPaint(hwnd, oldWndProc ? oldWndProc : DefWindowProc, wParam, lParam, hasTitleBar); + } + case WM_NCCALCSIZE: { + return FrameNCCalcSize(hwnd, oldWndProc, wParam, lParam, hasTitleBar); + } + case WM_PRINTCLIENT: + return 0; + default: + break; + } + if (oldWndProc) + return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +/* + * re-sort all frames and correct frame ordering + */ + +static int CLUIFramesReSort() +{ + int v = 0, i; + int order = 1; + + lockfrm(); + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + for (i = 0;i < nFramescount;i++) { + if (Frames[i].align != alTop) + continue; + g_sd[v].order = Frames[i].order; + g_sd[v].realpos = i; + v++; + } + if (v > 0) { + qsort(g_sd, v, sizeof(SortData), sortfunc); + for (i = 0; i < v; i++) + Frames[g_sd[i].realpos].order = order++; + } + + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + v = 0; + for (i = 0;i < nFramescount;i++) { + if (Frames[i].align != alBottom) + continue; + g_sd[v].order = Frames[i].order; + g_sd[v].realpos = i; + v++; + } + if (v > 0) { + qsort(g_sd, v, sizeof(SortData), sortfunc); + for (i = 0; i < v; i++) + Frames[g_sd[i].realpos].order = order++; + } + CLUIFramesStoreAllFrames(); + ulockfrm(); + return(0); +} + +//wparam=(CLISTFrame*)clfrm +INT_PTR CLUIFramesAddFrame(WPARAM wParam, LPARAM lParam) +{ + int style, retval; + char * CustomName = NULL; + CLISTFrame *clfrm = (CLISTFrame *)wParam; + + if (pcli->hwndContactList == 0) return -1; + if (FramesSysNotStarted) return -1; + if (clfrm->cbSize != sizeof(CLISTFrame)) return -1; + + lockfrm(); + if (nFramescount >= MAX_FRAMES) { + ulockfrm(); + return -1; + } + if (Frames == NULL) { + Frames = (wndFrame*)malloc(sizeof(wndFrame) * (MAX_FRAMES + 2)); + ZeroMemory(Frames, sizeof(wndFrame) * (MAX_FRAMES + 2)); + } + memset(&Frames[nFramescount], 0, sizeof(wndFrame)); + + Frames[nFramescount].id = NextFrameId++; + Frames[nFramescount].align = clfrm->align; + Frames[nFramescount].hWnd = clfrm->hWnd; + Frames[nFramescount].height = clfrm->height; + Frames[nFramescount].TitleBar.hicon = clfrm->hIcon; + //Frames[nFramescount].TitleBar.BackColour; + Frames[nFramescount].floating = FALSE; + + if (clfrm->Flags & F_NO_SUBCONTAINER) + Frames[nFramescount].OwnerWindow = (HWND) - 2; + else + Frames[nFramescount].OwnerWindow = pcli->hwndContactList; + + SetClassLong(clfrm->hWnd, GCL_STYLE, GetClassLong(clfrm->hWnd, GCL_STYLE) & ~(CS_VREDRAW | CS_HREDRAW)); + SetWindowLongPtr(clfrm->hWnd, GWL_STYLE, GetWindowLongPtr(clfrm->hWnd, GWL_STYLE) | WS_CLIPCHILDREN); + + if (GetCurrentThreadId() == GetWindowThreadProcessId(clfrm->hWnd, NULL)) { + if (clfrm->hWnd != pcli->hwndContactTree && clfrm->hWnd != g_hwndViewModeFrame && clfrm->hWnd != g_hwndEventArea) { + Frames[nFramescount].wndProc = (WNDPROC)GetWindowLongPtr(clfrm->hWnd, GWLP_WNDPROC); + SetWindowLongPtr(clfrm->hWnd, GWLP_WNDPROC, (LONG_PTR)FramesSubClassProc); + } + } + + if (clfrm->hWnd == g_hwndEventArea) + wndFrameEventArea = &Frames[nFramescount]; + else if (clfrm->hWnd == pcli->hwndContactTree) + wndFrameCLC = &Frames[nFramescount]; + else if (clfrm->hWnd == g_hwndViewModeFrame) + wndFrameViewMode = &Frames[nFramescount]; + + Frames[nFramescount].dwFlags = clfrm->Flags; + + if (clfrm->name == NULL || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->wname) : lstrlenA(clfrm->name)) == 0) { + TCHAR ptszClassName[ 256 ]; + GetClassName(Frames[nFramescount].hWnd, ptszClassName, SIZEOF(ptszClassName)); + Frames[nFramescount].name = mir_tstrdup(ptszClassName); + } else Frames[nFramescount].name = (clfrm->Flags & F_UNICODE) ? mir_u2t(clfrm->wname) : mir_a2t(clfrm->name); + + if (IsBadCodePtr((FARPROC)clfrm->TBname) || clfrm->TBname == NULL + || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->TBwname) : lstrlenA(clfrm->TBname)) == 0) + Frames[nFramescount].TitleBar.tbname = mir_tstrdup(Frames[nFramescount].name); + else + Frames[nFramescount].TitleBar.tbname = (clfrm->Flags & F_UNICODE) ? mir_u2t(clfrm->TBwname) : mir_a2t(clfrm->TBname); + Frames[nFramescount].needhide = FALSE; + Frames[nFramescount].TitleBar.ShowTitleBar = (clfrm->Flags & F_SHOWTB ? TRUE : FALSE); + Frames[nFramescount].TitleBar.ShowTitleBarTip = (clfrm->Flags & F_SHOWTBTIP ? TRUE : FALSE); + + Frames[nFramescount].collapsed = clfrm->Flags & F_UNCOLLAPSED ? FALSE : TRUE; + Frames[nFramescount].Locked = clfrm->Flags & F_LOCKED ? TRUE : FALSE; + Frames[nFramescount].visible = clfrm->Flags & F_VISIBLE ? TRUE : FALSE; + + Frames[nFramescount].UseBorder = (clfrm->Flags & F_NOBORDER) ? FALSE : TRUE; + Frames[nFramescount].Skinned = (clfrm->Flags & F_SKINNED) ? TRUE : FALSE; + + // create frame + Frames[nFramescount].TitleBar.hwnd = + CreateWindow(CLUIFrameTitleBarClassName, Frames[nFramescount].name, + (cfg::getByte(CLUIFrameModule, "RemoveAllTitleBarBorders", 1) ? 0 : WS_BORDER) + | WS_CHILD | WS_CLIPCHILDREN | (Frames[nFramescount].TitleBar.ShowTitleBar ? WS_VISIBLE : 0) | + WS_CLIPCHILDREN, 0, 0, 0, 0, pcli->hwndContactList, NULL, g_hInst, NULL); + + SetWindowLongPtr(Frames[nFramescount].TitleBar.hwnd, GWLP_USERDATA, Frames[nFramescount].id); + + Frames[nFramescount].TitleBar.hwndTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + pcli->hwndContactList, NULL, g_hInst, NULL); + + SetWindowPos(Frames[nFramescount].TitleBar.hwndTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + { + TOOLINFOA ti; + int res; + + ZeroMemory(&ti, sizeof(ti)); + ti.cbSize = sizeof(ti); + ti.lpszText = ""; + ti.hinst = g_hInst; + ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS ; + ti.uId = (UINT_PTR)Frames[nFramescount].TitleBar.hwnd; + res = SendMessageA(Frames[nFramescount].TitleBar.hwndTip, TTM_ADDTOOL, (WPARAM)0, (LPARAM) & ti); + } + + SendMessage(Frames[nFramescount].TitleBar.hwndTip, TTM_ACTIVATE, (WPARAM)Frames[nFramescount].TitleBar.ShowTitleBarTip, 0); + + Frames[nFramescount].oldstyles = GetWindowLongPtr(Frames[nFramescount].hWnd, GWL_STYLE); + Frames[nFramescount].TitleBar.oldstyles = GetWindowLongPtr(Frames[nFramescount].TitleBar.hwnd, GWL_STYLE); + //Frames[nFramescount].FloatingPos.x= + + retval = Frames[nFramescount].id; + Frames[nFramescount].order = nFramescount + 1; + nFramescount++; + + CLUIFramesLoadFrameSettings(id2pos(retval)); + style = GetWindowLongPtr(Frames[nFramescount-1].hWnd, GWL_STYLE); + style &= ~(WS_BORDER); + style |= ((Frames[nFramescount-1].UseBorder) ? WS_BORDER : 0); + + style |= Frames[nFramescount-1].Skinned ? CLS_SKINNEDFRAME : 0; + + SetWindowLongPtr(Frames[nFramescount-1].hWnd, GWL_STYLE, style); + SetWindowLongPtr(Frames[nFramescount-1].TitleBar.hwnd, GWL_STYLE, style & ~(WS_VSCROLL | WS_HSCROLL)); + + if (Frames[nFramescount-1].order == 0) { + Frames[nFramescount-1].order = nFramescount; + } + + ulockfrm(); + + alclientFrame = -1;//recalc it + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + + if (Frames[nFramescount-1].floating) { + Frames[nFramescount-1].floating = FALSE; + CLUIFrameSetFloat(retval, 1);//lparam=1 use stored width and height + } + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return retval; +} + +static INT_PTR CLUIFramesRemoveFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + if (FramesSysNotStarted) + return -1; + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + + if (pos < 0 || pos > nFramescount) { + ulockfrm(); + return(-1); + } + + { + wndFrame* F = &Frames[pos]; + if (F->hWnd == g_hwndEventArea) + wndFrameEventArea = NULL; + else if (F->hWnd == pcli->hwndContactTree) + wndFrameCLC = NULL; + else if (F->hWnd == g_hwndViewModeFrame) + wndFrameViewMode = NULL; + + mir_free(F->name); + mir_free(F->TitleBar.tbname); + mir_free(F->TitleBar.tooltip); + + DestroyWindow(F->hWnd); + F->hWnd = (HWND) - 1; + DestroyWindow(F->TitleBar.hwnd); + F->TitleBar.hwnd = (HWND) - 1; + DestroyWindow(F->ContainerWnd); + F->ContainerWnd = (HWND) - 1; + DestroyMenu(F->TitleBar.hmenu); + } + + RemoveItemFromList(pos, &Frames, &nFramescount); + + ulockfrm(); + if (!cfg::shutDown) { + InvalidateRect(pcli->hwndContactList, NULL, TRUE); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + } + return(0); +} + +INT_PTR CLUIFramesForceUpdateTB(const wndFrame *Frame) +{ + if (Frame->TitleBar.hwnd != 0) + RedrawWindow(Frame->TitleBar.hwnd, NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW | RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + return 0; +} + +INT_PTR CLUIFramesForceUpdateFrame(const wndFrame *Frame) +{ + if (Frame->hWnd != 0) + RedrawWindow(Frame->hWnd, NULL, NULL, RDW_UPDATENOW | RDW_FRAME | RDW_ERASE | RDW_INVALIDATE); + + if (Frame->floating) + if (Frame->ContainerWnd != 0) RedrawWindow(Frame->ContainerWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + return 0; +} + +int CLUIFrameMoveResize(const wndFrame *Frame) +{ + TitleBarH = cfg::dat.titleBarHeight; + // we need to show or hide the frame? + if (Frame->visible && (!Frame->needhide)) { + ShowWindow(Frame->hWnd, SW_SHOW); + ShowWindow(Frame->TitleBar.hwnd, Frame->TitleBar.ShowTitleBar == TRUE ? SW_SHOW : SW_HIDE); + } else { + ShowWindow(Frame->hWnd, SW_HIDE); + ShowWindow(Frame->TitleBar.hwnd, SW_HIDE); + return(0); + } + + SetWindowPos(Frame->hWnd, NULL, Frame->wndSize.left + cfg::dat.bCLeft, Frame->wndSize.top + cfg::dat.topOffset, + (Frame->wndSize.right - Frame->wndSize.left), + (Frame->wndSize.bottom - Frame->wndSize.top), SWP_NOZORDER | SWP_NOREDRAW); + if (Frame->TitleBar.ShowTitleBar) { + SetWindowPos(Frame->TitleBar.hwnd, NULL, Frame->wndSize.left + cfg::dat.bCLeft, Frame->wndSize.top + cfg::dat.topOffset - TitleBarH, + (Frame->wndSize.right - Frame->wndSize.left), + TitleBarH + (Frame->UseBorder ? (!Frame->collapsed ? (Frame->align == alClient ? 0 : 2) : 1) : 0), SWP_NOZORDER); + } + return 0; +} + +BOOLEAN CLUIFramesFitInSize(void) +{ + int i; + int sumheight = 0; + int tbh = 0; // title bar height + int clientfrm; + + TitleBarH = cfg::dat.titleBarHeight; + + clientfrm = CLUIFramesGetalClientFrame(); + if (clientfrm != -1) + tbh = TitleBarH * btoint(Frames[clientfrm].TitleBar.ShowTitleBar); + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].align != alClient) && (!Frames[i].floating) && (Frames[i].visible) && (!Frames[i].needhide)) { + sumheight += (Frames[i].height) + (TitleBarH * btoint(Frames[i].TitleBar.ShowTitleBar)) + 2/*+btoint(Frames[i].UseBorder)*2*/; + if (sumheight > ContactListHeight - tbh - 2) + return FALSE; + } + } + return TRUE; +} + +int CLUIFramesGetMinHeight() +{ + int i, tbh, clientfrm, sumheight = 0; + RECT border; + int allbord = 0; + + if (pcli->hwndContactList == NULL) + return 0; + + lockfrm(); + + TitleBarH = cfg::dat.titleBarHeight; + // search for alClient frame and get the titlebar's height + tbh = 0; + clientfrm = CLUIFramesGetalClientFrame(); + if (clientfrm != -1) + tbh = TitleBarH * btoint(Frames[clientfrm].TitleBar.ShowTitleBar); + + for (i = 0;i < nFramescount;i++) { + if ((Frames[i].align != alClient) && (Frames[i].visible) && (!Frames[i].needhide) && (!Frames[i].floating)) { + RECT wsize; + + GetWindowRect(Frames[i].hWnd, &wsize); + sumheight += (wsize.bottom - wsize.top) + (TitleBarH * btoint(Frames[i].TitleBar.ShowTitleBar)) + 3; + } + } + ulockfrm(); + GetBorderSize(pcli->hwndContactList, &border); + return(sumheight + border.top + border.bottom + allbord + tbh + 3); +} + +int SizeMoveNewSizes() +{ + int i; + for (i = 0;i < nFramescount;i++) { + + if (Frames[i].floating) { + CLUIFrameResizeFloatingFrame(i); + } else { + CLUIFrameMoveResize(&Frames[i]); + }; + } + return 0; +} + +/* + * changed Nightwish + * gap calculation was broken. Now, it doesn't calculate and store the gaps in Frames[] anymore. + * instead, it remembers the smallest wndSize.top value (which has to be the top frame) and then passes + * the gap to all following frame(s) to the actual resizing function which just adds the gap to + * wndSize.top and corrects the frame height accordingly. + + * Title bar gap has been removed (can be simulated by using a clist_nicer skin item for frame title bars + * and setting the bottom margin of the skin item + */ + +int CLUIFramesResize(const RECT newsize) +{ + int sumheight = 9999999, newheight; + int prevframe, prevframebottomline; + int tbh, curfrmtbh; + int drawitems; + int clientfrm, clientframe = -1; + int i, j; + int sepw; + int topOff = 0, botOff = 0, last_bottomtop;; + + GapBetweenFrames = cfg::dat.gapBetweenFrames; + sepw = GapBetweenFrames; + + if (nFramescount < 1 || cfg::shutDown) + return 0; + + newheight = newsize.bottom - newsize.top; + TitleBarH = cfg::dat.titleBarHeight; + + // search for alClient frame and get the titlebar's height + tbh = 0; + clientfrm = CLUIFramesGetalClientFrame(); + if (clientfrm != -1) + tbh = (TitleBarH) * btoint(Frames[clientfrm].TitleBar.ShowTitleBar); + + for (i = 0;i < nFramescount;i++) { + if (!Frames[i].floating) { + Frames[i].needhide = FALSE; + Frames[i].wndSize.left = 0; + Frames[i].wndSize.right = newsize.right - newsize.left; + } + } + { + //sorting stuff + memset(g_sd, 0, sizeof(SortData) * MAX_FRAMES); + for (i = 0;i < nFramescount;i++) { + g_sd[i].order = Frames[i].order; + g_sd[i].realpos = i; + } + qsort(g_sd, nFramescount, sizeof(SortData), sortfunc); + + } + drawitems = nFramescount; + while (sumheight > (newheight - tbh) && drawitems > 0) { + sumheight = 0; + drawitems = 0; + for (i = 0;i < nFramescount;i++) { + if (((Frames[i].align != alClient)) && (!Frames[i].floating) && (Frames[i].visible) && (!Frames[i].needhide)) { + drawitems++; + curfrmtbh = (TitleBarH) * btoint(Frames[i].TitleBar.ShowTitleBar); + sumheight += (Frames[i].height) + curfrmtbh + (i > 0 ? sepw : 0) + (Frames[i].UseBorder ? 2 : 0); + if (sumheight > newheight - tbh) { + sumheight -= (Frames[i].height) + curfrmtbh + (i > 0 ? sepw : 0); + Frames[i].needhide = TRUE; + drawitems--; + break; + } + } + } + } + + prevframe = -1; + prevframebottomline = 0; + for (j = 0;j < nFramescount;j++) { + //move all alTop frames + i = g_sd[j].realpos; + if ((!Frames[i].needhide) && (!Frames[i].floating) && (Frames[i].visible) && (Frames[i].align == alTop)) { + curfrmtbh = (TitleBarH) * btoint(Frames[i].TitleBar.ShowTitleBar); + Frames[i].wndSize.top = prevframebottomline + (prevframebottomline > 0 ? sepw : 0) + (curfrmtbh); + Frames[i].wndSize.bottom = Frames[i].height + Frames[i].wndSize.top + (Frames[i].UseBorder ? 2 : 0); + Frames[i].prevvisframe = prevframe; + prevframe = i; + prevframebottomline = Frames[i].wndSize.bottom; + topOff = prevframebottomline; + } + } + + if (sumheight < newheight) { + for (j = 0;j < nFramescount;j++) { + //move alClient frame + i = g_sd[j].realpos; + if ((!Frames[i].needhide) && (!Frames[i].floating) && (Frames[i].visible) && (Frames[i].align == alClient)) { + int oldh; + Frames[i].wndSize.top = prevframebottomline + (prevframebottomline > 0 ? sepw : 0) + (tbh); + Frames[i].wndSize.bottom = Frames[i].wndSize.top + newheight - sumheight - tbh - ((prevframebottomline > 0) ? sepw : 0); + clientframe = i; + oldh = Frames[i].height; + Frames[i].height = Frames[i].wndSize.bottom - Frames[i].wndSize.top; + Frames[i].prevvisframe = prevframe; + prevframe = i; + prevframebottomline = Frames[i].wndSize.bottom; + if (prevframebottomline > newheight) { + //prevframebottomline-=Frames[i].height+(tbh+1); + //Frames[i].needhide=TRUE; + } + break; + } + } + } + + //newheight + prevframebottomline = last_bottomtop = newheight; + //prevframe=-1; + for (j = nFramescount - 1;j >= 0;j--) { + //move all alBottom frames + i = g_sd[j].realpos; + if ((Frames[i].visible) && (!Frames[i].floating) && (!Frames[i].needhide) && (Frames[i].align == alBottom)) { + curfrmtbh = (TitleBarH) * btoint(Frames[i].TitleBar.ShowTitleBar); + Frames[i].wndSize.bottom = prevframebottomline - ((prevframebottomline < newheight) ? sepw : 0); + Frames[i].wndSize.top = Frames[i].wndSize.bottom - Frames[i].height - (Frames[i].UseBorder ? 2 : 0); + Frames[i].prevvisframe = prevframe; + prevframe = i; + prevframebottomline = Frames[i].wndSize.top - curfrmtbh; + botOff = prevframebottomline; + last_bottomtop = Frames[i].wndSize.top - curfrmtbh; + } + } + + // correct client frame bottom gap if there is no other top frame. + + if (clientframe != -1) { + Frames[clientframe].wndSize.bottom = last_bottomtop - (last_bottomtop < newheight ? sepw : 0); + Frames[clientframe].height = Frames[clientframe].wndSize.bottom - Frames[clientframe].wndSize.top; + } + return 0; +} + +INT_PTR CLUIFramesUpdateFrame(WPARAM wParam, LPARAM lParam) +{ + int pos; + if (FramesSysNotStarted) + return -1; + if (wParam == -1) { + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + return 0; + } + if (lParam&FU_FMPOS) + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 1); + + lockfrm(); + pos = id2pos((INT_PTR)wParam); + if (pos < 0 || pos >= nFramescount) { + ulockfrm(); + return -1; + } + if (lParam&FU_TBREDRAW) + CLUIFramesForceUpdateTB(&Frames[pos]); + if (lParam&FU_FMREDRAW) + CLUIFramesForceUpdateFrame(&Frames[pos]); + ulockfrm(); + return 0; +} + +int dock_prevent_moving = 0; + +int CLUIFramesApplyNewSizes(int mode) +{ + int i; + dock_prevent_moving = 0; + for (i = 0;i < nFramescount;i++) { + if ((mode == 1 && Frames[i].OwnerWindow != (HWND) - 2 && Frames[i].OwnerWindow) || + (mode == 2 && Frames[i].OwnerWindow == (HWND) - 2) || + (mode == 3)) + if (Frames[i].floating) + CLUIFrameResizeFloatingFrame(i); + else + CLUIFrameMoveResize(&Frames[i]); + } + dock_prevent_moving = 1; + return 0; +} + +RECT old_window_rect = {0}, new_window_rect = {0}; + +int SizeFramesByWindowRect(RECT *r) +{ + RECT nRect; + DWORD noSize = 0; + + if (FramesSysNotStarted) + return -1; + + TitleBarH = cfg::dat.titleBarHeight; + lockfrm(); + GapBetweenFrames = cfg::dat.gapBetweenFrames; + + nRect = *r; + + nRect.bottom -= (cfg::dat.statusBarHeight + cfg::dat.bottomOffset); + nRect.right -= cfg::dat.bCRight; + nRect.left = cfg::dat.bCLeft; + nRect.top = cfg::dat.topOffset; + ContactListHeight = nRect.bottom - nRect.top; + + CLUIFramesResize(nRect); + { + int i; + for (i = 0;i < nFramescount;i++) { + int dx; + int dy; + dx = new_window_rect.left - old_window_rect.left; + dy = new_window_rect.top - old_window_rect.top; + if (!Frames[i].floating) { + if (Frames[i].OwnerWindow && Frames[i].OwnerWindow != (HWND) - 2) { + /* + if(Frames[i].wndSize.right - Frames[i].wndSize.left == Frames[i].oldWndSize.right - Frames[i].oldWndSize.left && + Frames[i].wndSize.bottom - Frames[i].wndSize.top == Frames[i].oldWndSize.bottom - Frames[i].oldWndSize.top) + noSize = SWP_NOSIZE; + else { + noSize = 0; + CopyRect(&Frames[i].oldWndSize, &Frames[i].wndSize); + }*/ + SetWindowPos(Frames[i].hWnd, NULL, Frames[i].wndSize.left + cfg::dat.bCLeft, Frames[i].wndSize.top + cfg::dat.topOffset, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + (Frames[i].wndSize.bottom - Frames[i].wndSize.top), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS | noSize); + + if (Frames[i].TitleBar.ShowTitleBar) { + SetWindowPos(Frames[i].TitleBar.hwnd, NULL, Frames[i].wndSize.left + cfg::dat.bCLeft, Frames[i].wndSize.top + cfg::dat.topOffset - TitleBarH, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + TitleBarH + (Frames[i].UseBorder ? (!Frames[i].collapsed ? (Frames[i].align == alClient ? 0 : 2) : 1) : 0), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS); + } + } else { + int res = 0; + // set frame position + SetWindowPos(Frames[i].hWnd, NULL, Frames[i].wndSize.left + cfg::dat.bCLeft, Frames[i].wndSize.top + cfg::dat.topOffset, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + (Frames[i].wndSize.bottom - Frames[i].wndSize.top), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOREDRAW); + + // set titlebar position + if (Frames[i].TitleBar.ShowTitleBar) { + SetWindowPos(Frames[i].TitleBar.hwnd, NULL, Frames[i].wndSize.left + cfg::dat.bCLeft, Frames[i].wndSize.top + cfg::dat.topOffset - TitleBarH, + (Frames[i].wndSize.right - Frames[i].wndSize.left), + TitleBarH + (Frames[i].UseBorder ? (!Frames[i].collapsed ? (Frames[i].align == alClient ? 0 : 2) : 1) : 0), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOREDRAW); + } + //UpdateWindow(Frames[i].hWnd); + if (Frames[i].TitleBar.ShowTitleBar) + UpdateWindow(Frames[i].TitleBar.hwnd); + }; + } + + } + if (GetTickCount() - LastStoreTick > 1000) { + CLUIFramesStoreAllFrames(); + LastStoreTick = GetTickCount(); + } + } + ulockfrm(); + return 0; +} + +int CLUIFramesOnClistResize(WPARAM wParam, LPARAM lParam) +{ + RECT nRect, rcStatus; + int tick; + GapBetweenFrames = cfg::dat.gapBetweenFrames; + + if (FramesSysNotStarted || cfg::shutDown) + return -1; + + lockfrm(); + + GetClientRect(pcli->hwndContactList, &nRect); + if (lParam && lParam != 1) { + RECT oldRect; + POINT pt; + RECT * newRect = (RECT *)lParam; + int dl, dt, dr, db; + GetWindowRect((HWND)wParam, &oldRect); + pt.x = nRect.left; + pt.y = nRect.top; + ClientToScreen(pcli->hwndContactList, &pt); + dl = pt.x - oldRect.left; + dt = pt.y - oldRect.top; + dr = (oldRect.right - oldRect.left) - (nRect.right - nRect.left) - dl; + db = (oldRect.bottom - oldRect.top) - (nRect.bottom - nRect.top) - dt; + nRect.left = newRect->left + dl; + nRect.top = newRect->top + dt; + nRect.bottom = newRect->bottom - db; + nRect.right = newRect->right - dr; + } + + rcStatus.top = rcStatus.bottom = 0; + + nRect.bottom -= (cfg::dat.statusBarHeight + cfg::dat.bottomOffset); + nRect.right -= cfg::dat.bCRight; + nRect.left = cfg::dat.bCLeft; + nRect.top = cfg::dat.topOffset; + ContactListHeight = nRect.bottom - nRect.top; + + tick = GetTickCount(); + + CLUIFramesResize(nRect); + CLUIFramesApplyNewSizes(3); + + ulockfrm(); + tick = GetTickCount() - tick; + + if (pcli->hwndContactList != 0) + InvalidateRect(pcli->hwndContactList, NULL, TRUE); + if (pcli->hwndContactList != 0) + UpdateWindow(pcli->hwndContactList); + + Sleep(0); + + if (GetTickCount() - LastStoreTick > 2000) { + CLUIFramesStoreAllFrames(); + LastStoreTick = GetTickCount(); + } + return 0; +} + +static HBITMAP hBmpBackground; +static int backgroundBmpUse; +static COLORREF bkColour; +static COLORREF SelBkColour; +boolean AlignCOLLIconToLeft; //will hide frame icon + +int OnFrameTitleBarBackgroundChange() +{ + DBVARIANT dbv; + + AlignCOLLIconToLeft = cfg::getByte("FrameTitleBar", "AlignCOLLIconToLeft", 0); + + bkColour = cfg::getDword("FrameTitleBar", "BkColour", CLCDEFAULT_BKCOLOUR); + + if (hBmpBackground) { + DeleteObject(hBmpBackground); + hBmpBackground = NULL; + } + if (cfg::getByte("FrameTitleBar", "UseBitmap", CLCDEFAULT_USEBITMAP)) { + if (!DBGetContactSetting(NULL, "FrameTitleBar", "BkBitmap", &dbv)) { + hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (LPARAM)dbv.pszVal); + mir_free(dbv.pszVal); + } + } + backgroundBmpUse = cfg::getWord("FrameTitleBar", "BkBmpUse", CLCDEFAULT_BKBMPUSE); + + CLUIFramesOnClistResize(0, 0); + return 0; +} + +static int DrawTitleBar(HDC dc, RECT rect, int Frameid) +{ + HDC hdcMem; + HBITMAP hBmpOsb, hoBmp; + HBRUSH hBack, hoBrush; + int pos; + StatusItems_t *item = &StatusItems[ID_EXTBKFRAMETITLE - ID_STATUS_OFFLINE]; + + /* + * no need to redraw anything while shutting down + */ + if (cfg::shutDown) + return 0; + + TitleBarH = cfg::dat.titleBarHeight; + hdcMem = CreateCompatibleDC(dc); + hBmpOsb = CreateCompatibleBitmap(dc, rect.right, rect.bottom); + hoBmp = reinterpret_cast(SelectObject(hdcMem, hBmpOsb)); + + SetBkMode(hdcMem, TRANSPARENT); + + hBack = GetSysColorBrush(COLOR_3DFACE); + hoBrush = reinterpret_cast(SelectObject(hdcMem, hBack)); + + lockfrm(); + pos = id2pos(Frameid); + + if (pos >= 0 && pos < nFramescount) { + HFONT oFont; + int fHeight, fontTop; + GetClientRect(Frames[pos].TitleBar.hwnd, &Frames[pos].TitleBar.wndSize); + + if (cfg::clcdat) { + oFont = ChangeToFont(hdcMem, cfg::clcdat, FONTID_FRAMETITLE, &fHeight); + } else { + oFont = reinterpret_cast(SelectObject(hdcMem, GetStockObject(DEFAULT_GUI_FONT))); + fHeight = 10; + } + fontTop = (TitleBarH - fHeight) / 2; + + if (cfg::dat.bWallpaperMode && !Frames[pos].floating) + SkinDrawBg(Frames[pos].TitleBar.hwnd, hdcMem); + + if (!item->IGNORED) { + RECT rc = Frames[pos].TitleBar.wndSize; + rc.top += item->MARGIN_TOP; + rc.bottom -= item->MARGIN_BOTTOM; + rc.left += item->MARGIN_LEFT; + rc.right -= item->MARGIN_RIGHT; + DrawAlpha(hdcMem, &rc, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, + item->GRADIENT, item->CORNER, item->BORDERSTYLE, item->imageItem); + SetTextColor(hdcMem, item->TEXTCOLOR); + } else if (cfg::clcdat) { + FillRect(hdcMem, &rect, hBack); + SetTextColor(hdcMem, cfg::clcdat->fontInfo[FONTID_FRAMETITLE].colour); + } else { + FillRect(hdcMem, &rect, hBack); + SetTextColor(hdcMem, GetSysColor(COLOR_BTNTEXT)); + } + + + if (!AlignCOLLIconToLeft) { + if (Frames[pos].TitleBar.hicon != NULL) { + DrawIconEx(hdcMem, 6 + cfg::dat.bClipBorder, ((TitleBarH >> 1) - 8), Frames[pos].TitleBar.hicon, 16, 16, 0, NULL, DI_NORMAL); + TextOut(hdcMem, 24 + cfg::dat.bClipBorder, fontTop, Frames[pos].TitleBar.tbname, lstrlen(Frames[pos].TitleBar.tbname)); + } else + TextOut(hdcMem, 6 + cfg::dat.bClipBorder, fontTop, Frames[pos].TitleBar.tbname, lstrlen(Frames[pos].TitleBar.tbname)); + } else + TextOut(hdcMem, 18 + cfg::dat.bClipBorder, fontTop, Frames[pos].TitleBar.tbname, lstrlen(Frames[pos].TitleBar.tbname)); + + + if (!AlignCOLLIconToLeft) + DrawIconEx(hdcMem, Frames[pos].TitleBar.wndSize.right - 22, ((TitleBarH >> 1) - 8), Frames[pos].collapsed ? LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN) : LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT), 16, 16, 0, NULL, DI_NORMAL); + else + DrawIconEx(hdcMem, 0, ((TitleBarH >> 1) - 8), Frames[pos].collapsed ? LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN) : LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT), 16, 16, 0, NULL, DI_NORMAL); + SelectObject(hdcMem, oFont); + } + ulockfrm(); + BitBlt(dc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdcMem, rect.left, rect.top, SRCCOPY); + SelectObject(hdcMem, hoBmp); + SelectObject(hdcMem, hoBrush); + DeleteDC(hdcMem); + DeleteObject(hBack); + DeleteObject(hBmpOsb); + return 0; +} + +#define MPCF_CONTEXTFRAMEMENU 3 +POINT ptOld; +short nLeft = 0; +short nTop = 0; + +LRESULT CALLBACK CLUIFrameTitleBarProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + RECT rect; + int Frameid, Framemod, direction; + int xpos, ypos; + + Frameid = GetWindowLongPtr(hwnd, GWLP_USERDATA); + memset(&rect, 0, sizeof(rect)); + + switch (msg) { + case WM_CREATE: + return FALSE; + case WM_MEASUREITEM: + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + case WM_DRAWITEM: + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + + case WM_ENABLE: + if (hwnd != 0) InvalidateRect(hwnd, NULL, FALSE); + return 0; + case WM_SIZE: + return 0; + /* + case WM_PRINT: + case WM_PRINTCLIENT: + InvalidateRect(hwnd,NULL,FALSE); + { + RECT rect; + HDC dc; + GetClientRect(hwnd,&rect); + //DrawTitleBar(wParam,rect,Frameid); + SendMessage(hwnd,WM_PAINT,0,0); + SendMessage(hwnd,WM_NCPAINT,1,0); + dc=GetDC(hwnd); + SendMessage(hwnd,WM_ERASEBKGND,dc,0); + ReleaseDC(hwnd,dc); + SendMessage(hwnd,WM_PAINT,0,0); + // UpdateWindow(hwnd); + return(0); + } + */ + /* + case WM_NCPAINT: + { + + // if(wParam==1) break; + { POINT ptTopLeft={0,0}; + HRGN hClientRgn; + ClientToScreen(hwnd,&ptTopLeft); + hClientRgn=CreateRectRgn(0,0,1,1); + CombineRgn(hClientRgn,(HRGN)wParam,NULL,RGN_COPY); + OffsetRgn(hClientRgn,-ptTopLeft.x,-ptTopLeft.y); + InvalidateRgn(hwnd,hClientRgn,FALSE); + DeleteObject(hClientRgn); + UpdateWindow(hwnd); + } + //return(0); + }; + */ + + + case WM_COMMAND: + if (ServiceExists(MO_CREATENEWMENUOBJECT)) { + if (ProcessCommandProxy(MAKEWPARAM(LOWORD(wParam), 0), (LPARAM)Frameid)) + break; + } else { + if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTEXTFRAMEMENU), (LPARAM)Frameid)) + break; + } + + if (HIWORD(wParam) == 0) {//mouse events for self created menu + int framepos = id2pos(Frameid); + if (framepos == -1) + break; + + switch (LOWORD(wParam)) { + case frame_menu_lock: + Frames[framepos].Locked = !Frames[framepos].Locked; + break; + case frame_menu_visible: + Frames[framepos].visible = !Frames[framepos].visible; + break; + case frame_menu_showtitlebar: + Frames[framepos].TitleBar.ShowTitleBar = !Frames[framepos].TitleBar.ShowTitleBar; + break; + case frame_menu_floating: + CLUIFrameSetFloat(Frameid, 0); + break; + } + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + } + + break; + case WM_RBUTTONDOWN: { + HMENU hmenu; + POINT pt; + GetCursorPos(&pt); + + if (ServiceExists(MS_CLIST_MENUBUILDFRAMECONTEXT)) { + hmenu = (HMENU)CallService(MS_CLIST_MENUBUILDFRAMECONTEXT, Frameid, 0); + } else { + int framepos = id2pos(Frameid); + + lockfrm(); + if (framepos == -1) { + ulockfrm(); + break; + } + hmenu = CreatePopupMenu(); + AppendMenu(hmenu, MF_STRING | MF_DISABLED | MF_GRAYED, 15, Frames[framepos].name); + AppendMenu(hmenu, MF_SEPARATOR, 16, _T("")); + + if (Frames[framepos].Locked) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_lock, TranslateT("Lock Frame")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_lock, TranslateT("Lock Frame")); + + if (Frames[framepos].visible) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_visible, TranslateT("Visible")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_visible, TranslateT("Visible")); + + if (Frames[framepos].TitleBar.ShowTitleBar) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_showtitlebar, TranslateT("Show TitleBar")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_showtitlebar, TranslateT("Show TitleBar")); + + if (Frames[framepos].Skinned) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_skinned, TranslateT("Skinned frame")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_skinned, TranslateT("Skinned frame")); + + if (Frames[framepos].floating) + AppendMenu(hmenu, MF_STRING | MF_CHECKED, frame_menu_floating, TranslateT("Floating")); + else + AppendMenu(hmenu, MF_STRING, frame_menu_floating, TranslateT("Floating")); + + ulockfrm(); + } + TrackPopupMenu(hmenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, 0); + DestroyMenu(hmenu); + } + break; + case WM_LBUTTONDBLCLK: { + Framemod = -1; + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + CallService(MS_CLIST_FRAMES_UCOLLFRAME, Frameid, 0); + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + } + break; + + case WM_LBUTTONUP: { + if (GetCapture() != hwnd) { + break; + }; + curdragbar = -1; + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + break; + }; + case WM_LBUTTONDOWN: { + + int framepos = id2pos(Frameid); + lockfrm(); + if (framepos == -1) { + ulockfrm(); + break; + } + if (Frames[framepos].floating) { + + POINT pt; + GetCursorPos(&pt); + Frames[framepos].TitleBar.oldpos = pt; + } + + if ((!(wParam&MK_CONTROL)) && Frames[framepos].Locked && (!(Frames[framepos].floating))) { + if (cfg::getByte("CLUI", "ClientAreaDrag", 0)) { + POINT pt; + GetCursorPos(&pt); + ulockfrm(); + return SendMessage(GetParent(hwnd), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + } + } + if (Frames[framepos].floating) { + RECT rc; + GetCursorPos(&ptOld); + GetWindowRect(hwnd, &rc); + nLeft = (short)rc.left; + nTop = (short)rc.top; + } + ulockfrm(); + SetCapture(hwnd); + break; + } + case WM_MOUSEMOVE: { + POINT pt, pt2; + RECT wndr; + int pos; + { + char TBcapt[255]; + + lockfrm(); + pos = id2pos(Frameid); + + if (pos != -1) { + int oldflags; + wsprintfA(TBcapt, "%s - h:%d, vis:%d, fl:%d, fl:(%d,%d,%d,%d),or: %d", + Frames[pos].name, Frames[pos].height, Frames[pos].visible, Frames[pos].floating, + Frames[pos].FloatingPos.x, Frames[pos].FloatingPos.y, + Frames[pos].FloatingSize.x, Frames[pos].FloatingSize.y, + Frames[pos].order + ); + + oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, Frames[pos].id), (LPARAM)0); + if (!(oldflags&F_SHOWTBTIP)) + oldflags |= F_SHOWTBTIP; + } + ulockfrm(); + } + if ((wParam&MK_LBUTTON)/*&&(wParam&MK_CONTROL)*/) { + RECT rcMiranda; + RECT rcwnd, rcOverlap; + POINT newpt, ofspt, curpt, newpos; + + lockfrm(); + + pos = id2pos(Frameid); + if (Frames[pos].floating) { + GetCursorPos(&curpt); + rcwnd.bottom = curpt.y + 5; + rcwnd.top = curpt.y; + rcwnd.left = curpt.x; + rcwnd.right = curpt.x + 5; + + GetWindowRect(pcli->hwndContactList, &rcMiranda); + if (IsWindowVisible(pcli->hwndContactList) && IntersectRect(&rcOverlap, &rcwnd, &rcMiranda)) { + int id = Frames[pos].id; + + ulockfrm(); + ofspt.x = 0; + ofspt.y = 0; + ClientToScreen(Frames[pos].TitleBar.hwnd, &ofspt); + ofspt.x = curpt.x - ofspt.x; + ofspt.y = curpt.y - ofspt.y; + + CLUIFrameSetFloat(id, 0); + newpt.x = 0; + newpt.y = 0; + ClientToScreen(Frames[pos].TitleBar.hwnd, &newpt); + SetCursorPos(newpt.x + ofspt.x, newpt.y + ofspt.y); + GetCursorPos(&curpt); + lockfrm(); + Frames[pos].TitleBar.oldpos = curpt; + ulockfrm(); + return(0); + } + } else { + int id = Frames[pos].id; + + GetCursorPos(&curpt); + rcwnd.bottom = curpt.y + 5; + rcwnd.top = curpt.y; + rcwnd.left = curpt.x; + rcwnd.right = curpt.x + 5; + + GetWindowRect(pcli->hwndContactList, &rcMiranda); + + if (!IntersectRect(&rcOverlap, &rcwnd, &rcMiranda)) { + ulockfrm(); + GetCursorPos(&curpt); + GetWindowRect(Frames[pos].hWnd, &rcwnd); + rcwnd.left = rcwnd.right - rcwnd.left; + rcwnd.top = rcwnd.bottom - rcwnd.top; + newpos.x = curpt.x; + newpos.y = curpt.y; + if (curpt.x >= (rcMiranda.right - 1)) { + newpos.x = curpt.x + 5; + } + if (curpt.x <= (rcMiranda.left + 1)) { + newpos.x = curpt.x - (rcwnd.left) - 5; + } + if (curpt.y >= (rcMiranda.bottom - 1)) { + newpos.y = curpt.y + 5; + } + if (curpt.y <= (rcMiranda.top + 1)) { + newpos.y = curpt.y - (rcwnd.top) - 5; + }; + ofspt.x = 0; + ofspt.y = 0; + GetWindowRect(Frames[pos].TitleBar.hwnd, &rcwnd); + ofspt.x = curpt.x - ofspt.x; + ofspt.y = curpt.y - ofspt.y; + Frames[pos].FloatingPos.x = newpos.x; + Frames[pos].FloatingPos.y = newpos.y; + CLUIFrameSetFloat(id, 0); + lockfrm(); + newpt.x = 0; + newpt.y = 0; + ClientToScreen(Frames[pos].TitleBar.hwnd, &newpt); + GetWindowRect(Frames[pos].hWnd, &rcwnd); + SetCursorPos(newpt.x + (rcwnd.right - rcwnd.left) / 2, newpt.y + (rcwnd.bottom - rcwnd.top) / 2); + GetCursorPos(&curpt); + Frames[pos].TitleBar.oldpos = curpt; + ulockfrm(); + return(0); + } + } + ulockfrm(); + } + if (wParam&MK_LBUTTON) { + int newh = -1, prevold; + + if (GetCapture() != hwnd) + break; + + lockfrm(); + pos = id2pos(Frameid); + + if (Frames[pos].floating) { + GetCursorPos(&pt); + if ((Frames[pos].TitleBar.oldpos.x != pt.x) || (Frames[pos].TitleBar.oldpos.y != pt.y)) { + + pt2 = pt; + ScreenToClient(hwnd, &pt2); + GetWindowRect(Frames[pos].ContainerWnd, &wndr); + { + int dX, dY; + POINT ptNew; + + ptNew.x = pt.x; + ptNew.y = pt.y; + + dX = ptNew.x - ptOld.x; + dY = ptNew.y - ptOld.y; + + nLeft += (short)dX; + nTop += (short)dY; + + if (!(wParam&MK_CONTROL)) { + PositionThumb(&Frames[pos], nLeft, nTop); + } else { + + SetWindowPos(Frames[pos].ContainerWnd, + 0, + nLeft, + nTop, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER); + } + ptOld = ptNew; + } + pt.x = nLeft; + pt.y = nTop; + Frames[pos].TitleBar.oldpos = pt; + } + ulockfrm(); + return(0); + } + if (Frames[pos].prevvisframe != -1) { + GetCursorPos(&pt); + + if ((Frames[pos].TitleBar.oldpos.x == pt.x) && (Frames[pos].TitleBar.oldpos.y == pt.y)) { + ulockfrm(); + break; + } + + ypos = rect.top + pt.y; + xpos = rect.left + pt.x; + Framemod = -1; + + if (Frames[pos].align == alBottom) { + direction = -1; + Framemod = pos; + } else { + direction = 1; + Framemod = Frames[pos].prevvisframe; + } + if (Frames[Framemod].Locked) { + ulockfrm(); + break; + } + if (curdragbar != -1 && curdragbar != pos) { + ulockfrm(); + break; + } + + if (lbypos == -1) { + curdragbar = pos; + lbypos = ypos; + oldframeheight = Frames[Framemod].height; + SetCapture(hwnd); + ulockfrm(); + break;; + } + newh = oldframeheight + direction * (ypos - lbypos); + if (newh > 0) { + prevold = Frames[Framemod].height; + Frames[Framemod].height = newh; + if (!CLUIFramesFitInSize()) { + Frames[Framemod].height = prevold; + ulockfrm(); + return TRUE; + } + Frames[Framemod].height = newh; + if (newh > 3) Frames[Framemod].collapsed = TRUE; + + } + Frames[pos].TitleBar.oldpos = pt; + } + ulockfrm(); + if (newh > 0) { + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + } + break; + } + curdragbar = -1; + lbypos = -1; + oldframeheight = -1; + ReleaseCapture(); + } + break; + case WM_NCPAINT: { + if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_BORDER) { + HDC hdc = GetWindowDC(hwnd); + HPEN hPenOld = reinterpret_cast(SelectObject(hdc, g_hPenCLUIFrames)); + RECT rcWindow, rc; + HBRUSH brold; + + CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam); + GetWindowRect(hwnd, &rcWindow); + rc.left = rc.top = 0; + rc.right = rcWindow.right - rcWindow.left; + rc.bottom = rcWindow.bottom - rcWindow.top; + brold = reinterpret_cast(SelectObject(hdc, GetStockObject(HOLLOW_BRUSH))); + Rectangle(hdc, 0, 0, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top); + SelectObject(hdc, hPenOld); + SelectObject(hdc, brold); + ReleaseDC(hwnd, hdc); + return 0; + } + break; + } + case WM_PRINT: + case WM_PRINTCLIENT: { + GetClientRect(hwnd, &rect); + DrawTitleBar((HDC)wParam, rect, Frameid); + } + case WM_PAINT: { + HDC paintDC; + PAINTSTRUCT paintStruct; + + paintDC = BeginPaint(hwnd, &paintStruct); + rect = paintStruct.rcPaint; + DrawTitleBar(paintDC, rect, Frameid); + EndPaint(hwnd, &paintStruct); + return 0; + } + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return TRUE; +} +int CLUIFrameResizeFloatingFrame(int framepos) +{ + + int width, height, floatingHeight; + RECT rect; + + if (!Frames[framepos].floating) + return(0); + if (Frames[framepos].ContainerWnd == 0) + return(0); + GetClientRect(Frames[framepos].ContainerWnd, &rect); + + width = rect.right - rect.left; + height = rect.bottom - rect.top; + floatingHeight = cfg::dat.titleBarHeight; + + if(floatingHeight <= 0 || floatingHeight > 50) + floatingHeight = 18; + + Frames[framepos].visible ? ShowWindow(Frames[framepos].ContainerWnd, SW_SHOWNOACTIVATE) : ShowWindow(Frames[framepos].ContainerWnd, SW_HIDE); + + if (Frames[framepos].TitleBar.ShowTitleBar) { + ShowWindow(Frames[framepos].TitleBar.hwnd, SW_SHOWNOACTIVATE); + Frames[framepos].height = height - floatingHeight; + SetWindowPos(Frames[framepos].TitleBar.hwnd, HWND_TOP, 0, 0, width, floatingHeight, SWP_SHOWWINDOW | SWP_DRAWFRAME | SWP_NOACTIVATE); + InvalidateRect(Frames[framepos].TitleBar.hwnd, NULL, FALSE); + SetWindowPos(Frames[framepos].hWnd, HWND_TOP, 0, floatingHeight, width, height - floatingHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE); + + } else { + Frames[framepos].height = height; + ShowWindow(Frames[framepos].TitleBar.hwnd, SW_HIDE); + SetWindowPos(Frames[framepos].hWnd, HWND_TOP, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE); + } + + if (Frames[framepos].ContainerWnd != 0) + UpdateWindow(Frames[framepos].ContainerWnd); + GetWindowRect(Frames[framepos].hWnd, &Frames[framepos].wndSize); + + if (Frames[framepos].TitleBar.ShowTitleBar) + RedrawWindow(Frames[framepos].TitleBar.hwnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); + RedrawWindow(Frames[framepos].hWnd, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); + + return(0); +} + +static int CLUIFrameOnMainMenuBuild(WPARAM wParam, LPARAM lParam) +{ + CLUIFramesLoadMainMenu(); + return 0; +} + +LRESULT CALLBACK CLUIFrameContainerWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + + RECT rect; + INT_PTR Frameid = GetWindowLongPtr(hwnd, GWLP_USERDATA); + memset(&rect, 0, sizeof(rect)); + switch (msg) { + case WM_CREATE: { + int framepos; + lockfrm(); + framepos = id2pos(Frameid); + ulockfrm(); + return(0); + } + case WM_GETMINMAXINFO: { + int framepos; + MINMAXINFO minmax; + + TitleBarH = cfg::dat.titleBarHeight; + lockfrm(); + + framepos = id2pos(Frameid); + if (framepos < 0 || framepos >= nFramescount) { + ulockfrm(); + break; + } + if (!Frames[framepos].minmaxenabled) { + ulockfrm(); + break; + } + if (Frames[framepos].ContainerWnd == 0) { + ulockfrm(); + break; + } + if (Frames[framepos].Locked) { + RECT rct; + + GetWindowRect(hwnd, &rct); + ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = rct.right - rct.left; + ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rct.bottom - rct.top; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = rct.right - rct.left; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = rct.bottom - rct.top; + } + + memset(&minmax, 0, sizeof(minmax)); + if (SendMessage(Frames[framepos].hWnd, WM_GETMINMAXINFO, (WPARAM)0, (LPARAM)&minmax) == 0) { + RECT border; + int tbh = TitleBarH * btoint(Frames[framepos].TitleBar.ShowTitleBar); + GetBorderSize(hwnd, &border); + if (minmax.ptMaxTrackSize.x != 0 && minmax.ptMaxTrackSize.y != 0) { + + ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = minmax.ptMinTrackSize.x; + ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = minmax.ptMinTrackSize.y; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = minmax.ptMaxTrackSize.x + border.left + border.right; + ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = minmax.ptMaxTrackSize.y + tbh + border.top + border.bottom; + } + } else { + ulockfrm(); + return(DefWindowProc(hwnd, msg, wParam, lParam)); + } + ulockfrm(); + } + case WM_MOVE: { + int framepos; + RECT rect; + + lockfrm(); + framepos = id2pos(Frameid); + + if (framepos < 0 || framepos >= nFramescount) { + ulockfrm(); + break; + } + if (Frames[framepos].ContainerWnd == 0) { + ulockfrm(); + return(0); + } + GetWindowRect(Frames[framepos].ContainerWnd, &rect); + Frames[framepos].FloatingPos.x = rect.left; + Frames[framepos].FloatingPos.y = rect.top; + Frames[framepos].FloatingSize.x = rect.right - rect.left; + Frames[framepos].FloatingSize.y = rect.bottom - rect.top; + CLUIFramesStoreFrameSettings(framepos); + ulockfrm(); + return(0); + } + case WM_SIZE: { + int framepos; + RECT rect; + lockfrm(); + + framepos = id2pos(Frameid); + + if (framepos < 0 || framepos >= nFramescount) { + ulockfrm(); + break; + } + if (Frames[framepos].ContainerWnd == 0) { + ulockfrm(); + return(0); + } + CLUIFrameResizeFloatingFrame(framepos); + + GetWindowRect(Frames[framepos].ContainerWnd, &rect); + Frames[framepos].FloatingPos.x = rect.left; + Frames[framepos].FloatingPos.y = rect.top; + Frames[framepos].FloatingSize.x = rect.right - rect.left; + Frames[framepos].FloatingSize.y = rect.bottom - rect.top; + + CLUIFramesStoreFrameSettings(framepos); + ulockfrm(); + return(0); + } + case WM_CLOSE: { + DestroyWindow(hwnd); + break; + } + case WM_DESTROY: + return(0); + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static HWND CreateContainerWindow(HWND parent, int x, int y, int width, int height) +{ + return(CreateWindowA("FramesContainer", "aaaa", WS_POPUP | WS_THICKFRAME, x, y, width, height, parent, 0, g_hInst, 0)); +} + + +INT_PTR CLUIFrameSetFloat(WPARAM wParam, LPARAM lParam) +{ + HWND hwndtmp, hwndtooltiptmp; + + lockfrm(); + wParam = id2pos((INT_PTR)wParam); + if (wParam >= 0 && (int)wParam < nFramescount) + if (Frames[wParam].floating) { + SetParent(Frames[wParam].hWnd, pcli->hwndContactList); + SetParent(Frames[wParam].TitleBar.hwnd, pcli->hwndContactList); + Frames[wParam].floating = FALSE; + DestroyWindow(Frames[wParam].ContainerWnd); + Frames[wParam].ContainerWnd = 0; + } else { + RECT recttb, rectw, border; + int temp; + int neww, newh; + BOOLEAN locked; + + Frames[wParam].oldstyles = GetWindowLongPtr(Frames[wParam].hWnd, GWL_STYLE); + Frames[wParam].TitleBar.oldstyles = GetWindowLongPtr(Frames[wParam].TitleBar.hwnd, GWL_STYLE); + locked = Frames[wParam].Locked; + Frames[wParam].Locked = FALSE; + Frames[wParam].minmaxenabled = FALSE; + + GetWindowRect(Frames[wParam].hWnd, &rectw); + GetWindowRect(Frames[wParam].TitleBar.hwnd, &recttb); + if (!Frames[wParam].TitleBar.ShowTitleBar) { + recttb.top = recttb.bottom = recttb.left = recttb.right = 0; + } + Frames[wParam].ContainerWnd = CreateContainerWindow(pcli->hwndContactList, Frames[wParam].FloatingPos.x, Frames[wParam].FloatingPos.y, 10, 10); + + SetParent(Frames[wParam].hWnd, Frames[wParam].ContainerWnd); + SetParent(Frames[wParam].TitleBar.hwnd, Frames[wParam].ContainerWnd); + + GetBorderSize(Frames[wParam].ContainerWnd, &border); + + SetWindowLongPtr(Frames[wParam].ContainerWnd, GWLP_USERDATA, Frames[wParam].id); + if ((lParam == 1)) { + if ((Frames[wParam].FloatingPos.x != 0) && (Frames[wParam].FloatingPos.y != 0)) { + if (Frames[wParam].FloatingPos.x < 20) { + Frames[wParam].FloatingPos.x = 40; + } + if (Frames[wParam].FloatingPos.y < 20) { + Frames[wParam].FloatingPos.y = 40; + } + SetWindowPos(Frames[wParam].ContainerWnd, HWND_TOPMOST, Frames[wParam].FloatingPos.x, Frames[wParam].FloatingPos.y, Frames[wParam].FloatingSize.x, Frames[wParam].FloatingSize.y, SWP_HIDEWINDOW); + } else { + SetWindowPos(Frames[wParam].ContainerWnd, HWND_TOPMOST, 120, 120, 140, 140, SWP_HIDEWINDOW); + } + } else { + neww = rectw.right - rectw.left + border.left + border.right; + newh = (rectw.bottom - rectw.top) + (recttb.bottom - recttb.top) + border.top + border.bottom; + if (neww < 20) { + neww = 40; + } + if (newh < 20) { + newh = 40; + } + if (Frames[wParam].FloatingPos.x < 20) { + Frames[wParam].FloatingPos.x = 40; + } + if (Frames[wParam].FloatingPos.y < 20) { + Frames[wParam].FloatingPos.y = 40; + } + SetWindowPos(Frames[wParam].ContainerWnd, HWND_TOPMOST, Frames[wParam].FloatingPos.x, Frames[wParam].FloatingPos.y, neww, newh, SWP_HIDEWINDOW); + } + SetWindowText(Frames[wParam].ContainerWnd, Frames[wParam].TitleBar.tbname); + temp = GetWindowLongPtr(Frames[wParam].ContainerWnd, GWL_EXSTYLE); + temp |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST ; + SetWindowLongPtr(Frames[wParam].ContainerWnd, GWL_EXSTYLE, temp); + Frames[wParam].floating = TRUE; + Frames[wParam].Locked = locked; + + } + CLUIFramesStoreFrameSettings(wParam); + Frames[wParam].minmaxenabled = TRUE; + hwndtooltiptmp = Frames[wParam].TitleBar.hwndTip; + + hwndtmp = Frames[wParam].ContainerWnd; + ulockfrm(); + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, (LPARAM)0); + SendMessage(hwndtmp, WM_SIZE, 0, 0); + SetWindowPos(hwndtooltiptmp, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + return 0; +} + +TCHAR g_ptszEventName[100]; + +static int CLUIFrameOnModulesLoad(WPARAM wParam, LPARAM lParam) +{ + mir_sntprintf(g_ptszEventName, SIZEOF(g_ptszEventName), _T("mf_update_evt_%d"), GetCurrentThreadId()); + g_hEventThread = CreateEvent(NULL, TRUE, FALSE, g_ptszEventName); + hThreadMFUpdate = (HANDLE)mir_forkthreadex(reinterpret_cast(MF_UpdateThread), NULL, NULL); + SetThreadPriority(hThreadMFUpdate, THREAD_PRIORITY_IDLE); + CLUIFramesLoadMainMenu(); + CLUIFramesCreateMenuForFrame(-1, -1, 000010000, Menu_AddContextFrameMenuItem); + return 0; +} + +static int CLUIFrameOnModulesUnload(WPARAM wParam, LPARAM lParam) +{ + mf_updatethread_running = FALSE; + + SetThreadPriority(hThreadMFUpdate, THREAD_PRIORITY_NORMAL); + SetEvent(g_hEventThread); + WaitForSingleObject(hThreadMFUpdate, 2000); + CloseHandle(hThreadMFUpdate); + CloseHandle(g_hEventThread); + + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIVisible, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMITitle, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMITBVisible, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMILock, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIColl, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIFloating, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIAlignRoot, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIAlignTop, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIAlignClient, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIAlignBottom, 0); + CallService(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, (LPARAM)contMIBorder, 0); + return 0; +} + +static INT_PTR SetIconForExtraColumn(WPARAM wParam, LPARAM lParam) +{ + pIconExtraColumn piec; + + if (pcli->hwndContactTree == 0) + return -1; + + if (wParam == 0 || lParam == 0 || IsBadCodePtr((FARPROC)lParam)) + return -1; + + piec = (pIconExtraColumn)lParam; + + if (piec->cbSize != sizeof(IconExtraColumn)) + return -1; + + if (cfg::dat.bMetaAvail && cfg::dat.bMetaEnabled && cfg::getByte((HANDLE)wParam, cfg::dat.szMetaName, "IsSubcontact", 0)) + PostMessage(pcli->hwndContactTree, CLM_SETEXTRAIMAGEINTMETA, wParam, MAKELONG((WORD)piec->ColumnType, (WORD)piec->hImage)); + else + PostMessage(pcli->hwndContactTree, CLM_SETEXTRAIMAGEINT, wParam, MAKELONG((WORD)piec->ColumnType, (WORD)piec->hImage)); + return 0; +} + +/* + * wparam=hIcon + * return hImage on success,-1 on failure + */ +static INT_PTR AddIconToExtraImageList(WPARAM wParam, LPARAM lParam) +{ + if (himlExtraImages == 0 || wParam == 0) + return -1; + + return((int)ImageList_AddIcon(himlExtraImages, (HICON)wParam)); +} + +/* +static INT_PTR SkinDrawBgService(WPARAM wParam, LPARAM lParam) +{ + StatusItems_t item; + HWND hwnd; + RECT rc; + + SKINDRAWREQUEST *sdrq = (SKINDRAWREQUEST *)wParam; + + if(wParam == 0 || IsBadCodePtr((FARPROC)wParam) || pDrawAlpha == NULL) + return 0; + + hwnd = WindowFromDC(sdrq->hDC); + GetClientRect(hwnd, &rc); + if(strstr(sdrq->szObjectID, "/Background") && EqualRect(&sdrq->rcClipRect, &sdrq->rcDestRect)) { + SkinDrawBg(hwnd, sdrq->hDC); + GetItemByStatus(ID_EXTBKEVTAREA, &item); + if(item.IGNORED) + FillRect(sdrq->hDC, &(sdrq->rcClipRect), GetSysColorBrush(COLOR_3DFACE)); + else { + DrawAlpha(sdrq->hDC, &(sdrq->rcClipRect), item.COLOR, item.ALPHA, item.COLOR2, item.COLOR2_TRANSPARENT, + item.GRADIENT, item.CORNER, item.BORDERSTYLE, item.imageItem); + } + } + else { + GetItemByStatus(ID_EXTBKEVTAREA, &item); + if(item.IGNORED) + FillRect(sdrq->hDC, &(sdrq->rcClipRect), GetSysColorBrush(COLOR_3DFACE)); + else { + DrawAlpha(sdrq->hDC, &(sdrq->rcClipRect), item.COLOR, item.ALPHA, item.COLOR2, item.COLOR2_TRANSPARENT, + item.GRADIENT, item.CORNER, item.BORDERSTYLE, item.imageItem); + } + } +} +*/ + +void RegisterCLUIFrameClasses() +{ + WNDCLASS wndclass; + WNDCLASS cntclass; + + wndclass.style = CS_DBLCLKS;//|CS_HREDRAW|CS_VREDRAW ; + wndclass.lpfnWndProc = CLUIFrameTitleBarProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = g_hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = NULL; + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = CLUIFrameTitleBarClassName; + RegisterClass(&wndclass); + + cntclass.style = CS_DBLCLKS/*|CS_HREDRAW|CS_VREDRAW*/ | (IsWinVerXPPlus() ? CS_DROPSHADOW : 0); + cntclass.lpfnWndProc = CLUIFrameContainerWndProc; + cntclass.cbClsExtra = 0; + cntclass.cbWndExtra = 0; + cntclass.hInstance = g_hInst; + cntclass.hIcon = NULL; + cntclass.hCursor = LoadCursor(NULL, IDC_ARROW); + cntclass.hbrBackground = NULL; + cntclass.lpszMenuName = NULL; + cntclass.lpszClassName = _T("FramesContainer"); + RegisterClass(&cntclass); +} + +int LoadCLUIFramesModule(void) +{ + GapBetweenFrames = cfg::dat.gapBetweenFrames; + + nFramescount = 0; + InitializeCriticalSection(&csFrameHook); + InitFramesMenus(); + + HookEvent(ME_SYSTEM_MODULESLOADED, CLUIFrameOnModulesLoad); + HookEvent(ME_CLIST_PREBUILDFRAMEMENU, CLUIFramesModifyContextMenuForFrame); + HookEvent(ME_CLIST_PREBUILDMAINMENU, CLUIFrameOnMainMenuBuild); + HookEvent(ME_SYSTEM_PRESHUTDOWN, CLUIFrameOnModulesUnload); + + CreateServiceFunction(MS_CLIST_FRAMES_ADDFRAME, CLUIFramesAddFrame); + CreateServiceFunction(MS_CLIST_FRAMES_REMOVEFRAME, CLUIFramesRemoveFrame); + + CreateServiceFunction(MS_CLIST_FRAMES_SETFRAMEOPTIONS, CLUIFramesSetFrameOptions); + CreateServiceFunction(MS_CLIST_FRAMES_GETFRAMEOPTIONS, CLUIFramesGetFrameOptions); + CreateServiceFunction(MS_CLIST_FRAMES_UPDATEFRAME, CLUIFramesUpdateFrame); + + CreateServiceFunction(MS_CLIST_FRAMES_SHFRAMETITLEBAR, CLUIFramesShowHideFrameTitleBar); + CreateServiceFunction(MS_CLIST_FRAMES_SHOWALLFRAMESTB, CLUIFramesShowAllTitleBars); + CreateServiceFunction(MS_CLIST_FRAMES_HIDEALLFRAMESTB, CLUIFramesHideAllTitleBars); + CreateServiceFunction(MS_CLIST_FRAMES_SHFRAME, CLUIFramesShowHideFrame); + CreateServiceFunction(MS_CLIST_FRAMES_SHOWALLFRAMES, CLUIFramesShowAll); + + CreateServiceFunction(MS_CLIST_FRAMES_ULFRAME, CLUIFramesLockUnlockFrame); + CreateServiceFunction(MS_CLIST_FRAMES_UCOLLFRAME, CLUIFramesCollapseUnCollapseFrame); + CreateServiceFunction(MS_CLIST_FRAMES_SETUNBORDER, CLUIFramesSetUnSetBorder); + CreateServiceFunction(MS_CLIST_FRAMES_SETSKINNED, CLUIFramesSetUnSetSkinned); + + CreateServiceFunction(CLUIFRAMESSETALIGN, CLUIFramesSetAlign); + CreateServiceFunction(CLUIFRAMESMOVEDOWN, CLUIFramesMoveDown); + CreateServiceFunction(CLUIFRAMESMOVEUP, CLUIFramesMoveUp); + + CreateServiceFunction(CLUIFRAMESSETALIGNALTOP, CLUIFramesSetAlignalTop); + CreateServiceFunction(CLUIFRAMESSETALIGNALCLIENT, CLUIFramesSetAlignalClient); + CreateServiceFunction(CLUIFRAMESSETALIGNALBOTTOM, CLUIFramesSetAlignalBottom); + + CreateServiceFunction("Set_Floating", CLUIFrameSetFloat); + hWndExplorerToolBar = FindWindowExA(0, 0, "Shell_TrayWnd", NULL); + OnFrameTitleBarBackgroundChange(); + + FramesSysNotStarted = FALSE; + g_hPenCLUIFrames = CreatePen(PS_SOLID, 1, cfg::getDword("CLUI", "clr_frameborder", GetSysColor(COLOR_3DDKSHADOW))); + return 0; +} + +void LoadExtraIconModule() +{ + CreateServiceFunction(MS_CLIST_EXTRA_SET_ICON, SetIconForExtraColumn); + CreateServiceFunction(MS_CLIST_EXTRA_ADD_ICON, AddIconToExtraImageList); + + hExtraImageListRebuilding = CreateHookableEvent(ME_CLIST_EXTRA_LIST_REBUILD); + hExtraImageApplying = CreateHookableEvent(ME_CLIST_EXTRA_IMAGE_APPLY); + + hStatusBarShowToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_SHOW_TOOLTIP); + hStatusBarHideToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_HIDE_TOOLTIP); +} + +int UnLoadCLUIFramesModule(void) +{ + int i; + CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList, 0); + CLUIFramesStoreAllFrames(); + DeleteObject(g_hPenCLUIFrames); + EnterCriticalSection(&csFrameHook); + FramesSysNotStarted = TRUE; + for (i = 0;i < nFramescount;i++) { + DestroyWindow(Frames[i].hWnd); + Frames[i].hWnd = (HWND) - 1; + DestroyWindow(Frames[i].TitleBar.hwnd); + Frames[i].TitleBar.hwnd = (HWND) - 1; + DestroyWindow(Frames[i].ContainerWnd); + Frames[i].ContainerWnd = (HWND) - 1; + DestroyMenu(Frames[i].TitleBar.hmenu); + + if (Frames[i].name != NULL) + mir_free(Frames[i].name); + if (Frames[i].TitleBar.tbname != NULL) + mir_free(Frames[i].TitleBar.tbname); + } + if (Frames) + free(Frames); + Frames = NULL; + nFramescount = 0; + UnregisterClass(CLUIFrameTitleBarClassName, g_hInst); + LeaveCriticalSection(&csFrameHook); + DeleteCriticalSection(&csFrameHook); + UnitFramesMenu(); + return 0; +} + +void ReloadExtraIcons() +{ + NotifyEventHooks(hExtraImageListRebuilding, 0, 0); +} diff --git a/plugins/Clist_nicer/src/CLUIFrames/cluiframes.h b/plugins/Clist_nicer/src/CLUIFrames/cluiframes.h new file mode 100644 index 0000000000..083066ca6d --- /dev/null +++ b/plugins/Clist_nicer/src/CLUIFrames/cluiframes.h @@ -0,0 +1,105 @@ +/* +Miranda ICQ: the free icq client for MS Windows +Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. +*/ + +int LoadCLUIFramesModule(void); +int UnLoadCLUIFramesModule(void); +int CLUIFramesGetMinHeight(); +int CLUIFramesOnClistResize(WPARAM wParam,LPARAM lParam); +int SizeFramesByWindowRect(RECT *r); +int CLUIFramesResizeFrames(RECT *rc); + +typedef struct tagProtocolData { + char *RealName; + int statusbarpos; + boolean show; +} ProtocolData; + +#define OFFSET_PROTOPOS 200 +#define OFFSET_VISIBLE 400 + +#define CLUIFrameTitleBarClassName _T("CLUIFrameTitleBar") +#define CLUIFrameModule "CLUIFrames" + +//integrated menu module +#define MS_INT_MENUMEASUREITEM "CLUIFrames/IntMenuMeasureItem" +#define MS_INT_MENUDRAWITEM "CLUIFrames/IntMenuDrawItem" +#define MS_INT_MENUPROCESSCOMMAND "CLUIFrames/IntMenuProcessCommand" +#define MS_INT_MODIFYMENUITEM "CLUIFrames/IntModifyMenuItem" + +typedef struct _DockOpt { + HWND hwndLeft; + HWND hwndRight; +} +DockOpt; + +typedef struct tagMenuHandles { + HANDLE MainMenuItem; + HANDLE MIVisible,MITitle,MITBVisible,MILock,MIColl,MIFloating,MIAlignRoot; + HANDLE MIAlignTop,MIAlignClient,MIAlignBottom; + HANDLE MIBorder, MISkinned; +} FrameMenuHandles; + +typedef struct tagFrameTitleBar { + HWND hwnd; + HWND TitleBarbutt; + HWND hwndTip; + + LPTSTR tbname; + LPTSTR tooltip; + HMENU hmenu; + HICON hicon; + + BOOLEAN ShowTitleBar; + BOOLEAN ShowTitleBarTip; + int oldstyles; + POINT oldpos; + RECT wndSize; +} FrameTitleBar; + +typedef struct { + int id; + HWND hWnd ; + RECT wndSize; + RECT oldWndSize; + LPTSTR name; + int align; + int height; + int dwFlags; + BOOLEAN Locked; + BOOLEAN Skinned; + BOOLEAN visible; + BOOLEAN needhide; + BOOLEAN collapsed; + int prevvisframe; + int HeightWhenCollapsed; + FrameTitleBar TitleBar; + FrameMenuHandles MenuHandles; + int oldstyles; + BOOLEAN floating; + HWND ContainerWnd; + POINT FloatingPos; + POINT FloatingSize; + BOOLEAN minmaxenabled; + BOOLEAN UseBorder; + int order; + DockOpt dockOpt; + HWND OwnerWindow; + WNDPROC wndProc; +} wndFrame; + diff --git a/plugins/Clist_nicer/src/CLUIFrames/framesmenu.cpp b/plugins/Clist_nicer/src/CLUIFrames/framesmenu.cpp new file mode 100644 index 0000000000..07b6ebc4e6 --- /dev/null +++ b/plugins/Clist_nicer/src/CLUIFrames/framesmenu.cpp @@ -0,0 +1,228 @@ +#include +#include "cluiframes.h" + +//==========================Frames +HANDLE hFrameMenuObject; +static HANDLE hPreBuildFrameMenuEvent; +extern int InitCustomMenus(void); + +//contactmenu exec param(ownerdata) +//also used in checkservice +typedef struct{ + char *szServiceName; + int Frameid; + INT_PTR param1; +}FrameMenuExecParam,*lpFrameMenuExecParam; + +void FreeAndNil( void **p ) +{ + if (p!=NULL) + { + if (*p!=NULL) + { + if (!IsBadCodePtr((FARPROC)*p)) + { + mir_free(*p); + } + *p=NULL; + } + } +} + +INT_PTR FreeOwnerDataFrameMenu (WPARAM wParam,LPARAM lParam) +{ + + lpFrameMenuExecParam cmep; + + cmep=(lpFrameMenuExecParam)lParam; + if (cmep!=NULL){ + FreeAndNil((void **)&cmep->szServiceName); + FreeAndNil((void **)&cmep); + } + return(0); +} + +static INT_PTR AddContextFrameMenuItem(WPARAM wParam,LPARAM lParam) +{ + TMO_MenuItem tmi; + CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam; + if ( !pcli->pfnConvertMenu(mi, &tmi)) + return NULL; + + tmi.root = (mi->flags & CMIF_ROOTHANDLE) ? mi->hParentMenu : NULL; + + lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)mir_alloc(sizeof(FrameMenuExecParam)); + if (fmep == NULL) + return 0; + + fmep->szServiceName = mir_strdup(mi->pszService); + fmep->Frameid = mi->popupPosition; + fmep->param1 = (INT_PTR)mi->pszContactOwner; + tmi.ownerdata = fmep; + + return CallService(MO_ADDNEWMENUITEM,(WPARAM)hFrameMenuObject,(LPARAM)&tmi); +} + +static INT_PTR RemoveContextFrameMenuItem(WPARAM wParam,LPARAM lParam) +{ + /* this do by free service + lpFrameMenuExecParam fmep; + fmep=(lpFrameMenuExecParam)CallService(MO_MENUITEMGETOWNERDATA,wParam,lParam); + if (fmep!=NULL){ + if (fmep->szServiceName!=NULL){ + mir_free(fmep->szServiceName); + fmep->szServiceName=NULL; + }; + mir_free(fmep); + } + */ + CallService(MO_REMOVEMENUITEM,wParam,0); + return 0; +} + +//called with: +//wparam - ownerdata +//lparam - lparam from winproc +INT_PTR FrameMenuExecService(WPARAM wParam,LPARAM lParam) { + lpFrameMenuExecParam fmep=(lpFrameMenuExecParam)wParam; + if (fmep==NULL) + return(-1); + + CallService(fmep->szServiceName,lParam,fmep->param1); + RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN); + return(0); +} + +//true - ok,false ignore +INT_PTR FrameMenuCheckService(WPARAM wParam,LPARAM lParam) { + + PCheckProcParam pcpp=(PCheckProcParam)wParam; + lpFrameMenuExecParam fmep; + TMO_MenuItem mi; + + if (pcpp==NULL){return(FALSE);}; + if (CallService(MO_GETMENUITEM,(WPARAM)pcpp->MenuItemHandle,(LPARAM)&mi)==0) + { + fmep = reinterpret_cast(mi.ownerdata); + if (fmep!=NULL) + { + //pcpp->wParam - frameid + if (((WPARAM)fmep->Frameid==pcpp->wParam)||fmep->Frameid==-1) return(TRUE); + } + } + return(FALSE); +} + +static INT_PTR ContextFrameMenuNotify(WPARAM wParam,LPARAM lParam) +{ + NotifyEventHooks(hPreBuildFrameMenuEvent,wParam,lParam); + return(0); +} + +static INT_PTR BuildContextFrameMenu(WPARAM wParam,LPARAM lParam) +{ + CLISTMENUITEM *mi=(CLISTMENUITEM*)lParam; + HMENU hMenu; + ListParam param = { 0 }; + param.MenuObjectHandle=hFrameMenuObject; + param.wParam=wParam; + param.lParam=lParam; + + hMenu=CreatePopupMenu(); + //NotifyEventHooks(hPreBuildFrameMenuEvent,wParam,-1); + ContextFrameMenuNotify(wParam,-1); + CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)¶m); + return (INT_PTR)hMenu; +} + +//==========================Frames end +boolean InternalGenMenuModule=FALSE; + +INT_PTR MeasureItemProxy(WPARAM wParam,LPARAM lParam) +{ + int val; + if (InternalGenMenuModule) + { + val=CallService(MS_INT_MENUMEASUREITEM,wParam,lParam); + if (val) return(val); + } + + return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); +} + +INT_PTR DrawItemProxy(WPARAM wParam,LPARAM lParam) +{ + if (InternalGenMenuModule) + { + int val; + val=CallService(MS_INT_MENUDRAWITEM,wParam,lParam); + if (val) return(val); + } + return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); +} + +int ProcessCommandProxy(WPARAM wParam,LPARAM lParam) +{ + if (InternalGenMenuModule) { + int val; + val=CallService(MS_INT_MENUPROCESSCOMMAND,wParam,lParam); + if (val) + return(val); + } + return CallService(MS_CLIST_MENUPROCESSCOMMAND,wParam,lParam); +} + +INT_PTR ModifyMenuItemProxy(WPARAM wParam,LPARAM lParam) +{ + if (InternalGenMenuModule) + { + int val; + val=CallService(MS_INT_MODIFYMENUITEM,wParam,lParam); + if (val) return(val); + } + + return CallService(MS_CLIST_MODIFYMENUITEM,wParam,lParam); +} + +int InitFramesMenus(void) +{ + TMenuParam tmp; + + if (!ServiceExists(MO_REMOVEMENUOBJECT)) + InternalGenMenuModule=TRUE; + + if (ServiceExists(MO_REMOVEMENUOBJECT)) + { + CreateServiceFunction("FrameMenuExecService",FrameMenuExecService); + CreateServiceFunction("FrameMenuCheckService",FrameMenuCheckService); + CreateServiceFunction("FrameMenuFreeService",FreeOwnerDataFrameMenu); + + + CreateServiceFunction(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM,RemoveContextFrameMenuItem); + CreateServiceFunction("CList/AddContextFrameMenuItem",AddContextFrameMenuItem); + CreateServiceFunction(MS_CLIST_MENUBUILDFRAMECONTEXT,BuildContextFrameMenu); + CreateServiceFunction(MS_CLIST_FRAMEMENUNOTIFY,ContextFrameMenuNotify); + hPreBuildFrameMenuEvent=CreateHookableEvent(ME_CLIST_PREBUILDFRAMEMENU); + + //frame menu object + memset(&tmp,0,sizeof(tmp)); + tmp.cbSize=sizeof(tmp); + tmp.CheckService="FrameMenuCheckService"; + tmp.ExecService="FrameMenuExecService"; + tmp.name="Frames_Menu"; + hFrameMenuObject=(HANDLE)CallService(MO_CREATENEWMENUOBJECT,0,(LPARAM)&tmp); + { + OptParam op; + op.Handle=hFrameMenuObject; + op.Setting=OPT_MENUOBJECT_SET_FREE_SERVICE; + op.Value=(INT_PTR)"FrameMenuFreeService"; + CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op); + } + } + return 0; +} + +int UnitFramesMenu() +{ + return(0); +} diff --git a/plugins/Clist_nicer/src/CLUIFrames/groupmenu.cpp b/plugins/Clist_nicer/src/CLUIFrames/groupmenu.cpp new file mode 100644 index 0000000000..a784e30883 --- /dev/null +++ b/plugins/Clist_nicer/src/CLUIFrames/groupmenu.cpp @@ -0,0 +1,704 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 + +//////////////////////////////Group MENU///////////////////////// +HANDLE hGroupMenuObject; + +HANDLE hGroupMainMenuItemProxy; +HANDLE hHideShowMainMenuItem; +HANDLE hGroupStatusMenuItemProxy; +HANDLE hPreBuildGroupMenuEvent; +HANDLE hAppearanceMenuItemProxy; +HANDLE hEventAreaMenuItemProxy; + +static HMENU hMenuOldContext; + +HANDLE hHideOfflineUsersMenuItem; +HANDLE hHideOfflineUsersOutHereMenuItem; +HANDLE hHideEmptyGroupsMenuItem; +HANDLE hDisableGroupsMenuItem; +HANDLE hNewGroupMenuItem; +HANDLE hNewSubGroupMenuItem; + +int NewGroupIconidx; + +extern HIMAGELIST hCListImages; +extern HICON LoadIconFromExternalFile (char *filename,int i,boolean UseLibrary,boolean registerit,char *IconName,char *SectName,char *Description,int internalidx); + +void InitSubGroupMenus(void); + +//Groupmenu exec param(ownerdata) +typedef struct { + char *szServiceName; + int Param1,Param2; +}GroupMenuExecParam,*lpGroupMenuExecParam; + +/* +wparam=handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM +return 0 on success. +*/ +static INT_PTR RemoveGroupMenuItem(WPARAM wParam,LPARAM lParam) +{ + CallService(MO_REMOVEMENUITEM,wParam,0); + return 0; +} + + +static INT_PTR BuildGroupMenu(WPARAM wParam,LPARAM lParam) +{ + int tick; + HMENU hMenu; + ListParam param = { 0 }; + param.MenuObjectHandle=hGroupMenuObject; + + //hMenu=hMainMenu; + hMenu=CreatePopupMenu(); + //hMenu=wParam; + tick=GetTickCount(); + + NotifyEventHooks(hPreBuildGroupMenuEvent,0,0); + + CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)¶m); + //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0)); + tick=GetTickCount()-tick; + return(INT_PTR)hMenu; +} + +static INT_PTR AddGroupMenuItem(WPARAM wParam,LPARAM lParam) +{ + TMO_MenuItem tmi; + CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam; + if ( !pcli->pfnConvertMenu(mi, &tmi)) + return NULL; + + lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)mir_alloc(sizeof(GroupMenuExecParam)); + if (mmep == NULL) + return 0; + + //we need just one parametr. + mmep->szServiceName = mir_strdup(mi->pszService); + mmep->Param1 = mi->popupPosition; + lpGroupMenuParam gmp=(lpGroupMenuParam)wParam; + if (gmp != NULL) { + mmep->Param1 = gmp->wParam; + mmep->Param2 = gmp->lParam; + } + tmi.ownerdata=mmep; + + char buf[1024]; + sprintf(buf,"%s/%s",mi->pszService,mi->pszName); + + OptParam op; + op.Handle=(HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hGroupMenuObject,(LPARAM)&tmi); + op.Setting=OPT_MENUITEMSETUNIQNAME; + op.Value=(INT_PTR)buf; + CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op); + return (INT_PTR)op.Handle; +} + +INT_PTR GroupMenuCheckService(WPARAM wParam,LPARAM lParam) +{ + return 0; +} + +INT_PTR GroupMenuonAddService(WPARAM wParam,LPARAM lParam) { + + MENUITEMINFO *mii=(MENUITEMINFO* )wParam; + if (mii==NULL) return 0; + + if (hHideShowMainMenuItem==(HANDLE)lParam) { + mii->fMask|=MIIM_STATE; + mii->fState|=MFS_DEFAULT; + + } + if (hGroupMainMenuItemProxy==(HANDLE)lParam) { + mii->fMask|=MIIM_SUBMENU; + //mi.fType=MFT_STRING; + mii->hSubMenu=(HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0); + } + + if (hGroupStatusMenuItemProxy==(HANDLE)lParam) { + mii->fMask|=MIIM_SUBMENU; + //mi.fType=MFT_STRING; + mii->hSubMenu=(HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0); + } + if (hAppearanceMenuItemProxy==(HANDLE)lParam) { + hMenuOldContext = GetSubMenu(LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)), 3); + TranslateMenu(hMenuOldContext); + + CheckMenuItem(hMenuOldContext, POPUP_VISIBILITY, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_SHOWVISI ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hMenuOldContext, POPUP_FRAME, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hMenuOldContext, POPUP_BUTTONS, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hMenuOldContext, POPUP_SHOWMETAICONS, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_USEMETAICONS ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hMenuOldContext, POPUP_SHOWSTATUSICONS, MF_BYCOMMAND | (cfg::dat.dwFlags & CLUI_FRAME_STATUSICONS ? MF_CHECKED : MF_UNCHECKED)); + + // floater menu items + + EnableMenuItem(hMenuOldContext, POPUP_FLOATER_AUTOHIDE, MF_BYCOMMAND | (cfg::dat.bUseFloater & CLUI_USE_FLOATER ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(hMenuOldContext, POPUP_FLOATER_EVENTS, MF_BYCOMMAND | (cfg::dat.bUseFloater & CLUI_USE_FLOATER ? MF_ENABLED : MF_GRAYED)); + CheckMenuItem(hMenuOldContext, POPUP_FLOATER, MF_BYCOMMAND | (cfg::dat.bUseFloater & CLUI_USE_FLOATER ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hMenuOldContext, POPUP_FLOATER_AUTOHIDE, MF_BYCOMMAND | (cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hMenuOldContext, POPUP_FLOATER_EVENTS, MF_BYCOMMAND | (cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS ? MF_CHECKED : MF_UNCHECKED)); + + mii->fMask|=MIIM_SUBMENU; + //mi.fType=MFT_STRING; + mii->hSubMenu=(HMENU)hMenuOldContext; + } + return(TRUE); +}; + + +//called with: +//wparam - ownerdata +//lparam - lparam from winproc +INT_PTR GroupMenuExecService(WPARAM wParam,LPARAM lParam) { + if (wParam!=0) { + lpGroupMenuExecParam mmep=(lpGroupMenuExecParam)wParam; + if (!strcmp(mmep->szServiceName,"Help/AboutCommand")) { + //bug in help.c,it used wparam as parent window handle without reason. + mmep->Param1=0; + CallService(mmep->szServiceName,mmep->Param1,lParam); + } + else { + CallService(mmep->szServiceName,mmep->Param1,mmep->Param2); + } + + }; + return(1); +}; +INT_PTR FreeOwnerDataGroupMenu (WPARAM wParam,LPARAM lParam) +{ + + lpGroupMenuExecParam mmep; + mmep=(lpGroupMenuExecParam)lParam; + if (mmep!=NULL) { + FreeAndNil((void **)&mmep->szServiceName); + FreeAndNil((void **)&mmep); + } + + return(0); +}; + +INT_PTR HideGroupsHelper(WPARAM wParam,LPARAM lParam) +{ + int newVal=!(GetWindowLongPtr((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),GWL_STYLE)&CLS_HIDEEMPTYGROUPS); + cfg::writeByte("CList","HideEmptyGroups",(BYTE)newVal); + SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),CLM_SETHIDEEMPTYGROUPS,newVal,0); + return 0; +} + +INT_PTR UseGroupsHelper(WPARAM wParam,LPARAM lParam) +{ + int newVal=!(GetWindowLongPtr((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),GWL_STYLE)&CLS_USEGROUPS); + cfg::writeByte("CList","UseGroups",(BYTE)newVal); + SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),CLM_SETUSEGROUPS,newVal,0); + return 0; +} + +INT_PTR HideOfflineRootHelper(WPARAM wParam,LPARAM lParam) +{ + SendMessage( + (HWND)CallService(MS_CLUI_GETHWNDTREE,0,0), + CLM_SETHIDEOFFLINEROOT, + !SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),CLM_GETHIDEOFFLINEROOT,0,0), + 0); + return 0; +}; + +static int OnBuildGroupMenu(WPARAM wParam,LPARAM lParam) +{ + CLISTMENUITEM mi; + + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS | (cfg::getByte("CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)?CMIF_CHECKED:0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersMenuItem, (LPARAM)&mi); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS | (SendMessage(pcli->hwndContactTree,CLM_GETHIDEOFFLINEROOT,0,0)?CMIF_CHECKED:0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersOutHereMenuItem, (LPARAM)&mi); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_HIDEEMPTYGROUPS?CMIF_CHECKED:0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideEmptyGroupsMenuItem, (LPARAM)&mi); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_USEGROUPS?0:CMIF_CHECKED); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hDisableGroupsMenuItem, (LPARAM)&mi); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hGroupMainMenuItemProxy, (LPARAM)&mi); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hAppearanceMenuItemProxy, (LPARAM)&mi); + + return 0; +}; + +int static OnIconLibIconChanged(WPARAM wParam,LPARAM lParam) +{ + HICON hicon; + CLISTMENUITEM clmi={0}; + + //hicon=LoadIconFromExternalFile("clisticons.dll",2,TRUE,FALSE,"NewGroup","Contact List","New Group",-IDI_NEWGROUP); + NewGroupIconidx=ImageList_ReplaceIcon(hCListImages,NewGroupIconidx,hicon); + + clmi.cbSize=sizeof(clmi); + clmi.flags=CMIM_ICON; + clmi.hIcon=ImageList_GetIcon(hCListImages,NewGroupIconidx,0); + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hNewSubGroupMenuItem,(LPARAM)&clmi); + CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hNewGroupMenuItem,(LPARAM)&clmi); + // + + + return 0; +}; + +void InitGroupMenus(void) +{ + TMenuParam tmp; + OptParam op; + //hicon=LoadIconFromExternalFile("clisticons.dll",2,TRUE,TRUE,"NewGroup","Contact List","New Group",-IDI_NEWGROUP2); + //NewGroupIconidx=ImageList_AddIcon(hCListImages,hicon ); + + CreateServiceFunction("CLISTMENUSGroup/ExecService",GroupMenuExecService); + CreateServiceFunction("CLISTMENUSGroup/FreeOwnerDataGroupMenu",FreeOwnerDataGroupMenu); + CreateServiceFunction("CLISTMENUSGroup/GroupMenuonAddService",GroupMenuonAddService); + CreateServiceFunction("CLISTMENUSGroup/HideGroupsHelper",HideGroupsHelper); + CreateServiceFunction("CLISTMENUSGroup/UseGroupsHelper",UseGroupsHelper); + CreateServiceFunction("CLISTMENUSGroup/HideOfflineRootHelper",HideOfflineRootHelper); + + CreateServiceFunction("CList/AddGroupMenuItem",AddGroupMenuItem); + CreateServiceFunction(MS_CLIST_REMOVEGROUPMENUITEM,RemoveGroupMenuItem); + CreateServiceFunction(MS_CLIST_MENUBUILDGROUP,BuildGroupMenu); + hPreBuildGroupMenuEvent=CreateHookableEvent(ME_CLIST_PREBUILDGROUPMENU); + HookEvent(ME_CLIST_PREBUILDGROUPMENU,OnBuildGroupMenu); + + InitSubGroupMenus(); + + //Group menu + memset(&tmp,0,sizeof(tmp)); + tmp.cbSize=sizeof(tmp); + tmp.CheckService=NULL; + tmp.ExecService="CLISTMENUSGroup/ExecService"; + tmp.name="GroupMenu"; + hGroupMenuObject=(HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp); + + + op.Handle=hGroupMenuObject; + op.Setting=OPT_USERDEFINEDITEMS; + op.Value=TRUE; + CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op); + + op.Handle=hGroupMenuObject; + op.Setting=OPT_MENUOBJECT_SET_FREE_SERVICE; + op.Value=(INT_PTR)"CLISTMENUSGroup/FreeOwnerDataGroupMenu"; + CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op); + + op.Handle=hGroupMenuObject; + op.Setting=OPT_MENUOBJECT_SET_ONADD_SERVICE; + op.Value=(INT_PTR)"CLISTMENUSGroup/GroupMenuonAddService"; + CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op); + + { + //add exit command to menu + CLISTMENUITEM mi; + GroupMenuParam gmp; + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=1900000; + mi.pszService="CloseAction"; + mi.pszName=LPGEN("E&xit"); + AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=500; + mi.pszService=MS_CLIST_SHOWHIDE; + mi.pszName=LPGEN("&Hide/Show"); + hHideShowMainMenuItem=(HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=200000; + mi.flags = CMIF_ICONFROMICOLIB; + mi.icolibItem=LoadSkinnedIconHandle(SKINICON_OTHER_FINDUSER); //LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_FINDUSER)); + mi.pszService="FindAdd/FindAddCommand"; + mi.pszName=LPGEN("&Find/Add Contacts..."); + AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=300000; + mi.pszService=""; + mi.pszName=LPGEN("&Main Menu"); + hGroupMainMenuItemProxy=(HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=300100; + mi.pszService=""; + mi.pszName=LPGEN("&Status"); + hGroupStatusMenuItemProxy=(HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=390100; + mi.pszService=""; + mi.pszName=LPGEN("Appearance"); + hAppearanceMenuItemProxy=(HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=400000; + mi.flags = CMIF_ICONFROMICOLIB; + mi.icolibItem=LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS); //LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_OPTIONS)); + mi.pszService="Options/OptionsCommand"; + mi.pszName=LPGEN("&Options..."); + + AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=500000; + mi.flags = CMIF_ICONFROMICOLIB; + mi.icolibItem=LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA); //LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_MIRANDA)); + mi.pszService="CLN/About"; + mi.pszName=LPGEN("&About the contact list..."); + + AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=100000; + mi.hIcon=ImageList_GetIcon(hCListImages,NewGroupIconidx,0); + //mi.pszService=MS_CLIST_GROUPCREATE; + mi.pszService="CLISTMENUSSubGroup/GroupMenuExecProxy"; + //mi.pszService="CLISTMENUSGroup/ExecService"; + mi.pszName=LPGEN("&New Group"); + gmp.lParam=0;gmp.wParam=POPUP_NEWGROUP; + hNewGroupMenuItem=(HANDLE)AddGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=100001; + mi.hIcon=NULL; + mi.pszService=MS_CLIST_SETHIDEOFFLINE; + mi.pszName=LPGEN("&Hide Offline Users"); + gmp.lParam=0;gmp.wParam=-1; + hHideOfflineUsersMenuItem=(HANDLE)AddGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=100002; + mi.hIcon=NULL; + mi.pszService="CLISTMENUSGroup/HideOfflineRootHelper"; + mi.pszName=LPGEN("Hide &Offline Users out here"); + hHideOfflineUsersOutHereMenuItem=(HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=100003; + mi.hIcon=NULL; + mi.pszService="CLISTMENUSGroup/HideGroupsHelper"; + mi.pszName=LPGEN("Hide &Empty Groups"); + hHideEmptyGroupsMenuItem=(HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=100004; + mi.hIcon=NULL; + mi.pszService="CLISTMENUSGroup/UseGroupsHelper"; + mi.pszName=LPGEN("Disable &Groups"); + hDisableGroupsMenuItem=(HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi); + + + //MS_CLIST_GROUPCREATE + + }; +} + +HANDLE hSubGroupMenuObject; + +HANDLE hSubGroupMainMenuItemProxy; +//HANDLE hHideShowMainMenuItem; +HANDLE hSubGroupStatusMenuItemProxy; +HANDLE hPreBuildSubGroupMenuEvent; +HANDLE hHideOfflineUsersHereMenuItem; + +//SubGroupmenu exec param(ownerdata) +typedef struct { + char *szServiceName; + int Param1,Param2; +}SubGroupMenuExecParam,*lpSubGroupMenuExecParam; + +/* +wparam=handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM +return 0 on success. +*/ +static INT_PTR RemoveSubGroupMenuItem(WPARAM wParam,LPARAM lParam) +{ + CallService(MO_REMOVEMENUITEM,wParam,0); + return 0; +} + +static int OnBuildSubGroupMenu(WPARAM wParam,LPARAM lParam) +{ + ClcGroup *group=(struct ClcGroup *)wParam; + if (group == 0) + return 0; + + //contact->group + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + mi.flags = CMIM_FLAGS | (group->hideOffline?CMIF_CHECKED:0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersHereMenuItem, (LPARAM)&mi); + + return 0; +} + +static INT_PTR BuildSubGroupMenu(WPARAM wParam,LPARAM lParam) +{ + ListParam param = { 0 }; + param.MenuObjectHandle = hSubGroupMenuObject; + param.wParam = wParam; + + HMENU hMenu = CreatePopupMenu(); + int tick = GetTickCount(); + NotifyEventHooks(hPreBuildSubGroupMenuEvent,wParam,0); + + CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)¶m); + tick = GetTickCount()-tick; + return(INT_PTR)hMenu; +} + +static INT_PTR AddSubGroupMenuItem(WPARAM wParam,LPARAM lParam) +{ + TMO_MenuItem tmi; + CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam; + if ( !pcli->pfnConvertMenu(mi, &tmi)) + return NULL; + + lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)mir_alloc(sizeof(SubGroupMenuExecParam)); + if (mmep == NULL) + return 0; + + //we need just one parametr. + lpGroupMenuParam gmp=(lpGroupMenuParam)wParam; + mmep->szServiceName = mir_strdup(mi->pszService); + mmep->Param1 = mi->popupPosition; + if (gmp != NULL) { + mmep->Param1 = gmp->wParam; + mmep->Param2 = gmp->lParam; + } + tmi.ownerdata = mmep; + + char buf[1024]; + sprintf(buf,"%s/%s",mi->pszService,mi->pszName); + + OptParam op; + op.Handle=(HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hSubGroupMenuObject,(LPARAM)&tmi); + op.Setting=OPT_MENUITEMSETUNIQNAME; + op.Value=(INT_PTR)buf; + CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op); + return (INT_PTR)op.Handle; +} + +INT_PTR SubGroupMenuCheckService(WPARAM wParam,LPARAM lParam) { + //not used + return(0); +}; + +INT_PTR SubGroupMenuonAddService(WPARAM wParam,LPARAM lParam) { + + MENUITEMINFO *mii=(MENUITEMINFO* )wParam; + + if (mii==NULL) return 0; + + /* + if (hHideShowMainMenuItem==(HANDLE)lParam) + { + mii->fMask|=MIIM_STATE; + mii->fState|=MFS_DEFAULT; + + } + if (hSubGroupMainMenuItemProxy==(HANDLE)lParam) + { + mii->fMask|=MIIM_SUBMENU; + //mi.fType=MFT_STRING; + mii->hSubMenu=(HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0); + } + + if (hSubGroupStatusMenuItemProxy==(HANDLE)lParam) + { + mii->fMask|=MIIM_SUBMENU; + //mi.fType=MFT_STRING; + mii->hSubMenu=(HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0); + } + */ + return(TRUE); +}; + + +//called with: +//wparam - ownerdata +//lparam - lparam from winproc +INT_PTR SubGroupMenuExecService(WPARAM wParam,LPARAM lParam) { + if (wParam!=0) { + lpSubGroupMenuExecParam mmep=(lpSubGroupMenuExecParam)wParam; + if (!strcmp(mmep->szServiceName,"Help/AboutCommand")) { + //bug in help.c,it used wparam as parent window handle without reason. + mmep->Param1=0; + CallService(mmep->szServiceName,mmep->Param1,lParam); + } + else { + CallService(mmep->szServiceName,mmep->Param1,mmep->Param2); + } + } + return(1); +} + +INT_PTR FreeOwnerDataSubGroupMenu (WPARAM wParam,LPARAM lParam) +{ + lpSubGroupMenuExecParam mmep; + mmep=(lpSubGroupMenuExecParam)lParam; + if (mmep!=NULL) { + FreeAndNil((void **)&mmep->szServiceName); + FreeAndNil((void **)&mmep); + } + + return(0); +} + +//wparam menu handle to pass to clc.c +INT_PTR GroupMenuExecProxy(WPARAM wParam,LPARAM lParam) +{ + SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),WM_COMMAND,wParam,0); + return 0; +} + +void InitSubGroupMenus(void) +{ + TMenuParam tmp; + OptParam op; + + CreateServiceFunction("CLISTMENUSSubGroup/ExecService",SubGroupMenuExecService); + CreateServiceFunction("CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu",FreeOwnerDataSubGroupMenu); + CreateServiceFunction("CLISTMENUSSubGroup/SubGroupMenuonAddService",SubGroupMenuonAddService); + CreateServiceFunction("CLISTMENUSSubGroup/GroupMenuExecProxy",GroupMenuExecProxy); + + //CreateServiceFunction("CLISTMENUSSubGroup/HideSubGroupsHelper",HideSubGroupsHelper); + //CreateServiceFunction("CLISTMENUSSubGroup/UseSubGroupsHelper",UseSubGroupsHelper); + //CreateServiceFunction("CLISTMENUSSubGroup/HideOfflineRootHelper",HideOfflineRootHelper); + + CreateServiceFunction("CList/AddSubGroupMenuItem",AddSubGroupMenuItem); + CreateServiceFunction(MS_CLIST_REMOVESUBGROUPMENUITEM,RemoveSubGroupMenuItem); + CreateServiceFunction(MS_CLIST_MENUBUILDSUBGROUP,BuildSubGroupMenu); + hPreBuildSubGroupMenuEvent=CreateHookableEvent(ME_CLIST_PREBUILDSUBGROUPMENU); + HookEvent(ME_CLIST_PREBUILDSUBGROUPMENU,OnBuildSubGroupMenu); + + + //SubGroup menu + memset(&tmp,0,sizeof(tmp)); + tmp.cbSize=sizeof(tmp); + tmp.CheckService=NULL; + tmp.ExecService="CLISTMENUSSubGroup/ExecService"; + tmp.name="SubGroupMenu"; + hSubGroupMenuObject=(HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp); + + + op.Handle=hSubGroupMenuObject; + op.Setting=OPT_USERDEFINEDITEMS; + op.Value=TRUE; + CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op); + + op.Handle=hSubGroupMenuObject; + op.Setting=OPT_MENUOBJECT_SET_FREE_SERVICE; + op.Value=(INT_PTR)"CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu"; + CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op); + + op.Handle=hSubGroupMenuObject; + op.Setting=OPT_MENUOBJECT_SET_ONADD_SERVICE; + op.Value=(INT_PTR)"CLISTMENUSSubGroup/SubGroupMenuonAddService"; + CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op); + + { + //add exit command to menu + CLISTMENUITEM mi; + GroupMenuParam gmp; + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=1000; + mi.hIcon=ImageList_GetIcon(hCListImages,NewGroupIconidx,0); + mi.pszService="CLISTMENUSSubGroup/GroupMenuExecProxy"; + mi.pszName=LPGEN("&New SubGroup"); + gmp.lParam=0;gmp.wParam=POPUP_NEWSUBGROUP; + hNewSubGroupMenuItem=(HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=1001; + mi.hIcon=NULL; + mi.pszService="CLISTMENUSSubGroup/GroupMenuExecProxy"; + mi.pszName=LPGEN("&Hide Offline Users in here"); + gmp.lParam=0;gmp.wParam=POPUP_GROUPHIDEOFFLINE; + hHideOfflineUsersHereMenuItem=(HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=900001; + mi.flags = CMIF_ICONFROMICOLIB; + mi.icolibItem=LoadSkinnedIconHandle(SKINICON_OTHER_RENAME); //LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_RENAME)); + mi.pszService="CLISTMENUSSubGroup/GroupMenuExecProxy"; + mi.pszName=LPGEN("&Rename Group"); + gmp.lParam=0;gmp.wParam=POPUP_RENAMEGROUP; + AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi); + + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=900002; + mi.flags = CMIF_ICONFROMICOLIB; + mi.icolibItem=LoadSkinnedIconHandle(SKINICON_OTHER_DELETE); //LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_DELETE)); + mi.pszService="CLISTMENUSSubGroup/GroupMenuExecProxy"; + mi.pszName=LPGEN("&Delete Group"); + gmp.lParam=0;gmp.wParam=POPUP_DELETEGROUP; + AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi); + } +} + +//////////////////////////////END SubGroup MENU///////////////////////// diff --git a/plugins/Clist_nicer/src/CLUIFrames/movetogroup.cpp b/plugins/Clist_nicer/src/CLUIFrames/movetogroup.cpp new file mode 100644 index 0000000000..89bc2a42e4 --- /dev/null +++ b/plugins/Clist_nicer/src/CLUIFrames/movetogroup.cpp @@ -0,0 +1,60 @@ +#include + +HANDLE hOnCntMenuBuild; +HANDLE hPriorityItem = 0, hFloatingItem = 0; + +static int OnContactMenuBuild(WPARAM wParam,LPARAM lParam) +{ + CLISTMENUITEM mi; + BYTE bSetting; + + // Menu Item - Floating Contact + bSetting = cfg::getByte("CList", "flt_enabled", 0); + if (bSetting && !hFloatingItem) + { + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=200000; + mi.pszPopupName=(char *)-1; + mi.pszService="CList/SetContactFloating"; + mi.pszName=LPGEN("&Floating Contact"); + if (pcli) + { + if (SendMessage(pcli->hwndContactTree, CLM_QUERYFLOATINGCONTACT, wParam, 0)) + mi.flags=CMIF_CHECKED; + } + hFloatingItem = Menu_AddContactMenuItem(&mi); + } + else if (!bSetting && hFloatingItem) + { + CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)hFloatingItem, 0); + hFloatingItem = 0; + } + else + { + memset(&mi,0,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.flags=CMIM_FLAGS; + if (pcli) + { + if (SendMessage(pcli->hwndContactTree, CLM_QUERYFLOATINGCONTACT, wParam, 0)) + mi.flags |= CMIF_CHECKED; + } + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hFloatingItem, (LPARAM)&mi); + } + return 0; +} + +int MTG_OnmodulesLoad(WPARAM wParam,LPARAM lParam) +{ + hOnCntMenuBuild=HookEvent(ME_CLIST_PREBUILDCONTACTMENU,OnContactMenuBuild); + return 0; +} + +int UnloadMoveToGroup(void) +{ + if (hOnCntMenuBuild) + UnhookEvent(hOnCntMenuBuild); + + return 0; +} diff --git a/plugins/Clist_nicer/src/Coolsb/coolsb_internal.h b/plugins/Clist_nicer/src/Coolsb/coolsb_internal.h new file mode 100644 index 0000000000..8a394f8a51 --- /dev/null +++ b/plugins/Clist_nicer/src/Coolsb/coolsb_internal.h @@ -0,0 +1,95 @@ +#ifndef _COOLSB_INTERNAL_INCLUDED +#define _COOLSB_INTERNAL_INCLUDED + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + +// +// SCROLLBAR datatype. There are two of these structures per window +// +typedef struct +{ + UINT fScrollFlags; //flags + BOOL fScrollVisible; //if this scrollbar visible? + SCROLLINFO scrollInfo; //positional data (range, position, page size etc) + + int nArrowLength; //perpendicular size (height of a horizontal, width of a vertical) + int nArrowWidth; //parallel size (width of horz, height of vert) + + //data for inserted buttons + SCROLLBUT sbButtons[MAX_COOLSB_BUTS]; + int nButtons; + int nButSizeBefore; //size to the left / above the bar + int nButSizeAfter; //size to the right / below the bar + + BOOL fButVisibleBefore; //if the buttons to the left are visible + BOOL fButVisibleAfter; //if the buttons to the right are visible + + int nBarType; //SB_HORZ / SB_VERT + + UINT fFlatScrollbar; //do we display flat scrollbars? + int nMinThumbSize; + +} SCROLLBAR; + +// +// Container structure for a cool scrollbar window. +// +typedef struct +{ + UINT bars; //which of the scrollbars do we handle? SB_VERT / SB_HORZ / SB_BOTH + WNDPROC oldproc; //old window procedure to call for every message + + SCROLLBAR sbarHorz; //one scrollbar structure each for + SCROLLBAR sbarVert; //the horizontal and vertical scrollbars + + BOOL fThumbTracking; // are we currently thumb-tracking?? + BOOL fLeftScrollbar; // support the WS_EX_LEFTSCROLLBAR style + + HWND hwndToolTip; // tooltip support!!! + + //size of the window borders + int cxLeftEdge, cxRightEdge; + int cyTopEdge, cyBottomEdge; + + // To prevent calling original WindowProc in response + // to our own temporary style change (fixes TreeView problem) + BOOL bPreventStyleChange; + +} SCROLLWND; + + +// +// PRIVATE INTERNAL FUNCTIONS +// +SCROLLWND *GetScrollWndFromHwnd(HWND hwnd); +#define InvertCOLORREF(col) ((~col) & 0x00ffffff) + +#define COOLSB_TIMERID1 65533 //initial timer +#define COOLSB_TIMERID2 65534 //scroll message timer +#define COOLSB_TIMERID3 -14 //mouse hover timer +#define COOLSB_TIMERINTERVAL1 300 +#define COOLSB_TIMERINTERVAL2 55 +#define COOLSB_TIMERINTERVAL3 20 //mouse hover time + + +// +// direction: 0 - same axis as scrollbar (i.e. width of a horizontal bar) +// 1 - perpendicular dimesion (i.e. height of a horizontal bar) +// +#define SM_CXVERTSB 1 +#define SM_CYVERTSB 0 +#define SM_CXHORZSB 0 +#define SM_CYHORZSB 1 +#define SM_SCROLL_WIDTH 1 +#define SM_SCROLL_LENGTH 0 + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/Clist_nicer/src/Coolsb/coolsblib.cpp b/plugins/Clist_nicer/src/Coolsb/coolsblib.cpp new file mode 100644 index 0000000000..42f74c4ca0 --- /dev/null +++ b/plugins/Clist_nicer/src/Coolsb/coolsblib.cpp @@ -0,0 +1,1003 @@ +/* + + Cool Scrollbar Library Version 1.2 + + Module: coolsblib.c + Copyright (c) J Brown 2001 + + This code is freeware, however, you may not publish + this code elsewhere or charge any money for it. This code + is supplied as-is. I make no guarantees about the suitability + of this code - use at your own risk. + + It would be nice if you credited me, in the event + that you use this code in a product. + + VERSION HISTORY: + + V1.2: TreeView problem fixed by Diego Tartara + Small problem in thumbsize calculation also fixed (thanks Diego!) + + V1.1: Added support for Right-left windows + Changed calling convention of APIs to WINAPI (__stdcall) + Completely standalone (no need for c-runtime) + + V1.0: Apr 2001: Initial Version + +*/ + +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0501 + +#include +#include "coolscroll.h" +#include "userdefs.h" +#include "coolsb_internal.h" + +static TCHAR szPropStr[] = _T("CoolSBSubclassPtr"); + +LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +SCROLLWND *GetScrollWndFromHwnd(HWND hwnd) +{ + return (SCROLLWND *)GetProp(hwnd, szPropStr); +} + +SCROLLBAR *GetScrollBarFromHwnd(HWND hwnd, UINT nBar) +{ + SCROLLWND *sw = GetScrollWndFromHwnd(hwnd); + + if (!sw) return 0; + + if(nBar == SB_HORZ) + return &sw->sbarHorz; + else if(nBar == SB_VERT) + return &sw->sbarVert; + else + return 0; +} + +BOOL WINAPI CoolSB_IsCoolScrollEnabled(HWND hwnd) +{ + if(GetScrollWndFromHwnd(hwnd)) + return TRUE; + else + return FALSE; +} + +BOOL GetScrollRect(SCROLLWND *sw, UINT nBar, HWND hwnd, RECT *rect); + +// +// Special support for USER32.DLL patching (using Detours library) +// The only place we call a real scrollbar API is in InitializeCoolSB, +// where we call EnableScrollbar. +// +// We HAVE to call the origial EnableScrollbar function, +// so we need to be able to set a pointer to this func when using +// using Detours (or any other LIB??) +// + +typedef BOOL (WINAPI *WPROC)(HWND, UINT, UINT); + +static WPROC pEnableScrollBar = 0; + +void WINAPI CoolSB_SetESBProc(WPROC proc) +{ + pEnableScrollBar = proc; +} +// +// + +static void RedrawNonClient(HWND hwnd, BOOL fFrameChanged) +{ + if(fFrameChanged == FALSE) + { + /* + RECT rect; + HRGN hrgn1, hrgn2; + + SCROLLWND *sw = GetScrollWndFromHwnd(hwnd); + + GetScrollRect(sw, SB_HORZ, hwnd, &rect); + hrgn1 = CreateRectRgnIndirect(&rect); + + GetScrollRect(sw, SB_VERT, hwnd, &rect); + hrgn2 = CreateRectRgnIndirect(&rect); + + CombineRgn(hrgn1, hrgn2, hrgn1, RGN_OR); + + SendMessage(hwnd, WM_NCPAINT, (WPARAM)hrgn1, 0); + + DeleteObject(hrgn1); + DeleteObject(hrgn2);*/ + + SendMessage(hwnd, WM_NCPAINT, (WPARAM)1, 0); + } + else + { + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE + | SWP_FRAMECHANGED | SWP_DRAWFRAME); + } +} + +// +// return the default minimum size of a scrollbar thumb +// +int WINAPI CoolSB_GetDefaultMinThumbSize(void) +{ + DWORD dwVersion = GetVersion(); + + // set the minimum thumb size for a scrollbar. This + // differs between NT4 and 2000, so need to check to see + // which platform we are running under + if(dwVersion < 0x80000000) // Windows NT/2000 + { + if(LOBYTE(LOWORD(dwVersion)) >= 5) + return MINTHUMBSIZE_2000; + else + return MINTHUMBSIZE_NT4; + } + else + { + return MINTHUMBSIZE_NT4; + } +} + +static SCROLLINFO *GetScrollInfoFromHwnd(HWND hwnd, int fnBar) +{ + SCROLLBAR *sb = GetScrollBarFromHwnd(hwnd, fnBar); + + if(sb == 0) + return FALSE; + + if(fnBar == SB_HORZ) + { + return &sb->scrollInfo; + } + else if(fnBar == SB_VERT) + { + return &sb->scrollInfo; + } + else + return NULL; +} +// +// Initialize the cool scrollbars for a window by subclassing it +// and using the coolsb window procedure instead +// +BOOL WINAPI InitializeCoolSB(HWND hwnd) +{ + SCROLLWND *sw; + SCROLLINFO *si; + INITCOMMONCONTROLSEX ice; + TOOLINFO ti; + RECT rect; + DWORD dwCurStyle; + //BOOL fDisabled; + + if(pEnableScrollBar == 0) + pEnableScrollBar = EnableScrollBar; + + GetClientRect(hwnd, &rect); + + //if we have already initialized Cool Scrollbars for this window, + //then stop the user from doing it again + if(GetScrollWndFromHwnd(hwnd) != 0) + { + return FALSE; + } + + //allocate a private scrollbar structure which we + //will use to keep track of the scrollbar data + sw = (SCROLLWND *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SCROLLWND)); + + si = &sw->sbarHorz.scrollInfo; + si->cbSize = sizeof(SCROLLINFO); + si->fMask = SIF_ALL; + GetScrollInfo(hwnd, SB_HORZ, si); + + si = &sw->sbarVert.scrollInfo; + si->cbSize = sizeof(SCROLLINFO); + si->fMask = SIF_ALL; + GetScrollInfo(hwnd, SB_VERT, si); + + //check to see if the window has left-aligned scrollbars + if(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR) + sw->fLeftScrollbar = TRUE; + else + sw->fLeftScrollbar = FALSE; + + dwCurStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + + SetProp(hwnd, szPropStr, (HANDLE)sw); + + //try to enable the scrollbar arrows - if the return value is + //non-zero, then the scrollbars were previously disabled + //fDisabled = pEnableScrollBar(hwnd, SB_HORZ, ESB_ENABLE_BOTH); + + //scrollbars will automatically get enabled, even if + //they aren't to start with....sorry, but there isn't an + //easy alternative. + if(dwCurStyle & WS_HSCROLL) + sw->sbarHorz.fScrollFlags = CSBS_VISIBLE; + + if(dwCurStyle & WS_VSCROLL) + sw->sbarVert.fScrollFlags = CSBS_VISIBLE; + + //need to be able to distinguish between horizontal and vertical + //scrollbars in some instances + sw->sbarHorz.nBarType = SB_HORZ; + sw->sbarVert.nBarType = SB_VERT; + + sw->sbarHorz.fFlatScrollbar = CSBS_NORMAL; + sw->sbarVert.fFlatScrollbar = CSBS_NORMAL; + + //set the default arrow sizes for the scrollbars + sw->sbarHorz.nArrowLength = SYSTEM_METRIC; + sw->sbarHorz.nArrowWidth = SYSTEM_METRIC; + sw->sbarVert.nArrowLength = SYSTEM_METRIC; + sw->sbarVert.nArrowWidth = SYSTEM_METRIC; + + sw->bPreventStyleChange = FALSE; + + sw->oldproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)CoolSBWndProc); + + CoolSB_SetMinThumbSize(hwnd, SB_BOTH, CoolSB_GetDefaultMinThumbSize()); + +#ifdef COOLSB_TOOLTIPS + ice.dwSize = sizeof(ice); + ice.dwICC = ICC_BAR_CLASSES; + InitCommonControlsEx(&ice); + + sw->hwndToolTip = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, TOOLTIPS_CLASS, _T(""), + WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hwnd, NULL, GetModuleHandle(0), + NULL); + + ti.cbSize = sizeof(TOOLINFO); + ti.uFlags = TTF_IDISHWND; + ti.hwnd = hwnd; + ti.uId = (UINT)hwnd; + ti.lpszText = LPSTR_TEXTCALLBACK; + ti.hinst = GetModuleHandle(0); + + SendMessage(sw->hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); + +#else + + UNREFERENCED_PARAMETER(ice); + UNREFERENCED_PARAMETER(ti); + sw->hwndToolTip = 0; + +#endif + + //send the window a frame changed message to update the scrollbars + RedrawNonClient(hwnd, TRUE); + + return TRUE; +} + +BOOL WINAPI CoolSB_EnableScrollBar (HWND hwnd, int wSBflags, UINT wArrows) +{ + SCROLLBAR *sbar; + UINT oldstate; + BOOL bFailed = FALSE; + + if (!CoolSB_IsCoolScrollEnabled(hwnd)) + return EnableScrollBar(hwnd, wSBflags, wArrows); + + if ((wSBflags == SB_HORZ || wSBflags == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ))) + { + oldstate = sbar->fScrollFlags; + + //clear any existing state, and OR in the disabled flags + sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows; + + if(oldstate == sbar->fScrollFlags) + bFailed = TRUE; + + } + + if ((wSBflags == SB_VERT || wSBflags == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT))) + { + oldstate = sbar->fScrollFlags; + + //clear any existing state, and OR in the disabled flags + sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows; + + if(oldstate == sbar->fScrollFlags) + bFailed = TRUE; + } + + return !bFailed; +} + +BOOL WINAPI CoolSB_GetScrollBarInfo(HWND hwnd) +{ +// SCROLLBARINFO sbi; not defined in winuser.h + return FALSE; +} + +BOOL WINAPI CoolSB_GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi) +{ + SCROLLINFO *mysi; + BOOL copied = FALSE; + + if (!lpsi) + return FALSE; + + if (!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar))) + { + return GetScrollInfo(hwnd, fnBar, lpsi); + } + + if(lpsi->fMask & SIF_PAGE) + { + lpsi->nPage = mysi->nPage; + copied = TRUE; + } + + if(lpsi->fMask & SIF_POS) + { + lpsi->nPos = mysi->nPos; + copied = TRUE; + } + + if(lpsi->fMask & SIF_TRACKPOS) + { + lpsi->nTrackPos = mysi->nTrackPos; + copied = TRUE; + } + + if(lpsi->fMask & SIF_RANGE) + { + lpsi->nMin = mysi->nMin; + lpsi->nMax = mysi->nMax; + copied = TRUE; + } + + return copied; +} + +int WINAPI CoolSB_GetScrollPos (HWND hwnd, int nBar) +{ + SCROLLINFO *mysi; + + if (!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) + return GetScrollPos(hwnd, nBar); + + return mysi->nPos; +} + +BOOL WINAPI CoolSB_GetScrollRange (HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) +{ + SCROLLINFO *mysi; + + if (!lpMinPos || !lpMaxPos) + return FALSE; + + if (!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) + return GetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos); + + *lpMinPos = mysi->nMin; + *lpMaxPos = mysi->nMax; + + return TRUE; +} + +int WINAPI CoolSB_SetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw) +{ + SCROLLINFO *mysi; + SCROLLBAR *sbar; + BOOL fRecalcFrame = FALSE; + + if (!lpsi) + return FALSE; + + if (!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar))) + return SetScrollInfo(hwnd, fnBar, lpsi, fRedraw); + + //if(CoolSB_IsThumbTracking(hwnd)) + // return mysi->nPos; + + if(lpsi->fMask & SIF_RANGE) + { + mysi->nMin = lpsi->nMin; + mysi->nMax = lpsi->nMax; + } + + //The nPage member must specify a value from 0 to nMax - nMin +1. + if(lpsi->fMask & SIF_PAGE) + { + UINT t = (UINT)(mysi->nMax - mysi->nMin + 1); + mysi->nPage = min(max(0, lpsi->nPage), t); + } + + //The nPos member must specify a value between nMin and nMax - max(nPage - 1, 0). + if(lpsi->fMask & SIF_POS) + { + mysi->nPos = max(lpsi->nPos, mysi->nMin); + mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0)); + } + + sbar = GetScrollBarFromHwnd(hwnd, fnBar); + + if ((lpsi->fMask & SIF_DISABLENOSCROLL) || (sbar->fScrollFlags & CSBS_THUMBALWAYS)) + { + if (!sbar->fScrollVisible) + { + CoolSB_ShowScrollBar(hwnd, fnBar, TRUE); + fRecalcFrame = TRUE; + } + } + else + { + if ( mysi->nPage > (UINT)mysi->nMax + || mysi->nPage == (UINT)mysi->nMax && mysi->nMax == 0 + || mysi->nMax <= mysi->nMin) + { + if(sbar->fScrollVisible) + { + CoolSB_ShowScrollBar(hwnd, fnBar, FALSE); + fRecalcFrame = TRUE; + } + } + else + { + if (!sbar->fScrollVisible) + { + CoolSB_ShowScrollBar(hwnd, fnBar, TRUE); + fRecalcFrame = TRUE; + } + + } + + } + + if(fRedraw && !CoolSB_IsThumbTracking(hwnd)) + RedrawNonClient(hwnd, fRecalcFrame); + + return mysi->nPos; +} + + +int WINAPI CoolSB_SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL fRedraw) +{ + SCROLLINFO *mysi; + int oldpos; + + if (!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) + { + return SetScrollPos(hwnd, nBar, nPos, fRedraw); + } + + //this is what should happen, but real scrollbars don't work like this.. + //if(CoolSB_IsThumbTracking(hwnd)) + // return mysi->nPos; + + //validate and set the scollbar position + oldpos = mysi->nPos; + mysi->nPos = max(nPos, mysi->nMin); + mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0)); + + if(fRedraw && !CoolSB_IsThumbTracking(hwnd)) + RedrawNonClient(hwnd, FALSE); + + return oldpos; +} + +int WINAPI CoolSB_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw) +{ + SCROLLINFO *mysi; + + if (!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) + return SetScrollRange(hwnd, nBar, nMinPos, nMaxPos, fRedraw); + + if(CoolSB_IsThumbTracking(hwnd)) + return mysi->nPos; + + //hide the scrollbar if nMin == nMax + //nMax-nMin must not be greater than MAXLONG + mysi->nMin = nMinPos; + mysi->nMax = nMaxPos; + + if(fRedraw) + RedrawNonClient(hwnd, FALSE); + + return TRUE; +} + +// +// Show or hide the specified scrollbars +// +BOOL WINAPI CoolSB_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow) +{ + SCROLLBAR *sbar; + BOOL bFailed = FALSE; + DWORD dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + + if (!CoolSB_IsCoolScrollEnabled(hwnd)) + return ShowScrollBar(hwnd, wBar, fShow); + + if ((wBar == SB_HORZ || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ))) + { + sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE; + sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0); + //bFailed = TRUE; + + if(fShow) SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle | WS_HSCROLL); + else SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle & ~WS_HSCROLL); + } + + if ((wBar == SB_VERT || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT))) + { + sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE; + sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0); + //bFailed = TRUE; + + if(fShow) SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle | WS_VSCROLL); + else SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle & ~WS_VSCROLL); + } + + if(bFailed) + { + return FALSE; + } + else + { + //DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + //style |= WS_VSCROLL; + + //if(s + //SetWindowLongPtr(hwnd, GWL_STYLE, style); + + SetWindowPos(hwnd, 0, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | + SWP_NOACTIVATE | SWP_FRAMECHANGED); + + return TRUE; + } +} + +// +// Remove cool scrollbars from the specified window. +// +HRESULT WINAPI UninitializeCoolSB(HWND hwnd) +{ + int i = 0; + SCROLLWND *sw = GetScrollWndFromHwnd(hwnd); + if (!sw) return E_FAIL; + + //restore the window procedure with the original one + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)sw->oldproc); + + RemoveProp(hwnd, szPropStr); + //SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + + //finally, release the memory needed for the cool scrollbars + HeapFree(GetProcessHeap(), 0, sw); + + //Force WM_NCCALCSIZE and WM_NCPAINT so the original scrollbars can kick in + RedrawNonClient(hwnd, TRUE); + + return S_OK; +} + +#ifdef INCLUDE_BUTTONS + +// +// Cool scrollbar specific interface (BUTTON support) +// + +// +// Insert a button into the scrollbar area +// +// wSBflags - SB_HORZ / SB_VERT only +// uPos - position into which to insert. +// can be 0 to insert at the start, or -1 to insert +// at the end of previously inserted buttons +// + +BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb) +{ + SCROLLBAR *sbar; + SCROLLBUT *sbut; + UINT i; + + if (!psb) return FALSE; + + if (!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags))) + return FALSE; + + //check that we havn't reached the maximum allowed buttons yet + if(sbar->nButtons == MAX_COOLSB_BUTS) + return FALSE; + + //insert at end + if(nPos == -1) + { + sbut = &sbar->sbButtons[sbar->nButtons]; + } + //otherwise, need to make room + else if ((int)nPos < 0 || (int)nPos > (UINT)sbar->nButtons) + { + return FALSE; + } + else + { + //insert space for the button at the specified position + for (i = sbar->nButtons; i > nPos; i--) + { + sbar->sbButtons[i] = sbar->sbButtons[i-1]; + } + + sbut = &sbar->sbButtons[nPos]; + } + + //only set the button's properties if they are + //specified by the SCROLLBUT->fMask. + //Otherwise, use a default property value + + if(psb->fMask & SBBF_TYPE) + sbut->uButType = psb->uButType; + else + sbut->uButType = SBBT_PUSHBUTTON; + + if(psb->fMask & SBBF_STATE) + sbut->uState = psb->uState; + else + sbut->uState = 0; + + if(psb->fMask & SBBF_ID) + sbut->uCmdId = psb->uCmdId; + else + sbut->uCmdId = 0; + + if(psb->fMask & SBBF_SIZE) + sbut->nSize = psb->nSize; + else + sbut->nSize = -1; + + if(psb->fMask & SBBF_PLACEMENT) + sbut->uPlacement = psb->uPlacement; + else + sbut->uPlacement = SBBP_LEFT; + + if(psb->fMask & SBBF_BITMAP) + sbut->hBmp = psb->hBmp; + else + sbut->hBmp = 0; + + if(psb->fMask & SBBF_ENHMETAFILE) + sbut->hEmf = psb->hEmf; + else + sbut->hEmf = 0; + + if(psb->fMask & SBBF_CURSOR) + sbut->hCurs = psb->hCurs; + else + sbut->hCurs = 0; + + /* + We don't use the callback function anymore. The uButType + member must now specify SBBT_OWNERDRAW, and a WM_NOTIFY will + be sent when a button must be drawn + if ((psb->fMask & SBBF_OWNERDRAW) && ((psb->uButType & SBBT_MASK) == SBBT_OWNERDRAW)) + pDrawProc = psb->pDrawProc; + else + pDrawProc = 0;*/ + + sbar->nButtons++; + sbut->nSizeReserved = sbut->nSize; + + //MAKE SURE that any resizable buttons are only to the left / above + //a scrollbar. We don't support resize operations to the right of a scrollbar + if ((sbut->uButType & SBBM_RESIZABLE) && sbut->uPlacement == SBBP_RIGHT) + sbut->uButType &= ~SBBM_RESIZABLE; + + if(psb->fMask & SBBF_BUTMINMAX) + { + sbut->nMinSize = psb->nMinSize; + sbut->nMaxSize = psb->nMaxSize; + } + else + { + sbut->nMinSize = 0; + sbut->nMaxSize = -1; + } + + return TRUE; +} + +static SCROLLBUT *GetButtonFromId(SCROLLBAR *sbar, UINT uCmdId) +{ + int i; + for (i = 0; i < sbar->nButtons; i++) + { + if(sbar->sbButtons[i].uCmdId == uCmdId) + return &sbar->sbButtons[i]; + } + + return 0; +} + +// +// Modify the properties of the specified scrollbar button. +// wSBflags - SB_HORZ / SB_VERT only +// uItem - the command identifier specified when the button was created, +// or a non-negative position of the button, depending on if +// fByCmd is FALSE or TRUE, respectively +// +BOOL WINAPI CoolSB_ModifyButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) +{ + SCROLLBAR *sbar; + SCROLLBUT *sbut; + + if (!psb) return FALSE; + + //find if this window is CoolScroll enabled + if (!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags))) + return FALSE; + + //find the button to modify, depending on if we + //are modifying by position or command id + if(fByCmd == FALSE) + { + //button from position + if ((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons) + return FALSE; + else + sbut = &sbar->sbButtons[uItem]; + } + else if(fByCmd == TRUE) + { + //button from command identifier + if (!(sbut = GetButtonFromId(sbar, uItem))) + return FALSE; + } + + if(psb->fMask & SBBF_TYPE) sbut->uButType = psb->uButType; + if(psb->fMask & SBBF_STATE) sbut->uState = psb->uState; + if(psb->fMask & SBBF_ID) sbut->uCmdId = psb->uCmdId; + if(psb->fMask & SBBF_SIZE) sbut->nSize = psb->nSize; + if(psb->fMask & SBBF_PLACEMENT) sbut->uPlacement = psb->uPlacement; + if(psb->fMask & SBBF_BITMAP) sbut->hBmp = psb->hBmp; + if(psb->fMask & SBBF_ENHMETAFILE) sbut->hEmf = psb->hEmf; + if(psb->fMask & SBBF_CURSOR) sbut->hCurs = psb->hCurs; + + if(psb->fMask & SBBF_BUTMINMAX) + { + sbut->nMinSize = psb->nMinSize; + sbut->nMaxSize = psb->nMaxSize; + } + + return TRUE; +} + +BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd) +{ + int i; + SCROLLBAR *sbar; + + //find if this window is CoolScroll enabled + if (!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags))) + return FALSE; + + //find the button to modify, depending on if we + //are modifying by position or command id + if(fByCmd == FALSE && ((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons)) + { + return FALSE; + } + else if(fByCmd == TRUE) + { + //find the button with the specified command id + for (i = 0; i < sbar->nButtons; i++) + { + if(sbar->sbButtons[i].uCmdId == uItem) + { + //change the id to an index + uItem = i; + break; + } + } + + //if we failed to find the button... + if(i == sbar->nButtons) return FALSE; + } + + //remove the button! + for (i = uItem; i < sbar->nButtons - 1; i++) + { + sbar->sbButtons[i] = sbar->sbButtons[i+1]; + } + + sbar->nButtons--; + + RedrawNonClient(hwnd, TRUE); + + return TRUE; +} + +// +// fill in the supplied SCROLLBUT structure +// +BOOL WINAPI CoolSB_GetButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) +{ + SCROLLBAR *sbar; + SCROLLBUT *sbut; + + if (!psb) return FALSE; + + //find if this window is CoolScroll enabled + if (!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags))) + return FALSE; + + //find the button to modify, depending on if we + //are modifying by position or command id + if(fByCmd == FALSE) + { + //button from position + if ((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons) + return FALSE; + else + sbut = &sbar->sbButtons[uItem]; + } + else if(fByCmd == TRUE) + { + //button from command identifier + if (!(sbut = GetButtonFromId(sbar, uItem))) + return FALSE; + } + + //copy them across + *psb = *sbut; + + return FALSE; +} + +#else + +BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb) { return FALSE; } +BOOL WINAPI CoolSB_ModifyButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) { return FALSE; } +BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd) { return FALSE; } +BOOL WINAPI CoolSB_GetButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) { return FALSE; } + +#endif //INCLUDE_BUTTONS + +// +// Set the size of the scrollbars +// +BOOL WINAPI CoolSB_SetSize (HWND hwnd, int wBar, int nLength, int nWidth) +{ + SCROLLBAR *sbar; + + if(nLength == 0 || nWidth == 0) + return FALSE; + + if(nLength < -8 || nWidth < -8) + return FALSE; + + if(nLength > 256 || nWidth > 256) + return FALSE; + + if (!GetScrollWndFromHwnd(hwnd)) + return FALSE; + + if ((wBar == SB_HORZ || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ))) + { + sbar->nArrowLength = nLength; + sbar->nArrowWidth = nWidth; + } + + if ((wBar == SB_VERT || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT))) + { + sbar->nArrowLength = nLength; + sbar->nArrowWidth = nWidth; + } + + RedrawNonClient(hwnd, TRUE); + + return TRUE; +} + + +// +// Alter the display mode of the scrollbars +// wBar - SB_HORZ / SB_VERT / SB_BOTH +// nStyle - CSBF_NORMAL / CSBF_FLAT / CSBF_HOTTRACKED +// +BOOL WINAPI CoolSB_SetStyle(HWND hwnd, int wBar, UINT nStyle) +{ + SCROLLBAR *sbar; + + if (!GetScrollWndFromHwnd(hwnd)) + return FALSE; + + if ((wBar == SB_HORZ || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ))) + { + sbar->fFlatScrollbar = nStyle; + } + + if ((wBar == SB_VERT || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT))) + { + sbar->fFlatScrollbar = nStyle; + } + + RedrawNonClient(hwnd, FALSE); + + return TRUE; +} + +// +// Set if the thumb is always visible, even if there is no data to +// scroll. Setting this keeps the scrollbar enabled, but the thumb +// covers the whole area +// +BOOL WINAPI CoolSB_SetThumbAlways(HWND hwnd, int wBar, BOOL fThumbAlways) +{ + SCROLLBAR *sbar; + + if (!GetScrollWndFromHwnd(hwnd)) + return FALSE; + + if ((wBar == SB_HORZ || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ))) + { + if(fThumbAlways) + sbar->fScrollFlags |= CSBS_THUMBALWAYS; + else + sbar->fScrollFlags &= ~CSBS_THUMBALWAYS; + } + + if ((wBar == SB_VERT || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT))) + { + if(fThumbAlways) + sbar->fScrollFlags |= CSBS_THUMBALWAYS; + else + sbar->fScrollFlags &= ~CSBS_THUMBALWAYS; + } + + RedrawNonClient(hwnd, FALSE); + + return TRUE; +} + +// +// Set the minimum size, in pixels, that the thumb box will shrink to. +// +BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size) +{ + SCROLLBAR *sbar; + + if (!GetScrollWndFromHwnd(hwnd)) + return FALSE; + + if(size == -1) + size = CoolSB_GetDefaultMinThumbSize(); + + if ((wBar == SB_HORZ || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ))) + { + sbar->nMinThumbSize = size; + } + + if ((wBar == SB_VERT || wBar == SB_BOTH) && + (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT))) + { + sbar->nMinThumbSize = size; + } + + return TRUE; +} diff --git a/plugins/Clist_nicer/src/Coolsb/coolsblib.h b/plugins/Clist_nicer/src/Coolsb/coolsblib.h new file mode 100644 index 0000000000..d9b1c711f3 --- /dev/null +++ b/plugins/Clist_nicer/src/Coolsb/coolsblib.h @@ -0,0 +1,41 @@ +#ifndef _SUPERSCROLL_INCLUDED +#define _SUPERSCROLL_INCLUDED + +#ifdef __cplusplus +extern "C"{ +#endif + +#include + + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/Clist_nicer/src/Coolsb/coolscroll.cpp b/plugins/Clist_nicer/src/Coolsb/coolscroll.cpp new file mode 100644 index 0000000000..ac31f86c24 --- /dev/null +++ b/plugins/Clist_nicer/src/Coolsb/coolscroll.cpp @@ -0,0 +1,3206 @@ +/* + Cool Scrollbar Library Version 1.2 + + Module: coolscroll.c + Copyright (c) J Brown 2001 + + This code is freeware, however, you may not publish + this code elsewhere or charge any money for it. This code + is supplied as-is. I make no guarantees about the suitability + of this code - use at your own risk. + + It would be nice if you credited me, in the event + that you use this code in a product. + + VERSION HISTORY: + + V1.2: TreeView problem fixed by Diego Tartara + Small problem in thumbsize calculation also fixed (thanks Diego!) + + V1.1: Added support for Right-left windows + Changed calling convention of APIs to WINAPI (__stdcall) + Completely standalone (no need for c-runtime) + Now supports ALL windows with appropriate USER32.DLL patching + (you provide!!) + + V1.0: Apr 2001: Initial Version + + IMPORTANT: + This whole library is based around code for a horizontal scrollbar. + All "vertical" scrollbar drawing / mouse interaction uses the + horizontal scrollbar functions, but uses a trick to convert the vertical + scrollbar coordinates into horizontal equivelants. When I started this project, + I quickly realised that the code for horz/vert bars was IDENTICAL, apart + from the fact that horizontal code uses left/right coords, and vertical code + uses top/bottom coords. On entry to a "vertical" drawing function, for example, + the coordinates are "rotated" before the horizontal function is called, and + then rotated back once the function has completed. When something needs to + be drawn, the coords are converted back again before drawing. + + This trick greatly reduces the amount of code required, and makes + maintanence much simpler. This way, only one function is needed to draw + a scrollbar, but this can be used for both horizontal and vertical bars + with careful thought. +*/ + +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0501 + +#include +#include "coolscroll.h" +#include "userdefs.h" +#include "coolsb_internal.h" + +//define some values if the new version of common controls +//is not available. +#ifndef NM_CUSTOMDRAW +#define NM_CUSTOMDRAW (NM_FIRST-12) +#define CDRF_DODEFAULT 0x0000 +#define CDRF_SKIPDEFAULT 0x0004 +#define CDDS_PREPAINT 0x0001 +#define CDDS_POSTPAINT 0x0002 +#endif + +// +// Special thumb-tracking variables +// +// +static UINT uCurrentScrollbar = COOLSB_NONE; //SB_HORZ / SB_VERT +static UINT uCurrentScrollPortion = HTSCROLL_NONE; +static UINT uCurrentButton = 0; + +static RECT rcThumbBounds; //area that the scroll thumb can travel in +static int nThumbSize; //(pixels) +static int nThumbPos; //(pixels) +static int nThumbMouseOffset; //(pixels) +static int nLastPos = -1; //(scrollbar units) +static int nThumbPos0; //(pixels) initial thumb position + +// +// Temporary state used to auto-generate timer messages +// +static UINT_PTR uMouseOverId = 0; +static UINT uMouseOverScrollbar = COOLSB_NONE; +static UINT uHitTestPortion = HTSCROLL_NONE; +static UINT uLastHitTestPortion = HTSCROLL_NONE; +static RECT MouseOverRect; + +static UINT uScrollTimerMsg = 0; +static UINT uScrollTimerPortion = HTSCROLL_NONE; +static UINT_PTR uScrollTimerId = 0; +static HWND hwndCurCoolSB = 0; + +extern int CustomDrawScrollBars(NMCSBCUSTOMDRAW *nmcsbcd); + +// +// Provide this so there are NO dependencies on CRT +// +static void CoolSB_ZeroMemory(void *ptr, DWORD bytes) +{ + BYTE *bptr = (BYTE *)ptr; + + while(bytes--) *bptr++ = 0; +} + +BOOL WINAPI CoolSB_IsThumbTracking(HWND hwnd) +{ + SCROLLWND *sw; + + if ((sw = GetScrollWndFromHwnd(hwnd)) == NULL) + return FALSE; + else + return sw->fThumbTracking; +} + +// +// swap the rectangle's x coords with its y coords +// +static void __stdcall RotateRect(RECT *rect) +{ + int temp; + temp = rect->left; + rect->left = rect->top; + rect->top = temp; + + temp = rect->right; + rect->right = rect->bottom; + rect->bottom = temp; +} + +// +// swap the coords if the scrollbar is a SB_VERT +// +static void __stdcall RotateRect0(SCROLLBAR *sb, RECT *rect) +{ + if(sb->nBarType == SB_VERT) + RotateRect(rect); +} + +// +// Calculate if the SCROLLINFO members produce +// an enabled or disabled scrollbar +// +static BOOL IsScrollInfoActive(SCROLLINFO *si) +{ + if ((si->nPage > (UINT)si->nMax + || si->nMax <= si->nMin || si->nMax == 0)) + return FALSE; + else + return TRUE; +} + +// +// Return if the specified scrollbar is enabled or not +// +static BOOL IsScrollbarActive(SCROLLBAR *sb) +{ + SCROLLINFO *si = &sb->scrollInfo; + if (((sb->fScrollFlags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) || + !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(si)) + return FALSE; + else + return TRUE; +} + +// +// Draw a standard scrollbar arrow +// +static int DrawScrollArrow(SCROLLBAR *sbar, HDC hdc, RECT *rect, UINT arrow, BOOL fMouseDown, BOOL fMouseOver) +{ + UINT ret; + UINT flags = arrow; + + //HACKY bit so this routine can be called by vertical and horizontal code + if(sbar->nBarType == SB_VERT) + { + if(flags & DFCS_SCROLLLEFT) flags = flags & ~DFCS_SCROLLLEFT | DFCS_SCROLLUP; + if(flags & DFCS_SCROLLRIGHT) flags = flags & ~DFCS_SCROLLRIGHT | DFCS_SCROLLDOWN; + } + + if(fMouseDown) flags |= (DFCS_FLAT | DFCS_PUSHED); + +#ifdef FLAT_SCROLLBARS + if(sbar->fFlatScrollbar != CSBS_NORMAL) + { + HDC hdcmem1, hdcmem2; + HBITMAP hbm1, oldbm1; + HBITMAP hbm2, oldbm2; + RECT rc; + int width, height; + + rc = *rect; + width = rc.right-rc.left; + height = rc.bottom-rc.top; + SetRect(&rc, 0, 0, width, height); + + //MONOCHROME bitmap to convert the arrow to black/white mask + hdcmem1 = CreateCompatibleDC(hdc); + hbm1 = CreateBitmap(width, height, 1, 1, NULL); + UnrealizeObject(hbm1); + oldbm1 = reinterpret_cast(SelectObject(hdcmem1, hbm1)); + + + //NORMAL bitmap to draw the arrow into + hdcmem2 = CreateCompatibleDC(hdc); + hbm2 = CreateCompatibleBitmap(hdc, width, height); + UnrealizeObject(hbm2); + oldbm2 = reinterpret_cast(SelectObject(hdcmem2, hbm2)); + + + flags = flags & ~DFCS_PUSHED | DFCS_FLAT; //just in case + DrawFrameControl(hdcmem2, &rc, DFC_SCROLL, flags); + + +#ifndef HOT_TRACKING + if(fMouseDown) + { + //uncomment these to make the cool scrollbars + //look like the common controls flat scrollbars + //fMouseDown = FALSE; + //fMouseOver = TRUE; + } +#endif + //draw a flat monochrome version of a scrollbar arrow (dark) + if(fMouseDown) + { + SetBkColor(hdcmem2, GetSysColor(COLOR_BTNTEXT)); + BitBlt(hdcmem1, 0, 0, width, height, hdcmem2, 0, 0, SRCCOPY); + SetBkColor(hdc, 0x00ffffff); + SetTextColor(hdc, GetSysColor(COLOR_3DDKSHADOW)); + BitBlt(hdc, rect->left, rect->top, width, height, hdcmem1, 0, 0, SRCCOPY); + } + //draw a flat monochrome version of a scrollbar arrow (grey) + else if(fMouseOver) + { + SetBkColor(hdcmem2, GetSysColor(COLOR_BTNTEXT)); + FillRect(hdcmem1, &rc, reinterpret_cast(GetStockObject(WHITE_BRUSH))); + BitBlt(hdcmem1, 0, 0, width, height, hdcmem2, 0, 0, SRCINVERT); + + SetBkColor(hdc, GetSysColor(COLOR_3DSHADOW)); + SetTextColor(hdc, 0x00ffffff); + BitBlt(hdc, rect->left, rect->top, width, height, hdcmem1, 0, 0, SRCCOPY); + } + //draw the arrow normally + else + { + BitBlt(hdc, rect->left, rect->top, width, height, hdcmem2, 0, 0, SRCCOPY); + } + + SelectObject(hdcmem1, oldbm1); + SelectObject(hdcmem2, oldbm2); + DeleteObject(hbm1); + DeleteObject(hbm2); + DeleteDC(hdcmem1); + DeleteDC(hdcmem2); + + ret = 0; + } + else +#endif + ret = DrawFrameControl(hdc, rect, DFC_SCROLL, flags); + + return ret; +} + +// +// Return the size in pixels for the specified scrollbar metric, +// for the specified scrollbar +// +static int GetScrollMetric(SCROLLBAR *sbar, int metric) +{ + if(sbar->nBarType == SB_HORZ) + { + if(metric == SM_CXHORZSB) + { + if(sbar->nArrowLength < 0) + return -sbar->nArrowLength * GetSystemMetrics(SM_CXHSCROLL); + else + return sbar->nArrowLength; + } + else + { + if(sbar->nArrowWidth < 0) + return -sbar->nArrowWidth * GetSystemMetrics(SM_CYHSCROLL); + else + return sbar->nArrowWidth; + } + } + else if(sbar->nBarType == SB_VERT) + { + if(metric == SM_CYVERTSB) + { + if(sbar->nArrowLength < 0) + return -sbar->nArrowLength * GetSystemMetrics(SM_CYVSCROLL); + else + return sbar->nArrowLength; + } + else + { + if(sbar->nArrowWidth < 0) + return -sbar->nArrowWidth * GetSystemMetrics(SM_CXVSCROLL); + else + return sbar->nArrowWidth; + } + } + + return 0; +} + +// +// +// +static COLORREF GetSBForeColor(void) +{ + COLORREF c1 = GetSysColor(COLOR_3DHILIGHT); + COLORREF c2 = GetSysColor(COLOR_WINDOW); + + if(c1 != 0xffffff && c1 == c2) + { + return GetSysColor(COLOR_BTNFACE); + } + else + { + return GetSysColor(COLOR_3DHILIGHT); + } +} + +static COLORREF GetSBBackColor(void) +{ + return GetSysColor(COLOR_SCROLLBAR); +} + +// +// Paint a checkered rectangle, with each alternate +// pixel being assigned a different colour +// +static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg) +{ + static WORD wCheckPat[8] = + { + 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555 + }; + + HBITMAP hbmp; + HBRUSH hbr, hbrold; + COLORREF fgold, bgold; + + hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat); + hbr = CreatePatternBrush(hbmp); + + UnrealizeObject(hbr); + SetBrushOrgEx(hdc, rect->left, rect->top, 0); + + hbrold = (HBRUSH)SelectObject(hdc, hbr); + + fgold = SetTextColor(hdc, fg); + bgold = SetBkColor(hdc, bg); + + PatBlt(hdc, rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top, + PATCOPY); + + SetBkColor(hdc, bgold); + SetTextColor(hdc, fgold); + + SelectObject(hdc, hbrold); + DeleteObject(hbr); + DeleteObject(hbmp); +} + +// +// Fill the specifed rectangle using a solid colour +// +static void PaintRect(HDC hdc, RECT *rect, COLORREF color) +{ + COLORREF oldcol = SetBkColor(hdc, color); + ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, NULL); + SetBkColor(hdc, oldcol); +} + +// +// Draw a simple blank scrollbar push-button. Can be used +// to draw a push button, or the scrollbar thumb +// drawflag - could set to BF_FLAT to make flat scrollbars +// +void DrawBlankButton(HDC hdc, const RECT *rect, UINT drawflag) +{ + RECT rc = *rect; + +#ifndef FLAT_SCROLLBARS + drawflag &= ~BF_FLAT; +#endif + + DrawEdge(hdc, &rc, EDGE_RAISED, BF_RECT | drawflag | BF_ADJUST); + FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE)); +} + +// +// Send a WM_VSCROLL or WM_HSCROLL message +// +static void SendScrollMessage(HWND hwnd, UINT scrMsg, UINT scrId, UINT pos) +{ + SendMessage(hwnd, scrMsg, MAKEWPARAM(scrId, pos), 0); +} + +// +// Calculate the screen coordinates of the area taken by +// the horizontal scrollbar. Take into account the size +// of the window borders +// +static BOOL GetHScrollRect(SCROLLWND *sw, HWND hwnd, RECT *rect) +{ + GetWindowRect(hwnd, rect); + + if(sw->fLeftScrollbar) + { + rect->left += sw->cxLeftEdge + (sw->sbarVert.fScrollVisible ? + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0); + rect->right -= sw->cxRightEdge; + } + else + { + rect->left += sw->cxLeftEdge; //left window edge + + rect->right -= sw->cxRightEdge + //right window edge + (sw->sbarVert.fScrollVisible ? + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0); + } + + rect->bottom -= sw->cyBottomEdge; //bottom window edge + + rect->top = rect->bottom - + (sw->sbarHorz.fScrollVisible ? + GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0); + + return TRUE; +} + +// +// Calculate the screen coordinates of the area taken by the +// vertical scrollbar +// +static BOOL GetVScrollRect(SCROLLWND *sw, HWND hwnd, RECT *rect) +{ + GetWindowRect(hwnd, rect); + rect->top += sw->cyTopEdge; //top window edge + + rect->bottom -= sw->cyBottomEdge + + (sw->sbarHorz.fScrollVisible ? //bottom window edge + GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0); + + if(sw->fLeftScrollbar) + { + rect->left += sw->cxLeftEdge; + rect->right = rect->left + (sw->sbarVert.fScrollVisible ? + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0); + } + else + { + rect->right -= sw->cxRightEdge; + rect->left = rect->right - (sw->sbarVert.fScrollVisible ? + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0); + } + + return TRUE; +} + +// Depending on what type of scrollbar nBar refers to, call the +// appropriate Get?ScrollRect function +// +BOOL GetScrollRect(SCROLLWND *sw, UINT nBar, HWND hwnd, RECT *rect) +{ + if(nBar == SB_HORZ) + return GetHScrollRect(sw, hwnd, rect); + else if(nBar == SB_VERT) + return GetVScrollRect(sw, hwnd, rect); + else + return FALSE; +} + +// +// This code is a prime candidate for splitting out into a separate +// file at some stage +// +#ifdef INCLUDE_BUTTONS + +// +// Calculate the size in pixels of the specified button +// +static int GetSingleButSize(SCROLLBAR *sbar, SCROLLBUT *sbut) +{ + //multiple of the system button size + //or a specific button size + if(sbut->nSize < 0) + { + if(sbar->nBarType == SB_HORZ) + return -sbut->nSize * GetSystemMetrics(SM_CXHSCROLL); + else + return -sbut->nSize * GetSystemMetrics(SM_CYVSCROLL); + } + else + return sbut->nSize; +} + +// +// Find the size in pixels of all the inserted buttons, +// either before or after the specified scrollbar +// +static int GetButtonSize(SCROLLBAR *sbar, HWND hwnd, UINT uBeforeAfter) +{ + int i; + int nPixels = 0; + + SCROLLBUT *sbut = sbar->sbButtons; + + for (i = 0; i < sbar->nButtons; i++) + { + //only consider those buttons on the same side as nTopBottom says + if(sbut[i].uPlacement == uBeforeAfter) + { + nPixels += GetSingleButSize(sbar, &sbut[i]); + } + } + + return nPixels; +} +#endif //INCLUDE_BUTTONS + +// +// Work out the scrollbar width/height for either type of scrollbar (SB_HORZ/SB_VERT) +// rect - coords of the scrollbar. +// store results into *thumbsize and *thumbpos +// +static int CalcThumbSize(SCROLLBAR *sbar, const RECT *rect, int *pthumbsize, int *pthumbpos) +{ + SCROLLINFO *si; + int scrollsize; //total size of the scrollbar including arrow buttons + int workingsize; //working area (where the thumb can slide) + int siMaxMin; + int butsize; + int startcoord; + int thumbpos = 0, thumbsize = 0; + + int adjust=0; + static int count=0; + + //work out the width (for a horizontal) or the height (for a vertical) + //of a standard scrollbar button + butsize = GetScrollMetric(sbar, SM_SCROLL_LENGTH); + + if(1) //sbar->nBarType == SB_HORZ) + { + scrollsize = rect->right - rect->left; + startcoord = rect->left; + } + /*else if(sbar->nBarType == SB_VERT) + { + scrollsize = rect->bottom - rect->top; + startcoord = rect->top; + } + else + { + return 0; + }*/ + + si = &sbar->scrollInfo; + siMaxMin = si->nMax - si->nMin + 1; + workingsize = scrollsize - butsize * 2; + + // + // Work out the scrollbar thumb SIZE + // + if(si->nPage == 0) + { + thumbsize = butsize; + } + else if(siMaxMin > 0) + { + thumbsize = MulDiv(si->nPage, workingsize, siMaxMin); + + if(thumbsize < sbar->nMinThumbSize) + thumbsize = sbar->nMinThumbSize; + } + + // + // Work out the scrollbar thumb position + // + if(siMaxMin > 0) + { + int pagesize = max(1, si->nPage); + thumbpos = MulDiv(si->nPos - si->nMin, workingsize-thumbsize, siMaxMin - pagesize); + + if(thumbpos < 0) + thumbpos = 0; + + if(thumbpos >= workingsize-thumbsize) + thumbpos = workingsize-thumbsize; + } + + thumbpos += startcoord + butsize; + + *pthumbpos = thumbpos; + *pthumbsize = thumbsize; + + return 1; +} + +// +// return a hit-test value for whatever part of the scrollbar x,y is located in +// rect, x, y: SCREEN coordinates +// the rectangle must not include space for any inserted buttons +// (i.e, JUST the scrollbar area) +// +static UINT GetHorzScrollPortion(SCROLLBAR *sbar, HWND hwnd, const RECT *rect, int x, int y) +{ + int thumbwidth, thumbpos; + int butwidth = GetScrollMetric(sbar, SM_SCROLL_LENGTH); + int scrollwidth = rect->right-rect->left; + int workingwidth = scrollwidth - butwidth*2; + + if(y < rect->top || y >= rect->bottom) + return HTSCROLL_NONE; + + CalcThumbSize(sbar, rect, &thumbwidth, &thumbpos); + + //if we have had to scale the buttons to fit in the rect, + //then adjust the button width accordingly + if(scrollwidth <= butwidth * 2) + { + butwidth = scrollwidth / 2; + } + + //check for left button click + if(x >= rect->left && x < rect->left + butwidth) + { + return HTSCROLL_LEFT; + } + //check for right button click + else if(x >= rect->right-butwidth && x < rect->right) + { + return HTSCROLL_RIGHT; + } + + //if the thumb is too big to fit (i.e. it isn't visible) + //then return a NULL scrollbar area + if(thumbwidth >= workingwidth) + return HTSCROLL_NONE; + + //check for point in the thumbbar + if(x >= thumbpos && x < thumbpos+thumbwidth) + { + return HTSCROLL_THUMB; + } + //check for left margin + else if(x >= rect->left+butwidth && x < thumbpos) + { + return HTSCROLL_PAGELEFT; + } + else if(x >= thumbpos+thumbwidth && x < rect->right-butwidth) + { + return HTSCROLL_PAGERIGHT; + } + + return HTSCROLL_NONE; +} + +// +// For vertical scrollbars, rotate all coordinates by -90 degrees +// so that we can use the horizontal version of this function +// +static UINT GetVertScrollPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y) +{ + UINT r; + + RotateRect(rect); + r = GetHorzScrollPortion(sb, hwnd, rect, y, x); + RotateRect(rect); + return r; +} + +// +// CUSTOM DRAW support +// +static LRESULT PostCustomPrePostPaint(HWND hwnd, HDC hdc, SCROLLBAR *sb, UINT dwStage) +{ +#ifdef CUSTOM_DRAW + NMCSBCUSTOMDRAW nmcd; + + CoolSB_ZeroMemory(&nmcd, sizeof nmcd); + nmcd.hdr.hwndFrom = hwnd; + nmcd.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID); + nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW; + nmcd.nBar = sb->nBarType; + nmcd.dwDrawStage = dwStage; + nmcd.hdc = hdc; + + hwnd = GetParent(hwnd); + return CustomDrawScrollBars(&nmcd); +#else + return 0; +#endif +} + +static LRESULT PostCustomDrawNotify(HWND hwnd, HDC hdc, UINT nBar, RECT *prect, UINT nItem, BOOL fMouseDown, BOOL fMouseOver, BOOL fInactive) +{ +#ifdef CUSTOM_DRAW + NMCSBCUSTOMDRAW nmcd; + + //fill in the standard header + nmcd.hdr.hwndFrom = hwnd; + nmcd.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID); + nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW; + + nmcd.dwDrawStage = CDDS_ITEMPREPAINT; + nmcd.nBar = nBar; + nmcd.rect = *prect; + nmcd.uItem = nItem; + nmcd.hdc = hdc; + + if(fMouseDown) + nmcd.uState = CDIS_SELECTED; + else if(fMouseOver) + nmcd.uState = CDIS_HOT; + else if(fInactive) + nmcd.uState = CDIS_DISABLED; + else + nmcd.uState = CDIS_DEFAULT; + + hwnd = GetParent(hwnd); + return CustomDrawScrollBars(&nmcd); +#else + return 0; +#endif +} + +// Depending on if we are supporting custom draw, either define +// a macro to the function name, or to nothing at all. If custom draw +// is turned off, then we can save ALOT of code space by binning all +// calls to the custom draw support. + +/* +#ifdef CUSTOM_DRAW +#define PostCustomDrawNotify PostCustomDrawNotify0 +#define PostCustomPrePostPaint PostCustomPrePostPaint0 +#else +#define PostCustomDrawNotify 1 ? (void)0 : PostCustomDrawNotify0 +#define PostCustomPrePostPaint 1 ? (void)0 : PostCustomPrePostPaint0 +#endif +*/ + +static LRESULT PostMouseNotify0(HWND hwnd, UINT msg, UINT nBar, RECT *prect, UINT nCmdId, POINT pt) +{ +#ifdef NOTIFY_MOUSE + NMCOOLBUTMSG nmcb; + + //fill in the standard header + nmcb.hdr.hwndFrom = hwnd; + nmcb.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID); + nmcb.hdr.code = NM_CLICK; + + nmcb.nBar = nBar; + nmcb.uCmdId = nCmdId; + nmcb.uState = 0; + nmcb.rect = *prect; + nmcb.pt = pt; + + hwnd = GetParent(hwnd); + return SendMessage(hwnd, WM_NOTIFY, nmcb.hdr.idFrom, (LPARAM)&nmcb); +#else + return 0; +#endif +} + +#ifdef NOTIFY_MOUSE +#define PostMouseNotify PostMouseNotify0 +#else +#define PostMouseNotify 1 ? (void)0 : PostMouseNotify0 +#endif + + + +// +// Draw a complete HORIZONTAL scrollbar in the given rectangle +// Don't draw any inserted buttons in this procedure +// +// uDrawFlags - hittest code, to say if to draw the +// specified portion in an active state or not. +// +// +static LRESULT NCDrawHScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags) +{ + SCROLLINFO *si; + RECT ctrl, thumb; + RECT sbm; + int butwidth = GetScrollMetric(sb, SM_SCROLL_LENGTH); + int scrollwidth = rect->right-rect->left; + int workingwidth = scrollwidth - butwidth*2; + int thumbwidth = 0, thumbpos = 0; + int siMaxMin; + + BOOL fCustomDraw = 0; + + BOOL fMouseDownL = 0, fMouseOverL = 0, fBarHot = 0; + BOOL fMouseDownR = 0, fMouseOverR = 0; + + COLORREF crCheck1 = GetSBForeColor(); + COLORREF crCheck2 = GetSBBackColor(); + COLORREF crInverse1 = InvertCOLORREF(crCheck1); + COLORREF crInverse2 = InvertCOLORREF(crCheck2); + + UINT uDFCFlat = sb->fFlatScrollbar ? DFCS_FLAT : 0; + UINT uDEFlat = sb->fFlatScrollbar ? BF_FLAT : 0; + + //drawing flags to modify the appearance of the scrollbar buttons + UINT uLeftButFlags = DFCS_SCROLLLEFT; + UINT uRightButFlags = DFCS_SCROLLRIGHT; + + if(scrollwidth <= 0) + return 0; + + si = &sb->scrollInfo; + siMaxMin = si->nMax - si->nMin; + + if(hwnd != hwndCurCoolSB) + uDrawFlags = HTSCROLL_NONE; + // + // work out the thumb size and position + // + CalcThumbSize(sb, rect, &thumbwidth, &thumbpos); + + if(sb->fScrollFlags & ESB_DISABLE_LEFT) uLeftButFlags |= DFCS_INACTIVE; + if(sb->fScrollFlags & ESB_DISABLE_RIGHT) uRightButFlags |= DFCS_INACTIVE; + + //if we need to grey the arrows because there is no data to scroll + if (!IsScrollInfoActive(si) && !(sb->fScrollFlags & CSBS_THUMBALWAYS)) + { + uLeftButFlags |= DFCS_INACTIVE; + uRightButFlags |= DFCS_INACTIVE; + } + + if(hwnd == hwndCurCoolSB) + { +#ifdef FLAT_SCROLLBARS + BOOL ldis = !(uLeftButFlags & DFCS_INACTIVE); + BOOL rdis = !(uRightButFlags & DFCS_INACTIVE); + + fBarHot = (sb->nBarType == (int)uMouseOverScrollbar && sb->fFlatScrollbar == CSBS_HOTTRACKED); + + fMouseOverL = uHitTestPortion == HTSCROLL_LEFT && fBarHot && ldis; + fMouseOverR = uHitTestPortion == HTSCROLL_RIGHT && fBarHot && rdis; +#endif + fMouseDownL = (uDrawFlags == HTSCROLL_LEFT); + fMouseDownR = (uDrawFlags == HTSCROLL_RIGHT); + } + + +//#ifdef CUSTOM_DRAW + fCustomDraw = ((PostCustomPrePostPaint(hwnd, hdc, sb, CDDS_PREPAINT)) == CDRF_SKIPDEFAULT); +//#endif + + // + // Draw the scrollbar now + // + if(scrollwidth > butwidth*2) + { + //LEFT ARROW + SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom); + + RotateRect0(sb, &ctrl); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE); + else + DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL); + + RotateRect0(sb, &ctrl); + + //MIDDLE PORTION + //if we can fit the thumbbar in, then draw it + if(thumbwidth > 0 && thumbwidth <= workingwidth + && IsScrollInfoActive(si) && ((sb->fScrollFlags & ESB_DISABLE_BOTH) != ESB_DISABLE_BOTH)) + { + //Draw the scrollbar margin above the thumb + SetRect(&sbm, rect->left + butwidth, rect->top, thumbpos, rect->bottom); + + RotateRect0(sb, &sbm); + + if(fCustomDraw) + { + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGELEFT, uDrawFlags == HTSCROLL_PAGELEFT, FALSE, FALSE); + } + else + { + if(uDrawFlags == HTSCROLL_PAGELEFT) + DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2); + else + DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2); + + } + + RotateRect0(sb, &sbm); + + //Draw the margin below the thumb + sbm.left = thumbpos+thumbwidth; + sbm.right = rect->right - butwidth; + + RotateRect0(sb, &sbm); + if(fCustomDraw) + { + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGERIGHT, uDrawFlags == HTSCROLL_PAGERIGHT, 0, 0); + } + else + { + if(uDrawFlags == HTSCROLL_PAGERIGHT) + DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2); + else + DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2); + + } + RotateRect0(sb, &sbm); + + //Draw the THUMB finally + SetRect(&thumb, thumbpos, rect->top, thumbpos+thumbwidth, rect->bottom); + + RotateRect0(sb, &thumb); + + if(fCustomDraw) + { + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &thumb, SB_THUMBTRACK, uDrawFlags==HTSCROLL_THUMB, uHitTestPortion == HTSCROLL_THUMB && fBarHot, FALSE); + } + else + { + +#ifdef FLAT_SCROLLBARS + if(hwnd == hwndCurCoolSB && sb->fFlatScrollbar && (uDrawFlags == HTSCROLL_THUMB || + (uHitTestPortion == HTSCROLL_THUMB && fBarHot))) + { + PaintRect(hdc, &thumb, GetSysColor(COLOR_3DSHADOW)); + } + else +#endif + { + DrawBlankButton(hdc, &thumb, uDEFlat); + } + } + RotateRect0(sb, &thumb); + + } + //otherwise, just leave that whole area blank + else + { + OffsetRect(&ctrl, butwidth, 0); + ctrl.right = rect->right - butwidth; + + //if we always show the thumb covering the whole scrollbar, + //then draw it that way + if (!IsScrollInfoActive(si) && (sb->fScrollFlags & CSBS_THUMBALWAYS) + && ctrl.right - ctrl.left > sb->nMinThumbSize) + { + //leave a 1-pixel gap between the thumb + right button + ctrl.right --; + RotateRect0(sb, &ctrl); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_THUMBTRACK, fMouseDownL, FALSE, FALSE); + else + { +#ifdef FLAT_SCROLLBARS + if(sb->fFlatScrollbar == CSBS_HOTTRACKED && uDrawFlags == HTSCROLL_THUMB) + PaintRect(hdc, &ctrl, GetSysColor(COLOR_3DSHADOW)); + else +#endif + DrawBlankButton(hdc, &ctrl, uDEFlat); + + } + RotateRect0(sb, &ctrl); + + //draw the single-line gap + ctrl.left = ctrl.right; + ctrl.right += 1; + + RotateRect0(sb, &ctrl); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0); + else + PaintRect(hdc, &ctrl, GetSysColor(COLOR_SCROLLBAR)); + + RotateRect0(sb, &ctrl); + } + //otherwise, paint a blank if the thumb doesn't fit in + else + { + RotateRect0(sb, &ctrl); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0); + else + DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2); + + RotateRect0(sb, &ctrl); + } + } + + //RIGHT ARROW + SetRect(&ctrl, rect->right - butwidth, rect->top, rect->right, rect->bottom); + + RotateRect0(sb, &ctrl); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE); + else + DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR); + + RotateRect0(sb, &ctrl); + } + //not enough room for the scrollbar, so just draw the buttons (scaled in size to fit) + else + { + butwidth = scrollwidth / 2; + + //LEFT ARROW + SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom); + + RotateRect0(sb, &ctrl); + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE); + else + DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL); + RotateRect0(sb, &ctrl); + + //RIGHT ARROW + OffsetRect(&ctrl, scrollwidth - butwidth, 0); + + RotateRect0(sb, &ctrl); + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE); + else + DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR); + RotateRect0(sb, &ctrl); + + //if there is a gap between the buttons, fill it with a solid color + //if(butwidth & 0x0001) + if(ctrl.left != rect->left + butwidth) + { + ctrl.left --; + ctrl.right -= butwidth; + RotateRect0(sb, &ctrl); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0); + else + DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2); + + RotateRect0(sb, &ctrl); + } + + } + +//#ifdef CUSTOM_DRAW + PostCustomPrePostPaint(hwnd, hdc, sb, CDDS_POSTPAINT); +//#endif + + return fCustomDraw; +} + +// +// Draw a vertical scrollbar using the horizontal draw routine, but +// with the coordinates adjusted accordingly +// +static LRESULT NCDrawVScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags) +{ + LRESULT ret; + RECT rc; + + rc = *rect; + RotateRect(&rc); + ret = NCDrawHScrollbar(sb, hwnd, hdc, &rc, uDrawFlags); + RotateRect(&rc); + + return ret; +} + +// +// Generic wrapper function for the scrollbar drawing +// +static LRESULT NCDrawScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags) +{ + if(sb->nBarType == SB_HORZ) + return NCDrawHScrollbar(sb, hwnd, hdc, rect, uDrawFlags); + else + return NCDrawVScrollbar(sb, hwnd, hdc, rect, uDrawFlags); +} + +#ifdef INCLUDE_BUTTONS + +// +// Draw the specified bitmap centered in the rectangle +// +static void DrawImage(HDC hdc, HBITMAP hBitmap, RECT *rc) +{ + BITMAP bm; + int cx; + int cy; + HDC memdc; + HBITMAP hOldBM; + RECT rcDest = *rc; + POINT p; + SIZE delta; + COLORREF colorOld; + + if(hBitmap == NULL) + return; + + // center bitmap in caller's rectangle + GetObject(hBitmap, sizeof bm, &bm); + + cx = bm.bmWidth; + cy = bm.bmHeight; + + delta.cx = (rc->right-rc->left - cx) / 2; + delta.cy = (rc->bottom-rc->top - cy) / 2; + + if(rc->right-rc->left > cx) + { + SetRect(&rcDest, rc->left+delta.cx, rc->top + delta.cy, 0, 0); + rcDest.right = rcDest.left + cx; + rcDest.bottom = rcDest.top + cy; + p.x = 0; + p.y = 0; + } + else + { + p.x = -delta.cx; + p.y = -delta.cy; + } + + // select checkmark into memory DC + memdc = CreateCompatibleDC(hdc); + hOldBM = (HBITMAP)SelectObject(memdc, hBitmap); + + // set BG color based on selected state + colorOld = SetBkColor(hdc, GetSysColor(COLOR_3DFACE)); + + BitBlt(hdc, rcDest.left, rcDest.top, rcDest.right-rcDest.left, rcDest.bottom-rcDest.top, memdc, p.x, p.y, SRCCOPY); + + // restore + SetBkColor(hdc, colorOld); + SelectObject(memdc, hOldBM); + DeleteDC(memdc); +} + +// +// Draw the specified metafile +// +static void DrawMetaFile(HDC hdc, HENHMETAFILE hemf, RECT *rect) +{ + RECT rc; + POINT pt; + + SetRect(&rc, 0, 0, rect->right-rect->left, rect->bottom-rect->top); + SetWindowOrgEx(hdc, -rect->left, -rect->top, &pt); + PlayEnhMetaFile(hdc, hemf, &rc); + SetWindowOrgEx(hdc, pt.x, pt.y, 0); +} + +// +// Draw a single scrollbar inserted button, in whatever style +// it has been defined to use. +// +static UINT DrawScrollButton(SCROLLBUT *sbut, HDC hdc, const RECT *pctrl, UINT flags) +{ + NMCSBCUSTOMDRAW nmcd; + HWND hwnd; + RECT rect = *pctrl; + UINT f; + + switch(sbut->uButType & SBBT_MASK) + { + case SBBT_OWNERDRAW: + + hwnd = WindowFromDC(hdc); + + //fill in the standard header + nmcd.hdr.hwndFrom = hwnd; + nmcd.hdr.idFrom = GetWindowLongPtr(hwnd, GWLP_ID); + nmcd.hdr.code = NM_COOLSB_CUSTOMDRAW; + + nmcd.dwDrawStage = CDDS_ITEMPREPAINT; + nmcd.nBar = SB_INSBUT; + nmcd.rect = *pctrl; + nmcd.uItem = sbut->uCmdId; + nmcd.hdc = hdc; + nmcd.uState = flags; + + IntersectClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom); + SendMessage(GetParent(hwnd), WM_NOTIFY, nmcd.hdr.idFrom, (LPARAM)&nmcd); + SelectClipRgn(hdc, NULL); + + break; + + case SBBT_FIXED: + flags &= ~SBBS_PUSHED; + + case SBBT_TOGGLEBUTTON: + if(sbut->uState != SBBS_NORMAL) + flags |= SBBS_PUSHED; + + //intentionally fall through here... + + case SBBT_PUSHBUTTON: + + f = flags & SBBS_PUSHED ? DFCS_PUSHED | DFCS_FLAT : 0; + if(sbut->uButType & SBBM_LEFTARROW) + { + DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLLEFT | f); + } + else if(sbut->uButType & SBBM_RIGHTARROW) + { + DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLRIGHT | f); + } + else if(sbut->uButType & SBBM_UPARROW) + { + DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLUP | f); + } + else if(sbut->uButType & SBBM_DOWNARROW) + { + DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | f); + } + else + { + // + if(flags & SBBS_PUSHED) + { + if(sbut->uButType & SBBM_RECESSED) + { + InflateRect(&rect, -1, -1); + DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT|BF_FLAT); + InflateRect(&rect, 1, 1); + + FrameRect(hdc, &rect, GetSysColorBrush(COLOR_3DDKSHADOW)); + InflateRect(&rect, -2, -2); + } + else + { + DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_FLAT | BF_ADJUST); + InflateRect(&rect, 1, 1); + } + } + else + { + // draw the button borders + if(sbut->uButType & SBBM_TYPE2) + { + DrawFrameControl(hdc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH); + InflateRect(&rect, -2, -2); + } + + else if(sbut->uButType & SBBM_TYPE3) + { + DrawFrameControl(hdc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH); + InflateRect(&rect, -1, -1); + } + else + { + DrawEdge(hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST); + rect.bottom++; + rect.right++; + } + + OffsetRect(&rect, -1, -1); + rect.top++; rect.left++; + } + + if(sbut->hBmp) + { + PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE)); + + if(flags & SBBS_PUSHED) + { + rect.top++; rect.left++; + } + + IntersectClipRect(hdc, rect.left, rect.top, rect.right,rect.bottom); + DrawImage(hdc, sbut->hBmp, &rect); + SelectClipRgn(hdc, 0); + } + else if(sbut->hEmf) + { + PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE)); + InflateRect(&rect, -1, -1); + + if(flags & SBBS_PUSHED) + { + rect.top++; rect.left++; + } + + IntersectClipRect(hdc, rect.left, rect.top, rect.right,rect.bottom); + DrawMetaFile(hdc, sbut->hEmf, &rect); + SelectClipRgn(hdc, 0); + } + else + { + PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE)); + } + } + + + break; + + case SBBT_BLANK: + PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE)); + break; + + case SBBT_FLAT: + DrawBlankButton(hdc, &rect, BF_FLAT); + break; + + case SBBT_DARK: + PaintRect(hdc, &rect, GetSysColor(COLOR_3DDKSHADOW)); + break; + } + + return 0; +} + +// +// Draw any buttons inserted into the horizontal scrollbar +// assume that the button widths have already been calculated +// Note: RECT *rect is the rectangle of the scrollbar +// leftright: 1 = left, 2 = right, 3 = both +// +static LRESULT DrawHorzButtons(SCROLLBAR *sbar, HDC hdc, const RECT *rect, int leftright) +{ + int i; + int xposl, xposr; + RECT ctrl; + SCROLLBUT *sbut = sbar->sbButtons; + + xposl = rect->left - sbar->nButSizeBefore; + xposr = rect->right; + + for (i = 0; i < sbar->nButtons; i++) + { + if ((leftright & SBBP_LEFT) && sbut[i].uPlacement == SBBP_LEFT) + { + int butwidth = GetSingleButSize(sbar, &sbut[i]); + SetRect(&ctrl, xposl, rect->top, xposl + butwidth, rect->bottom); + RotateRect0(sbar, &ctrl); + DrawScrollButton(&sbut[i], hdc, &ctrl, SBBS_NORMAL); + + xposl += butwidth; + } + + if ((leftright & SBBP_RIGHT) && sbut[i].uPlacement == SBBP_RIGHT) + { + int butwidth = GetSingleButSize(sbar, &sbut[i]); + SetRect(&ctrl, xposr, rect->top, xposr + butwidth, rect->bottom); + RotateRect0(sbar, &ctrl); + DrawScrollButton(&sbut[i], hdc, &ctrl, SBBS_NORMAL); + xposr += butwidth; + } + } + return 0; +} + +static LRESULT DrawVertButtons(SCROLLBAR *sbar, HDC hdc, const RECT *rect, int leftright) +{ + RECT rc = *rect; + RotateRect(&rc); + DrawHorzButtons(sbar, hdc, &rc, leftright); + return 0; +} +#endif // INCLUDE_BUTTONS + +// +// Define these two for proper processing of NCPAINT +// NOT needed if we don't bother to mask the scrollbars we draw +// to prevent the old window procedure from accidently drawing over them +// +HDC CoolSB_GetDC(HWND hwnd, WPARAM wParam) +{ + // I just can't figure out GetDCEx, so I'll just use this: + return GetWindowDC(hwnd); + + /* + RECT rc; + DWORD flags = 0x10000; + HRGN hrgn = (HRGN)wParam; + + if(hrgn == (HRGN)1) + { + GetWindowRect(hwnd, &rc); + OffsetRect(&rc, -rc.left, -rc.top); + hrgn = CreateRectRgnIndirect(&rc); + } + + if(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CLIPCHILDREN) + flags |= DCX_CLIPCHILDREN; + + if(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CLIPSIBLINGS) + flags |= DCX_CLIPSIBLINGS; + + return GetDCEx(hwnd, hrgn, flags | DCX_CACHE|DCX_NORESETATTRS|DCX_WINDOW | DCX_INTERSECTUPDATE); + */ + //return GetDCEx(hwnd, NULL, flags | DCX_WINDOW| DCX_NORESETATTRS); +} + +static LRESULT NCPaint(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + SCROLLBAR *sb; + HDC hdc; + HRGN hrgn; + RECT winrect, rect; + HRGN clip = 0; + BOOL fUpdateAll = ((LONG)wParam == 1); + BOOL fCustomDraw = FALSE; + LRESULT ret; + DWORD dwStyle; + + GetWindowRect(hwnd, &winrect); + + //if entire region needs painting, then make a region to cover the entire window + if(fUpdateAll) + hrgn = (HRGN)wParam; + else + hrgn = (HRGN)wParam; + + //hdc = GetWindowDC(hwnd); + hdc = CoolSB_GetDC(hwnd, wParam); + + // + // Only draw the horizontal scrollbar if the window is tall enough + // + sb = &sw->sbarHorz; + if(sb->fScrollVisible) + { + int hbarwidth = 0, leftright = 0; + + //get the screen coordinates of the whole horizontal scrollbar area + GetHScrollRect(sw, hwnd, &rect); + + //make the coordinates relative to the window for drawing + OffsetRect(&rect, -winrect.left, -winrect.top); + +#ifdef INCLUDE_BUTTONS + + //work out the size of any inserted buttons so we can dra them + sb->nButSizeBefore = GetButtonSize(sb, hwnd, SBBP_LEFT); + sb->nButSizeAfter = GetButtonSize(sb, hwnd, SBBP_RIGHT); + + //make sure there is room for the buttons + hbarwidth = rect.right - rect.left; + + //check that we can fit any left/right buttons in the available space + if(sb->nButSizeAfter < (hbarwidth - MIN_COOLSB_SIZE)) + { + //adjust the scrollbar rectangle to fit the buttons into + sb->fButVisibleAfter = TRUE; + rect.right -= sb->nButSizeAfter; + leftright |= SBBP_RIGHT; + + //check that there is enough space for the right buttons + if(sb->nButSizeBefore + sb->nButSizeAfter < (hbarwidth - MIN_COOLSB_SIZE)) + { + sb->fButVisibleBefore = TRUE; + rect.left += sb->nButSizeBefore; + leftright |= SBBP_LEFT; + } + else + sb->fButVisibleBefore = FALSE; + } + else + sb->fButVisibleAfter = FALSE; + + + DrawHorzButtons(sb, hdc, &rect, leftright); +#endif// INCLUDE_BUTTONS + + if(uCurrentScrollbar == SB_HORZ) + fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion); + else + fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE); + } + + // + // Only draw the vertical scrollbar if the window is wide enough to accomodate it + // + sb = &sw->sbarVert; + if(sb->fScrollVisible) + { + int vbarheight = 0, updown = 0; + + //get the screen cooridinates of the whole horizontal scrollbar area + GetVScrollRect(sw, hwnd, &rect); + + //make the coordinates relative to the window for drawing + OffsetRect(&rect, -winrect.left, -winrect.top); + +#ifdef INCLUDE_BUTTONS + + //work out the size of any inserted buttons so we can dra them + sb->nButSizeBefore = GetButtonSize(sb, hwnd, SBBP_LEFT); + sb->nButSizeAfter = GetButtonSize(sb, hwnd, SBBP_RIGHT); + + //make sure there is room for the buttons + vbarheight = rect.bottom - rect.top; + + //check that we can fit any left/right buttons in the available space + if(sb->nButSizeAfter < (vbarheight - MIN_COOLSB_SIZE)) + { + //adjust the scrollbar rectangle to fit the buttons into + sb->fButVisibleAfter = TRUE; + rect.bottom -= sb->nButSizeAfter; + updown |= SBBP_BOTTOM; + + //check that there is enough space for the right buttons + if(sb->nButSizeBefore + sb->nButSizeAfter < (vbarheight - MIN_COOLSB_SIZE)) + { + sb->fButVisibleBefore = TRUE; + rect.top += sb->nButSizeBefore; + updown |= SBBP_TOP; + } + else + sb->fButVisibleBefore = FALSE; + } + else + sb->fButVisibleAfter = FALSE; + + + DrawVertButtons(sb, hdc, &rect, updown); +#endif // INCLUDE_BUTTONS + + if(uCurrentScrollbar == SB_VERT) + fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion); + else + fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE); + } + + //Call the default window procedure for WM_NCPAINT, with the + //new window region. ** region must be in SCREEN coordinates ** + dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + + // If the window has WS_(H-V)SCROLL bits set, we should reset them + // to avoid windows taking the scrollbars into account. + // We temporarily set a flag preventing the subsecuent + // WM_STYLECHANGING/WM_STYLECHANGED to be forwarded to + // the original window procedure + if ( dwStyle & (WS_VSCROLL|WS_HSCROLL)) + { + sw->bPreventStyleChange = TRUE; + SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL|WS_HSCROLL)); + } + + ret = CallWindowProc(sw->oldproc, hwnd, WM_NCPAINT, (WPARAM)hrgn, lParam); + + if ( dwStyle & (WS_VSCROLL|WS_HSCROLL)) + { + SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle); + sw->bPreventStyleChange = FALSE; + } + + + // DRAW THE DEAD AREA + // only do this if the horizontal and vertical bars are visible + if(sw->sbarHorz.fScrollVisible && sw->sbarVert.fScrollVisible) + { + GetWindowRect(hwnd, &rect); + OffsetRect(&rect, -winrect.left, -winrect.top); + + rect.bottom -= sw->cyBottomEdge; + rect.top = rect.bottom - GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB); + + if(sw->fLeftScrollbar) + { + rect.left += sw->cxLeftEdge; + rect.right = rect.left + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB); + } + else + { + rect.right -= sw->cxRightEdge; + rect.left = rect.right - GetScrollMetric(&sw->sbarVert, SM_CXVERTSB); + } + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, SB_BOTH, &rect, 32, 0, 0, 0); + else + { + //calculate the position of THIS window's dead area + //with the position of the PARENT window's client rectangle. + //if THIS window has been positioned such that its bottom-right + //corner sits in the parent's bottom-right corner, then we should + //show the sizing-grip. + //Otherwise, assume this window is not in the right place, and + //just draw a blank rectangle + RECT parent; + RECT rect2; + HWND hwndParent = GetParent(hwnd); + + GetClientRect(hwndParent, &parent); + MapWindowPoints(hwndParent, 0, (POINT *)&parent, 2); + + CopyRect(&rect2, &rect); + OffsetRect(&rect2, winrect.left, winrect.top); + + if (!sw->fLeftScrollbar && parent.right == rect2.right+sw->cxRightEdge && parent.bottom == rect2.bottom+sw->cyBottomEdge + || sw->fLeftScrollbar && parent.left == rect2.left -sw->cxLeftEdge && parent.bottom == rect2.bottom+sw->cyBottomEdge) + DrawFrameControl(hdc, &rect, DFC_SCROLL, sw->fLeftScrollbar ? DFCS_SCROLLSIZEGRIPRIGHT : DFCS_SCROLLSIZEGRIP ); + else + PaintRect(hdc, &rect, GetSysColor(COLOR_3DFACE)); + } + } + + UNREFERENCED_PARAMETER(clip); + ReleaseDC(hwnd, hdc); + return ret; +} + +// +// Need to detect if we have clicked in the scrollbar region or not +// +static LRESULT NCHitTest(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + RECT hrect; + RECT vrect; + POINT pt; + + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + + //work out exactly where the Horizontal and Vertical scrollbars are + GetHScrollRect(sw, hwnd, &hrect); + GetVScrollRect(sw, hwnd, &vrect); + + //Clicked in the horizontal scrollbar area + if(sw->sbarHorz.fScrollVisible && PtInRect(&hrect, pt)) + { + return HTHSCROLL; + } + //Clicked in the vertical scrollbar area + else if(sw->sbarVert.fScrollVisible && PtInRect(&vrect, pt)) + { + return HTVSCROLL; + } + //clicked somewhere else + else + { + return CallWindowProc(sw->oldproc, hwnd, WM_NCHITTEST, wParam, lParam); + } +} + +// +// Return a HT* value indicating what part of the scrollbar was clicked +// Rectangle is not adjusted +// +static UINT GetHorzPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y) +{ + RECT rc = *rect; + + if(y < rc.top || y >= rc.bottom) return HTSCROLL_NONE; + +#ifdef INCLUDE_BUTTONS + + if(sb->fButVisibleBefore) + { + //clicked on the buttons to the left of the scrollbar + if(x >= rc.left && x < rc.left + sb->nButSizeBefore) + return HTSCROLL_INSERTED; + + //adjust the rectangle to exclude the left-side buttons, now that we + //know we havn't clicked on them + rc.left += sb->nButSizeBefore; + } + + if(sb->fButVisibleAfter) + { + //clicked on the buttons to the right of the scrollbar + if(x >= rc.right - sb->nButSizeAfter && x < rc.right) + return HTSCROLL_INSERTED; + + //adjust the rectangle to exclude the right-side buttons, now that we + //know we havn't clicked on them + rc.right -= sb->nButSizeAfter; + } + +#endif INCLUDE_BUTTONS + + //Now we have the rectangle for the scrollbar itself, so work out + //what part we clicked on. + return GetHorzScrollPortion(sb, hwnd, &rc, x, y); +} + +// +// Just call the horizontal version, with adjusted coordinates +// +static UINT GetVertPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y) +{ + UINT ret; + RotateRect(rect); + ret = GetHorzPortion(sb, hwnd, rect, y, x); + RotateRect(rect); + return ret; +} + +// +// Wrapper function for GetHorzPortion and GetVertPortion +// +static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y) +{ + if(sb->nBarType == SB_HORZ) + return GetHorzPortion(sb, hwnd, rect, x, y); + else if(sb->nBarType == SB_VERT) + return GetVertPortion(sb, hwnd, rect, x, y); + else + return HTSCROLL_NONE; +} + +// +// Input: rectangle of the total scrollbar area +// Output: adjusted to take the inserted buttons into account +// +static void GetRealHorzScrollRect(SCROLLBAR *sb, RECT *rect) +{ + if(sb->fButVisibleBefore) rect->left += sb->nButSizeBefore; + if(sb->fButVisibleAfter) rect->right -= sb->nButSizeAfter; +} + +// +// Input: rectangle of the total scrollbar area +// Output: adjusted to take the inserted buttons into account +// +static void GetRealVertScrollRect(SCROLLBAR *sb, RECT *rect) +{ + if(sb->fButVisibleBefore) rect->top += sb->nButSizeBefore; + if(sb->fButVisibleAfter) rect->bottom -= sb->nButSizeAfter; +} + +// +// Decide which type of scrollbar we have before calling +// the real function to do the job +// +static void GetRealScrollRect(SCROLLBAR *sb, RECT *rect) +{ + if(sb->nBarType == SB_HORZ) + { + GetRealHorzScrollRect(sb, rect); + } + else if(sb->nBarType == SB_VERT) + { + GetRealVertScrollRect(sb, rect); + } +} + +// +// All button code shoule be collected together +// +// +#ifdef INCLUDE_BUTTONS + +// +// Return the index of the button covering the specified point +// rect - rectangle of the whole scrollbar area +// pt - screen coords of the mouse +// fReturnRect - do/don't modify the rect to return the button's area +// +static UINT GetHorzButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect) +{ + int leftpos = rect->left, rightpos = rect->right; + int i; + int butwidth; + SCROLLBUT *sbut = sb->sbButtons; + + if (!PtInRect(rect, pt)) + return -1; + + if(sb->fButVisibleAfter) + rightpos -= sb->nButSizeAfter; + + for (i = 0; i < sb->nButtons; i++) + { + if(sb->fButVisibleBefore && sbut[i].uPlacement == SBBP_LEFT) + { + butwidth = GetSingleButSize(sb, &sbut[i]); + + //if the current button is under the specified point + if(pt.x >= leftpos && pt.x < leftpos + butwidth) + { + //if the caller wants us to return the rectangle of the button + if(fReturnRect) + { + rect->left = leftpos; + rect->right = leftpos + butwidth; + } + + return i; + } + + leftpos += butwidth; + } + else if(sb->fButVisibleAfter && sbut[i].uPlacement == SBBP_RIGHT) + { + butwidth = GetSingleButSize(sb, &sbut[i]); + + //if the current button is under the specified point + if(pt.x >= rightpos && pt.x < rightpos + butwidth) + { + //if the caller wants us to return the rectangle of the button + if(fReturnRect) + { + rect->left = rightpos; + rect->right = rightpos + butwidth; + } + return i; + } + + rightpos += butwidth; + } + } + + return -1; +} + + +static UINT GetVertButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect) +{ + UINT ret; + int temp; + + //swap the X/Y coords + temp = pt.x; + pt.x = pt.y; + pt.y = temp; + + //swap the rectangle + RotateRect(rect); + + ret = GetHorzButtonFromPt(sb, rect, pt, fReturnRect); + + RotateRect(rect); + return ret; +} + +// +// +// +static UINT GetButtonFromPt(SCROLLBAR *sb, RECT *rect, POINT pt, BOOL fReturnRect) +{ + if(sb->nBarType == SB_HORZ) + { + return GetHorzButtonFromPt(sb, rect, pt, fReturnRect); + } + else + { + return GetVertButtonFromPt(sb, rect, pt, fReturnRect); + } +} + +// +// Find the coordinates (in RECT format) of the specified button index +// +static UINT GetHorzButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index) +{ + UINT i; + SCROLLBUT *sbut = sb->sbButtons; + int leftpos = rect->left, rightpos = rect->right; + + if(sb->fButVisibleAfter) + rightpos -= sb->nButSizeAfter; + + //find the particular button in question + for (i = 0; i < index; i++) + { + if(sb->fButVisibleBefore && sbut[i].uPlacement == SBBP_LEFT) + { + leftpos += GetSingleButSize(sb, &sbut[i]); + } + else if(sb->fButVisibleAfter && sbut[i].uPlacement == SBBP_RIGHT) + { + rightpos += GetSingleButSize(sb, &sbut[i]); + } + } + + //now return the rectangle + if(sbut[i].uPlacement == SBBP_LEFT) + { + rect->left = leftpos; + rect->right = leftpos + GetSingleButSize(sb, &sbut[i]); + } + else + { + rect->left = rightpos; + rect->right = rightpos + GetSingleButSize(sb, &sbut[i]); + } + + return 0; +} + +static UINT GetVertButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index) +{ + UINT ret; + RotateRect(rect); + ret = GetHorzButtonRectFromId(sb, rect, index); + RotateRect(rect); + return ret; +} + +static UINT GetButtonRectFromId(SCROLLBAR *sb, RECT *rect, UINT index) +{ + if(sb->nBarType == SB_HORZ) + { + return GetHorzButtonRectFromId(sb, rect, index); + } + else + { + return GetVertButtonRectFromId(sb, rect, index); + } +} +#endif //INCLUDE_BUTTONS + +// +// Left button click in the non-client area +// +static LRESULT NCLButtonDown(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + RECT rect, winrect; + HDC hdc; + SCROLLBAR *sb; + SCROLLBUT *sbut = 0; + POINT pt; + + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + + hwndCurCoolSB = hwnd; + + // + // HORIZONTAL SCROLLBAR PROCESSING + // + if(wParam == HTHSCROLL) + { + uScrollTimerMsg = WM_HSCROLL; + uCurrentScrollbar = SB_HORZ; + sb = &sw->sbarHorz; + + //get the total area of the normal Horz scrollbar area + GetHScrollRect(sw, hwnd, &rect); + uCurrentScrollPortion = GetHorzPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam)); + } + // + // VERTICAL SCROLLBAR PROCESSING + // + else if(wParam == HTVSCROLL) + { + uScrollTimerMsg = WM_VSCROLL; + uCurrentScrollbar = SB_VERT; + sb = &sw->sbarVert; + + //get the total area of the normal Horz scrollbar area + GetVScrollRect(sw, hwnd, &rect); + uCurrentScrollPortion = GetVertPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam)); + } + // + // NORMAL PROCESSING + // + else + { + uCurrentScrollPortion = HTSCROLL_NONE; + return CallWindowProc(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam); + } + + // + // we can now share the same code for vertical + // and horizontal scrollbars + // + switch(uCurrentScrollPortion) + { + //inserted buttons to the left/right +#ifdef INCLUDE_BUTTONS + case HTSCROLL_INSERTED: + +#ifdef HOT_TRACKING + KillTimer(hwnd, uMouseOverId); + uMouseOverId = 0; + uMouseOverScrollbar = COOLSB_NONE; +#endif + + //find the index of the button that has been clicked + //adjust the rectangle to give the button's rectangle + uCurrentButton = GetButtonFromPt(sb, &rect, pt, TRUE); + + sbut = &sb->sbButtons[uCurrentButton]; + + //post a notification message + PostMouseNotify(hwnd, NM_CLICK, sb->nBarType, &rect, sbut->uCmdId, pt); + + GetWindowRect(hwnd, &winrect); + OffsetRect(&rect, -winrect.left, -winrect.top); + hdc = GetWindowDC(hwnd); + + DrawScrollButton(sbut, hdc, &rect, SBBS_PUSHED); + + ReleaseDC(hwnd, hdc); + + break; +#endif //INCLUDE_BUTTONS + + case HTSCROLL_THUMB: + + //if the scrollbar is disabled, then do no further processing + if (!IsScrollbarActive(sb)) + return 0; + + GetRealScrollRect(sb, &rect); + RotateRect0(sb, &rect); + CalcThumbSize(sb, &rect, &nThumbSize, &nThumbPos); + RotateRect0(sb, &rect); + + //remember the bounding rectangle of the scrollbar work area + rcThumbBounds = rect; + + sw->fThumbTracking = TRUE; + sb->scrollInfo.nTrackPos = sb->scrollInfo.nPos; + + if(wParam == HTVSCROLL) + nThumbMouseOffset = pt.y - nThumbPos; + else + nThumbMouseOffset = pt.x - nThumbPos; + + nLastPos = -sb->scrollInfo.nPos; + nThumbPos0 = nThumbPos; + + //if(sb->fFlatScrollbar) + //{ + GetWindowRect(hwnd, &winrect); + OffsetRect(&rect, -winrect.left, -winrect.top); + hdc = GetWindowDC(hwnd); + NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_THUMB); + ReleaseDC(hwnd, hdc); + //} + + break; + + //Any part of the scrollbar + case HTSCROLL_LEFT: + if(sb->fScrollFlags & ESB_DISABLE_LEFT) return 0; + else goto target1; + + case HTSCROLL_RIGHT: + if(sb->fScrollFlags & ESB_DISABLE_RIGHT) return 0; + else goto target1; + + goto target1; + + case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT: + + target1: + + //if the scrollbar is disabled, then do no further processing + if (!IsScrollbarActive(sb)) + break; + + //ajust the horizontal rectangle to NOT include + //any inserted buttons + GetRealScrollRect(sb, &rect); + + SendScrollMessage(hwnd, uScrollTimerMsg, uCurrentScrollPortion, 0); + + // Check what area the mouse is now over : + // If the scroll thumb has moved under the mouse in response to + // a call to SetScrollPos etc, then we don't hilight the scrollbar margin + if(uCurrentScrollbar == SB_HORZ) + uScrollTimerPortion = GetHorzScrollPortion(sb, hwnd, &rect, pt.x, pt.y); + else + uScrollTimerPortion = GetVertScrollPortion(sb, hwnd, &rect, pt.x, pt.y); + + GetWindowRect(hwnd, &winrect); + OffsetRect(&rect, -winrect.left, -winrect.top); + hdc = GetWindowDC(hwnd); + +#ifndef HOT_TRACKING + //if we aren't hot-tracking, then don't highlight + //the scrollbar thumb unless we click on it + if(uScrollTimerPortion == HTSCROLL_THUMB) + uScrollTimerPortion = HTSCROLL_NONE; +#endif + NCDrawScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion); + ReleaseDC(hwnd, hdc); + + //Post the scroll message!!!! + uScrollTimerPortion = uCurrentScrollPortion; + + //set a timer going on the first click. + //if this one expires, then we can start off a more regular timer + //to generate the auto-scroll behaviour + uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID1, COOLSB_TIMERINTERVAL1, 0); + break; + default: + return CallWindowProc(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam); + //return 0; + } + + SetCapture(hwnd); + return 0; +} + +// +// Left button released +// +static LRESULT LButtonUp(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + RECT rect; + //UINT thisportion; + HDC hdc; + POINT pt; + RECT winrect; + UINT buttonIdx = 0; + + //current scrollportion is the button that we clicked down on + if(uCurrentScrollPortion != HTSCROLL_NONE) + { + SCROLLBAR *sb = &sw->sbarHorz; + lParam = GetMessagePos(); + ReleaseCapture(); + + GetWindowRect(hwnd, &winrect); + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + + //emulate the mouse input on a scrollbar here... + if(uCurrentScrollbar == SB_HORZ) + { + //get the total area of the normal Horz scrollbar area + sb = &sw->sbarHorz; + GetHScrollRect(sw, hwnd, &rect); + } + else if(uCurrentScrollbar == SB_VERT) + { + //get the total area of the normal Horz scrollbar area + sb = &sw->sbarVert; + GetVScrollRect(sw, hwnd, &rect); + } + + //we need to do different things depending on if the + //user is activating the scrollbar itself, or one of + //the inserted buttons + switch(uCurrentScrollPortion) + { +#ifdef INCLUDE_BUTTONS + //inserted buttons are being clicked + case HTSCROLL_INSERTED: + + //get the rectangle of the ACTIVE button + buttonIdx = GetButtonFromPt(sb, &rect, pt, FALSE); + GetButtonRectFromId(sb, &rect, uCurrentButton); + + OffsetRect(&rect, -winrect.left, -winrect.top); + + //Send the notification BEFORE we redraw, so the + //bitmap can be changed smoothly by the user if they require + if(uCurrentButton == buttonIdx) + { + SCROLLBUT *sbut = &sb->sbButtons[buttonIdx]; + UINT cmdid = sbut->uCmdId; + + if ((sbut->uButType & SBBT_MASK) == SBBT_TOGGLEBUTTON) + sbut->uState ^= 1; + + //send a notify?? + //only post a message if the command id is valid + if(cmdid != -1 && cmdid > 0) + SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(cmdid, CSBN_CLICKED), 0); + + //user might have deleted this button, so redraw whole area + NCPaint(sw, hwnd, 1, 0); + } + else + { + //otherwise, just redraw the button in its new state + hdc = GetWindowDC(hwnd); + DrawScrollButton(&sb->sbButtons[uCurrentButton], hdc, &rect, SBBS_NORMAL); + ReleaseDC(hwnd, hdc); + } + + break; +#endif // INCLUDE_BUTTONS + + //The scrollbar is active + case HTSCROLL_LEFT: case HTSCROLL_RIGHT: + case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT: + case HTSCROLL_NONE: + + KillTimer(hwnd, uScrollTimerId); + + case HTSCROLL_THUMB: + + //In case we were thumb tracking, make sure we stop NOW + if(sw->fThumbTracking == TRUE) + { + SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBPOSITION, nLastPos); + sw->fThumbTracking = FALSE; + } + + //send the SB_ENDSCROLL message now that scrolling has finished + SendScrollMessage(hwnd, uScrollTimerMsg, SB_ENDSCROLL, 0); + + //adjust the total scroll area to become where the scrollbar + //really is (take into account the inserted buttons) + GetRealScrollRect(sb, &rect); + OffsetRect(&rect, -winrect.left, -winrect.top); + hdc = GetWindowDC(hwnd); + + //draw whichever scrollbar sb is + NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL); + + ReleaseDC(hwnd, hdc); + break; + } + + //reset our state to default + uCurrentScrollPortion = HTSCROLL_NONE; + uScrollTimerPortion = HTSCROLL_NONE; + uScrollTimerId = 0; + + uScrollTimerMsg = 0; + uCurrentScrollbar = COOLSB_NONE; + + return 0; + } + else + { + /* + // Can't remember why I did this! + if(GetCapture() == hwnd) + { + ReleaseCapture(); + }*/ + } + + return CallWindowProc(sw->oldproc, hwnd, WM_LBUTTONUP, wParam, lParam); +} + +// +// This function is called whenever the mouse is moved and +// we are dragging the scrollbar thumb about. +// +static LRESULT ThumbTrackHorz(SCROLLBAR *sbar, HWND hwnd, int x, int y) +{ + POINT pt; + RECT rc, winrect, rc2; + COLORREF crCheck1 = GetSBForeColor(); + COLORREF crCheck2 = GetSBBackColor(); + HDC hdc; + int thumbpos = nThumbPos; + int pos; + int siMaxMin = 0; + UINT flatflag = sbar->fFlatScrollbar ? BF_FLAT : 0; + BOOL fCustomDraw = FALSE; + + SCROLLINFO *si; + si = &sbar->scrollInfo; + + pt.x = x; + pt.y = y; + + //draw the thumb at whatever position + rc = rcThumbBounds; + + SetRect(&rc2, rc.left - THUMBTRACK_SNAPDIST*2, rc.top - THUMBTRACK_SNAPDIST, + rc.right + THUMBTRACK_SNAPDIST*2, rc.bottom + THUMBTRACK_SNAPDIST); + + rc.left += GetScrollMetric(sbar, SM_CXHORZSB); + rc.right -= GetScrollMetric(sbar, SM_CXHORZSB); + + //if the mouse is not in a suitable distance of the scrollbar, + //then "snap" the thumb back to its initial position +#ifdef SNAP_THUMB_BACK + if (!PtInRect(&rc2, pt)) + { + thumbpos = nThumbPos0; + } + //otherwise, move the thumb to where the mouse is + else +#endif //SNAP_THUMB_BACK + { + //keep the thumb within the scrollbar limits + thumbpos = pt.x - nThumbMouseOffset; + if(thumbpos < rc.left) thumbpos = rc.left; + if(thumbpos > rc.right - nThumbSize) thumbpos = rc.right - nThumbSize; + } + + GetWindowRect(hwnd, &winrect); + + if(sbar->nBarType == SB_VERT) + RotateRect(&winrect); + + hdc = GetWindowDC(hwnd); + +//#ifdef CUSTOM_DRAW + fCustomDraw = PostCustomPrePostPaint(hwnd, hdc, sbar, CDDS_PREPAINT) == CDRF_SKIPDEFAULT; +//#endif + + OffsetRect(&rc, -winrect.left, -winrect.top); + thumbpos -= winrect.left; + + //draw the margin before the thumb + SetRect(&rc2, rc.left, rc.top, thumbpos, rc.bottom); + RotateRect0(sbar, &rc2); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGELEFT, 0, 0, 0); + else + DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2); + + RotateRect0(sbar, &rc2); + + //draw the margin after the thumb + SetRect(&rc2, thumbpos+nThumbSize, rc.top, rc.right, rc.bottom); + + RotateRect0(sbar, &rc2); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGERIGHT, 0, 0, 0); + else + DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2); + + RotateRect0(sbar, &rc2); + + //finally draw the thumb itelf. This is how it looks on win2000, anyway + SetRect(&rc2, thumbpos, rc.top, thumbpos+nThumbSize, rc.bottom); + + RotateRect0(sbar, &rc2); + + if(fCustomDraw) + PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_THUMBTRACK, TRUE, TRUE, FALSE); + else + { + +#ifdef FLAT_SCROLLBARS + if(sbar->fFlatScrollbar) + PaintRect(hdc, &rc2, GetSysColor(COLOR_3DSHADOW)); + else +#endif + { + DrawBlankButton(hdc, &rc2, flatflag); + } + } + + RotateRect0(sbar, &rc2); + ReleaseDC(hwnd, hdc); + + //post a SB_TRACKPOS message!!! + siMaxMin = si->nMax - si->nMin; + + if(siMaxMin > 0) + pos = MulDiv(thumbpos-rc.left, siMaxMin-si->nPage + 1, rc.right-rc.left-nThumbSize); + else + pos = thumbpos - rc.left; + + if(pos != nLastPos) + { + si->nTrackPos = pos; + SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, pos); + } + + nLastPos = pos; + +//#ifdef CUSTOM_DRAW + PostCustomPrePostPaint(hwnd, hdc, sbar, CDDS_POSTPAINT); +//#endif + + return 0; +} + +// +// remember to rotate the thumb bounds rectangle!! +// +static LRESULT ThumbTrackVert(SCROLLBAR *sb, HWND hwnd, int x, int y) +{ + //sw->swapcoords = TRUE; + RotateRect(&rcThumbBounds); + ThumbTrackHorz(sb, hwnd, y, x); + RotateRect(&rcThumbBounds); + //sw->swapcoords = FALSE; + + return 0; +} + +// +// Called when we have set the capture from the NCLButtonDown(...) +// +static LRESULT MouseMove(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + RECT rect; + UINT thisportion; + HDC hdc; + static UINT lastportion = 0; + static UINT lastbutton = 0; + POINT pt; + RECT winrect; + UINT buttonIdx = 0; + + if(sw->fThumbTracking == TRUE) + { + int x, y; + lParam = GetMessagePos(); + x = LOWORD(lParam); + y = HIWORD(lParam); + + if(uCurrentScrollbar == SB_HORZ) + return ThumbTrackHorz(&sw->sbarHorz, hwnd, x,y); + + + else if(uCurrentScrollbar == SB_VERT) + return ThumbTrackVert(&sw->sbarVert, hwnd, x,y); + } + + if(uCurrentScrollPortion == HTSCROLL_NONE) + { + return CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam); + } + else + { + LPARAM nlParam; + SCROLLBAR *sb = &sw->sbarHorz; + SCROLLBUT *sbut = 0; + + nlParam = GetMessagePos(); + + GetWindowRect(hwnd, &winrect); + + pt.x = LOWORD(nlParam); + pt.y = HIWORD(nlParam); + + //emulate the mouse input on a scrollbar here... + if(uCurrentScrollbar == SB_HORZ) + { + sb = &sw->sbarHorz; + } + else if(uCurrentScrollbar == SB_VERT) + { + sb = &sw->sbarVert; + } + + //get the total area of the normal scrollbar area + GetScrollRect(sw, sb->nBarType, hwnd, &rect); + + //see if we clicked in the inserted buttons / normal scrollbar + //thisportion = GetPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam)); + thisportion = GetPortion(sb, hwnd, &rect, pt.x, pt.y); + + //we need to do different things depending on if the + //user is activating the scrollbar itself, or one of + //the inserted buttons + switch(uCurrentScrollPortion) + { +#ifdef INCLUDE_BUTTONS + //inserted buttons are being clicked + case HTSCROLL_INSERTED: + + //find the index of the button that has been clicked + //Don't adjust the rectangle though + buttonIdx = GetButtonFromPt(sb, &rect, pt, FALSE); + + //Get the rectangle of the active button + GetButtonRectFromId(sb, &rect, uCurrentButton); + + //if the button to the LEFT of the current + //button is resizable, then resize it +#ifdef RESIZABLE_BUTTONS + if(uCurrentButton > 0) + { + sbut = &sb->sbButtons[uCurrentButton - 1]; + + //only resize if BOTH buttons are on same side of scrollbar + if(sbut->uPlacement == (sbut+1)->uPlacement && (sbut->uButType & SBBM_RESIZABLE)) + { + int oldsize = sbut->nSize; + int butsize1, butsize2; + RECT rect2; + int scrollsize; + + if(uCurrentScrollbar == SB_HORZ) + { + rect.left -= GetSingleButSize(sb, sbut); + sbut->nSize = pt.x - rect.left; + } + else + { + rect.top -= GetSingleButSize(sb, sbut); + sbut->nSize = pt.y - rect.top; + } + + //if(sbut->nSize < 0) sbut->nSize = 0; + if(sbut->nSize < (int)sbut->nMinSize) + sbut->nSize = sbut->nMinSize; + + if ((UINT)sbut->nSize > (UINT)sbut->nMaxSize) + sbut->nSize = sbut->nMaxSize; + + GetScrollRect(sw, uCurrentScrollbar, hwnd, &rect2); + + if(uCurrentScrollbar == SB_HORZ) + scrollsize = rect2.right-rect2.left; + else + scrollsize = rect2.bottom-rect2.top; + + butsize1 = GetButtonSize(sb, hwnd, SBBP_LEFT); + butsize2 = GetButtonSize(sb, hwnd, SBBP_RIGHT); + + //adjust the button size if it gets too big + if(butsize1 + butsize2 > scrollsize - MINSCROLLSIZE) + { + sbut->nSize -= (butsize1+butsize2) - (scrollsize - MINSCROLLSIZE); + } + + //remember what size the USER set the button to + sbut->nSizeReserved = sbut->nSize; + NCPaint(sw, hwnd, (WPARAM)1, (LPARAM)0); + return 0; + } + } +#endif //RESIZABLE_BUTTONS + + OffsetRect(&rect, -winrect.left, -winrect.top); + + hdc = GetWindowDC(hwnd); + + //if the button under the mouse is not the active button, + //then display the active button in its normal state + if(buttonIdx != uCurrentButton + //include this if toggle buttons always stay depressed + //if they are being activated + && (sb->sbButtons[uCurrentButton].uButType & SBBT_MASK) != SBBT_TOGGLEBUTTON) + { + if(lastbutton != buttonIdx) + DrawScrollButton(&sb->sbButtons[uCurrentButton], hdc, &rect, SBBS_NORMAL); + } + //otherwise, depress the active button if the mouse is over + //it (just like a normal scroll button works) + else + { + if(lastbutton != buttonIdx) + DrawScrollButton(&sb->sbButtons[uCurrentButton], hdc, &rect, SBBS_PUSHED); + } + + ReleaseDC(hwnd, hdc); + return CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam); + //break; + +#endif //INCLUDE_BUTTONS + + //The scrollbar is active + case HTSCROLL_LEFT: case HTSCROLL_RIGHT:case HTSCROLL_THUMB: + case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT: + case HTSCROLL_NONE: + + //adjust the total scroll area to become where the scrollbar + //really is (take into account the inserted buttons) + GetRealScrollRect(sb, &rect); + + OffsetRect(&rect, -winrect.left, -winrect.top); + hdc = GetWindowDC(hwnd); + + if(thisportion != uCurrentScrollPortion) + { + uScrollTimerPortion = HTSCROLL_NONE; + + if(lastportion != thisportion) + NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL); + } + //otherwise, draw the button in its depressed / clicked state + else + { + uScrollTimerPortion = uCurrentScrollPortion; + + if(lastportion != thisportion) + NCDrawScrollbar(sb, hwnd, hdc, &rect, thisportion); + } + + ReleaseDC(hwnd, hdc); + + break; + } + + + lastportion = thisportion; + lastbutton = buttonIdx; + + //must return zero here, because we might get cursor anomilies + //CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam); + return 0; + + } +} + +#ifdef INCLUDE_BUTTONS +#ifdef RESIZABLE_BUTTONS +// +// Any resizable buttons must be shrunk to fit if the window is made too small +// +static void ResizeButtonsToFit(SCROLLWND *sw, SCROLLBAR *sbar, HWND hwnd) +{ + int butsize1, butsize2; + RECT rc; + int scrollsize; + int i; + SCROLLBUT *sbut; + + //make sure that the scrollbar can fit into space, by + //shrinking any resizable buttons + GetScrollRect(sw, sbar->nBarType, hwnd, &rc); + + if(sbar->nBarType == SB_HORZ) + scrollsize = rc.right-rc.left; + else + scrollsize = rc.bottom-rc.top; + + //restore any resizable buttons to their user-defined sizes, + //before shrinking them to fit. This means when we make the window + //bigger, the buttons will restore to their initial sizes + for (i = 0; i < sbar->nButtons; i++) + { + sbut = &sbar->sbButtons[i]; + if(sbut->uButType & SBBM_RESIZABLE) + { + sbut->nSize = sbut->nSizeReserved; + } + } + + butsize1 = GetButtonSize(sbar, hwnd, SBBP_LEFT); + butsize2 = GetButtonSize(sbar, hwnd, SBBP_RIGHT); + + if(butsize1 + butsize2 > scrollsize - MINSCROLLSIZE) + { + i = 0; + while(i < sbar->nButtons && + butsize1 + butsize2 > scrollsize - MINSCROLLSIZE) + { + sbut = &sbar->sbButtons[i++]; + if(sbut->uButType & SBBM_RESIZABLE) + { + int oldsize = sbut->nSize; + sbut->nSize -= (butsize1+butsize2) - (scrollsize-MINSCROLLSIZE); + + if(sbut->nSize < (int)sbut->nMinSize) + sbut->nSize = sbut->nMinSize; + + if ((UINT)sbut->nSize > (UINT)sbut->nMaxSize) + sbut->nSize = sbut->nMaxSize; + + + butsize1 -= (oldsize - sbut->nSize); + } + } + } + +} +#endif +#endif + +// +// We must allocate from in the non-client area for our scrollbars +// Call the default window procedure first, to get the borders (if any) +// allocated some space, then allocate the space for the scrollbars +// if they fit +// +static LRESULT NCCalcSize(SCROLLWND *sw, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + NCCALCSIZE_PARAMS *nccsp; + RECT *rect; + RECT oldrect; + BOOL fCalcValidRects = (wParam == TRUE); + SCROLLBAR *sb; + LRESULT ret; + DWORD dwStyle; + + //Regardless of the value of fCalcValidRects, the first rectangle + //in the array specified by the rgrc structure member of the + //NCCALCSIZE_PARAMS structure contains the coordinates of the window, + //so we can use the exact same code to modify this rectangle, when + //wParam is TRUE and when it is FALSE. + nccsp = (NCCALCSIZE_PARAMS *)lParam; + rect = &nccsp->rgrc[0]; + oldrect = *rect; + + dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + + // TURN OFF SCROLL-STYLES. + if ( dwStyle & (WS_VSCROLL|WS_HSCROLL)) + { + sw->bPreventStyleChange = TRUE; + SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL|WS_HSCROLL)); + } + + //call the default procedure to get the borders allocated + ret = CallWindowProc(sw->oldproc, hwnd, WM_NCCALCSIZE, wParam, lParam); + + // RESTORE PREVIOUS STYLES (if present at all) + if ( dwStyle & (WS_VSCROLL|WS_HSCROLL)) + { + SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle); + sw->bPreventStyleChange = FALSE; + } + + // calculate what the size of each window border is, + sw->cxLeftEdge = rect->left - oldrect.left; + sw->cxRightEdge = oldrect.right - rect->right; + sw->cyTopEdge = rect->top - oldrect.top; + sw->cyBottomEdge = oldrect.bottom - rect->bottom; + + sb = &sw->sbarHorz; + + //if there is room, allocate some space for the horizontal scrollbar + //NOTE: Change the ">" to a ">=" to make the horz bar totally fill the + //window before disappearing + if ((sb->fScrollFlags & CSBS_VISIBLE) && +#ifdef COOLSB_FILLWINDOW + rect->bottom - rect->top >= GetScrollMetric(sb, SM_CYHORZSB)) +#else + rect->bottom - rect->top > GetScrollMetric(sb, SM_CYHORZSB)) +#endif + { + rect->bottom -= GetScrollMetric(sb, SM_CYHORZSB); + sb->fScrollVisible = TRUE; + } + else + sb->fScrollVisible = FALSE; + + sb = &sw->sbarVert; + + //if there is room, allocate some space for the vertical scrollbar + if ((sb->fScrollFlags & CSBS_VISIBLE) && + rect->right - rect->left >= GetScrollMetric(sb, SM_CXVERTSB)) + { + if(sw->fLeftScrollbar) + rect->left += GetScrollMetric(sb, SM_CXVERTSB); + else + rect->right -= GetScrollMetric(sb, SM_CXVERTSB); + + sb->fScrollVisible = TRUE; + } + else + sb->fScrollVisible = FALSE; + +#ifdef INCLUDE_BUTTONS +#ifdef RESIZABLE_BUTTONS + ResizeButtonsToFit(sw, &sw->sbarHorz, hwnd); + ResizeButtonsToFit(sw, &sw->sbarVert, hwnd); +#endif +#endif + + //don't return a value unless we actually modify the other rectangles + //in the NCCALCSIZE_PARAMS structure. In this case, we return 0 + //no matter what the value of fCalcValidRects is + return ret;//FALSE; +} + +// +// used for hot-tracking over the scroll buttons +// +static LRESULT NCMouseMove(SCROLLWND *sw, HWND hwnd, WPARAM wHitTest, LPARAM lParam) +{ + //install a timer for the mouse-over events, if the mouse moves + //over one of the scrollbars +#ifdef HOT_TRACKING + hwndCurCoolSB = hwnd; + if(wHitTest == HTHSCROLL) + { + if(uMouseOverScrollbar == SB_HORZ) + return CallWindowProc(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam); + + uLastHitTestPortion = HTSCROLL_NONE; + uHitTestPortion = HTSCROLL_NONE; + GetScrollRect(sw, SB_HORZ, hwnd, &MouseOverRect); + uMouseOverScrollbar = SB_HORZ; + uMouseOverId = SetTimer(hwnd, COOLSB_TIMERID3, COOLSB_TIMERINTERVAL3, 0); + + NCPaint(sw, hwnd, 1, 0); + } + else if(wHitTest == HTVSCROLL) + { + if(uMouseOverScrollbar == SB_VERT) + return CallWindowProc(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam); + + uLastHitTestPortion = HTSCROLL_NONE; + uHitTestPortion = HTSCROLL_NONE; + GetScrollRect(sw, SB_VERT, hwnd, &MouseOverRect); + uMouseOverScrollbar = SB_VERT; + uMouseOverId = SetTimer(hwnd, COOLSB_TIMERID3, COOLSB_TIMERINTERVAL3, 0); + + NCPaint(sw, hwnd, 1, 0); + } + +#endif //HOT_TRACKING + return CallWindowProc(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam); +} + +// +// Timer routine to generate scrollbar messages +// +static LRESULT CoolSB_Timer(SCROLLWND *swnd, HWND hwnd, WPARAM wTimerId, LPARAM lParam) +{ + //let all timer messages go past if we don't have a timer installed ourselves + if(uScrollTimerId == 0 && uMouseOverId == 0) + { + return CallWindowProc(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam); + } + +#ifdef HOT_TRACKING + //mouse-over timer + if(wTimerId == COOLSB_TIMERID3) + { + POINT pt; + RECT rect, winrect; + HDC hdc; + SCROLLBAR *sbar; + + if(swnd->fThumbTracking) + return 0; + + //if the mouse moves outside the current scrollbar, + //then kill the timer.. + GetCursorPos(&pt); + + if (!PtInRect(&MouseOverRect, pt)) + { + KillTimer(hwnd, uMouseOverId); + uMouseOverId = 0; + uMouseOverScrollbar = COOLSB_NONE; + uLastHitTestPortion = HTSCROLL_NONE; + + uHitTestPortion = HTSCROLL_NONE; + NCPaint(swnd, hwnd, 1, 0); + } + else + { + if(uMouseOverScrollbar == SB_HORZ) + { + sbar = &swnd->sbarHorz; + uHitTestPortion = GetHorzPortion(sbar, hwnd, &MouseOverRect, pt.x, pt.y); + } + else + { + sbar = &swnd->sbarVert; + uHitTestPortion = GetVertPortion(sbar, hwnd, &MouseOverRect, pt.x, pt.y); + } + + if(uLastHitTestPortion != uHitTestPortion) + { + rect = MouseOverRect; + GetRealScrollRect(sbar, &rect); + + GetWindowRect(hwnd, &winrect); + OffsetRect(&rect, -winrect.left, -winrect.top); + + hdc = GetWindowDC(hwnd); + NCDrawScrollbar(sbar, hwnd, hdc, &rect, HTSCROLL_NONE); + ReleaseDC(hwnd, hdc); + } + + uLastHitTestPortion = uHitTestPortion; + } + + return 0; + } +#endif // HOT_TRACKING + + //if the first timer goes off, then we can start a more + //regular timer interval to auto-generate scroll messages + //this gives a slight pause between first pressing the scroll arrow, and the + //actual scroll starting + if(wTimerId == COOLSB_TIMERID1) + { + KillTimer(hwnd, uScrollTimerId); + uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID2, COOLSB_TIMERINTERVAL2, 0); + return 0; + } + //send the scrollbar message repeatedly + else if(wTimerId == COOLSB_TIMERID2) + { + //need to process a spoof WM_MOUSEMOVE, so that + //we know where the mouse is each time the scroll timer goes off. + //This is so we can stop sending scroll messages if the thumb moves + //under the mouse. + POINT pt; + GetCursorPos(&pt); + ScreenToClient(hwnd, &pt); + + MouseMove(swnd, hwnd, MK_LBUTTON, MAKELPARAM(pt.x, pt.y)); + + if(uScrollTimerPortion != HTSCROLL_NONE) + SendScrollMessage(hwnd, uScrollTimerMsg, uScrollTimerPortion, 0); + + return 0; + } + else + { + return CallWindowProc(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam); + } +} + +// +// We must intercept any calls to SetWindowLongPtr, to check if +// left-scrollbars are taking effect or not +// +static LRESULT CoolSB_StyleChange(SCROLLWND *swnd, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + STYLESTRUCT *ss = (STYLESTRUCT *)lParam; + + if(wParam == GWL_EXSTYLE) + { + if(ss->styleNew & WS_EX_LEFTSCROLLBAR) + swnd->fLeftScrollbar = TRUE; + else + swnd->fLeftScrollbar = FALSE; + } + + return CallWindowProc(swnd->oldproc, hwnd, msg, wParam, lParam); +} + +static UINT curTool = -1; +static LRESULT CoolSB_Notify(SCROLLWND *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ +#ifdef COOLSB_TOOLTIPS + + NMTTDISPINFO *nmdi = (NMTTDISPINFO *)lParam; + + if(nmdi->hdr.hwndFrom == swnd->hwndToolTip && + nmdi->hdr.code == TTN_GETDISPINFO) + { + //convert the tooltip notify from a "ISHWND" style + //request to an id-based request. + //We do this because our tooltip is a window-style + //tip, with no tools, and the GETDISPINFO request must + //indicate which button to retrieve the text for + //nmdi->hdr.idFrom = curTool; + nmdi->hdr.idFrom = curTool; + nmdi->hinst = GetModuleHandle(0); + nmdi->uFlags &= ~TTF_IDISHWND; + } +#endif //COOLSB_TOOLTIPS + + return CallWindowProc(swnd->oldproc, hwnd, WM_NOTIFY, wParam, lParam); +} + +static LRESULT SendToolTipMessage0(HWND hwndTT, UINT message, WPARAM wParam, LPARAM lParam) +{ + return SendMessage(hwndTT, message, wParam, lParam); +} + +#ifdef COOLSB_TOOLTIPS +#define SendToolTipMessage SendToolTipMessage0 +#else +#define SendToolTipMessage 1 ? (void)0 : SendToolTipMessage0 +#endif + + +// +// We must intercept any calls to SetWindowLongPtr, to make sure that +// the user does not set the WS_VSCROLL or WS_HSCROLL styles +// +static LRESULT CoolSB_SetCursor(SCROLLWND *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam) +{ +#ifdef INCLUDE_BUTTONS + UINT lo = LOWORD(lParam); + UINT hi = HIWORD(lParam); + UINT xy; + RECT rect; + SCROLLBAR *sbar; + SCROLLBUT *sbut; + POINT pt; + UINT id; + static UINT lastid; + +#ifdef HIDE_CURSOR_AFTER_MOUSEUP + static UINT lastmsg; + if(lastmsg == WM_LBUTTONDOWN) + { + lastmsg = hi; + return CallWindowProc(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam); + } + else + lastmsg = hi; +#endif + + //if we are over either or our scrollbars + if(lo == HTHSCROLL || lo == HTVSCROLL) + { + xy = GetMessagePos(); + pt.x = LOWORD(xy); + pt.y = HIWORD(xy); + + if(lo == HTHSCROLL) + { + sbar = &swnd->sbarHorz; + GetScrollRect(swnd, SB_HORZ, hwnd, &rect); + id = GetHorzPortion(sbar, hwnd, &rect, pt.x, pt.y); + } + else + { + sbar = &swnd->sbarVert; + GetScrollRect(swnd, SB_VERT, hwnd, &rect); + id = GetVertPortion(sbar, hwnd, &rect, pt.x, pt.y); + } + + if(id != HTSCROLL_INSERTED) + { + if(swnd->hwndToolTip != 0) + { + SendToolTipMessage(swnd->hwndToolTip, TTM_ACTIVATE, FALSE, 0); + SendToolTipMessage(swnd->hwndToolTip, TTM_POP, 0, 0); + } + + return CallWindowProc(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam); + } + + if(swnd->hwndToolTip != 0) + { + SendToolTipMessage(swnd->hwndToolTip, TTM_ACTIVATE, TRUE, 0); + } + + //set the cursor if one has been specified + if ((id = GetButtonFromPt(sbar, &rect, pt, TRUE)) != -1) + { + sbut = &sbar->sbButtons[id]; + curTool = sbut->uCmdId; + + if(lastid != id && swnd->hwndToolTip != 0) + { + if(IsWindowVisible(swnd->hwndToolTip)) + SendToolTipMessage(swnd->hwndToolTip, TTM_UPDATE, TRUE, 0); + } + + lastid = id; + + if(sbut->hCurs != 0) + { + SetCursor(sbut->hCurs); + return 0; + } + } + else + { + curTool = -1; + lastid = -1; + } + } + else if(swnd->hwndToolTip != 0) + { + SendToolTipMessage(swnd->hwndToolTip, TTM_ACTIVATE, FALSE, 0); + SendToolTipMessage(swnd->hwndToolTip, TTM_POP, 0, 0); + } + +#endif //INCLUDE_BUTTONS + return CallWindowProc(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam); +} + + +// +// Send the specified message to the tooltip control +// +static void __stdcall RelayMouseEvent(HWND hwnd, HWND hwndToolTip, UINT event) +{ +#ifdef COOLSB_TOOLTIPS + MSG msg; + + CoolSB_ZeroMemory(&msg, sizeof(MSG)); + msg.hwnd = hwnd; + msg.message = event; + + SendMessage(hwndToolTip, TTM_RELAYEVENT, 0, (LONG)&msg); +#else + UNREFERENCED_PARAMETER(hwnd); + UNREFERENCED_PARAMETER(hwndToolTip); + UNREFERENCED_PARAMETER(event); +#endif +} + + +// +// CoolScrollbar subclass procedure. +// Handle all messages needed to mimick normal windows scrollbars +// +LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WNDPROC oldproc; + SCROLLWND *swnd = GetScrollWndFromHwnd(hwnd); + static int count; + + switch(message) + { + case WM_NCDESTROY: + //this should NEVER be called, because the user + //should have called Uninitialize() themselves. + + //However, if the user tries to call Uninitialize().. + //after this window is destroyed, this window's entry in the lookup + //table will not be there, and the call will fail + oldproc = swnd->oldproc; + UninitializeCoolSB(hwnd); + + //we must call the original window procedure, otherwise it + //will never get the WM_NCDESTROY message, and it wouldn't + //be able to clean up etc. + return CallWindowProc(oldproc, hwnd, message, wParam, lParam); + + case WM_NCCALCSIZE: + return NCCalcSize(swnd, hwnd, wParam, lParam); + + case WM_NCPAINT: + return NCPaint(swnd, hwnd, wParam, lParam); + + case WM_NCHITTEST: + return NCHitTest(swnd, hwnd, wParam, lParam); + + case WM_NCRBUTTONDOWN: case WM_NCRBUTTONUP: + case WM_NCMBUTTONDOWN: case WM_NCMBUTTONUP: + RelayMouseEvent(hwnd, swnd->hwndToolTip, (WM_MOUSEMOVE-WM_NCMOUSEMOVE) + (message)); + if(wParam == HTHSCROLL || wParam == HTVSCROLL) + return 0; + else + break; + + case WM_NCLBUTTONDBLCLK: + //TRACE("WM_NCLBUTTONDBLCLK %d\n", count++); + if(wParam == HTHSCROLL || wParam == HTVSCROLL) + return NCLButtonDown(swnd, hwnd, wParam, lParam); + else + break; + + case WM_NCLBUTTONDOWN: + //TRACE("WM_NCLBUTTONDOWN%d\n", count++); + RelayMouseEvent(hwnd, swnd->hwndToolTip, WM_LBUTTONDOWN); + return NCLButtonDown(swnd, hwnd, wParam, lParam); + + + case WM_LBUTTONUP: + //TRACE("WM_LBUTTONUP %d\n", count++); + RelayMouseEvent(hwnd, swnd->hwndToolTip, WM_LBUTTONUP); + return LButtonUp(swnd, hwnd, wParam, lParam); + + case WM_NOTIFY: + return CoolSB_Notify(swnd, hwnd, wParam, lParam); + + //Mouse moves are received when we set the mouse capture, + //even when the mouse moves over the non-client area + case WM_MOUSEMOVE: + //TRACE("WM_MOUSEMOVE %d\n", count++); + return MouseMove(swnd, hwnd, wParam, lParam); + + case WM_TIMER: + return CoolSB_Timer(swnd, hwnd, wParam, lParam); + + //case WM_STYLECHANGING: + // return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGING, wParam, lParam); + case WM_STYLECHANGED: + + if(swnd->bPreventStyleChange) + { + // the NCPAINT handler has told us to eat this message! + return 0; + } + else + { + if (message == WM_STYLECHANGED) + return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGED, wParam, lParam); + else + break; + } + + case WM_NCMOUSEMOVE: + { + static LONG_PTR lastpos = -1; + + //TRACE("WM_NCMOUSEMOVE %d\n", count++); + + //The problem with NCMOUSEMOVE is that it is sent continuously + //even when the mouse is stationary (under win2000 / win98) + // + //Tooltips don't like being sent a continous stream of mouse-moves + //if the cursor isn't moving, because they will think that the mouse + //is moving position, and the internal timer will never expire + // + if(lastpos != lParam) + { + RelayMouseEvent(hwnd, swnd->hwndToolTip, WM_MOUSEMOVE); + lastpos = lParam; + } + } + + return NCMouseMove(swnd, hwnd, wParam, lParam); + + + case WM_SETCURSOR: + return CoolSB_SetCursor(swnd, hwnd, wParam, lParam); + + case WM_CAPTURECHANGED: + break; + + default: + break; + } + + return CallWindowProc(swnd->oldproc, hwnd, message, wParam, lParam); +} + diff --git a/plugins/Clist_nicer/src/Coolsb/coolscroll.h b/plugins/Clist_nicer/src/Coolsb/coolscroll.h new file mode 100644 index 0000000000..c5fe848a83 --- /dev/null +++ b/plugins/Clist_nicer/src/Coolsb/coolscroll.h @@ -0,0 +1,232 @@ +#ifndef _COOLSBLIB_INCLUDED +#define _COOLSBLIB_INCLUDED + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include + +// To complement the exisiting SB_HORZ, SB_VERT, SB_BOTH +// scrollbar identifiers +#define COOLSB_NONE (-1) +#define SB_INSBUT (-2) + +// +// Arrow size defines +// +#define SYSTEM_METRIC (-1) + + +// +// general scrollbar styles +// +// use the standard ESB_DISABLE_xxx flags to represent the +// enabled / disabled states. (defined in winuser.h) +// +#define CSBS_THUMBALWAYS 4 +#define CSBS_VISIBLE 8 + +//cool scrollbar styles for Flat scrollbars +#define CSBS_NORMAL 0 +#define CSBS_FLAT 1 +#define CSBS_HOTTRACKED 2 + +// +// Button mask flags for indicating which members of SCROLLBUT +// to use during a button insertion / modification +// +#define SBBF_TYPE 0x0001 +#define SBBF_ID 0x0002 +#define SBBF_PLACEMENT 0x0004 +#define SBBF_SIZE 0x0008 +#define SBBF_BITMAP 0x0010 +#define SBBF_ENHMETAFILE 0x0020 +//#define SBBF_OWNERDRAW 0x0040 //unused at present +#define SBBF_CURSOR 0x0080 +#define SBBF_BUTMINMAX 0x0100 +#define SBBF_STATE 0x0200 + +//button styles (states) +#define SBBS_NORMAL 0 +#define SBBS_PUSHED 1 +#define SBBS_CHECKED SBBS_PUSHED + +// +// scrollbar button types +// +#define SBBT_PUSHBUTTON 1 //standard push button +#define SBBT_TOGGLEBUTTON 2 //toggle button +#define SBBT_FIXED 3 //fixed button (non-clickable) +#define SBBT_FLAT 4 //blank area (flat, with border) +#define SBBT_BLANK 5 //blank area (flat, no border) +#define SBBT_DARK 6 //dark blank area (flat) +#define SBBT_OWNERDRAW 7 //user draws the button via a WM_NOTIFY + +#define SBBT_MASK 0x1f //mask off low 5 bits + +//button type modifiers +#define SBBM_RECESSED 0x0020 //recessed when clicked (like Word 97) +#define SBBM_LEFTARROW 0x0040 +#define SBBM_RIGHTARROW 0x0080 +#define SBBM_UPARROW 0x0100 +#define SBBM_DOWNARROW 0x0200 +#define SBBM_RESIZABLE 0x0400 +#define SBBM_TYPE2 0x0800 +#define SBBM_TYPE3 0x1000 +#define SBBM_TOOLTIPS 0x2000 //currently unused (define COOLSB_TOOLTIPS in userdefs.h) + +//button placement flags +#define SBBP_LEFT 1 +#define SBBP_RIGHT 2 +#define SBBP_TOP 1 //3 +#define SBBP_BOTTOM 2 //4 + + +// +// Button command notification codes +// for sending with a WM_COMMAND message +// +#define CSBN_BASE 0 +#define CSBN_CLICKED (1 + CSBN_BASE) +#define CSBN_HILIGHT (2 + CSBN_BASE) + +// +// Minimum size in pixels of a scrollbar thumb +// +#define MINTHUMBSIZE_NT4 8 +#define MINTHUMBSIZE_2000 6 + +//define some more hittest values for our cool-scrollbar +#define HTSCROLL_LEFT (SB_LINELEFT) +#define HTSCROLL_RIGHT (SB_LINERIGHT) +#define HTSCROLL_UP (SB_LINEUP) +#define HTSCROLL_DOWN (SB_LINEDOWN) +#define HTSCROLL_THUMB (SB_THUMBTRACK) +#define HTSCROLL_PAGEGUP (SB_PAGEUP) +#define HTSCROLL_PAGEGDOWN (SB_PAGEDOWN) +#define HTSCROLL_PAGELEFT (SB_PAGELEFT) +#define HTSCROLL_PAGERIGHT (SB_PAGERIGHT) + +#define HTSCROLL_NONE (-1) +#define HTSCROLL_NORMAL (-1) + +#define HTSCROLL_INSERTED (128) +#define HTSCROLL_PRE (32 | HTSCROLL_INSERTED) +#define HTSCROLL_POST (64 | HTSCROLL_INSERTED) + +/* + + Public interface to the Cool Scrollbar library + + +*/ + +BOOL WINAPI InitializeCoolSB(HWND hwnd); +HRESULT WINAPI UninitializeCoolSB (HWND hwnd); + +BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size); +BOOL WINAPI CoolSB_IsThumbTracking(HWND hwnd); +BOOL WINAPI CoolSB_IsCoolScrollEnabled(HWND hwnd); + +// +BOOL WINAPI CoolSB_EnableScrollBar (HWND hwnd, int wSBflags, UINT wArrows); +BOOL WINAPI CoolSB_GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi); +int WINAPI CoolSB_GetScrollPos (HWND hwnd, int nBar); +BOOL WINAPI CoolSB_GetScrollRange (HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos); + +// +int WINAPI CoolSB_SetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw); +int WINAPI CoolSB_SetScrollPos (HWND hwnd, int nBar, int nPos, BOOL fRedraw); +int WINAPI CoolSB_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw); +BOOL WINAPI CoolSB_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow); + +// +// Scrollbar dimension functions +// +BOOL WINAPI CoolSB_SetSize (HWND hwnd, int wBar, int nLength, int nWidth); + +// +// Set the visual nature of a scrollbar (flat, normal etc) +// +BOOL WINAPI CoolSB_SetStyle (HWND hwnd, int wBar, UINT nStyle); +BOOL WINAPI CoolSB_SetThumbAlways (HWND hwnd, int wBar, BOOL fThumbAlways); + +// +// Scrollbar button structure, for inserted buttons only +// +typedef struct +{ + UINT fMask; //which members are in use + UINT uPlacement; //is this button to the left/right (above/below) of the scrollbar?? + UINT uCmdId; //command identifier (WM_COMMAND value to send) + UINT uButType; // + UINT uState; //toggled etc + int nSize; //size in pixels. -1 for autosize + + HBITMAP hBmp; //handle to a bitmap to use as the button face + HENHMETAFILE hEmf; //handle to an enhanced metafile + + HCURSOR hCurs; //handle to a user-supplied mouse cursor to apply + //to this button + + int nSizeReserved; //internal variable used for resizing + int nMinSize; //min size + int nMaxSize; //max size + +} SCROLLBUT; + +BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb); +BOOL WINAPI CoolSB_ModifyButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb); +BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd); +BOOL WINAPI CoolSB_GetButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb); + +void WINAPI CoolSB_SetESBProc(void *proc); + +typedef struct +{ + NMHDR hdr; + DWORD dwDrawStage; + HDC hdc; + RECT rect; + UINT uItem; + UINT uState; + UINT nBar; + +} NMCSBCUSTOMDRAW; + +typedef struct +{ + NMHDR hdr; + RECT rect; + POINT pt; + UINT uCmdId; + UINT uState; + int nBar; +} NMCOOLBUTMSG; + +/* +typedef struct +{ + NMHDR hdr; + DWORD dwDrawStage; + HDC hdc; + RECT rect; + UINT uCmdId; + UINT uState; + +} NMCOOLBUTTON_CUSTOMDRAW; +*/ + + +// +// Define the WM_NOTIFY code value for cool-scrollbar custom drawing +// +#define NM_COOLSB_CUSTOMDRAW (0-0xfffU) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/Clist_nicer/src/Coolsb/userdefs.h b/plugins/Clist_nicer/src/Coolsb/userdefs.h new file mode 100644 index 0000000000..ea7ea1fe92 --- /dev/null +++ b/plugins/Clist_nicer/src/Coolsb/userdefs.h @@ -0,0 +1,79 @@ +#ifndef _USERDEFINES_INCLUDED +#define _USERDEFINES_INCLUDED + +/* + + Define these values to alter the various + features of the coolscroll library. If you don't want + a certain feature, then you might be able to reduce the + size of your app by a few kb... + +*/ + +/* allow inserted buttons. Without this, all button code will + be excluded, resulting in a smaller build (about 4kb less). This + may not seem much, but it is a 25% reduction! */ +//#define INCLUDE_BUTTONS + +/* Allow user-resizable buttons. Makes no difference if INCLUDE_BUTTONS + is not defined for the project */ +#define RESIZABLE_BUTTONS + +/* Include tooltip support for inserted buttons. Without this, no + tooltip requests (TTN_GETDISPINFO's) will be sent to the window */ +//#define COOLSB_TOOLTIPS + +/* Define this to include the custom-draw support */ +#define CUSTOM_DRAW + +/* Define to enable WM_NOTIFY messages to be sent for mouse event */ +#define NOTIFY_MOUSE + +/* Define this value to make the horizontal scrollbar stay visible even + if the window is sized to small vertically. Normal scrollbars always leave + a 1-pixel line of "client" area before hiding the horizontal scrollbar. This + value allows the window to be sized so the client area totally disappears if + sized too small */ +//#define COOLSB_FILLWINDOW + +/* minimum size of scrollbar before inserted buttons are + hidden to make room when the window is sized too small */ +#define MIN_COOLSB_SIZE 24 + +/* min size of scrollbar when resizing a button, before the + resize is stopped because the scrollbar has gotten too small */ +#define MINSCROLLSIZE 50 + +/* define this to display the default mouse arrow whenever the + the mouse is released over a button which has a user-defined cursor. + not really very useful, just provides a different type of feedback */ +#undef HIDE_CURSOR_AFTER_MOUSEUP + +/* enable HOT_TRACKING to provide visual feedback when the mouse + moves over a scrollbar area (like Flat Scrollbars) */ +#define HOT_TRACKING + +/* enable FLAT_SCROLLBARS to include support for flat scrollbars + note that they must be enabled by the user first of all */ +#define FLAT_SCROLLBARS + +/* a normal scrollbar "snaps" its scroll-thumb back into position if + you move the mouse too far away from the window, whilst you are + dragging the thumb, that is. #undeffing this results in the thumb + never snapping back into position, no matter how far away you move + the mouse */ +#define SNAP_THUMB_BACK + +/* distance (in pixels) the mouse must move away from the thumb + during tracking to cause the thumb bar to snap back to its + starting place. Has no effect unless SNAP_THUMB_BACK is defined */ +#define THUMBTRACK_SNAPDIST 24 + +/* maximum number of inserted buttons per bar */ +#define MAX_COOLSB_BUTS 16 + +/* maximum number of coolsb windows per application. + Set to lower if you don't need many. */ +#define MAX_COOLSB 4 + +#endif /* _USERDEFINES_INCLUDED */ \ No newline at end of file diff --git a/plugins/Clist_nicer/src/Docking.cpp b/plugins/Clist_nicer/src/Docking.cpp new file mode 100644 index 0000000000..42feed1bee --- /dev/null +++ b/plugins/Clist_nicer/src/Docking.cpp @@ -0,0 +1,286 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE - done. + +*/ +#include "commonheaders.h" + +#define WM_DOCKCALLBACK (WM_USER+121) +#define WM_CREATEDOCKED (WM_USER+122) +#define EDGESENSITIVITY 3 + +#define DOCKED_NONE 0 +#define DOCKED_LEFT 1 +#define DOCKED_RIGHT 2 +static int docked; + +extern RECT cluiPos; + +static void Docking_GetMonitorRectFromPoint(POINT pt, RECT *rc) +{ + if ( API::pfnMonitorFromPoint ) { + MONITORINFO monitorInfo; + HMONITOR hMonitor = API::pfnMonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); // always returns a valid value + monitorInfo.cbSize = sizeof(MONITORINFO); + + if ( API::pfnGetMonitorInfo( hMonitor, &monitorInfo )) { + CopyMemory(rc, &monitorInfo.rcMonitor, sizeof(RECT)); + return; + } + } + + // "generic" win95/NT support, also serves as failsafe + rc->left = 0; + rc->top = 0; + rc->bottom = GetSystemMetrics(SM_CYSCREEN); + rc->right = GetSystemMetrics(SM_CXSCREEN); +} + +static void Docking_GetMonitorRectFromWindow(HWND hWnd, RECT *rc) +{ + POINT ptWindow; + GetWindowRect(hWnd, rc); + ptWindow.x = rc->left; + ptWindow.y = rc->top; + Docking_GetMonitorRectFromPoint(ptWindow, rc); +} + +static void Docking_AdjustPosition(HWND hwnd, RECT *rcDisplay, RECT *rc) +{ + APPBARDATA abd; + + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = hwnd; + abd.uEdge = docked == DOCKED_LEFT ? ABE_LEFT : ABE_RIGHT; + abd.rc = *rc; + abd.rc.top = rcDisplay->top; + abd.rc.bottom = rcDisplay->bottom; + if (docked == DOCKED_LEFT) { + abd.rc.right = rcDisplay->left + (abd.rc.right - abd.rc.left) - cfg::dat.bClipBorder; + abd.rc.left = rcDisplay->left - cfg::dat.bClipBorder; + } else { + abd.rc.left = rcDisplay->right - (abd.rc.right - abd.rc.left) + cfg::dat.bClipBorder; + abd.rc.right = rcDisplay->right + cfg::dat.bClipBorder; + } + SHAppBarMessage(ABM_SETPOS, &abd); + *rc = abd.rc; +} + +int Docking_IsDocked(WPARAM wParam, LPARAM lParam) +{ + return docked; +} + +int Docking_ProcessWindowMessage(WPARAM wParam, LPARAM lParam) +{ + APPBARDATA abd; + static int draggingTitle; + MSG *msg = (MSG *) wParam; + + if (msg->message == WM_DESTROY) + cfg::writeByte("CList", "Docked", (BYTE) docked); + if (!docked && msg->message != WM_CREATE && msg->message != WM_MOVING && msg->message != WM_CREATEDOCKED && msg->message != WM_MOVE) + return 0; + switch (msg->message) { + case WM_CREATE: + //if(GetSystemMetrics(SM_CMONITORS)>1) return 0; + if (cfg::getByte("CList", "Docked", 0)) + PostMessage(msg->hwnd, WM_CREATEDOCKED, 0, 0); + draggingTitle = 0; + return 0; + case WM_CREATEDOCKED: + //we need to post a message just after creation to let main message function do some work + docked = (int) (char) cfg::getByte("CList", "Docked", 0); + if (IsWindowVisible(msg->hwnd) && !IsIconic(msg->hwnd)) { + RECT rc, rcMonitor; + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = msg->hwnd; + abd.lParam = 0; + abd.uCallbackMessage = WM_DOCKCALLBACK; + SHAppBarMessage(ABM_NEW, &abd); + GetWindowRect(msg->hwnd, &rc); + Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor); + Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc); + MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); + } + break; + case WM_ACTIVATE: + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = msg->hwnd; + SHAppBarMessage(ABM_ACTIVATE, &abd); + return 0; + case WM_WINDOWPOSCHANGED: + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = msg->hwnd; + SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd); + return 0; + case WM_MOVING: + { + RECT rcMonitor; + POINT ptCursor; + + // stop early + if (GetAsyncKeyState(VK_CONTROL) & 0x8000) + return 0; + + // GetMessagePos() is no good, position is always unsigned + GetCursorPos(&ptCursor); + Docking_GetMonitorRectFromPoint(ptCursor, &rcMonitor); + + if ((ptCursor.x < rcMonitor.left + EDGESENSITIVITY) || (ptCursor.x >= rcMonitor.right - EDGESENSITIVITY)) { + if (!(GetWindowLongPtr(msg->hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)) { + SendMessage(msg->hwnd, CLUIINTM_REDRAW, 0, 0); + MessageBox(0, TranslateT("The clist cannot be docked when using the default title bar and border. Use a toolwindow or borderless style instead."), + TranslateT("Clist docking"), MB_OK); + return 0; + } + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = msg->hwnd; + abd.lParam = 0; + abd.uCallbackMessage = WM_DOCKCALLBACK; + SHAppBarMessage(ABM_NEW, &abd); + if (ptCursor.x < rcMonitor.left + EDGESENSITIVITY) + docked = DOCKED_LEFT; + else + docked = DOCKED_RIGHT; + SendMessage(msg->hwnd, WM_LBUTTONUP, 0, MAKELPARAM(ptCursor.x, ptCursor.y)); + GetWindowRect(msg->hwnd, (LPRECT) msg->lParam); + Docking_AdjustPosition(msg->hwnd, (LPRECT) &rcMonitor, (LPRECT) msg->lParam); + PostMessage(msg->hwnd, CLUIINTM_REDRAW, 0, 0); + return TRUE; + } + return 0; + } + case WM_MOVE: + { + if (docked) { + RECT rc, rcMonitor; + Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor); + GetWindowRect(msg->hwnd, &rc); + Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc); + MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); + return 1; + } + return 0; + } + case WM_SIZING: + { + RECT rcMonitor; + Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor); + Docking_AdjustPosition(msg->hwnd, &rcMonitor, (LPRECT) msg->lParam); + *((LRESULT *) lParam) = TRUE; + return TRUE; + } + case WM_SHOWWINDOW: + if (msg->lParam) + return 0; + if ((msg->wParam && docked < 0) || (!msg->wParam && docked > 0)) + docked = -docked; + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = msg->hwnd; + if (msg->wParam) { + RECT rc, rcMonitor; + Docking_GetMonitorRectFromWindow(msg->hwnd, &rcMonitor); + abd.lParam = 0; + abd.uCallbackMessage = WM_DOCKCALLBACK; + SHAppBarMessage(ABM_NEW, &abd); + GetWindowRect(msg->hwnd, &rc); + Docking_AdjustPosition(msg->hwnd, &rcMonitor, &rc); + MoveWindow(msg->hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE); + } else { + SHAppBarMessage(ABM_REMOVE, &abd); + } + return 0; + case WM_NCHITTEST: + { + LONG result; + result = DefWindowProc(msg->hwnd, WM_NCHITTEST, msg->wParam, msg->lParam); + if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT || result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT) { + *((LRESULT *) lParam) = HTCLIENT; return TRUE; + } + if (docked == DOCKED_LEFT && result == HTLEFT) { + *((LRESULT *) lParam) = HTCLIENT; return TRUE; + } + if (docked == DOCKED_RIGHT && result == HTRIGHT) { + *((LRESULT *) lParam) = HTCLIENT; return TRUE; + } + return 0; + } + case WM_SYSCOMMAND: + if ((msg->wParam & 0xFFF0) != SC_MOVE) + return 0; + SetActiveWindow(msg->hwnd); + SetCapture(msg->hwnd); + draggingTitle = 1; + *((LRESULT *) lParam) = 0; + return TRUE; + case WM_MOUSEMOVE: + if (!draggingTitle) + return 0; { + RECT rc; + POINT pt; + GetClientRect(msg->hwnd, &rc); + if (((docked == DOCKED_LEFT || docked == -DOCKED_LEFT) && (short) LOWORD(msg->lParam) > rc.right) || ((docked == DOCKED_RIGHT || docked == -DOCKED_RIGHT) && (short) LOWORD(msg->lParam) < 0)) { + ReleaseCapture(); + draggingTitle = 0; + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = msg->hwnd; + SHAppBarMessage(ABM_REMOVE, &abd); + docked = 0; + GetCursorPos(&pt); + PostMessage(msg->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pt.x, pt.y)); + SetWindowPos(msg->hwnd, 0, pt.x - rc.right / 2, pt.y - GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYSMCAPTION) / 2, cluiPos.right, cluiPos.bottom, SWP_NOZORDER); + } + return 1; + } + case WM_LBUTTONUP: + if (draggingTitle) { + ReleaseCapture(); + draggingTitle = 0; + } + return 0; + case WM_DOCKCALLBACK: + switch (msg->wParam) { + case ABN_WINDOWARRANGE: + ShowWindow(msg->hwnd, msg->lParam ? SW_HIDE : SW_SHOW); + break; + } + return TRUE; + case WM_DESTROY: + if (docked > 0) { + ZeroMemory(&abd, sizeof(abd)); + abd.cbSize = sizeof(abd); + abd.hWnd = msg->hwnd; + SHAppBarMessage(ABM_REMOVE, &abd); + } + return 0; + } + return 0; +} diff --git a/plugins/Clist_nicer/src/Include/alphablend.h b/plugins/Clist_nicer/src/Include/alphablend.h new file mode 100644 index 0000000000..de0e7c4fa8 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/alphablend.h @@ -0,0 +1,30 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +void __inline gradientVertical(UCHAR *ubRedFinal, UCHAR *ubGreenFinal, UCHAR *ubBlueFinal, + ULONG ulBitmapHeight, UCHAR ubRed, UCHAR ubGreen, UCHAR ubBlue, UCHAR ubRed2, + UCHAR ubGreen2, UCHAR ubBlue2, DWORD FLG_GRADIENT, BOOL transparent, UINT32 y, UCHAR *ubAlpha); + +void __inline gradientHorizontal( UCHAR *ubRedFinal, UCHAR *ubGreenFinal, UCHAR *ubBlueFinal, + ULONG ulBitmapWidth, UCHAR ubRed, UCHAR ubGreen, UCHAR ubBlue, UCHAR ubRed2, + UCHAR ubGreen2, UCHAR ubBlue2, DWORD FLG_GRADIENT, BOOL transparent, UINT32 x, UCHAR *ubAlpha); \ No newline at end of file diff --git a/plugins/Clist_nicer/src/Include/clc.h b/plugins/Clist_nicer/src/Include/clc.h new file mode 100644 index 0000000000..879fc52553 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/clc.h @@ -0,0 +1,632 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clc.h 13850 2011-09-10 03:26:59Z borkra $ + * + */ + +#define MAXEXTRACOLUMNS 16 + +#define INTM_XSTATUSCHANGED (WM_USER+26) +#define INTM_METACHANGEDEVENT (WM_USER+27) +#define INTM_CODEPAGECHANGED (WM_USER+28) +//#define INTM_CLIENTCHANGED (WM_USER+29) +#define INTM_AVATARCHANGED (WM_USER+30) +#define INTM_STATUSMSGCHANGED (WM_USER+31) +#define INTM_SORTCLC (WM_USER+32) +#define INTM_STATUSCHANGED (WM_USER+33) +#define INTM_METACHANGED (WM_USER+34) +#define INTM_INVALIDATECONTACT (WM_USER+35) +#define INTM_FORCESORT (WM_USER+36) + +#define DEFAULT_TITLEBAR_HEIGHT 18 + +#define CLS_SKINNEDFRAME 0x0800 //this control will be the main contact list (v. 0.3.4.3+ 2004/11/02) + +#define TIMERID_RENAME 10 +#define TIMERID_DRAGAUTOSCROLL 11 +#define TIMERID_INFOTIP 13 +#define TIMERID_SORT 15 +#define TIMERID_REFRESH 18 +#define TIMERID_PAINT 19 +struct ClcGroup; + +#define CONTACTF_ONLINE 1 +#define CONTACTF_INVISTO 2 +#define CONTACTF_VISTO 4 +#define CONTACTF_NOTONLIST 8 +#define CONTACTF_CHECKED 16 +#define CONTACTF_IDLE 32 +#define CONTACTF_STICKY 64 +#define CONTACTF_PRIORITY 128 + +#define STATUSMSG_XSTATUSID 1 +#define STATUSMSG_XSTATUSNAME 2 +#define STATUSMSG_CLIST 4 +#define STATUSMSG_YIM 8 +#define STATUSMSG_GG 16 +#define STATUSMSG_XSTATUS 32 + +#define STATUSMSG_NOTFOUND 0 + +#define SMSG_MAXLEN 700 + +#define EXTRAIMAGECACHESIZE 1000 + +// extra cache contact flags + +#define ECF_RTLNICK 1 +#define ECF_RTLSTATUSMSG 2 +#define ECF_FORCEAVATAR 4 +#define ECF_HIDEAVATAR 8 +#define ECF_FORCEOVERLAY 16 +#define ECF_HIDEOVERLAY 32 +#define ECF_FORCELOCALTIME 64 +#define ECF_HIDELOCALTIME 128 +#define ECF_FORCEVISIBILITY 256 +#define ECF_HIDEVISIBILITY 512 +#define ECF_HASREALTIMEZONE 1024 + +// other contact flags (struct ClCContact; + +#define ECF_AVATAR 1 +#define ECF_SECONDLINE 2 + +struct ContactFloater { + struct ContactFloater *pNextFloater; + HWND hwnd; + HDC hdc; + HBITMAP hbm, hbmOld; + HANDLE hContact; +}; + +typedef struct ContactFloater CONTACTFLOATER; + +#define DSPF_CENTERSTATUSICON 1 +#define DSPF_DIMIDLE 2 +#define DSPF_NOFFLINEAVATARS 4 +#define DSPF_SHOWLOCALTIME 8 +#define DSPF_LOCALTIMESELECTIVE 16 +#define DSPF_DONTSEPARATEOFFLINE 32 +#define DSPF_CENTERGROUPNAMES 64 + +#define EXICON_COUNT 11 + +/* Extra icons settings */ +typedef struct _OrderTreeData +{ + BYTE ID; + const TCHAR * Name; + BYTE Position; + BOOL Visible; + BOOL fReserved; +} *PORDERTREEDATA, ORDERTREEDATA; + +struct DisplayProfile +{ + DWORD dwFlags; + DWORD dwExtraImageMask; + int exIconScale; + BOOL bCenterStatusIcons; + BOOL bDimIdle, bNoOfflineAvatars, bShowLocalTime, bShowLocalTimeSelective, bDontSeparateOffline, bCenterGroupNames; + BYTE dualRowMode; + COLORREF avatarBorder; + DWORD avatarRadius; + int avatarSize; + DWORD clcExStyle; + DWORD clcOfflineModes; + BYTE sortOrder[3], bUseDCMirroring, bGroupAlign; + BYTE avatarPadding; + BYTE bLeftMargin, bRightMargin, bRowSpacing, bGroupIndent, bRowHeight, bGroupRowHeight; + BYTE exIconOrder[EXICON_COUNT]; +}; +typedef struct DisplayProfile DISPLAYPROFILE; + +/* + * a set of 4 (online, offline, selected, hottracked) display profiles + */ + +struct DisplayProfileSet { + UINT uID; + TCHAR tszName[60]; + DISPLAYPROFILE dp[4]; +}; +typedef struct DisplayProfileSet DISPLAYPROFILESET; + +#define DSP_PROFILES_MODULE "CLN_DspProfiles" // db module for display profiles + +struct TExtraCache +{ + BYTE iExtraImage[MAXEXTRACOLUMNS]; + HANDLE hContact; + HANDLE hTimeZone; + DWORD iExtraValid; + BYTE valid; + TCHAR *statusMsg; + BYTE bStatusMsgValid; + DWORD dwCFlags; + DWORD dwDFlags; // display flags for caching only + DWORD dwXMask; // local extra icon mask, calculated from CLN_xmask + StatusItems_t *status_item, *proto_status_item; + CONTACTFLOATER *floater; + DWORD dwLastMsgTime; + DWORD msgFrequency; + BOOL isChatRoom; +}; + +struct ClcContact : public ClcContactBase +{ + BOOL bIsMeta; + HANDLE hSubContact; + BYTE xStatus; + char *metaProto; + DWORD codePage; + struct avatarCacheEntry *ace; + WORD wStatus; + int extraCacheEntry; + int avatarLeft, extraIconRightBegin; + int isRtl; + DWORD cFlags; + BYTE bSecondLine; +}; + +#define DRAGSTAGE_NOTMOVED 0 +#define DRAGSTAGE_ACTIVE 1 +#define DRAGSTAGEM_STAGE 0x00FF +#define DRAGSTAGEF_MAYBERENAME 0x8000 +#define DRAGSTAGEF_OUTSIDE 0x4000 + +#define FONTID_CONTACTS 0 +#define FONTID_INVIS 1 +#define FONTID_OFFLINE 2 +#define FONTID_NOTONLIST 3 +#define FONTID_GROUPS 4 +#define FONTID_GROUPCOUNTS 5 +#define FONTID_DIVIDERS 6 +#define FONTID_OFFINVIS 7 +#define FONTID_STATUS 8 +#define FONTID_FRAMETITLE 9 +#define FONTID_EVENTAREA 10 +#define FONTID_TIMESTAMP 11 +#define FONTID_LAST FONTID_TIMESTAMP + +struct ClcData : public ClcDataBase +{ + int *row_heights; + int row_heights_size; + int row_heights_allocated; + + int row_border; + int min_row_heigh, group_row_height; + + int currentFontID; + int rightMargin; + BYTE SelectMode; + BYTE isMultiSelect; + HWND hwndParent; + DWORD lastSort; + BOOL bNeedPaint, bisEmbedded, bHideSubcontacts; + DWORD lastRepaint; + BOOL forceScroll; + int oldSelection; +}; + +//#define CLUI_FRAME_SHOWTOPBUTTONS 1 +#define CLUI_FRAME_SHOWBOTTOMBUTTONS 2 +#define CLUI_SHOWCLIENTICONS 4 +#define CLUI_SHOWVISI 8 +#define CLUI_FRAME_CLISTSUNKEN 16 +#define CLUI_SHOWXSTATUS 32 +#define CLUI_FRAME_BUTTONSFLAT 64 +#define CLUI_FRAME_BUTTONSCLASSIC 128 +#define CLUI_USEMETAICONS 256 +#define CLUI_FRAME_AUTOHIDENOTIFY 512 +#define CLUI_FRAME_USEXSTATUSASSTATUS 1024 +#define CLUI_STICKYEVENTS 2048 +#define CLUI_FRAME_SBARSHOW 4096 +#define CLUI_STATUSASTEXT 8192 +#define CLUI_FULLROWSELECT 16384 +#define CLUI_FRAME_EVENTAREASUNKEN 32768 +//#define CLUI_FRAME_BUTTONBARSUNKEN 65536 +#define CLUI_FRAME_AVATARS 0x20000 +#define CLUI_FRAME_AVATARSLEFT 0x40000 +#define CLUI_FRAME_GDIPLUS 0x80000 +#define CLUI_FRAME_AVATARBORDER 0x100000 +#define CLUI_FRAME_STATUSICONS 0x200000 +#define CLUI_FRAME_AVATARSRIGHTWITHNICK 0x400000 +#define CLUI_FRAME_TRANSPARENTAVATAR 0x800000 +#define CLUI_FRAME_ROUNDAVATAR 0x1000000 +#define CLUI_FRAME_ALWAYSALIGNNICK 0x2000000 +#define CLUI_FRAME_AVATARSRIGHT 0x4000000 +#define CLUI_FRAME_SHOWSTATUSMSG 0x8000000 +#define CLUI_FRAME_OVERLAYICONS 0x10000000 +#define CLUI_FRAME_SELECTIVEICONS 0x20000000 +#define CLUI_FRAME_ROUNDEDFRAME 0x40000000 +#define CLUI_FRAME_NOGROUPICON 0x80000000 + +#define MULTIROW_NEVER 0 +#define MULTIROW_ALWAYS 1 +#define MULTIROW_IFSPACE 2 +#define MULTIROW_IFNEEDED 3 + +#define CLUI_USE_FLOATER 1 +#define CLUI_FLOATER_AUTOHIDE 2 +#define CLUI_FLOATER_EVENTS 4 + +#define CLC_GROUPALIGN_LEFT 0 +#define CLC_GROUPALIGN_RIGHT 1 +#define CLC_GROUPALIGN_AUTO 2 + +struct TCluiData { + DWORD dwFlags; + DWORD topOffset, bottomOffset; + int statusBarHeight; + int soundsOff; + BYTE tabSRMM_Avail; + BYTE bMetaAvail; + BYTE bAvatarServiceAvail; + HICON hIconVisible, hIconInvisible, hIconChatactive, hIconConnecting; + DWORD winFlags; + DWORD winFlagsEx; + int notifyActive; + int hIconNotify; + HMENU hMenuNotify; + int iLastEventAdded; + int wNextMenuID; + HANDLE hUpdateContact; + DWORD sortTimer; + TCHAR *szNoEvents; + BOOL forceResize; + BOOL neeedSnap; + COLORREF avatarBorder; + HBRUSH hBrushAvatarBorder, hBrushColorKey; + HBRUSH hBrushCLCBk; + DWORD avatarRadius; + int avatarSize; + BOOL bForceRefetchOnPaint; + BYTE dualRowMode; + BYTE avatarPadding; + BYTE cornerRadius; + BYTE isTransparent; + BYTE alpha, autoalpha; + BYTE fadeinout; + BYTE autosize; + BYTE gapBetweenFrames; + BYTE titleBarHeight; + DWORD dwExtraImageMask; + BYTE bClipBorder, bRowSpacing; + HBITMAP bmpBackground, hbmBgOld, hbmBg; + HDC hdcBg; + HDC hdcPic; + HBITMAP hbmPicOld; + BITMAP bminfoBg; + SIZE dcSize; + POINT ptW; + BOOL bWallpaperMode; + BOOL bNoOfflineAvatars; + BOOL bEventAreaEnabled; + BOOL bFullTransparent; + BOOL bDblClkAvatars; + BOOL bApplyIndentToBg; + BOOL bEqualSections; + DWORD bFilterEffective; + BOOL bCenterStatusIcons; + BOOL bSkinnedToolbar; + BOOL bSkinnedStatusBar; + BOOL bUsePerProto; + BOOL bOverridePerStatusColors; + BOOL bDontSeparateOffline; + TCHAR groupFilter[2048]; + char protoFilter[2048]; + char varFilter[2048]; + DWORD lastMsgFilter; + char current_viewmode[256], old_viewmode[256]; + BYTE boldHideOffline; + DWORD statusMaskFilter; + DWORD stickyMaskFilter; + DWORD filterFlags; + COLORREF colorkey; + char szMetaName[256]; + BOOL bMetaEnabled; + BOOL bSecIMAvail; + BOOL bNoTrayTips; + int exIconScale; + BOOL bShowLocalTime; + BOOL bShowLocalTimeSelective; + BOOL bShowXStatusOnSbar; + BOOL bLayeredHack; + HPEN hPen3DBright, hPen3DDark; + BYTE bSkinnedButtonMode; + BYTE bFirstRun; + BYTE bUseDCMirroring; + BYTE bCLeft, bCRight, bCTop, bCBottom; + BYTE bUseFloater; + BYTE fullyInited; + BYTE bAutoExpandGroups; + SIZE szOldCTreeSize; + BYTE bWantFastGradients, bUseFastGradients; + BYTE sortOrder[3]; + BYTE bGroupAlign; + BYTE bSkinnedScrollbar; + DWORD langPackCP; + BOOL fOnDesktop; + int group_padding; + DWORD t_now; + BYTE exIconOrder[EXICON_COUNT]; + BOOL realTimeSaving; + TCHAR tszProfilePath[MAX_PATH]; + FILETIME ft; + SYSTEMTIME st; +}; + +#define SORTBY_NAME 1 +#define SORTBY_PROTO 2 +#define SORTBY_STATUS 3 +#define SORTBY_LASTMSG 4 +#define SORTBY_FREQUENCY 5 +#define SORTBY_PRIOCONTACTS 6 + +struct IconDesc { + char *szName; + char *szDesc; + int uId; // icon ID +}; + +struct NotifyMenuItemExData { + HANDLE hContact; + int iIcon; // icon index in the image list + HICON hIcon; // corresponding icon handle + HANDLE hDbEvent; +}; + +// #define NOTIFY_HEIGHT 24 + +struct TrayIconInfo { + union { + HICON hIcon; + int iIcon; + }; +}; + +typedef struct { + char protoName[50]; + UINT menuID; + BOOL added; + HICON hIcon; +} protoMenu; + +//clcidents.c +int FindItem(HWND hwnd, struct ClcData *dat, HANDLE hItem, struct ClcContact **contact, struct ClcGroup **subgroup, int *isVisible); +HANDLE ContactToItemHandle(struct ClcContact *contact, DWORD *nmFlags); + +//clcitems.c +void RebuildEntireList(HWND hwnd, struct ClcData *dat); +void SaveStateAndRebuildList(HWND hwnd, struct ClcData *dat); +DWORD INTSORT_GetLastMsgTime(HANDLE hContact); + +//clcmsgs.c +LRESULT ProcessExternalMessages(HWND hwnd, struct ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam); + +//clcutils.c +void SetGroupExpand(HWND hwnd, struct ClcData *dat, struct ClcGroup *group, int newState); +void DoSelectionDefaultAction(HWND hwnd, struct ClcData *dat); +int FindRowByText(HWND hwnd, struct ClcData *dat, const TCHAR *text, int prefixOk); +void BeginRenameSelection(HWND hwnd, struct ClcData *dat); +int HitTest(HWND hwnd, struct ClcData *dat, int testx, int testy, struct ClcContact **contact, struct ClcGroup **group, DWORD *flags); +void ScrollTo(HWND hwnd, struct ClcData *dat, int desty, int noSmooth); +void RecalcScrollBar(HWND hwnd, struct ClcData *dat); +size_t MY_pathToRelative(const TCHAR *pSrc, TCHAR *pOut); +size_t MY_pathToAbsolute(const TCHAR *pSrc, TCHAR *pOut); + +#define DROPTARGET_OUTSIDE 0 +#define DROPTARGET_ONSELF 1 +#define DROPTARGET_ONNOTHING 2 +#define DROPTARGET_ONGROUP 3 +#define DROPTARGET_ONCONTACT 4 +#define DROPTARGET_INSERTION 5 +int GetDropTargetInformation(HWND hwnd, struct ClcData *dat, POINT pt); +void LoadClcOptions(HWND hwnd, struct ClcData *dat); +void RecalculateGroupCheckboxes(HWND hwnd, struct ClcData *dat); +void SetGroupChildCheckboxes(struct ClcGroup *group, int checked); +BYTE GetCachedStatusMsg(int iExtraCacheEntry, char *szProto); +int __fastcall GetStatusOnlineness(int status); +void GetExtendedInfo(struct ClcContact *contact, struct ClcData *dat); +extern LRESULT CALLBACK NewStatusBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +void HideShowNotifyFrame(); +DWORD GetCLUIWindowStyle(BYTE style); +void ApplyCLUIBorderStyle(HWND hwnd); + +int FrameNCCalcSize(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar); +int FrameNCPaint(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam, BOOL hasTitleBar); + +void FreeProtocolData( void ); + +void GetClientID(struct ClcContact *contact, char *client); +int LoadCLCButtonModule(void); +void SetButtonStates(HWND hwnd); +void ConfigureCLUIGeometry(int mode); +void IcoLibReloadIcons(); +int CompareContacts(const struct ClcContact* p1, const struct ClcContact* p2); +void PaintNotifyArea(HDC hDC, RECT *rc); +int AvatarChanged(WPARAM wParam, LPARAM lParam); +void ConfigureFrame(); +void ConfigureEventArea(HWND hwnd); +void ClearIcons(int mode); +void SkinDrawBg(HWND hwnd, HDC hdc); +int GetBasicFontID(struct ClcContact * contact); +extern int __fastcall CLVM_GetContactHiddenStatus(HANDLE hContact, char *szStatus, struct ClcData *dat); +void CreateViewModeFrame(); +int GetExtraCache(HANDLE hContact, char *szProto); +void ReloadExtraInfo(HANDLE hContact); +void LoadAvatarForContact(struct ClcContact *p); +void ApplyViewMode(const char *name); +DWORD CalcXMask(HANDLE hContact); +void ClcSetButtonState(int ctrlId, int status); + +//clcpaint.c +void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint); +void __inline PaintItem(HDC hdcMem, struct ClcGroup *group, struct ClcContact *contact, int indent, int y, struct ClcData *dat, int index, HWND hwnd, DWORD style, RECT *clRect, BOOL *bFirstNGdrawn, int groupCountsFontTopShift, int rowHeight); +void Reload3dBevelColors(); +void ReloadThemedOptions(); +void SetButtonToSkinned(); +void RTL_DetectAndSet(struct ClcContact *contact, HANDLE hContact); +void RTL_DetectGroupName(struct ClcContact *group); +void CLN_LoadAllIcons(BOOL mode); +void ReloadSkinItemsToCache(); +void SFL_RegisterWindowClass(), SFL_UnregisterWindowClass(); +void SFL_Create(); +void SFL_Destroy(); +void SFL_SetState(int iMode); +void SFL_SetSize(); +void SFL_PaintNotifyArea(); +void SFL_Update(HICON hIcon, int iIcon, HIMAGELIST hIml, const TCHAR *szText, BOOL refresh); + +void FLT_Update(struct ClcData *dat, struct ClcContact *contact); +int FLT_CheckAvail(); +void FLT_Create(int iEntry); +void FLT_SetSize(struct TExtraCache *centry, LONG width, LONG height); +void FLT_SyncWithClist(); +void FLT_ReadOptions(), FLT_WriteOptions(), FLT_RefreshAll(); + +//clcopts.c +int ClcOptInit(WPARAM wParam, LPARAM lParam); +DWORD GetDefaultExStyle(void); +void GetFontSetting(int i, LOGFONTA *lf, COLORREF *colour); +void CluiProtocolStatusChanged( int parStatus, const char* szProto ); + +void LoadSkinItemToCache(struct TExtraCache *cEntry, const char *szProto); + +// debugging support + +void _DebugTraceW(const wchar_t *fmt, ...); +#ifdef _CLN_GDIP +extern "C" void _DebugTraceA(const char *fmt, ...); +#else +void _DebugTraceA(const char *fmt, ...); +#endif + +// Docking.c + +int Docking_IsDocked(WPARAM wParam, LPARAM lParam); + +// Buttons + +#define BUTTONSETIMLICON (WM_USER+20) +#define BUTTONSETSKINNED (WM_USER+21) +#define BUTTONSETASMENUACTION (WM_USER+22) +#define BUTTONSETBTNITEM (WM_USER+23) + +// Menus + +void IMG_DeleteItems(); +int CoolSB_SetupScrollBar(); + +#define NIIF_INTERN_UNICODE 0x00000100 + +#define SETTING_WINDOWSTYLE_DEFAULT 0 + +#define SETTING_TRAYICON_SINGLE 0 +#define SETTING_TRAYICON_CYCLE 1 +#define SETTING_TRAYICON_MULTI 2 + +#define SETTING_STATE_HIDDEN 0 +#define SETTING_STATE_MINIMIZED 1 +#define SETTING_STATE_NORMAL 2 + +#define SETTING_BRINGTOFRONT_DEFAULT 0 + +#define SETTING_WINDOWSTYLE_TOOLWINDOW 1 +#define SETTING_WINDOWSTYLE_THINBORDER 2 +#define SETTING_WINDOWSTYLE_NOBORDER 3 + +#define EIMG_SHOW_RES0 8 +#define EIMG_SHOW_EMAIL 1 +#define EIMG_SHOW_WEB 2 +#define EIMG_SHOW_SMS 4 +#define EIMG_SHOW_ADV1 16 +#define EIMG_SHOW_ADV2 32 +#define EIMG_SHOW_ADV3 512 +#define EIMG_SHOW_CLIENT 64 +#define EIMG_SHOW_ADV4 1024 +#define EIMG_SHOW_RES1 128 +#define EIMG_SHOW_RES2 256 + +#define CLCHT_ONITEMEXTRAEX 0x1000 //on an extra icon, HIBYTE(HIWORD()) says which +#define CLCHT_ONAVATAR 0x2000 +#define CLCHT_ONITEMSPACE 0x4000 + +#define CLM_SETEXTRAIMAGEINT (CLM_FIRST+101) +#define CLM_SETSTICKY (CLM_FIRST+100) +#define CLM_ISMULTISELECT (CLM_FIRST+102) +#define CLM_SETEXTRAIMAGEINTMETA (CLM_FIRST+104) +#define CLM_GETSTATUSMSG (CLM_FIRST+105) +#define CLM_SETHIDESUBCONTACTS (CLM_FIRST+106) +#define CLM_TOGGLEPRIORITYCONTACT (CLM_FIRST+107) +#define CLM_QUERYPRIORITYCONTACT (CLM_FIRST+108) +#define CLM_TOGGLEFLOATINGCONTACT (CLM_FIRST+109) +#define CLM_QUERYFLOATINGCONTACT (CLM_FIRST+110) + +#define IDC_RESETMODES 110 +#define IDC_SELECTMODE 108 +#define IDC_CONFIGUREMODES 109 + +#define NR_CLIENTS 40 + +typedef BOOL (WINAPI *PGF)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG); + +/* + * floating stuff + */ + +#define FLT_SIMPLE 1 +#define FLT_AVATARS 2 +#define FLT_DUALROW 4 +#define FLT_EXTRAICONS 8 +#define FLT_SYNCWITHCLIST 16 +#define FLT_AUTOHIDE 32 +#define FLT_SNAP 64 +#define FLT_BORDER 128 +#define FLT_ROUNDED 256 +#define FLT_FILLSTDCOLOR 512 +#define FLT_SHOWTOOLTIPS 1024 + +typedef struct _floatopts { + DWORD dwFlags; + BYTE pad_left, pad_right, pad_top, pad_bottom; + DWORD width; + COLORREF border_colour; + BYTE trans, act_trans; + BYTE radius; + BYTE enabled; + BYTE def_hover_time; + WORD hover_time; +} FLOATINGOPTIONS; + +extern FLOATINGOPTIONS g_floatoptions; + + diff --git a/plugins/Clist_nicer/src/Include/clist.h b/plugins/Clist_nicer/src/Include/clist.h new file mode 100644 index 0000000000..1969039350 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/clist.h @@ -0,0 +1,48 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ +void LoadContactTree(void); +int IconFromStatusMode(const char *szProto, int status, HANDLE hContact, HICON *phIcon); +HTREEITEM GetTreeItemByHContact(HANDLE hContact); +void SortContacts(void); + +#define CLUIINTM_REDRAW (WM_USER+100) +#define CLUIINTM_STATUSBARUPDATE (WM_USER+101) +#define CLUIINTM_REMOVEFROMTASKBAR (WM_USER+102) + +#define CLVM_FILTER_PROTOS 1 +#define CLVM_FILTER_GROUPS 2 +#define CLVM_FILTER_STATUS 4 +#define CLVM_FILTER_VARIABLES 8 +#define CLVM_STICKY_CONTACTS 16 +#define CLVM_FILTER_STICKYSTATUS 32 +#define CLVM_FILTER_LASTMSG 64 +#define CLVM_FILTER_LASTMSG_OLDERTHAN 128 +#define CLVM_FILTER_LASTMSG_NEWERTHAN 256 + +#define CLVM_PROTOGROUP_OP 1 +#define CLVM_GROUPSTATUS_OP 2 +#define CLVM_AUTOCLEAR 4 +#define CLVM_INCLUDED_UNGROUPED 8 +#define CLVM_USELASTMSG 16 + +#define CLVM_MODULE "CLVM_W" diff --git a/plugins/Clist_nicer/src/Include/commonheaders.h b/plugins/Clist_nicer/src/Include/commonheaders.h new file mode 100644 index 0000000000..9d2c14f304 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/commonheaders.h @@ -0,0 +1,223 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: commonheaders.h 14157 2012-03-10 18:53:26Z george.hazan $ + * + */ + +#define MIRANDA_VER 0x0A00 + +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0501 + +#define _CRT_SECURE_NO_WARNINGS +#define EXTRA_ICON_COUNT 11 + +#undef FASTCALL + +#define TSAPI __stdcall +#define FASTCALL __fastcall + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "resource.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extbackg.h" +#include "clc.h" +#include + + +#include "clist.h" +#include "alphablend.h" +#include "rowheight_funcs.h" + + /* + * text shadow types (DrawThemeTextEx() / Vista+ uxtheme) + */ + #define TST_NONE 0 + #define TST_SINGLE 1 + #define TST_CONTINUOUS 2 + + typedef struct _DWM_THUMBNAIL_PROPERTIES + { + DWORD dwFlags; + RECT rcDestination; + RECT rcSource; + BYTE opacity; + BOOL fVisible; + BOOL fSourceClientAreaOnly; + } DWM_THUMBNAIL_PROPERTIES, *PDWM_THUMBNAIL_PROPERTIES; + + enum DWMWINDOWATTRIBUTE + { + DWMWA_NCRENDERING_ENABLED = 1, // [get] Is non-client rendering enabled/disabled + DWMWA_NCRENDERING_POLICY, // [set] Non-client rendering policy + DWMWA_TRANSITIONS_FORCEDISABLED, // [set] Potentially enable/forcibly disable transitions + DWMWA_ALLOW_NCPAINT, // [set] Allow contents rendered in the non-client area to be visible on the DWM-drawn frame. + DWMWA_CAPTION_BUTTON_BOUNDS, // [get] Bounds of the caption button area in window-relative space. + DWMWA_NONCLIENT_RTL_LAYOUT, // [set] Is non-client content RTL mirrored + DWMWA_FORCE_ICONIC_REPRESENTATION, // [set] Force this window to display iconic thumbnails. + DWMWA_FLIP3D_POLICY, // [set] Designates how Flip3D will treat the window. + DWMWA_EXTENDED_FRAME_BOUNDS, // [get] Gets the extended frame bounds rectangle in screen space + DWMWA_HAS_ICONIC_BITMAP, // [set] Indicates an available bitmap when there is no better thumbnail representation. + DWMWA_DISALLOW_PEEK, // [set] Don't invoke Peek on the window. + DWMWA_EXCLUDED_FROM_PEEK, // [set] LivePreview exclusion information + DWMWA_LAST + }; + + #define DWM_TNP_RECTDESTINATION 0x00000001 + #define DWM_TNP_RECTSOURCE 0x00000002 + #define DWM_TNP_OPACITY 0x00000004 + #define DWM_TNP_VISIBLE 0x00000008 + #define DWM_TNP_SOURCECLIENTAREAONLY 0x00000010 + + #define DWM_SIT_DISPLAYFRAME 0x00000001 // Display a window frame around the provided bitmap + + typedef HANDLE HTHUMBNAIL; + typedef HTHUMBNAIL* PHTHUMBNAIL; + +#ifndef BPPF_ERASE + typedef enum _BP_BUFFERFORMAT + { + BPBF_COMPATIBLEBITMAP, // Compatible bitmap + BPBF_DIB, // Device-independent bitmap + BPBF_TOPDOWNDIB, // Top-down device-independent bitmap + BPBF_TOPDOWNMONODIB // Top-down monochrome device-independent bitmap + } BP_BUFFERFORMAT; + + + typedef struct _BP_PAINTPARAMS + { + DWORD cbSize; + DWORD dwFlags; // BPPF_ flags + const RECT * prcExclude; + const BLENDFUNCTION * pBlendFunction; + } BP_PAINTPARAMS, *PBP_PAINTPARAMS; + + #define BPPF_ERASE 1 + #define BPPF_NOCLIP 2 + #define BPPF_NONCLIENT 4 +#endif + + typedef struct _DWM_BLURBEHIND + { + DWORD dwFlags; + BOOL fEnable; + HRGN hRgnBlur; + BOOL fTransitionOnMaximized; + } DWM_BLURBEHIND, *PDWM_BLURBEHIND; + + #define DWM_BB_ENABLE 1 + +#ifndef LOCALE_SISO3166CTRYNAME2 + #define LOCALE_SISO3166CTRYNAME2 0x00000068 // 3 character ISO country name, eg "USA Vista+ + #define LOCALE_SISO639LANGNAME2 0x00000067 // 3 character ISO abbreviated language name, eg "eng" +#endif + +#ifndef WM_DWMCOMPOSITIONCHANGED + #define WM_DWMCOMPOSITIONCHANGED 0x031E + #define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320 +#endif + +#ifndef WM_DWMSENDICONICTHUMBNAIL + #define WM_DWMSENDICONICTHUMBNAIL 0x0323 + #define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326 +#endif + +// shared vars +extern HINSTANCE g_hInst; +extern LONG g_cxsmIcon, g_cysmIcon; +extern StatusItems_t *StatusItems; +extern ImageItem *g_glyphItem; + +/* most free()'s are invalid when the code is executed from a dll, so this changes + all the bad free()'s to good ones, however it's still incorrect code. The reasons for not + changing them include: + + * DBFreeVariant has a CallService() lookup + * free() is executed in some large loops to do with clist creation of group data + * easy search and replace + +*/ + +#define MAX_REGS(_A_) (sizeof(_A_)/sizeof(_A_[0])) + +typedef int (__cdecl *pfnDrawAvatar)(HDC hdcOrig, HDC hdcMem, RECT *rc, struct ClcContact *contact, int y, struct ClcData *dat, int selected, WORD cstatus, int rowHeight); + +#define safe_sizeof(a) (sizeof((a)) / sizeof((a)[0])) + +BOOL __forceinline GetItemByStatus(int status, StatusItems_t *retitem); + +void DrawAlpha(HDC hdcwnd, PRECT rc, DWORD basecolor, int alpha, DWORD basecolor2, BOOL transparent, BYTE FLG_GRADIENT, BYTE FLG_CORNER, DWORD BORDERSTYLE, ImageItem *item); + +void CustomizeButton(HWND hWnd, bool bIsSkinned, bool bIsThemed, bool bIsFlat); + +void FreeAndNil( void** ); + +#if _MSC_VER >= 1500 + #define wEffects wReserved +#endif diff --git a/plugins/Clist_nicer/src/Include/config.h b/plugins/Clist_nicer/src/Include/config.h new file mode 100644 index 0000000000..4ee9983798 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/config.h @@ -0,0 +1,209 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: config.h 12709 2010-09-16 12:06:06Z borkra $ + * + */ + +#include + +#ifndef __CONFIG_H_ +#define __CONFIG_H_ + +#define DEFAULT_MODULE "Clist" + +#define IS_THEMED (API::sysState.isThemed) +#define IS_AERO (API::sysState.isAero) + +typedef int (__cdecl *pfnDrawAvatar)(HDC hdcOrig, HDC hdcMem, RECT *rc, struct ClcContact *contact, int y, struct ClcData *dat, int selected, WORD cstatus, int rowHeight); +typedef BOOL (WINAPI *pfnSetLayeredWindowAttributes_t)(HWND, COLORREF, BYTE, DWORD); +typedef BOOL (WINAPI *pfnUpdateLayeredWindow_t)(HWND, HDC, POINT *, SIZE *, HDC, POINT *, COLORREF, BLENDFUNCTION *, DWORD); +typedef HMONITOR (WINAPI *pfnMonitorFromPoint_t)(POINT,DWORD); +typedef HMONITOR (WINAPI *pfnMonitorFromWindow_t)(HWND,DWORD); +typedef BOOL (WINAPI *pfnGetMonitorInfo_t)(HMONITOR,LPMONITORINFO); +typedef BOOL (WINAPI *pfnTrackMouseEvent_t)(LPTRACKMOUSEEVENT); +typedef DWORD (WINAPI *pfnSetLayout_t )(HDC, DWORD); +typedef void (__cdecl *pfnDrawAlpha_t)(HDC hdcwnd, PRECT rc, DWORD basecolor, BYTE alpha, DWORD basecolor2, BOOL transparent, DWORD FLG_GRADIENT, DWORD FLG_CORNER, DWORD BORDERSTYLE, ImageItem *item); +typedef BOOL (WINAPI *pfnAlphaBlend_t)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION); + +typedef BOOL (WINAPI *pfnIsThemeActive_t)(); +typedef HANDLE (WINAPI *pfnOpenThemeData_t)(HWND, LPCWSTR); +typedef UINT (WINAPI *pfnDrawThemeBackground_t)(HANDLE, HDC, int, int, RECT *, RECT *); +typedef UINT (WINAPI *pfnCloseThemeData_t)(HANDLE); +typedef UINT (WINAPI *pfnDrawThemeText_t)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, RECT *); +typedef UINT (WINAPI *pfnDrawThemeTextEx_t)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, RECT *, const DTTOPTS *); +typedef BOOL (WINAPI *pfnIsThemeBackgroundPartiallyTransparent_t)(HANDLE, int, int); +typedef HRESULT (WINAPI *pfnDrawThemeParentBackground_t)(HWND, HDC, RECT *); +typedef HRESULT (WINAPI *pfnGetThemeBackgroundContentRect_t)(HANDLE, HDC, int, int, const RECT *, const RECT *); +typedef BOOL (WINAPI *pfnEnableThemeDialogTexture_t)(HANDLE, DWORD); +typedef HRESULT (WINAPI *pfnDwmExtendFrameIntoClientArea_t)(HWND hwnd, const MARGINS *margins); +typedef HRESULT (WINAPI *pfnDwmIsCompositionEnabled_t)(BOOL *); + +class CRTException : public std::runtime_error +{ +public: + CRTException(const char *szMsg, const TCHAR *szParam); + ~CRTException() {} + + void display() const; + +private: + TCHAR m_szParam[MAX_PATH]; +}; + +class cfg +{ +public: + static void init (); + + static DWORD getDword (const HANDLE hContact, const char *szModule, const char *szSetting, DWORD uDefault); + static DWORD getDword (const char *szModule, const char *szSetting, DWORD uDefault); + static DWORD getDword (const char *szSetting, DWORD uDefault); + + static WORD getWord (const HANDLE hContact, const char *szModule, const char *szSetting, WORD uDefault); + static WORD getWord (const char *szModule, const char *szSetting, WORD uDefault); + static WORD getWord (const char *szSetting, WORD uDefault); + + static int getByte (const HANDLE hContact, const char *szModule, const char *szSetting, int uDefault); + static int getByte (const char *szModule, const char *szSetting, int uDefault); + static int getByte (const char *szSetting, int uDefault); + + static INT_PTR getTString (const HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv); + static INT_PTR getString (const HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv); + + static INT_PTR writeDword (const HANDLE hContact, const char *szModule, const char *szSetting, DWORD value); + static INT_PTR writeDword (const char *szModule, const char *szSetting, DWORD value); + + static INT_PTR writeWord (const HANDLE hContact, const char *szModule, const char *szSetting, WORD value); + static INT_PTR writeWord (const char *szModule, const char *szSetting, WORD value); + + static INT_PTR writeByte (const HANDLE hContact, const char *szModule, const char *szSetting, BYTE value); + static INT_PTR writeByte (const char *szModule, const char *szSetting, BYTE value); + + static INT_PTR writeTString (const HANDLE hContact, const char *szModule, const char *szSetting, const TCHAR *st); + static INT_PTR writeString (const HANDLE hContact, const char *szModule, const char *szSetting, const char *st); + static int getCache (const HANDLE hContact, const char *szProto); + +public: + static TCluiData dat; + static ClcData* clcdat; + static TExtraCache* eCache; + static int nextCacheEntry, maxCacheEntry; + + static CRITICAL_SECTION cachecs; + + static bool shutDown; +}; + +struct TSysConfig { + bool isVistaPlus; + bool isSevenPlus; + bool isXPPlus; + bool uxThemeValid; + bool isWin2KPlus; +}; + +struct TSysState { + bool isThemed; + bool isAero; + bool isDwmActive; +}; + +class API +{ +public: + static void onInit (); + static void onUnload (); + static void updateState (); + + static void Ex_CopyEditToClipboard (HWND hWnd); + static INT_PTR CALLBACK Ex_DlgProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + static void Ex_Handler (); + static int Ex_ShowDialog (EXCEPTION_POINTERS *ep, const char *szFile, int line, TCHAR* szReason, bool fAllowContinue); + + + /* + * helpers + */ + + static BOOL SetLayeredWindowAttributes(HWND hWnd, COLORREF clr, BYTE alpha, DWORD dwFlags); + + static pfnSetLayeredWindowAttributes_t pfnSetLayeredWindowAttributes; + static pfnUpdateLayeredWindow_t pfnUpdateLayeredWindow; + static pfnMonitorFromPoint_t pfnMonitorFromPoint; + static pfnMonitorFromWindow_t pfnMonitorFromWindow; + static pfnGetMonitorInfo_t pfnGetMonitorInfo; + static pfnTrackMouseEvent_t pfnTrackMouseEvent; + // static pfnDrawAlpha_t pfnDrawAlpha; + static pfnSetLayout_t pfnSetLayout; + static PGF pfnGradientFill; + static pfnAlphaBlend_t pfnAlphaBlend; + + /* + * uxtheme + */ + + static pfnIsThemeActive_t pfnIsThemeActive; + static pfnOpenThemeData_t pfnOpenThemeData; + static pfnDrawThemeBackground_t pfnDrawThemeBackground; + static pfnCloseThemeData_t pfnCloseThemeData; + static pfnDrawThemeText_t pfnDrawThemeText; + static pfnDrawThemeTextEx_t pfnDrawThemeTextEx; + static pfnIsThemeBackgroundPartiallyTransparent_t pfnIsThemeBackgroundPartiallyTransparent; + static pfnDrawThemeParentBackground_t pfnDrawThemeParentBackground; + static pfnGetThemeBackgroundContentRect_t pfnGetThemeBackgroundContentRect; + static pfnEnableThemeDialogTexture_t pfnEnableThemeDialogTexture; + + static pfnDwmExtendFrameIntoClientArea_t pfnDwmExtendFrameIntoClientArea; + static pfnDwmIsCompositionEnabled_t pfnDwmIsCompositionEnabled; + + static TSysConfig sysConfig; + static TSysState sysState; + + static EXCEPTION_RECORD exRecord; + static CONTEXT exCtx; + static LRESULT exLastResult; + static char exSzFile[MAX_PATH]; + static TCHAR exReason[256]; + static int exLine; + static bool exAllowContinue; + + static HMODULE hUxTheme, hDwm; +}; + + +class Utils +{ +public: + static void TSAPI enableDlgControl(const HWND hwnd, UINT id, BOOL fEnable); + static void TSAPI showDlgControl(const HWND hwnd, UINT id, int showCmd); + static HMODULE loadSystemLibrary(const TCHAR* szFilename, bool useGetHandle = false); + +}; + +#endif /* __CONFIG_H_*/ diff --git a/plugins/Clist_nicer/src/Include/extBackg.h b/plugins/Clist_nicer/src/Include/extBackg.h new file mode 100644 index 0000000000..53450dcc0b --- /dev/null +++ b/plugins/Clist_nicer/src/Include/extBackg.h @@ -0,0 +1,97 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. +*/ + +#define ID_EXTBKIDLE 40081 +#define ID_EXTBKEXPANDEDGROUP 40082 +#define ID_EXTBKCOLLAPSEDDGROUP 40083 +#define ID_EXTBKEMPTYGROUPS 40084 +#define ID_EXTBKFIRSTITEM 40085 +#define ID_EXTBKSINGLEITEM 40086 +#define ID_EXTBKLASTITEM 40087 + + +#define ID_EXTBKFIRSTITEM_NG 40088 +#define ID_EXTBKSINGLEITEM_NG 40089 +#define ID_EXTBKLASTITEM_NG 40090 + +#define ID_EXTBKEVEN_CNTCTPOS 40091 +#define ID_EXTBKODD_CNTCTPOS 40092 + +#define ID_EXTBKSELECTION 40093 +#define ID_EXTBKHOTTRACK 40094 +#define ID_EXTBKFRAMETITLE 40095 +#define ID_EXTBKEVTAREA 40096 +#define ID_EXTBKSTATUSBAR 40097 +#define ID_EXTBKBUTTONBAR 40098 +#define ID_EXTBKBUTTONSPRESSED 40099 +#define ID_EXTBKBUTTONSNPRESSED 40100 +#define ID_EXTBKBUTTONSMOUSEOVER 40101 +#define ID_EXTBKTBBUTTONSPRESSED 40102 +#define ID_EXTBKTBBUTTONSNPRESSED 40103 +#define ID_EXTBKTBBUTTONMOUSEOVER 40104 +#define ID_EXTBKSTATUSFLOATER 40105 +#define ID_EXTBKOWNEDFRAMEBORDER 40106 +#define ID_EXTBKOWNEDFRAMEBORDERTB 40107 +#define ID_EXTBKAVATARFRAME 40108 +#define ID_EXTBKAVATARFRAMEOFFLINE 40109 +#define ID_EXTBKSCROLLBACK 40110 +#define ID_EXTBKSCROLLBACKLOWER 40111 +#define ID_EXTBKSCROLLTHUMB 40112 +#define ID_EXTBKSCROLLTHUMBHOVER 40113 +#define ID_EXTBKSCROLLTHUMBPRESSED 40114 +#define ID_EXTBKSCROLLBUTTON 40115 +#define ID_EXTBKSCROLLBUTTONHOVER 40116 +#define ID_EXTBKSCROLLBUTTONPRESSED 40117 +#define ID_EXTBKSCROLLARROWUP 40118 +#define ID_EXTBKSCROLLARROWDOWN 40119 +#define ID_EXTBK_LAST_D 40119 + +#define ID_EXTBKSEPARATOR 40200 + +BOOL CheckItem(int item, HWND hwndDlg); +BOOL isValidItem(void); +void extbk_export(char *file); +void extbk_import(char *file, HWND hwndDlg); + +void LoadExtBkSettingsFromDB(); +void IMG_LoadItems(); +void __fastcall IMG_RenderImageItem(HDC hdc, ImageItem *item, RECT *rc); +void IMG_InitDecoder(); +void LoadPerContactSkins(TCHAR *file); + +static void SaveCompleteStructToDB(); +StatusItems_t *GetProtocolStatusItem(const char *szProto); + +void OnListItemsChange(HWND hwndDlg); + +void UpdateStatusStructSettingsFromOptDlg(HWND hwndDlg, int index); + +void SaveNonStatusItemsSettings(HWND hwndDlg); + +void FillItemList(HWND hwndDlg); +void FillOptionDialogByCurrentSel(HWND hwndDlg); +void ReActiveCombo(HWND hwndDlg); +//BOOL __fastcall GetItemByStatus(int status, StatusItems_t *retitem); + +void FillOptionDialogByStatusItem(HWND hwndDlg, StatusItems_t *item); + diff --git a/plugins/Clist_nicer/src/Include/m_cln_skinedit.h b/plugins/Clist_nicer/src/Include/m_cln_skinedit.h new file mode 100644 index 0000000000..a1e69bb6e1 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/m_cln_skinedit.h @@ -0,0 +1,174 @@ + +/* + * services + */ + +#define MS_CLNSE_INVOKE "CLN_Skinedit/Invoke" +#define MS_CLNSE_FILLBYCURRENTSEL "CLN_Skinedit/FillByCurrentSel" + +/* + * data structs + */ + +typedef struct _tagImageItem { + char szName[40]; + HBITMAP hbm; + BYTE bLeft, bRight, bTop, bBottom; // sizing margins + BYTE alpha; + DWORD dwFlags; + HDC hdc; + HBITMAP hbmOld; + LONG inner_height, inner_width; + LONG width, height; + BLENDFUNCTION bf; + BYTE bStretch; + HBRUSH fillBrush; + LONG glyphMetrics[4]; + struct _tagImageItem *nextItem; +} ImageItem; + +typedef struct _tagButtonItem { + char szName[40]; + HWND hWnd; + LONG xOff, yOff; + LONG width, height; + ImageItem *imgNormal, *imgPressed, *imgHover; + LONG normalGlyphMetrics[4]; + LONG hoverGlyphMetrics[4]; + LONG pressedGlyphMetrics[4]; + DWORD dwFlags, dwStockFlags; + DWORD uId; + TCHAR szTip[256]; + char szService[256]; + char szModule[256], szSetting[256]; + BYTE bValuePush[256], bValueRelease[256]; + DWORD type; + void (*pfnAction)(struct _tagButtonItem *item, HWND hwndDlg, struct MessageWindowData *dat, HWND hwndItem); + void (*pfnCallback)(struct _tagButtonItem *item, HWND hwndDlg, struct MessageWindowData *dat, HWND hwndItem); + TCHAR tszLabel[40]; + struct _tagButtonItem *nextItem; +} ButtonItem; + +typedef struct _tagButtonSet { + ButtonItem *items; + LONG left, top, right, bottom; // client area offsets, calculated from button layout +} ButtonSet; + +typedef struct { + char szName[40]; + char szDBname[40]; + int statusID; + + BYTE GRADIENT; + BYTE CORNER; + + DWORD COLOR; + DWORD COLOR2; + + BYTE COLOR2_TRANSPARENT; + + DWORD TEXTCOLOR; + + int ALPHA; + + int MARGIN_LEFT; + int MARGIN_TOP; + int MARGIN_RIGHT; + int MARGIN_BOTTOM; + BYTE IGNORED; + DWORD BORDERSTYLE; + ImageItem *imageItem; +} StatusItems_t; + +typedef struct { + BOOL bGRADIENT; + BOOL bCORNER; + BOOL bCOLOR; + BOOL bCOLOR2; + BOOL bCOLOR2_TRANSPARENT; + BOOL bTEXTCOLOR; + BOOL bALPHA; + BOOL bMARGIN_LEFT; + BOOL bMARGIN_TOP; + BOOL bMARGIN_RIGHT; + BOOL bMARGIN_BOTTOM; + BOOL bIGNORED; + BOOL bBORDERSTYLE; +} ChangedSItems_t; + +typedef struct _tagSkinDescription { + DWORD cbSize; + StatusItems_t *StatusItems; + int lastItem; + int firstItem; + char szModule[100]; + HWND hWndParent, hWndTab; + HWND hwndCLUI; + HWND hwndSkinEdit; /* out param */ + HWND hwndImageEdit; /* out param */ + HMENU hMenuItems; + void (*pfnSaveCompleteStruct)(void); + void (*pfnClcOptionsChanged )(void); + void* (*pfnMalloc)(unsigned int); + void (*pfnFree)(void); + void* (*pfnRealloc)(void *, unsigned int); + void* reserved[20]; +} SKINDESCRIPTION; + +// defines + +// FLAGS +#define CORNER_NONE 0 +#define CORNER_ACTIVE 1 +#define CORNER_TL 2 +#define CORNER_TR 4 +#define CORNER_BR 8 +#define CORNER_BL 16 + +#define GRADIENT_NONE 0 +#define GRADIENT_ACTIVE 1 +#define GRADIENT_LR 2 +#define GRADIENT_RL 4 +#define GRADIENT_TB 8 +#define GRADIENT_BT 16 + +#define IMAGE_PERPIXEL_ALPHA 1 +#define IMAGE_FLAG_DIVIDED 2 +#define IMAGE_FILLSOLID 4 +#define IMAGE_GLYPH 8 + +#define IMAGE_STRETCH_V 1 +#define IMAGE_STRETCH_H 2 +#define IMAGE_STRETCH_B 4 + +#define BUTTON_ISINTERNAL 1 +#define BUTTON_ISTOGGLE 2 +#define BUTTON_ISSERVICE 4 +#define BUTTON_ISPROTOSERVICE 8 +#define BUTTON_PASSHCONTACTW 16 +#define BUTTON_PASSHCONTACTL 32 +#define BUTTON_ISDBACTION 64 +#define BUTTON_ISCONTACTDBACTION 128 +#define BUTTON_DBACTIONONCONTACT 256 +#define BUTTON_ISSIDEBAR 512 +#define BUTTON_NORMALGLYPHISICON 1024 +#define BUTTON_PRESSEDGLYPHISICON 2048 +#define BUTTON_HOVERGLYPHISICON 4096 +#define BUTTON_HASLABEL 8192 + +#define CLCDEFAULT_GRADIENT 0 +#define CLCDEFAULT_CORNER 0 + +#define CLCDEFAULT_COLOR 0xd0d0d0 +#define CLCDEFAULT_COLOR2 0xd0d0d0 + +#define CLCDEFAULT_TEXTCOLOR 0x000000 + +#define CLCDEFAULT_COLOR2_TRANSPARENT 1 + +#define CLCDEFAULT_ALPHA 100 +#define CLCDEFAULT_MRGN_LEFT 0 +#define CLCDEFAULT_MRGN_TOP 0 +#define CLCDEFAULT_MRGN_RIGHT 0 +#define CLCDEFAULT_MRGN_BOTTOM 0 +#define CLCDEFAULT_IGNORE 1 diff --git a/plugins/Clist_nicer/src/Include/resource.h b/plugins/Clist_nicer/src/Include/resource.h new file mode 100644 index 0000000000..a2b1f5a072 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/resource.h @@ -0,0 +1,416 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by D:\Develop\miranda\plugins\miranda\miranda\plugins\clist_nicer\resource.rc +// +#define IDD_OPT_VIEWMODES 1 +#define IDD_OPT_FLOATING 3 +#define IDD_OPT_SKIN 4 +#define IDD_QUICKIGNORE 5 +#define IDD_OPT 6 +#define IDD_EXCEPTION 20 +#define IDD_OPTIONSDIALOG 101 +#define IDD_CLNABOUT 102 +#define IDD_OPT_CLIST 126 +#define IDI_NOTICK 143 +#define IDI_TICK 146 +#define IDI_OPTIONS 163 +#define IDI_RENAME 173 +#define IDI_DELETE 175 +#define IDI_CLVM_OPTIONS 176 +#define IDI_CLVM_SELECT 177 +#define IDR_CONTEXT 180 +#define IDC_DROP 183 +#define IDR_CLISTMENU 199 +#define IDI_BLANK 200 +#define IDI_ADDCONTACT 210 +#define IDC_HYPERLINKHAND 214 +#define IDC_DROPUSER 215 +#define IDD_OPT_CLUI 218 +#define IDD_OPT_XICONS 219 +#define IDD_OPT_CLC 228 +#define IDD_OPT_CLCBKG 230 +#define IDD_OPT_SBAR 234 +#define IDD_DELETECONTACT 254 +#define IDD_OPT_DSPPROFILES 300 +#define IDD_OPT_DSPADVANCED 301 +#define IDD_OPT_DSPITEMS 302 +#define IDD_OPT_DSPGROUPS 303 +#define IDC_ACTIVEPERC 1000 +#define IDC_OPTIONSTAB 1000 +#define IDC_ALWAYSSTATUS 1009 +#define IDC_APPLY 1011 +#define IDC_AUTOSIZE 1013 +#define IDC_AUTOSIZEUPWARD 1014 +#define IDC_AVATARSIZESPIN 1015 +#define IDC_SKINMODE 1020 +#define IDC_FULLTRANSPARENT 1020 +#define IDC_STATUSICONSCENTERED 1020 +#define IDC_NOTRAYINFOTIPS 1020 +#define IDC_SHOWXSTATUS 1020 +#define IDC_AUTOCLEAR 1020 +#define IDC_FLT_SIMPLELAYOUT 1020 +#define IDC_USESKIN 1020 +#define IDC_IGN_MSGEVENTS 1020 +#define IDC_AUTOCLEARVAL 1021 +#define IDC_MARKLOCKED 1021 +#define IDC_IGN_FILEEVENTS 1021 +#define IDC_AUTOCLEARSPIN 1022 +#define IDC_IGN_URLEVENTS 1022 +#define IDC_LASTMSG 1023 +#define IDC_IGN_AUTH 1023 +#define IDC_IGN_ADD 1024 +#define IDC_CONFIRMDELETE 1025 +#define IDC_IGN_ONLINE 1025 +#define IDC_IGN_ALWAYSONLINE 1026 +#define IDC_IGN_ALWAYSOFFLINE 1027 +#define IDC_IGN_PRIORITY 1028 +#define IDC_DISABLEGROUPS 1030 +#define IDC_DROPSHADOW 1035 +#define IDC_EQUALSELECTION 1040 +#define IDC_USEPERPROTO 1041 +#define IDC_OVERRIDEPERSTATUSCOLOR 1042 +#define IDC_EVENTAREASUNKEN 1043 +#define IDC_SETALLBUTTONSKINNED 1043 +#define IDC_EVENTSONTOP 1044 +#define IDC_FASTGRADIENT 1044 +#define IDC_EXTRA_ICON_EMAIL 1045 +#define IDC_DONTSEPARATE 1045 +#define IDC_EXTRA_ICON_SMS 1047 +#define IDC_EXTRA_ICON_RES0 1054 +#define IDC_EXTRA_ICON_WEB 1055 +#define IDC_FADEINOUT 1056 +#define IDC_EXTRA_ICON_ADV2 1057 +#define IDC_EXTRA_ICON_RES1 1058 +#define IDC_EXTRA_ICON_RES2 1059 +#define IDC_EXTRA_ICON_ADV3 1060 +#define IDC_EXTRAORDER 1061 +#define IDC_FRAMEGAP 1064 +#define IDC_FRAMEGAPSPIN 1065 +#define IDC_CLIPBORDER 1066 +#define IDC_FULLROWSELECT 1067 +#define IDC_CLIPBORDERSPIN 1067 +#define IDC_LOCALTIME 1068 +#define IDC_EXICONSCALE 1068 +#define IDC_EXICONSCALESPIN 1069 +#define IDC_CLEFT 1070 +#define IDC_CLEFTSPIN 1071 +#define IDC_GREYOUT 1072 +#define IDC_CTOP 1072 +#define IDC_ONTOP 1074 +#define IDC_SHOWMAINMENU 1075 +#define IDC_CLIENTDRAG 1076 +#define IDC_HIDEEMPTYGROUPS 1077 +#define IDC_CTOPSPIN 1077 +#define IDC_CBOTTOM 1078 +#define IDC_CBOTTOMSPIN 1079 +#define IDC_CRIGHT 1080 +#define IDC_HIDEOFFLINE 1081 +#define IDC_CRIGHTSPIN 1081 +#define IDC_HIDEOFFLINEOPTS 1082 +#define IDC_EXTRA_ICON_ADV4 1085 +#define IDC_LEFTMARGINSPIN 1092 +#define IDC_NOGROUPICON 1102 +#define IDC_ONECLK 1105 +#define IDC_BUILDTIME 1108 +#define IDC_RIGHTMARGIN 1121 +#define IDC_ROWGAP 1122 +#define IDC_TRANSPARENT 1124 +#define IDC_ROWHEIGHT 1125 +#define IDC_TRANSINACTIVE 1126 +#define IDC_GROUPROWHEIGHT 1126 +#define IDC_TRANSACTIVE 1128 +#define IDC_PROFILELIST 1134 +#define IDC_CLASSLIST 1135 +#define IDC_SELBLEND 1140 +#define IDC_SHOWBOTTOMBUTTONS 1148 +#define IDC_STATIC11 1154 +#define IDC_STATIC12 1155 +#define IDC_STATIC21 1156 +#define IDC_STATIC13 1156 +#define IDC_STATIC22 1157 +#define IDC_STATIC14 1157 +#define IDC_STATIC15 1158 +#define IDC_EXTRA_ICON_CLIENT 1164 +#define IDC_EXTRA_ICON_ADV1 1166 +#define IDC_SHOWGRIP 1169 +#define IDC_SKINBACKGROUND 1170 +#define IDC_FILLWALLPAPER 1171 +#define IDC_SHOWMETA 1172 +#define IDC_CENTERGROUPNAMES 1173 +#define IDC_APPLYINDENTBG 1174 +#define IDC_COPYRIGHT 1178 +#define IDC_VERSION 1179 +#define IDC_SHOWSTATUSICONS 1180 +#define IDC_BROWSE 1184 +#define IDC_INACTIVEPERC 1187 +#define IDC_SHOWSTATUSMSG 1188 +#define IDC_SHOWLOCALTIME 1189 +#define IDC_SHOWVISIBILITY 1190 +#define IDC_SHOWLOCALTIMEONLYWHENDIFFERENT 1191 +#define IDC_TITLETEXT 1196 +#define IDC_EXCEPTION_DETAILS 1200 +#define IDC_COPY_EXCEPTION 1201 +#define IDC_EX_REASON 1202 +#define IDC_TILEH 1208 +#define IDC_WHITERECT 1225 +#define IDC_AUTOHIDE 1235 +#define IDC_HIDETIME 1236 +#define IDC_ALWAYSHIDEONTASKBAR 1237 +#define IDC_IMPORT 1241 +#define IDC_MAXSIZEHEIGHT 1254 +#define IDC_MAXSIZESPIN 1255 +#define IDC_BKGCOLOUR 1269 +#define IDC_FILENAME 1271 +#define IDC_SCROLL 1277 +#define IDC_PROPORTIONAL 1278 +#define IDC_SMOOTHTIME 1283 +#define IDC_SMOOTHTIMESPIN 1284 +#define IDC_ROWHEIGHTSPIN 1286 +#define IDC_GROUPROWHEIGHTSPIN 1287 +#define IDC_GREYOUTOPTS 1288 +#define IDC_GROUPINDENT 1289 +#define IDC_GROUPINDENTSPIN 1290 +#define IDC_LEFTMARGIN 1291 +#define IDC_RIGHTMARGINSPIN 1294 +#define IDC_ROWGAPSPIN 1295 +#define IDC_STRETCHH 1298 +#define IDC_STRETCHV 1299 +#define IDC_TILEV 1301 +#define IDC_DONTCYCLE 1315 +#define IDC_PRIMARYSTATUS 1316 +#define IDC_CYCLE 1317 +#define IDC_CYCLETIME 1318 +#define IDC_CYCLETIMESPIN 1319 +#define IDC_HIDETIMESPIN 1320 +#define IDC_MULTITRAY 1321 +#define IDC_ALWAYSMULTI 1322 +#define IDC_SHOWICON 1323 +#define IDC_SORTTHEN 1323 +#define IDC_SHOWPROTO 1324 +#define IDC_SORTFINALLY 1324 +#define IDC_SHOWSTATUS 1325 +#define IDC_EQUALSECTIONS 1326 +#define IDC_SHOWSBAR 1329 +#define IDC_RIGHTMIRANDA 1330 +#define IDC_RIGHTSTATUS 1331 +#define IDC_STCLISTGROUP 1350 +#define IDC_DISABLEDRAGDROP 1351 +#define IDC_NOTEDITLABELS 1352 +#define IDC_SHOWSELALWAYS 1353 +#define IDC_TRACKSELECT 1354 +#define IDC_SHOWGROUPCOUNTS 1355 +#define IDC_HIDECOUNTSWHENEMPTY 1356 +#define IDC_DIVIDERONOFF 1357 +#define IDC_NOTNOTRANSLUCENTSEL 1358 +#define IDC_LINEWITHGROUPS 1359 +#define IDC_QUICKSEARCHVISONLY 1360 +#define IDC_SORTGROUPSALPHA 1361 +#define IDC_NOTNOSMOOTHSCROLLING 1362 +#define IDC_BITMAP 1363 +#define IDC_STWINDOWGROUP 1364 +#define IDC_STATIC01 1365 +#define IDC_SORTPRIMARY 1420 +#define IDC_HIDE 1534 +#define IDC_TOPLINE 1535 +#define IDC_BRINGTOFRONT 1579 +#define IDC_LOGO 1591 +#define IDC_BLINKTIME 1607 +#define IDC_BLINKSPIN 1608 +#define IDC_DISABLEBLINK 1609 +#define IDC_IDLE 1610 +#define IDC_SBPANELBEVEL 1611 +#define IDC_DBLCLKAVATARS 1611 +#define IDC_XSTATUSASSTATUS 1611 +#define IDC_NOSCROLLBAR 1613 +#define IDC_ADDVIEWMODE 1633 +#define IDC_SKINFILESELECT 1633 +#define IDC_IGN_ALL 1633 +#define IDC_EXPORT 1634 +#define IDC_DELETEVIEWMODE 1634 +#define IDC_IGN_NONE 1634 +#define IDC_RELOAD 1635 +#define IDC_IGN_ADDPERMANENTLY 1635 +#define IDC_DSP_LOADDEFAULT 1636 +#define IDC_ONDESKTOP 1657 +#define IDC_WINCOLOUR 1659 +#define IDC_ICONBLINK 1660 +#define IDC_APPLYLASTVIEWMODE 1661 +#define IDC_IGNORESELFORGROUPS 1722 +#define IDC_CLISTAVATARS 1729 +#define IDC_ALIGNMENT 1730 +#define IDC_AVATARSBORDER 1732 +#define IDC_AVATARBORDERCLR 1733 +#define IDC_AVATARSROUNDED 1734 +#define IDC_DUALROWMODE 1735 +#define IDC_CLISTALIGN 1737 +#define IDC_CLISTSUNKEN 1738 +#define IDC_EVENTAREAAUTOHIDE 1740 +#define IDC_RADIUS 1742 +#define IDC_RADIUSSPIN 1743 +#define IDC_ALWAYSALIGNNICK 1744 +#define IDC_SELECTIVEICONS 1746 +#define IDC_OVERLAYICONS 1747 +#define IDC_AVATARHEIGHT 1748 +#define IDC_NOAVATARSOFFLINE 1749 +#define IDC_CORNERRAD 1751 +#define IDC_CORNERSPIN 1752 +#define IDC_AVATARPADDING 1753 +#define IDC_GRPTOPPADDING 1753 +#define IDC_AVATARPADDINGSPIN 1754 +#define IDC_GRPPADDINGSPIN 1754 +#define IDC_LASTITEMPADDING 1755 +#define IDC_LASTITEMPADDINGSPIN 1756 +#define IDC_TBHIDEOFFLINE 1800 +#define IDC_TBHIDEGROUPS 1801 +#define IDC_TBSOUND 1802 +#define IDC_TBFINDANDADD 1803 +#define IDC_TBOPTIONS 1804 +#define IDC_TBMINIMIZE 1805 +#define IDC_TBMENU 1806 +#define IDC_TBGLOBALSTATUS 1807 +#define IDC_TABSRMMSLIST 1808 +#define IDC_TABSRMMMENU 1809 +#define IDC_TBSELECTVIEWMODE 1810 +#define IDC_ROUNDEDBORDER 1810 +#define IDC_TBCLEARVIEWMODE 1811 +#define IDC_TBCONFIGUREVIEWMODE 1812 +#define IDC_TBTOPMENU 1813 +#define IDC_TBTOPSTATUS 1814 +#define IDC_TBFOLDER 1815 +#define IDC_TBPOPUP 1816 +#define IDC_TBACCOUNTS 1817 +#define IDC_TBFIRSTUID 1820 +#define IDC_NOTIFYBUTTON 1900 +#define IDC_CLNICER 2002 +#define IDC_SUPPORT 2003 +#define IDI_OVL_OFFLINE 2050 +#define IDI_OVL_ONLINE 2051 +#define IDI_OVL_AWAY 2052 +#define IDI_OVL_DND 2053 +#define IDI_OVL_NA 2054 +#define IDI_OVL_OCCUPIED 2055 +#define IDI_OVL_FREEFORCHAT 2056 +#define IDI_OVL_INVISIBLE 2057 +#define IDI_OVL_ONTHEPHONE 2058 +#define IDI_OVL_OUTTOLUNCH 2059 +#define IDI_HIDEOFFLINE 2100 +#define IDI_HIDEGROUPS 2101 +#define IDI_SOUNDSON 2102 +#define IDI_FINDANDADD 2103 +#define IDI_TBOPTIONS 2104 +#define IDI_MINIMIZE 2105 +#define IDI_SOUNDSOFF 2106 +#define IDI_TABSRMMSESSIONLIST 2107 +#define IDI_TABSRMMMENU 2108 +#define IDI_CLVISIBLE 2109 +#define IDI_CLINVISIBLE 2110 +#define IDI_PROTOCONNECTING 2111 +#define IDI_TBTOPMENU 2112 +#define IDI_TBACCOUNTS 2113 +#define IDC_FLT_DEFHOVERTIME 2200 +#define IDC_CLUIFRAMESBDR 25492 +#define IDC_FLT_PADLEFTSPIN 25494 +#define IDC_FLT_PADLEFT 25495 +#define IDC_GROUPALIGN 25499 +#define IDC_BORDERSTYLE 25501 +#define IDC_CURVIEWMODE2 25503 +#define ID_ICQ_EXIT 40001 +#define IDC_STATIC7 40002 +#define POPUP_HIDEEMPTYGROUPS 40003 +#define POPUP_NEWSUBGROUP 40004 +#define POPUP_HIDEOFFLINE 40005 +#define POPUP_GROUPHIDEOFFLINE 40006 +#define POPUP_HIDEOFFLINEROOT 40007 +#define POPUP_DISABLEGROUPS 40008 +#define IDC_VIEWMODES 40010 +#define IDC_PROTOCOLS 40011 +#define IDC_GROUPS 40012 +#define IDC_STATUSMODES 40013 +#define IDC_NEWVIEMODE 40014 +#define POPUP_HIDEMIRANDA 40017 +#define IDC_TAB 40017 +#define IDC_STATIC1 40018 +#define IDC_STATIC2 40019 +#define IDC_STATIC3 40020 +#define POPUP_VISIBILITY 40021 +#define IDC_STATIC16 40021 +#define IDC_STATIC4 40022 +#define IDC_STATIC5 40023 +#define IDC_CLIST 40025 +#define IDC_STATIC8 40026 +#define IDC_STATIC9 40027 +#define POPUP_BUTTONS 40028 +#define IDC_CLEARALL 40028 +#define POPUP_FRAME 40029 +#define IDC_STATIC10 40029 +#define IDC_PROTOGROUPOP 40030 +#define POPUP_MOVEMARKEDHERE 40031 +#define IDC_GROUPSTATUSOP 40031 +#define IDC_LASTMESSAGEOP 40032 +#define ID_BUTTONS_ONLINE 40033 +#define IDC_SKINFILE 40034 +#define IDC_LASTMESSAGEUNIT 40034 +#define IDC_FLT_AVATARS 40036 +#define IDC_HIDECONTACT 40036 +#define IDC_FLT_DUALROWS 40037 +#define IDC_FLT_EXTRAICONS 40038 +#define ID_TRAY_HIDE 40038 +#define ID_TRAY_EXIT 40039 +#define IDC_FLT_SYNCED 40039 +#define POPUP_SHOWMETAICONS 40040 +#define IDC_FLT_AUTOHIDE 40040 +#define IDC_FLT_FILLSTD 40041 +#define IDC_FLT_PADRIGHT 40043 +#define IDC_LASTMSGVALUE 40043 +#define IDC_FLT_PADRIGHTSPIN 40044 +#define IDC_FLT_PADTOP 40045 +#define IDC_SKINFILENAME 40045 +#define IDC_FLT_PADTOPSPIN 40046 +#define IDC_SELECTSKINFILE 40046 +#define IDC_FLT_PADBOTTOM 40047 +#define IDC_RELOADSKIN 40047 +#define IDC_FLT_PADBOTTOMSPIN 40048 +#define IDC_UNLOAD 40048 +#define POPUP_NEWGROUP 40050 +#define IDC_SECONDLINEMODE 40050 +#define POPUP_SHOWSTATUSICONS 40051 +#define IDC_OVERLAYICON 40051 +#define IDC_SHOWLOCALTIME1 40052 +#define POPUP_RENAMEGROUP 40052 +#define POPUP_DELETEGROUP 40053 +#define IDC_DSP_ADD -25483 +#define IDC_DSP_DELETE 40054 +#define IDC_FLT_ENABLED 40054 +#define IDC_DSP_RENAME 40055 +#define IDC_FLT_OPACITY 40055 +#define IDC_DSP_APPLY 40056 +#define IDC_FLT_ACTIVEOPACITY 40056 +#define POPUP_FLOATER 40057 +#define POPUP_FLOATER_AUTOHIDE 40058 +#define IDC_FLT_WIDTH 40058 +#define IDC_AVATARDISPMODE 40059 +#define IDC_FLT_WIDTHSPIN 40059 +#define POPUP_FLOATER_EVENTS 40060 +#define IDC_FLT_SNAP 40060 +#define IDC_FLT_ACTIVEOPACITYVALUE 40061 +#define IDC_FLT_BORDER 40062 +#define IDC_FLT_ROUNDED 40063 +#define IDC_FLT_RADIUS 40065 +#define IDC_FLT_RADIUSSPIN 40066 +#define IDC_FLT_HOVERTIME 40067 +#define IDC_RESETXICONS 40067 +#define IDC_FLT_SHOWTOOLTIPS 40068 +#define IDC_FLT_HOVERTIMESPIN 40069 +#define IDC_FLT_OPACITYVALUE 40070 +#define IDC_FLT_BORDERCOLOUR 40072 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 10 +#define _APS_NEXT_COMMAND_VALUE 40061 +#define _APS_NEXT_CONTROL_VALUE 40066 +#define _APS_NEXT_SYMED_VALUE 40154 +#endif +#endif diff --git a/plugins/Clist_nicer/src/Include/rowheight_funcs.h b/plugins/Clist_nicer/src/Include/rowheight_funcs.h new file mode 100644 index 0000000000..383db5b592 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/rowheight_funcs.h @@ -0,0 +1,85 @@ +#ifndef __ROWHEIGHT_FUNCS_H__ +# define __ROWHEIGHT_FUNCS_H__ + +#define ROW_SPACE_BEETWEEN_LINES 0 +#define ICON_HEIGHT 16 + +class RowHeight { + +public: + static BOOL Alloc (ClcData *dat, int size); + static BOOL Init (ClcData *dat); + static void Free (ClcData *dat); + static void Clear (ClcData *dat); + + // Calc and store max row height + static int getMaxRowHeight (ClcData *dat, const HWND hwnd); + + + // Calc and store row height + static int getRowHeight (ClcData *dat, const HWND hwnd, ClcContact* contact, int item, DWORD style) + { + int height = 0; + //DWORD style=GetWindowLongPtr(hwnd,GWL_STYLE); + + //if(contact->iRowHeight == item) + // return(dat->row_heights[item]); + + if (!Alloc(dat, item + 1)) + return -1; + + height = dat->fontInfo[GetBasicFontID(contact)].fontHeight; + + if (!dat->bisEmbedded) { + if(contact->bSecondLine != MULTIROW_NEVER && contact->bSecondLine != MULTIROW_IFSPACE && contact->type == CLCIT_CONTACT) { + if ((contact->bSecondLine == MULTIROW_ALWAYS || ((cfg::dat.dwFlags & CLUI_FRAME_SHOWSTATUSMSG && contact->bSecondLine == MULTIROW_IFNEEDED) && (contact->xStatus > 0 || cfg::eCache[contact->extraCacheEntry].bStatusMsgValid > STATUSMSG_XSTATUSID)))) + height += (dat->fontInfo[FONTID_STATUS].fontHeight + cfg::dat.avatarPadding); + } + + // Avatar size + if (contact->cFlags & ECF_AVATAR && contact->type == CLCIT_CONTACT && contact->ace != NULL && !(contact->ace->dwFlags & AVS_HIDEONCLIST)) + height = max(height, cfg::dat.avatarSize + cfg::dat.avatarPadding); + } + + // Checkbox size + if ((style&CLS_CHECKBOXES && contact->type==CLCIT_CONTACT) || + (style&CLS_GROUPCHECKBOXES && contact->type==CLCIT_GROUP) || + (contact->type==CLCIT_INFO && contact->flags&CLCIIF_CHECKBOX)) + { + height = max(height, dat->checkboxSize); + } + + //height += 2 * dat->row_border; + // Min size + height = max(height, contact->type == CLCIT_GROUP ? dat->group_row_height : dat->min_row_heigh); + height += cfg::dat.bRowSpacing; + + dat->row_heights[item] = height; + //contact->iRowHeight = item; + + return height; + } + + // Calc and store row height for all itens in the list + static void calcRowHeights (ClcData *dat, HWND hwnd); + + // Calc item top Y (using stored data) + static int getItemTopY (ClcData *dat, int item); + + // Calc item bottom Y (using stored data) + static int getItemBottomY (ClcData *dat, int item); + + // Calc total height of rows (using stored data) + static int getTotalHeight (ClcData *dat); + + // Return the line that pos_y is at or -1 (using stored data). Y start at 0 + static int hitTest (ClcData *dat, int pos_y); + + // Returns the height of the chosen row + static int getHeight (ClcData *dat, int item); + + // returns the height for a floating contact + static int getFloatingRowHeight(const ClcData *dat, HWND hwnd, ClcContact *contact, DWORD dwFlags); +}; + +#endif // __ROWHEIGHT_FUNCS_H__ diff --git a/plugins/Clist_nicer/src/Include/vsstyle.h b/plugins/Clist_nicer/src/Include/vsstyle.h new file mode 100644 index 0000000000..b65e223b51 --- /dev/null +++ b/plugins/Clist_nicer/src/Include/vsstyle.h @@ -0,0 +1,1606 @@ +//-------------------------------------------------------------------------// +// VisualStyle Style Guide symbols +//-------------------------------------------------------------------------// + +#ifndef __VSSTYLE_H__ +#define __VSSTYLE_H__ + +// +// property symbol definitions +// + +#define TMTVS_RESERVEDLOW 100000 +#define TMTVS_RESERVEDHIGH 19999 + + + +// +// AEROWIZARDSTYLE class parts and states +// +#define VSCLASS_AEROWIZARDSTYLE L"AEROWIZARDSTYLE" +#define VSCLASS_AEROWIZARD L"AEROWIZARD" + +enum AEROWIZARDPARTS { + AW_TITLEBAR = 1, + AW_HEADERAREA = 2, + AW_CONTENTAREA = 3, + AW_COMMANDAREA = 4, + AW_BUTTON = 5, +}; + +#define AEROWIZARDSTYLEPARTS AEROWIZARDPARTS; + +enum TITLEBARSTATES { + AW_S_TITLEBAR_ACTIVE = 1, + AW_S_TITLEBAR_INACTIVE = 2, +}; + +enum HEADERAREASTATES { + AW_S_HEADERAREA_NOMARGIN = 1, +}; + +enum CONTENTAREASTATES { + AW_S_CONTENTAREA_NOMARGIN = 1, +}; + + +// +// BUTTONSTYLE class parts and states +// +#define VSCLASS_BUTTONSTYLE L"BUTTONSTYLE" +#define VSCLASS_BUTTON L"BUTTON" + +enum BUTTONPARTS { + BP_PUSHBUTTON = 1, + BP_RADIOBUTTON = 2, + BP_CHECKBOX = 3, + BP_GROUPBOX = 4, + BP_USERBUTTON = 5, + BP_COMMANDLINK = 6, + BP_COMMANDLINKGLYPH = 7, +}; + +#define BUTTONSTYLEPARTS BUTTONPARTS; + +enum PUSHBUTTONSTATES { + PBS_NORMAL = 1, + PBS_HOT = 2, + PBS_PRESSED = 3, + PBS_DISABLED = 4, + PBS_DEFAULTED = 5, + PBS_DEFAULTED_ANIMATING = 6, +}; + +enum RADIOBUTTONSTATES { + RBS_UNCHECKEDNORMAL = 1, + RBS_UNCHECKEDHOT = 2, + RBS_UNCHECKEDPRESSED = 3, + RBS_UNCHECKEDDISABLED = 4, + RBS_CHECKEDNORMAL = 5, + RBS_CHECKEDHOT = 6, + RBS_CHECKEDPRESSED = 7, + RBS_CHECKEDDISABLED = 8, +}; + +enum CHECKBOXSTATES { + CBS_UNCHECKEDNORMAL = 1, + CBS_UNCHECKEDHOT = 2, + CBS_UNCHECKEDPRESSED = 3, + CBS_UNCHECKEDDISABLED = 4, + CBS_CHECKEDNORMAL = 5, + CBS_CHECKEDHOT = 6, + CBS_CHECKEDPRESSED = 7, + CBS_CHECKEDDISABLED = 8, + CBS_MIXEDNORMAL = 9, + CBS_MIXEDHOT = 10, + CBS_MIXEDPRESSED = 11, + CBS_MIXEDDISABLED = 12, + CBS_IMPLICITNORMAL = 13, + CBS_IMPLICITHOT = 14, + CBS_IMPLICITPRESSED = 15, + CBS_IMPLICITDISABLED = 16, + CBS_EXCLUDEDNORMAL = 17, + CBS_EXCLUDEDHOT = 18, + CBS_EXCLUDEDPRESSED = 19, + CBS_EXCLUDEDDISABLED = 20, +}; + +enum GROUPBOXSTATES { + GBS_NORMAL = 1, + GBS_DISABLED = 2, +}; + +enum COMMANDLINKSTATES { + CMDLS_NORMAL = 1, + CMDLS_HOT = 2, + CMDLS_PRESSED = 3, + CMDLS_DISABLED = 4, + CMDLS_DEFAULTED = 5, + CMDLS_DEFAULTED_ANIMATING = 6, +}; + +enum COMMANDLINKGLYPHSTATES { + CMDLGS_NORMAL = 1, + CMDLGS_HOT = 2, + CMDLGS_PRESSED = 3, + CMDLGS_DISABLED = 4, + CMDLGS_DEFAULTED = 5, +}; + + +// +// COMBOBOXSTYLE class parts and states +// +#define VSCLASS_COMBOBOXSTYLE L"COMBOBOXSTYLE" +#define VSCLASS_COMBOBOX L"COMBOBOX" + +enum COMBOBOXPARTS { + CP_DROPDOWNBUTTON = 1, + CP_BACKGROUND = 2, + CP_TRANSPARENTBACKGROUND = 3, + CP_BORDER = 4, + CP_READONLY = 5, + CP_DROPDOWNBUTTONRIGHT = 6, + CP_DROPDOWNBUTTONLEFT = 7, + CP_CUEBANNER = 8, +}; + +#define COMBOBOXSTYLEPARTS COMBOBOXPARTS; + +enum COMBOBOXSTYLESTATES { + CBXS_NORMAL = 1, + CBXS_HOT = 2, + CBXS_PRESSED = 3, + CBXS_DISABLED = 4, +}; + +enum DROPDOWNBUTTONRIGHTSTATES { + CBXSR_NORMAL = 1, + CBXSR_HOT = 2, + CBXSR_PRESSED = 3, + CBXSR_DISABLED = 4, +}; + +enum DROPDOWNBUTTONLEFTSTATES { + CBXSL_NORMAL = 1, + CBXSL_HOT = 2, + CBXSL_PRESSED = 3, + CBXSL_DISABLED = 4, +}; + +enum TRANSPARENTBACKGROUNDSTATES { + CBTBS_NORMAL = 1, + CBTBS_HOT = 2, + CBTBS_DISABLED = 3, + CBTBS_FOCUSED = 4, +}; + +enum BORDERSTATES { + CBB_NORMAL = 1, + CBB_HOT = 2, + CBB_FOCUSED = 3, + CBB_DISABLED = 4, +}; + +enum READONLYSTATES { + CBRO_NORMAL = 1, + CBRO_HOT = 2, + CBRO_PRESSED = 3, + CBRO_DISABLED = 4, +}; + +enum CUEBANNERSTATES { + CBCB_NORMAL = 1, + CBCB_HOT = 2, + CBCB_PRESSED = 3, + CBCB_DISABLED = 4, +}; + + +// +// COMMUNICATIONSSTYLE class parts and states +// +#define VSCLASS_COMMUNICATIONSSTYLE L"COMMUNICATIONSSTYLE" +#define VSCLASS_COMMUNICATIONS L"COMMUNICATIONS" + +enum COMMUNICATIONSPARTS { + CSST_TAB = 1, +}; + +#define COMMUNICATIONSSTYLEPARTS COMMUNICATIONSPARTS; + +enum TABSTATES { + CSTB_NORMAL = 1, + CSTB_HOT = 2, + CSTB_SELECTED = 3, +}; + + +// +// CONTROLPANELSTYLE class parts and states +// +#define VSCLASS_CONTROLPANELSTYLE L"CONTROLPANELSTYLE" +#define VSCLASS_CONTROLPANEL L"CONTROLPANEL" + +enum CONTROLPANELPARTS { + CPANEL_NAVIGATIONPANE = 1, + CPANEL_CONTENTPANE = 2, + CPANEL_NAVIGATIONPANELABEL = 3, + CPANEL_CONTENTPANELABEL = 4, + CPANEL_TITLE = 5, + CPANEL_BODYTEXT = 6, + CPANEL_HELPLINK = 7, + CPANEL_TASKLINK = 8, + CPANEL_GROUPTEXT = 9, + CPANEL_CONTENTLINK = 10, + CPANEL_SECTIONTITLELINK = 11, + CPANEL_LARGECOMMANDAREA = 12, + CPANEL_SMALLCOMMANDAREA = 13, + CPANEL_BUTTON = 14, + CPANEL_MESSAGETEXT = 15, + CPANEL_NAVIGATIONPANELINE = 16, + CPANEL_CONTENTPANELINE = 17, + CPANEL_BANNERAREA = 18, + CPANEL_BODYTITLE = 19, +}; + +#define CONTROLPANELSTYLEPARTS CONTROLPANELPARTS; + +enum HELPLINKSTATES { + CPHL_NORMAL = 1, + CPHL_HOT = 2, + CPHL_PRESSED = 3, + CPHL_DISABLED = 4, +}; + +enum TASKLINKSTATES { + CPTL_NORMAL = 1, + CPTL_HOT = 2, + CPTL_PRESSED = 3, + CPTL_DISABLED = 4, + CPTL_PAGE = 5, +}; + +enum CONTENTLINKSTATES { + CPCL_NORMAL = 1, + CPCL_HOT = 2, + CPCL_PRESSED = 3, + CPCL_DISABLED = 4, +}; + +enum SECTIONTITLELINKSTATES { + CPSTL_NORMAL = 1, + CPSTL_HOT = 2, +}; + + +// +// DATEPICKERSTYLE class parts and states +// +#define VSCLASS_DATEPICKERSTYLE L"DATEPICKERSTYLE" +#define VSCLASS_DATEPICKER L"DATEPICKER" + +enum DATEPICKERPARTS { + DP_DATETEXT = 1, + DP_DATEBORDER = 2, + DP_SHOWCALENDARBUTTONRIGHT = 3, +}; + +#define DATEPICKERSTYLEPARTS DATEPICKERPARTS; + +enum DATETEXTSTATES { + DPDT_NORMAL = 1, + DPDT_DISABLED = 2, + DPDT_SELECTED = 3, +}; + +enum DATEBORDERSTATES { + DPDB_NORMAL = 1, + DPDB_HOT = 2, + DPDB_FOCUSED = 3, + DPDB_DISABLED = 4, +}; + +enum SHOWCALENDARBUTTONRIGHTSTATES { + DPSCBR_NORMAL = 1, + DPSCBR_HOT = 2, + DPSCBR_PRESSED = 3, + DPSCBR_DISABLED = 4, +}; + + +// +// DRAGDROPSTYLE class parts and states +// +#define VSCLASS_DRAGDROPSTYLE L"DRAGDROPSTYLE" +#define VSCLASS_DRAGDROP L"DRAGDROP" + +enum DRAGDROPPARTS { + DD_COPY = 1, + DD_MOVE = 2, + DD_UPDATEMETADATA = 3, + DD_CREATELINK = 4, + DD_WARNING = 5, + DD_NONE = 6, + DD_IMAGEBG = 7, + DD_TEXTBG = 8, +}; + +#define DRAGDROPSTYLEPARTS DRAGDROPPARTS; + +enum COPYSTATES { + DDCOPY_HIGHLIGHT = 1, + DDCOPY_NOHIGHLIGHT = 2, +}; + +enum MOVESTATES { + DDMOVE_HIGHLIGHT = 1, + DDMOVE_NOHIGHLIGHT = 2, +}; + +enum UPDATEMETADATASTATES { + DDUPDATEMETADATA_HIGHLIGHT = 1, + DDUPDATEMETADATA_NOHIGHLIGHT = 2, +}; + +enum CREATELINKSTATES { + DDCREATELINK_HIGHLIGHT = 1, + DDCREATELINK_NOHIGHLIGHT = 2, +}; + +enum WARNINGSTATES { + DDWARNING_HIGHLIGHT = 1, + DDWARNING_NOHIGHLIGHT = 2, +}; + +enum NONESTATES { + DDNONE_HIGHLIGHT = 1, + DDNONE_NOHIGHLIGHT = 2, +}; + + +// +// EDITSTYLE class parts and states +// +#define VSCLASS_EDITSTYLE L"EDITSTYLE" +#define VSCLASS_EDIT L"EDIT" + +enum EDITPARTS { + EP_EDITTEXT = 1, + EP_CARET = 2, + EP_BACKGROUND = 3, + EP_PASSWORD = 4, + EP_BACKGROUNDWITHBORDER = 5, + EP_EDITBORDER_NOSCROLL = 6, + EP_EDITBORDER_HSCROLL = 7, + EP_EDITBORDER_VSCROLL = 8, + EP_EDITBORDER_HVSCROLL = 9, +}; + +#define EDITSTYLEPARTS EDITPARTS; + +enum EDITTEXTSTATES { + ETS_NORMAL = 1, + ETS_HOT = 2, + ETS_SELECTED = 3, + ETS_DISABLED = 4, + ETS_FOCUSED = 5, + ETS_READONLY = 6, + ETS_ASSIST = 7, + ETS_CUEBANNER = 8, +}; + +enum BACKGROUNDSTATES { + EBS_NORMAL = 1, + EBS_HOT = 2, + EBS_DISABLED = 3, + EBS_FOCUSED = 4, + EBS_READONLY = 5, + EBS_ASSIST = 6, +}; + +enum BACKGROUNDWITHBORDERSTATES { + EBWBS_NORMAL = 1, + EBWBS_HOT = 2, + EBWBS_DISABLED = 3, + EBWBS_FOCUSED = 4, +}; + +enum EDITBORDER_NOSCROLLSTATES { + EPSN_NORMAL = 1, + EPSN_HOT = 2, + EPSN_FOCUSED = 3, + EPSN_DISABLED = 4, +}; + +enum EDITBORDER_HSCROLLSTATES { + EPSH_NORMAL = 1, + EPSH_HOT = 2, + EPSH_FOCUSED = 3, + EPSH_DISABLED = 4, +}; + +enum EDITBORDER_VSCROLLSTATES { + EPSV_NORMAL = 1, + EPSV_HOT = 2, + EPSV_FOCUSED = 3, + EPSV_DISABLED = 4, +}; + +enum EDITBORDER_HVSCROLLSTATES { + EPSHV_NORMAL = 1, + EPSHV_HOT = 2, + EPSHV_FOCUSED = 3, + EPSHV_DISABLED = 4, +}; + + +// +// EXPLORERBARSTYLE class parts and states +// +#define VSCLASS_EXPLORERBARSTYLE L"EXPLORERBARSTYLE" +#define VSCLASS_EXPLORERBAR L"EXPLORERBAR" + +enum EXPLORERBARPARTS { + EBP_HEADERBACKGROUND = 1, + EBP_HEADERCLOSE = 2, + EBP_HEADERPIN = 3, + EBP_IEBARMENU = 4, + EBP_NORMALGROUPBACKGROUND = 5, + EBP_NORMALGROUPCOLLAPSE = 6, + EBP_NORMALGROUPEXPAND = 7, + EBP_NORMALGROUPHEAD = 8, + EBP_SPECIALGROUPBACKGROUND = 9, + EBP_SPECIALGROUPCOLLAPSE = 10, + EBP_SPECIALGROUPEXPAND = 11, + EBP_SPECIALGROUPHEAD = 12, +}; + +#define EXPLORERBARSTYLEPARTS EXPLORERBARPARTS; + +enum HEADERCLOSESTATES { + EBHC_NORMAL = 1, + EBHC_HOT = 2, + EBHC_PRESSED = 3, +}; + +enum HEADERPINSTATES { + EBHP_NORMAL = 1, + EBHP_HOT = 2, + EBHP_PRESSED = 3, + EBHP_SELECTEDNORMAL = 4, + EBHP_SELECTEDHOT = 5, + EBHP_SELECTEDPRESSED = 6, +}; + +enum IEBARMENUSTATES { + EBM_NORMAL = 1, + EBM_HOT = 2, + EBM_PRESSED = 3, +}; + +enum NORMALGROUPCOLLAPSESTATES { + EBNGC_NORMAL = 1, + EBNGC_HOT = 2, + EBNGC_PRESSED = 3, +}; + +enum NORMALGROUPEXPANDSTATES { + EBNGE_NORMAL = 1, + EBNGE_HOT = 2, + EBNGE_PRESSED = 3, +}; + +enum SPECIALGROUPCOLLAPSESTATES { + EBSGC_NORMAL = 1, + EBSGC_HOT = 2, + EBSGC_PRESSED = 3, +}; + +enum SPECIALGROUPEXPANDSTATES { + EBSGE_NORMAL = 1, + EBSGE_HOT = 2, + EBSGE_PRESSED = 3, +}; + + +// +// FLYOUTSTYLE class parts and states +// +#define VSCLASS_FLYOUTSTYLE L"FLYOUTSTYLE" +#define VSCLASS_FLYOUT L"FLYOUT" + +enum FLYOUTPARTS { + FLYOUT_HEADER = 1, + FLYOUT_BODY = 2, + FLYOUT_LABEL = 3, + FLYOUT_LINK = 4, + FLYOUT_DIVIDER = 5, + FLYOUT_WINDOW = 6, + FLYOUT_LINKAREA = 7, + FLYOUT_LINKHEADER = 8, +}; + +#define FLYOUTSTYLEPARTS FLYOUTPARTS; + +enum LABELSTATES { + FLS_NORMAL = 1, + FLS_SELECTED = 2, + FLS_EMPHASIZED = 3, + FLS_DISABLED = 4, +}; + +enum LINKSTATES { + FLYOUTLINK_NORMAL = 1, + FLYOUTLINK_HOVER = 2, +}; + +enum BODYSTATES { + FBS_NORMAL = 1, + FBS_EMPHASIZED = 2, +}; + +enum LINKHEADERSTATES { + FLH_NORMAL = 1, + FLH_HOVER = 2, +}; + + +// +// HEADERSTYLE class parts and states +// +#define VSCLASS_HEADERSTYLE L"HEADERSTYLE" +#define VSCLASS_HEADER L"HEADER" + +enum HEADERPARTS { + HP_HEADERITEM = 1, + HP_HEADERITEMLEFT = 2, + HP_HEADERITEMRIGHT = 3, + HP_HEADERSORTARROW = 4, + HP_HEADERDROPDOWN = 5, + HP_HEADERDROPDOWNFILTER = 6, + HP_HEADEROVERFLOW = 7, +}; + +#define HEADERSTYLEPARTS HEADERPARTS; + +enum HEADERSTYLESTATES { + HBG_DETAILS = 1, + HBG_ICON = 2, +}; + +enum HEADERITEMSTATES { + HIS_NORMAL = 1, + HIS_HOT = 2, + HIS_PRESSED = 3, + HIS_SORTEDNORMAL = 4, + HIS_SORTEDHOT = 5, + HIS_SORTEDPRESSED = 6, + HIS_ICONNORMAL = 7, + HIS_ICONHOT = 8, + HIS_ICONPRESSED = 9, + HIS_ICONSORTEDNORMAL = 10, + HIS_ICONSORTEDHOT = 11, + HIS_ICONSORTEDPRESSED = 12, +}; + +enum HEADERITEMLEFTSTATES { + HILS_NORMAL = 1, + HILS_HOT = 2, + HILS_PRESSED = 3, +}; + +enum HEADERITEMRIGHTSTATES { + HIRS_NORMAL = 1, + HIRS_HOT = 2, + HIRS_PRESSED = 3, +}; + +enum HEADERSORTARROWSTATES { + HSAS_SORTEDUP = 1, + HSAS_SORTEDDOWN = 2, +}; + +enum HEADERDROPDOWNSTATES { + HDDS_NORMAL = 1, + HDDS_SOFTHOT = 2, + HDDS_HOT = 3, +}; + +enum HEADERDROPDOWNFILTERSTATES { + HDDFS_NORMAL = 1, + HDDFS_SOFTHOT = 2, + HDDFS_HOT = 3, +}; + +enum HEADEROVERFLOWSTATES { + HOFS_NORMAL = 1, + HOFS_HOT = 2, +}; + + +// +// LISTBOXSTYLE class parts and states +// +#define VSCLASS_LISTBOXSTYLE L"LISTBOXSTYLE" +#define VSCLASS_LISTBOX L"LISTBOX" + +enum LISTBOXPARTS { + LBCP_BORDER_HSCROLL = 1, + LBCP_BORDER_HVSCROLL = 2, + LBCP_BORDER_NOSCROLL = 3, + LBCP_BORDER_VSCROLL = 4, + LBCP_ITEM = 5, +}; + +#define LISTBOXSTYLEPARTS LISTBOXPARTS; + +enum BORDER_HSCROLLSTATES { + LBPSH_NORMAL = 1, + LBPSH_FOCUSED = 2, + LBPSH_HOT = 3, + LBPSH_DISABLED = 4, +}; + +enum BORDER_HVSCROLLSTATES { + LBPSHV_NORMAL = 1, + LBPSHV_FOCUSED = 2, + LBPSHV_HOT = 3, + LBPSHV_DISABLED = 4, +}; + +enum BORDER_NOSCROLLSTATES { + LBPSN_NORMAL = 1, + LBPSN_FOCUSED = 2, + LBPSN_HOT = 3, + LBPSN_DISABLED = 4, +}; + +enum BORDER_VSCROLLSTATES { + LBPSV_NORMAL = 1, + LBPSV_FOCUSED = 2, + LBPSV_HOT = 3, + LBPSV_DISABLED = 4, +}; + +enum ITEMSTATES { + LBPSI_HOT = 1, + LBPSI_HOTSELECTED = 2, + LBPSI_SELECTED = 3, + LBPSI_SELECTEDNOTFOCUS = 4, +}; + + +// +// LISTVIEWSTYLE class parts and states +// +#define VSCLASS_LISTVIEWSTYLE L"LISTVIEWSTYLE" +#define VSCLASS_LISTVIEW L"LISTVIEW" + +enum LISTVIEWPARTS { + LVP_LISTITEM = 1, + LVP_LISTGROUP = 2, + LVP_LISTDETAIL = 3, + LVP_LISTSORTEDDETAIL = 4, + LVP_EMPTYTEXT = 5, + LVP_GROUPHEADER = 6, + LVP_GROUPHEADERLINE = 7, + LVP_EXPANDBUTTON = 8, + LVP_COLLAPSEBUTTON = 9, + LVP_COLUMNDETAIL = 10, +}; + +#define LISTVIEWSTYLEPARTS LISTVIEWPARTS; + +enum LISTITEMSTATES { + LISS_NORMAL = 1, + LISS_HOT = 2, + LISS_SELECTED = 3, + LISS_DISABLED = 4, + LISS_SELECTEDNOTFOCUS = 5, + LISS_HOTSELECTED = 6, +}; + +enum GROUPHEADERSTATES { + LVGH_OPEN = 1, + LVGH_OPENHOT = 2, + LVGH_OPENSELECTED = 3, + LVGH_OPENSELECTEDHOT = 4, + LVGH_OPENSELECTEDNOTFOCUSED = 5, + LVGH_OPENSELECTEDNOTFOCUSEDHOT = 6, + LVGH_OPENMIXEDSELECTION = 7, + LVGH_OPENMIXEDSELECTIONHOT = 8, + LVGH_CLOSE = 9, + LVGH_CLOSEHOT = 10, + LVGH_CLOSESELECTED = 11, + LVGH_CLOSESELECTEDHOT = 12, + LVGH_CLOSESELECTEDNOTFOCUSED = 13, + LVGH_CLOSESELECTEDNOTFOCUSEDHOT = 14, + LVGH_CLOSEMIXEDSELECTION = 15, + LVGH_CLOSEMIXEDSELECTIONHOT = 16, +}; + +enum GROUPHEADERLINESTATES { + LVGHL_OPEN = 1, + LVGHL_OPENHOT = 2, + LVGHL_OPENSELECTED = 3, + LVGHL_OPENSELECTEDHOT = 4, + LVGHL_OPENSELECTEDNOTFOCUSED = 5, + LVGHL_OPENSELECTEDNOTFOCUSEDHOT = 6, + LVGHL_OPENMIXEDSELECTION = 7, + LVGHL_OPENMIXEDSELECTIONHOT = 8, + LVGHL_CLOSE = 9, + LVGHL_CLOSEHOT = 10, + LVGHL_CLOSESELECTED = 11, + LVGHL_CLOSESELECTEDHOT = 12, + LVGHL_CLOSESELECTEDNOTFOCUSED = 13, + LVGHL_CLOSESELECTEDNOTFOCUSEDHOT = 14, + LVGHL_CLOSEMIXEDSELECTION = 15, + LVGHL_CLOSEMIXEDSELECTIONHOT = 16, +}; + +enum EXPANDBUTTONSTATES { + LVEB_NORMAL = 1, + LVEB_HOVER = 2, + LVEB_PUSHED = 3, +}; + +enum COLLAPSEBUTTONSTATES { + LVCB_NORMAL = 1, + LVCB_HOVER = 2, + LVCB_PUSHED = 3, +}; + + +// +// MENUSTYLE class parts and states +// +#define VSCLASS_MENUSTYLE L"MENUSTYLE" +#define VSCLASS_MENU L"MENU" + +enum MENUPARTS { + MENU_MENUITEM_TMSCHEMA = 1, + MENU_MENUDROPDOWN_TMSCHEMA = 2, + MENU_MENUBARITEM_TMSCHEMA = 3, + MENU_MENUBARDROPDOWN_TMSCHEMA = 4, + MENU_CHEVRON_TMSCHEMA = 5, + MENU_SEPARATOR_TMSCHEMA = 6, + MENU_BARBACKGROUND = 7, + MENU_BARITEM = 8, + MENU_POPUPBACKGROUND = 9, + MENU_POPUPBORDERS = 10, + MENU_POPUPCHECK = 11, + MENU_POPUPCHECKBACKGROUND = 12, + MENU_POPUPGUTTER = 13, + MENU_POPUPITEM = 14, + MENU_POPUPSEPARATOR = 15, + MENU_POPUPSUBMENU = 16, + MENU_SYSTEMCLOSE = 17, + MENU_SYSTEMMAXIMIZE = 18, + MENU_SYSTEMMINIMIZE = 19, + MENU_SYSTEMRESTORE = 20, +}; + +#define MENUSTYLEPARTS MENUPARTS; + +enum BARBACKGROUNDSTATES { + MB_ACTIVE = 1, + MB_INACTIVE = 2, +}; + +enum BARITEMSTATES { + MBI_NORMAL = 1, + MBI_HOT = 2, + MBI_PUSHED = 3, + MBI_DISABLED = 4, + MBI_DISABLEDHOT = 5, + MBI_DISABLEDPUSHED = 6, +}; + +enum POPUPCHECKSTATES { + MC_CHECKMARKNORMAL = 1, + MC_CHECKMARKDISABLED = 2, + MC_BULLETNORMAL = 3, + MC_BULLETDISABLED = 4, +}; + +enum POPUPCHECKBACKGROUNDSTATES { + MCB_DISABLED = 1, + MCB_NORMAL = 2, + MCB_BITMAP = 3, +}; + +enum POPUPITEMSTATES { + MPI_NORMAL = 1, + MPI_HOT = 2, + MPI_DISABLED = 3, + MPI_DISABLEDHOT = 4, +}; + +enum POPUPSUBMENUSTATES { + MSM_NORMAL = 1, + MSM_DISABLED = 2, +}; + +enum SYSTEMCLOSESTATES { + MSYSC_NORMAL = 1, + MSYSC_DISABLED = 2, +}; + +enum SYSTEMMAXIMIZESTATES { + MSYSMX_NORMAL = 1, + MSYSMX_DISABLED = 2, +}; + +enum SYSTEMMINIMIZESTATES { + MSYSMN_NORMAL = 1, + MSYSMN_DISABLED = 2, +}; + +enum SYSTEMRESTORESTATES { + MSYSR_NORMAL = 1, + MSYSR_DISABLED = 2, +}; + + +// +// NAVIGATION class parts and states +// +#define VSCLASS_NAVIGATION L"NAVIGATION" + +enum NAVIGATIONPARTS { + NAV_BACKBUTTON = 1, + NAV_FORWARDBUTTON = 2, + NAV_MENUBUTTON = 3, +}; + +enum NAV_BACKBUTTONSTATES { + NAV_BB_NORMAL = 1, + NAV_BB_HOT = 2, + NAV_BB_PRESSED = 3, + NAV_BB_DISABLED = 4, +}; + +enum NAV_FORWARDBUTTONSTATES { + NAV_FB_NORMAL = 1, + NAV_FB_HOT = 2, + NAV_FB_PRESSED = 3, + NAV_FB_DISABLED = 4, +}; + +enum NAV_MENUBUTTONSTATES { + NAV_MB_NORMAL = 1, + NAV_MB_HOT = 2, + NAV_MB_PRESSED = 3, + NAV_MB_DISABLED = 4, +}; + + +// +// PROGRESSSTYLE class parts and states +// +#define VSCLASS_PROGRESSSTYLE L"PROGRESSSTYLE" +#define VSCLASS_PROGRESS L"PROGRESS" + +enum PROGRESSPARTS { + PP_BAR = 1, + PP_BARVERT = 2, + PP_CHUNK = 3, + PP_CHUNKVERT = 4, + PP_FILL = 5, + PP_FILLVERT = 6, + PP_PULSEOVERLAY = 7, + PP_MOVEOVERLAY = 8, + PP_PULSEOVERLAYVERT = 9, + PP_MOVEOVERLAYVERT = 10, + PP_TRANSPARENTBAR = 11, + PP_TRANSPARENTBARVERT = 12, +}; + +#define PROGRESSSTYLEPARTS PROGRESSPARTS; + +enum TRANSPARENTBARSTATES { + PBBS_NORMAL = 1, + PBBS_PARTIAL = 2, +}; + +enum TRANSPARENTBARVERTSTATES { + PBBVS_NORMAL = 1, + PBBVS_PARTIAL = 2, +}; + +enum FILLSTATES { + PBFS_NORMAL = 1, + PBFS_ERROR = 2, + PBFS_PAUSED = 3, + PBFS_PARTIAL = 4, +}; + +enum FILLVERTSTATES { + PBFVS_NORMAL = 1, + PBFVS_ERROR = 2, + PBFVS_PAUSED = 3, + PBFVS_PARTIAL = 4, +}; + + +// +// REBARSTYLE class parts and states +// +#define VSCLASS_REBARSTYLE L"REBARSTYLE" +#define VSCLASS_REBAR L"REBAR" + +enum REBARPARTS { + RP_GRIPPER = 1, + RP_GRIPPERVERT = 2, + RP_BAND = 3, + RP_CHEVRON = 4, + RP_CHEVRONVERT = 5, + RP_BACKGROUND = 6, + RP_SPLITTER = 7, + RP_SPLITTERVERT = 8, +}; + +#define REBARSTYLEPARTS REBARPARTS; + +enum CHEVRONSTATES { + CHEVS_NORMAL = 1, + CHEVS_HOT = 2, + CHEVS_PRESSED = 3, +}; + +enum CHEVRONVERTSTATES { + CHEVSV_NORMAL = 1, + CHEVSV_HOT = 2, + CHEVSV_PRESSED = 3, +}; + +enum SPLITTERSTATES { + SPLITS_NORMAL = 1, + SPLITS_HOT = 2, + SPLITS_PRESSED = 3, +}; + +enum SPLITTERVERTSTATES { + SPLITSV_NORMAL = 1, + SPLITSV_HOT = 2, + SPLITSV_PRESSED = 3, +}; + + +// +// SCROLLBARSTYLE class parts and states +// +#define VSCLASS_SCROLLBARSTYLE L"SCROLLBARSTYLE" +#define VSCLASS_SCROLLBAR L"SCROLLBAR" + +enum SCROLLBARPARTS { + SBP_ARROWBTN = 1, + SBP_THUMBBTNHORZ = 2, + SBP_THUMBBTNVERT = 3, + SBP_LOWERTRACKHORZ = 4, + SBP_UPPERTRACKHORZ = 5, + SBP_LOWERTRACKVERT = 6, + SBP_UPPERTRACKVERT = 7, + SBP_GRIPPERHORZ = 8, + SBP_GRIPPERVERT = 9, + SBP_SIZEBOX = 10, +}; + +#define SCROLLBARSTYLEPARTS SCROLLBARPARTS; + +enum ARROWBTNSTATES { + ABS_UPNORMAL = 1, + ABS_UPHOT = 2, + ABS_UPPRESSED = 3, + ABS_UPDISABLED = 4, + ABS_DOWNNORMAL = 5, + ABS_DOWNHOT = 6, + ABS_DOWNPRESSED = 7, + ABS_DOWNDISABLED = 8, + ABS_LEFTNORMAL = 9, + ABS_LEFTHOT = 10, + ABS_LEFTPRESSED = 11, + ABS_LEFTDISABLED = 12, + ABS_RIGHTNORMAL = 13, + ABS_RIGHTHOT = 14, + ABS_RIGHTPRESSED = 15, + ABS_RIGHTDISABLED = 16, + ABS_UPHOVER = 17, + ABS_DOWNHOVER = 18, + ABS_LEFTHOVER = 19, + ABS_RIGHTHOVER = 20, +}; + +enum SCROLLBARSTYLESTATES { + SCRBS_NORMAL = 1, + SCRBS_HOT = 2, + SCRBS_PRESSED = 3, + SCRBS_DISABLED = 4, + SCRBS_HOVER = 5, +}; + +enum SIZEBOXSTATES { + SZB_RIGHTALIGN = 1, + SZB_LEFTALIGN = 2, + SZB_TOPRIGHTALIGN = 3, + SZB_TOPLEFTALIGN = 4, + SZB_HALFBOTTOMRIGHTALIGN = 5, + SZB_HALFBOTTOMLEFTALIGN = 6, + SZB_HALFTOPRIGHTALIGN = 7, + SZB_HALFTOPLEFTALIGN = 8, +}; + + +// +// SPINSTYLE class parts and states +// +#define VSCLASS_SPINSTYLE L"SPINSTYLE" +#define VSCLASS_SPIN L"SPIN" + +enum SPINPARTS { + SPNP_UP = 1, + SPNP_DOWN = 2, + SPNP_UPHORZ = 3, + SPNP_DOWNHORZ = 4, +}; + +#define SPINSTYLEPARTS SPINPARTS; + +enum UPSTATES { + UPS_NORMAL = 1, + UPS_HOT = 2, + UPS_PRESSED = 3, + UPS_DISABLED = 4, +}; + +enum DOWNSTATES { + DNS_NORMAL = 1, + DNS_HOT = 2, + DNS_PRESSED = 3, + DNS_DISABLED = 4, +}; + +enum UPHORZSTATES { + UPHZS_NORMAL = 1, + UPHZS_HOT = 2, + UPHZS_PRESSED = 3, + UPHZS_DISABLED = 4, +}; + +enum DOWNHORZSTATES { + DNHZS_NORMAL = 1, + DNHZS_HOT = 2, + DNHZS_PRESSED = 3, + DNHZS_DISABLED = 4, +}; + + +// +// STATUSSTYLE class parts and states +// +#define VSCLASS_STATUSSTYLE L"STATUSSTYLE" +#define VSCLASS_STATUS L"STATUS" + +enum STATUSPARTS { + SP_PANE = 1, + SP_GRIPPERPANE = 2, + SP_GRIPPER = 3, +}; + +#define STATUSSTYLEPARTS STATUSPARTS; + + +// +// TABSTYLE class parts and states +// +#define VSCLASS_TABSTYLE L"TABSTYLE" +#define VSCLASS_TAB L"TAB" + +enum TABPARTS { + TABP_TABITEM = 1, + TABP_TABITEMLEFTEDGE = 2, + TABP_TABITEMRIGHTEDGE = 3, + TABP_TABITEMBOTHEDGE = 4, + TABP_TOPTABITEM = 5, + TABP_TOPTABITEMLEFTEDGE = 6, + TABP_TOPTABITEMRIGHTEDGE = 7, + TABP_TOPTABITEMBOTHEDGE = 8, + TABP_PANE = 9, + TABP_BODY = 10, + TABP_AEROWIZARDBODY = 11, +}; + +#define TABSTYLEPARTS TABPARTS; + +enum TABITEMSTATES { + TIS_NORMAL = 1, + TIS_HOT = 2, + TIS_SELECTED = 3, + TIS_DISABLED = 4, + TIS_FOCUSED = 5, +}; + +enum TABITEMLEFTEDGESTATES { + TILES_NORMAL = 1, + TILES_HOT = 2, + TILES_SELECTED = 3, + TILES_DISABLED = 4, + TILES_FOCUSED = 5, +}; + +enum TABITEMRIGHTEDGESTATES { + TIRES_NORMAL = 1, + TIRES_HOT = 2, + TIRES_SELECTED = 3, + TIRES_DISABLED = 4, + TIRES_FOCUSED = 5, +}; + +enum TABITEMBOTHEDGESTATES { + TIBES_NORMAL = 1, + TIBES_HOT = 2, + TIBES_SELECTED = 3, + TIBES_DISABLED = 4, + TIBES_FOCUSED = 5, +}; + +enum TOPTABITEMSTATES { + TTIS_NORMAL = 1, + TTIS_HOT = 2, + TTIS_SELECTED = 3, + TTIS_DISABLED = 4, + TTIS_FOCUSED = 5, +}; + +enum TOPTABITEMLEFTEDGESTATES { + TTILES_NORMAL = 1, + TTILES_HOT = 2, + TTILES_SELECTED = 3, + TTILES_DISABLED = 4, + TTILES_FOCUSED = 5, +}; + +enum TOPTABITEMRIGHTEDGESTATES { + TTIRES_NORMAL = 1, + TTIRES_HOT = 2, + TTIRES_SELECTED = 3, + TTIRES_DISABLED = 4, + TTIRES_FOCUSED = 5, +}; + +enum TOPTABITEMBOTHEDGESTATES { + TTIBES_NORMAL = 1, + TTIBES_HOT = 2, + TTIBES_SELECTED = 3, + TTIBES_DISABLED = 4, + TTIBES_FOCUSED = 5, +}; + + +// +// TASKDIALOGSTYLE class parts and states +// +#define VSCLASS_TASKDIALOGSTYLE L"TASKDIALOGSTYLE" +#define VSCLASS_TASKDIALOG L"TASKDIALOG" + +enum TASKDIALOGPARTS { + TDLG_PRIMARYPANEL = 1, + TDLG_MAININSTRUCTIONPANE = 2, + TDLG_MAINICON = 3, + TDLG_CONTENTPANE = 4, + TDLG_CONTENTICON = 5, + TDLG_EXPANDEDCONTENT = 6, + TDLG_COMMANDLINKPANE = 7, + TDLG_SECONDARYPANEL = 8, + TDLG_CONTROLPANE = 9, + TDLG_BUTTONSECTION = 10, + TDLG_BUTTONWRAPPER = 11, + TDLG_EXPANDOTEXT = 12, + TDLG_EXPANDOBUTTON = 13, + TDLG_VERIFICATIONTEXT = 14, + TDLG_FOOTNOTEPANE = 15, + TDLG_FOOTNOTEAREA = 16, + TDLG_FOOTNOTESEPARATOR = 17, + TDLG_EXPANDEDFOOTERAREA = 18, + TDLG_PROGRESSBAR = 19, + TDLG_IMAGEALIGNMENT = 20, + TDLG_RADIOBUTTONPANE = 21, +}; + +#define TASKDIALOGSTYLEPARTS TASKDIALOGPARTS; + +enum CONTENTPANESTATES { + TDLGCPS_STANDALONE = 1, +}; + +enum EXPANDOBUTTONSTATES { + TDLGEBS_NORMAL = 1, + TDLGEBS_HOVER = 2, + TDLGEBS_PRESSED = 3, + TDLGEBS_EXPANDEDNORMAL = 4, + TDLGEBS_EXPANDEDHOVER = 5, + TDLGEBS_EXPANDEDPRESSED = 6, +}; + + +// +// TEXTSTYLE class parts and states +// +#define VSCLASS_TEXTSTYLE L"TEXTSTYLE" + +enum TEXTSTYLEPARTS { + TEXT_MAININSTRUCTION = 1, + TEXT_INSTRUCTION = 2, + TEXT_BODYTITLE = 3, + TEXT_BODYTEXT = 4, + TEXT_SECONDARYTEXT = 5, + TEXT_HYPERLINKTEXT = 6, + TEXT_EXPANDED = 7, + TEXT_LABEL = 8, + TEXT_CONTROLLABEL = 9, +}; + +enum HYPERLINKTEXTSTATES { + TS_HYPERLINK_NORMAL = 1, + TS_HYPERLINK_HOT = 2, + TS_HYPERLINK_PRESSED = 3, + TS_HYPERLINK_DISABLED = 4, +}; + +enum CONTROLLABELSTATES { + TS_CONTROLLABEL_NORMAL = 1, + TS_CONTROLLABEL_DISABLED = 2, +}; + + +// +// TOOLBARSTYLE class parts and states +// +#define VSCLASS_TOOLBARSTYLE L"TOOLBARSTYLE" +#define VSCLASS_TOOLBAR L"TOOLBAR" + +enum TOOLBARPARTS { + TP_BUTTON = 1, + TP_DROPDOWNBUTTON = 2, + TP_SPLITBUTTON = 3, + TP_SPLITBUTTONDROPDOWN = 4, + TP_SEPARATOR = 5, + TP_SEPARATORVERT = 6, + TP_DROPDOWNBUTTONGLYPH = 7, +}; + +#define TOOLBARSTYLEPARTS TOOLBARPARTS; + +enum TOOLBARSTYLESTATES { + TS_NORMAL = 1, + TS_HOT = 2, + TS_PRESSED = 3, + TS_DISABLED = 4, + TS_CHECKED = 5, + TS_HOTCHECKED = 6, + TS_NEARHOT = 7, + TS_OTHERSIDEHOT = 8, +}; + + +// +// TOOLTIPSTYLE class parts and states +// +#define VSCLASS_TOOLTIPSTYLE L"TOOLTIPSTYLE" +#define VSCLASS_TOOLTIP L"TOOLTIP" + +enum TOOLTIPPARTS { + TTP_STANDARD = 1, + TTP_STANDARDTITLE = 2, + TTP_BALLOON = 3, + TTP_BALLOONTITLE = 4, + TTP_CLOSE = 5, + TTP_BALLOONSTEM = 6, + TTP_WRENCH = 7, +}; + +#define TOOLTIPSTYLEPARTS TOOLTIPPARTS; + +enum CLOSESTATES { + TTCS_NORMAL = 1, + TTCS_HOT = 2, + TTCS_PRESSED = 3, +}; + +enum STANDARDSTATES { + TTSS_NORMAL = 1, + TTSS_LINK = 2, +}; + +enum BALLOONSTATES { + TTBS_NORMAL = 1, + TTBS_LINK = 2, +}; + +enum BALLOONSTEMSTATES { + TTBSS_POINTINGUPLEFTWALL = 1, + TTBSS_POINTINGUPCENTERED = 2, + TTBSS_POINTINGUPRIGHTWALL = 3, + TTBSS_POINTINGDOWNRIGHTWALL = 4, + TTBSS_POINTINGDOWNCENTERED = 5, + TTBSS_POINTINGDOWNLEFTWALL = 6, +}; + +enum WRENCHSTATES { + TTWS_NORMAL = 1, + TTWS_HOT = 2, + TTWS_PRESSED = 3, +}; + + +// +// TRACKBARSTYLE class parts and states +// +#define VSCLASS_TRACKBARSTYLE L"TRACKBARSTYLE" +#define VSCLASS_TRACKBAR L"TRACKBAR" + +enum TRACKBARPARTS { + TKP_TRACK = 1, + TKP_TRACKVERT = 2, + TKP_THUMB = 3, + TKP_THUMBBOTTOM = 4, + TKP_THUMBTOP = 5, + TKP_THUMBVERT = 6, + TKP_THUMBLEFT = 7, + TKP_THUMBRIGHT = 8, + TKP_TICS = 9, + TKP_TICSVERT = 10, +}; + +#define TRACKBARSTYLEPARTS TRACKBARPARTS; + +enum TRACKBARSTYLESTATES { + TKS_NORMAL = 1, +}; + +enum TRACKSTATES { + TRS_NORMAL = 1, +}; + +enum TRACKVERTSTATES { + TRVS_NORMAL = 1, +}; + +enum THUMBSTATES { + TUS_NORMAL = 1, + TUS_HOT = 2, + TUS_PRESSED = 3, + TUS_FOCUSED = 4, + TUS_DISABLED = 5, +}; + +enum THUMBBOTTOMSTATES { + TUBS_NORMAL = 1, + TUBS_HOT = 2, + TUBS_PRESSED = 3, + TUBS_FOCUSED = 4, + TUBS_DISABLED = 5, +}; + +enum THUMBTOPSTATES { + TUTS_NORMAL = 1, + TUTS_HOT = 2, + TUTS_PRESSED = 3, + TUTS_FOCUSED = 4, + TUTS_DISABLED = 5, +}; + +enum THUMBVERTSTATES { + TUVS_NORMAL = 1, + TUVS_HOT = 2, + TUVS_PRESSED = 3, + TUVS_FOCUSED = 4, + TUVS_DISABLED = 5, +}; + +enum THUMBLEFTSTATES { + TUVLS_NORMAL = 1, + TUVLS_HOT = 2, + TUVLS_PRESSED = 3, + TUVLS_FOCUSED = 4, + TUVLS_DISABLED = 5, +}; + +enum THUMBRIGHTSTATES { + TUVRS_NORMAL = 1, + TUVRS_HOT = 2, + TUVRS_PRESSED = 3, + TUVRS_FOCUSED = 4, + TUVRS_DISABLED = 5, +}; + +enum TICSSTATES { + TSS_NORMAL = 1, +}; + +enum TICSVERTSTATES { + TSVS_NORMAL = 1, +}; + + +// +// TREEVIEWSTYLE class parts and states +// +#define VSCLASS_TREEVIEWSTYLE L"TREEVIEWSTYLE" +#define VSCLASS_TREEVIEW L"TREEVIEW" + +enum TREEVIEWPARTS { + TVP_TREEITEM = 1, + TVP_GLYPH = 2, + TVP_BRANCH = 3, + TVP_HOTGLYPH = 4, +}; + +#define TREEVIEWSTYLEPARTS TREEVIEWPARTS; + +enum TREEITEMSTATES { + TREIS_NORMAL = 1, + TREIS_HOT = 2, + TREIS_SELECTED = 3, + TREIS_DISABLED = 4, + TREIS_SELECTEDNOTFOCUS = 5, + TREIS_HOTSELECTED = 6, +}; + +enum GLYPHSTATES { + GLPS_CLOSED = 1, + GLPS_OPENED = 2, +}; + +enum HOTGLYPHSTATES { + HGLPS_CLOSED = 1, + HGLPS_OPENED = 2, +}; + + +// +// WINDOWSTYLE class parts and states +// +#define VSCLASS_WINDOWSTYLE L"WINDOWSTYLE" +#define VSCLASS_WINDOW L"WINDOW" + +enum WINDOWPARTS { + WP_CAPTION = 1, + WP_SMALLCAPTION = 2, + WP_MINCAPTION = 3, + WP_SMALLMINCAPTION = 4, + WP_MAXCAPTION = 5, + WP_SMALLMAXCAPTION = 6, + WP_FRAMELEFT = 7, + WP_FRAMERIGHT = 8, + WP_FRAMEBOTTOM = 9, + WP_SMALLFRAMELEFT = 10, + WP_SMALLFRAMERIGHT = 11, + WP_SMALLFRAMEBOTTOM = 12, + WP_SYSBUTTON = 13, + WP_MDISYSBUTTON = 14, + WP_MINBUTTON = 15, + WP_MDIMINBUTTON = 16, + WP_MAXBUTTON = 17, + WP_CLOSEBUTTON = 18, + WP_SMALLCLOSEBUTTON = 19, + WP_MDICLOSEBUTTON = 20, + WP_RESTOREBUTTON = 21, + WP_MDIRESTOREBUTTON = 22, + WP_HELPBUTTON = 23, + WP_MDIHELPBUTTON = 24, + WP_HORZSCROLL = 25, + WP_HORZTHUMB = 26, + WP_VERTSCROLL = 27, + WP_VERTTHUMB = 28, + WP_DIALOG = 29, + WP_CAPTIONSIZINGTEMPLATE = 30, + WP_SMALLCAPTIONSIZINGTEMPLATE = 31, + WP_FRAMELEFTSIZINGTEMPLATE = 32, + WP_SMALLFRAMELEFTSIZINGTEMPLATE = 33, + WP_FRAMERIGHTSIZINGTEMPLATE = 34, + WP_SMALLFRAMERIGHTSIZINGTEMPLATE = 35, + WP_FRAMEBOTTOMSIZINGTEMPLATE = 36, + WP_SMALLFRAMEBOTTOMSIZINGTEMPLATE = 37, + WP_FRAME = 38, +}; + +#define WINDOWSTYLEPARTS WINDOWPARTS; + +enum FRAMESTATES { + FS_ACTIVE = 1, + FS_INACTIVE = 2, +}; + +enum CAPTIONSTATES { + CS_ACTIVE = 1, + CS_INACTIVE = 2, + CS_DISABLED = 3, +}; + +enum MAXCAPTIONSTATES { + MXCS_ACTIVE = 1, + MXCS_INACTIVE = 2, + MXCS_DISABLED = 3, +}; + +enum MINCAPTIONSTATES { + MNCS_ACTIVE = 1, + MNCS_INACTIVE = 2, + MNCS_DISABLED = 3, +}; + +enum HORZSCROLLSTATES { + HSS_NORMAL = 1, + HSS_HOT = 2, + HSS_PUSHED = 3, + HSS_DISABLED = 4, +}; + +enum HORZTHUMBSTATES { + HTS_NORMAL = 1, + HTS_HOT = 2, + HTS_PUSHED = 3, + HTS_DISABLED = 4, +}; + +enum VERTSCROLLSTATES { + VSS_NORMAL = 1, + VSS_HOT = 2, + VSS_PUSHED = 3, + VSS_DISABLED = 4, +}; + +enum VERTTHUMBSTATES { + VTS_NORMAL = 1, + VTS_HOT = 2, + VTS_PUSHED = 3, + VTS_DISABLED = 4, +}; + +enum SYSBUTTONSTATES { + SBS_NORMAL = 1, + SBS_HOT = 2, + SBS_PUSHED = 3, + SBS_DISABLED = 4, +}; + +enum MINBUTTONSTATES { + MINBS_NORMAL = 1, + MINBS_HOT = 2, + MINBS_PUSHED = 3, + MINBS_DISABLED = 4, +}; + +enum MAXBUTTONSTATES { + MAXBS_NORMAL = 1, + MAXBS_HOT = 2, + MAXBS_PUSHED = 3, + MAXBS_DISABLED = 4, +}; + +enum RESTOREBUTTONSTATES { + RBS_NORMAL = 1, + RBS_HOT = 2, + RBS_PUSHED = 3, + RBS_DISABLED = 4, +}; + +enum HELPBUTTONSTATES { + HBS_NORMAL = 1, + HBS_HOT = 2, + HBS_PUSHED = 3, + HBS_DISABLED = 4, +}; + +enum CLOSEBUTTONSTATES { + CBS_NORMAL = 1, + CBS_HOT = 2, + CBS_PUSHED = 3, + CBS_DISABLED = 4, +}; + + +#endif //__VSSTYLE_H__ + diff --git a/plugins/Clist_nicer/src/Include/vssym32.h b/plugins/Clist_nicer/src/Include/vssym32.h new file mode 100644 index 0000000000..4d2b6fd62d --- /dev/null +++ b/plugins/Clist_nicer/src/Include/vssym32.h @@ -0,0 +1,712 @@ +//-------------------------------------------------------------------------// +// VisualStyle Core Win32/ComCtl32 symbols +//-------------------------------------------------------------------------// + +#ifndef __VSSYM32_H__ +#define __VSSYM32_H__ + +#include "VSStyle.h" + +// +// enumerated property values +// + +enum BGTYPE { + BT_IMAGEFILE = 0, + BT_BORDERFILL = 1, + BT_NONE = 2, +}; + + +// +// enumerated property values +// + +enum IMAGELAYOUT { + IL_VERTICAL = 0, + IL_HORIZONTAL = 1, +}; + + +// +// enumerated property values +// + +enum BORDERTYPE { + BT_RECT = 0, + BT_ROUNDRECT = 1, + BT_ELLIPSE = 2, +}; + + +// +// enumerated property values +// + +enum FILLTYPE { + FT_SOLID = 0, + FT_VERTGRADIENT = 1, + FT_HORZGRADIENT = 2, + FT_RADIALGRADIENT = 3, + FT_TILEIMAGE = 4, +}; + + +// +// enumerated property values +// + +enum SIZINGTYPE { + ST_TRUESIZE = 0, + ST_STRETCH = 1, + ST_TILE = 2, +}; + + +// +// enumerated property values +// + +enum HALIGN { + HA_LEFT = 0, + HA_CENTER = 1, + HA_RIGHT = 2, +}; + + +// +// enumerated property values +// + +enum CONTENTALIGNMENT { + CA_LEFT = 0, + CA_CENTER = 1, + CA_RIGHT = 2, +}; + + +// +// enumerated property values +// + +enum VALIGN { + VA_TOP = 0, + VA_CENTER = 1, + VA_BOTTOM = 2, +}; + + +// +// enumerated property values +// + +enum OFFSETTYPE { + OT_TOPLEFT = 0, + OT_TOPRIGHT = 1, + OT_TOPMIDDLE = 2, + OT_BOTTOMLEFT = 3, + OT_BOTTOMRIGHT = 4, + OT_BOTTOMMIDDLE = 5, + OT_MIDDLELEFT = 6, + OT_MIDDLERIGHT = 7, + OT_LEFTOFCAPTION = 8, + OT_RIGHTOFCAPTION = 9, + OT_LEFTOFLASTBUTTON = 10, + OT_RIGHTOFLASTBUTTON = 11, + OT_ABOVELASTBUTTON = 12, + OT_BELOWLASTBUTTON = 13, +}; + + +// +// enumerated property values +// + +enum ICONEFFECT { + ICE_NONE = 0, + ICE_GLOW = 1, + ICE_SHADOW = 2, + ICE_PULSE = 3, + ICE_ALPHA = 4, +}; + + +// +// enumerated property values +// + +enum TEXTSHADOWTYPE { + TST_NONE = 0, + TST_SINGLE = 1, + TST_CONTINUOUS = 2, +}; + + +// +// enumerated property values +// + +enum GLYPHTYPE { + GT_NONE = 0, + GT_IMAGEGLYPH = 1, + GT_FONTGLYPH = 2, +}; + + +// +// enumerated property values +// + +enum IMAGESELECTTYPE { + IST_NONE = 0, + IST_SIZE = 1, + IST_DPI = 2, +}; + + +// +// enumerated property values +// + +enum TRUESIZESCALINGTYPE { + TSST_NONE = 0, + TSST_SIZE = 1, + TSST_DPI = 2, +}; + + +// +// enumerated property values +// + +enum GLYPHFONTSIZINGTYPE { + GFST_NONE = 0, + GFST_SIZE = 1, + GFST_DPI = 2, +}; + +// +// property symbol definitions +// + +#define TMT_RESERVEDLOW 0 +#define TMT_RESERVEDHIGH 7999 + +#define TMT_DIBDATA 2 +#define TMT_GLYPHDIBDATA 8 +#define TMT_ENUM 200 +#define TMT_STRING 201 +#define TMT_INT 202 +#define TMT_BOOL 203 +#define TMT_COLOR 204 +#define TMT_MARGINS 205 +#define TMT_FILENAME 206 +#define TMT_SIZE 207 +#define TMT_POSITION 208 +#define TMT_RECT 209 +#define TMT_FONT 210 +#define TMT_INTLIST 211 +#define TMT_HBITMAP 212 +#define TMT_DISKSTREAM 213 +#define TMT_STREAM 214 +#define TMT_BITMAPREF 215 +#define TMT_COLORSCHEMES 401 +#define TMT_SIZES 402 +#define TMT_CHARSET 403 +#define TMT_NAME 600 +#define TMT_DISPLAYNAME 601 +#define TMT_TOOLTIP 602 +#define TMT_COMPANY 603 +#define TMT_AUTHOR 604 +#define TMT_COPYRIGHT 605 +#define TMT_URL 606 +#define TMT_VERSION 607 +#define TMT_DESCRIPTION 608 +#define TMT_FIRST_RCSTRING_NAME TMT_DISPLAYNAME +#define TMT_LAST_RCSTRING_NAME TMT_DESCRIPTION +#define TMT_CAPTIONFONT 801 +#define TMT_SMALLCAPTIONFONT 802 +#define TMT_MENUFONT 803 +#define TMT_STATUSFONT 804 +#define TMT_MSGBOXFONT 805 +#define TMT_ICONTITLEFONT 806 +#define TMT_HEADING1FONT 807 +#define TMT_HEADING2FONT 808 +#define TMT_BODYFONT 809 +#define TMT_FIRSTFONT TMT_CAPTIONFONT +#define TMT_LASTFONT TMT_BODYFONT +#define TMT_FLATMENUS 1001 +#define TMT_FIRSTBOOL TMT_FLATMENUS +#define TMT_LASTBOOL TMT_FLATMENUS +#define TMT_SIZINGBORDERWIDTH 1201 +#define TMT_SCROLLBARWIDTH 1202 +#define TMT_SCROLLBARHEIGHT 1203 +#define TMT_CAPTIONBARWIDTH 1204 +#define TMT_CAPTIONBARHEIGHT 1205 +#define TMT_SMCAPTIONBARWIDTH 1206 +#define TMT_SMCAPTIONBARHEIGHT 1207 +#define TMT_MENUBARWIDTH 1208 +#define TMT_MENUBARHEIGHT 1209 +#define TMT_PADDEDBORDERWIDTH 1210 +#define TMT_FIRSTSIZE TMT_SIZINGBORDERWIDTH +#define TMT_LASTSIZE TMT_PADDEDBORDERWIDTH +#define TMT_MINCOLORDEPTH 1301 +#define TMT_FIRSTINT TMT_MINCOLORDEPTH +#define TMT_LASTINT TMT_MINCOLORDEPTH +#define TMT_CSSNAME 1401 +#define TMT_XMLNAME 1402 +#define TMT_LASTUPDATED 1403 +#define TMT_ALIAS 1404 +#define TMT_FIRSTSTRING TMT_CSSNAME +#define TMT_LASTSTRING TMT_ALIAS +#define TMT_SCROLLBAR 1601 +#define TMT_BACKGROUND 1602 +#define TMT_ACTIVECAPTION 1603 +#define TMT_INACTIVECAPTION 1604 +#define TMT_MENU 1605 +#define TMT_WINDOW 1606 +#define TMT_WINDOWFRAME 1607 +#define TMT_MENUTEXT 1608 +#define TMT_WINDOWTEXT 1609 +#define TMT_CAPTIONTEXT 1610 +#define TMT_ACTIVEBORDER 1611 +#define TMT_INACTIVEBORDER 1612 +#define TMT_APPWORKSPACE 1613 +#define TMT_HIGHLIGHT 1614 +#define TMT_HIGHLIGHTTEXT 1615 +#define TMT_BTNFACE 1616 +#define TMT_BTNSHADOW 1617 +#define TMT_GRAYTEXT 1618 +#define TMT_BTNTEXT 1619 +#define TMT_INACTIVECAPTIONTEXT 1620 +#define TMT_BTNHIGHLIGHT 1621 +#define TMT_DKSHADOW3D 1622 +#define TMT_LIGHT3D 1623 +#define TMT_INFOTEXT 1624 +#define TMT_INFOBK 1625 +#define TMT_BUTTONALTERNATEFACE 1626 +#define TMT_HOTTRACKING 1627 +#define TMT_GRADIENTACTIVECAPTION 1628 +#define TMT_GRADIENTINACTIVECAPTION 1629 +#define TMT_MENUHILIGHT 1630 +#define TMT_MENUBAR 1631 +#define TMT_FIRSTCOLOR TMT_SCROLLBAR +#define TMT_LASTCOLOR TMT_MENUBAR +#define TMT_FROMHUE1 1801 +#define TMT_FROMHUE2 1802 +#define TMT_FROMHUE3 1803 +#define TMT_FROMHUE4 1804 +#define TMT_FROMHUE5 1805 +#define TMT_TOHUE1 1806 +#define TMT_TOHUE2 1807 +#define TMT_TOHUE3 1808 +#define TMT_TOHUE4 1809 +#define TMT_TOHUE5 1810 +#define TMT_FROMCOLOR1 2001 +#define TMT_FROMCOLOR2 2002 +#define TMT_FROMCOLOR3 2003 +#define TMT_FROMCOLOR4 2004 +#define TMT_FROMCOLOR5 2005 +#define TMT_TOCOLOR1 2006 +#define TMT_TOCOLOR2 2007 +#define TMT_TOCOLOR3 2008 +#define TMT_TOCOLOR4 2009 +#define TMT_TOCOLOR5 2010 +#define TMT_TRANSPARENT 2201 +#define TMT_AUTOSIZE 2202 +#define TMT_BORDERONLY 2203 +#define TMT_COMPOSITED 2204 +#define TMT_BGFILL 2205 +#define TMT_GLYPHTRANSPARENT 2206 +#define TMT_GLYPHONLY 2207 +#define TMT_ALWAYSSHOWSIZINGBAR 2208 +#define TMT_MIRRORIMAGE 2209 +#define TMT_UNIFORMSIZING 2210 +#define TMT_INTEGRALSIZING 2211 +#define TMT_SOURCEGROW 2212 +#define TMT_SOURCESHRINK 2213 +#define TMT_DRAWBORDERS 2214 +#define TMT_NOETCHEDEFFECT 2215 +#define TMT_TEXTAPPLYOVERLAY 2216 +#define TMT_TEXTGLOW 2217 +#define TMT_TEXTITALIC 2218 +#define TMT_COMPOSITEDOPAQUE 2219 +#define TMT_LOCALIZEDMIRRORIMAGE 2220 +#define TMT_IMAGECOUNT 2401 +#define TMT_ALPHALEVEL 2402 +#define TMT_BORDERSIZE 2403 +#define TMT_ROUNDCORNERWIDTH 2404 +#define TMT_ROUNDCORNERHEIGHT 2405 +#define TMT_GRADIENTRATIO1 2406 +#define TMT_GRADIENTRATIO2 2407 +#define TMT_GRADIENTRATIO3 2408 +#define TMT_GRADIENTRATIO4 2409 +#define TMT_GRADIENTRATIO5 2410 +#define TMT_PROGRESSCHUNKSIZE 2411 +#define TMT_PROGRESSSPACESIZE 2412 +#define TMT_SATURATION 2413 +#define TMT_TEXTBORDERSIZE 2414 +#define TMT_ALPHATHRESHOLD 2415 +#define TMT_WIDTH 2416 +#define TMT_HEIGHT 2417 +#define TMT_GLYPHINDEX 2418 +#define TMT_TRUESIZESTRETCHMARK 2419 +#define TMT_MINDPI1 2420 +#define TMT_MINDPI2 2421 +#define TMT_MINDPI3 2422 +#define TMT_MINDPI4 2423 +#define TMT_MINDPI5 2424 +#define TMT_TEXTGLOWSIZE 2425 +#define TMT_FRAMESPERSECOND 2426 +#define TMT_PIXELSPERFRAME 2427 +#define TMT_ANIMATIONDELAY 2428 +#define TMT_GLOWINTENSITY 2429 +#define TMT_OPACITY 2430 +#define TMT_COLORIZATIONCOLOR 2431 +#define TMT_COLORIZATIONOPACITY 2432 +#define TMT_GLYPHFONT 2601 +#define TMT_IMAGEFILE 3001 +#define TMT_IMAGEFILE1 3002 +#define TMT_IMAGEFILE2 3003 +#define TMT_IMAGEFILE3 3004 +#define TMT_IMAGEFILE4 3005 +#define TMT_IMAGEFILE5 3006 +#define TMT_GLYPHIMAGEFILE 3008 +#define TMT_TEXT 3201 +#define TMT_CLASSICVALUE 3202 +#define TMT_OFFSET 3401 +#define TMT_TEXTSHADOWOFFSET 3402 +#define TMT_MINSIZE 3403 +#define TMT_MINSIZE1 3404 +#define TMT_MINSIZE2 3405 +#define TMT_MINSIZE3 3406 +#define TMT_MINSIZE4 3407 +#define TMT_MINSIZE5 3408 +#define TMT_NORMALSIZE 3409 +#define TMT_SIZINGMARGINS 3601 +#define TMT_CONTENTMARGINS 3602 +#define TMT_CAPTIONMARGINS 3603 +#define TMT_BORDERCOLOR 3801 +#define TMT_FILLCOLOR 3802 +#define TMT_TEXTCOLOR 3803 +#define TMT_EDGELIGHTCOLOR 3804 +#define TMT_EDGEHIGHLIGHTCOLOR 3805 +#define TMT_EDGESHADOWCOLOR 3806 +#define TMT_EDGEDKSHADOWCOLOR 3807 +#define TMT_EDGEFILLCOLOR 3808 +#define TMT_TRANSPARENTCOLOR 3809 +#define TMT_GRADIENTCOLOR1 3810 +#define TMT_GRADIENTCOLOR2 3811 +#define TMT_GRADIENTCOLOR3 3812 +#define TMT_GRADIENTCOLOR4 3813 +#define TMT_GRADIENTCOLOR5 3814 +#define TMT_SHADOWCOLOR 3815 +#define TMT_GLOWCOLOR 3816 +#define TMT_TEXTBORDERCOLOR 3817 +#define TMT_TEXTSHADOWCOLOR 3818 +#define TMT_GLYPHTEXTCOLOR 3819 +#define TMT_GLYPHTRANSPARENTCOLOR 3820 +#define TMT_FILLCOLORHINT 3821 +#define TMT_BORDERCOLORHINT 3822 +#define TMT_ACCENTCOLORHINT 3823 +#define TMT_TEXTCOLORHINT 3824 +#define TMT_HEADING1TEXTCOLOR 3825 +#define TMT_HEADING2TEXTCOLOR 3826 +#define TMT_BODYTEXTCOLOR 3827 +#define TMT_BGTYPE 4001 +#define TMT_BORDERTYPE 4002 +#define TMT_FILLTYPE 4003 +#define TMT_SIZINGTYPE 4004 +#define TMT_HALIGN 4005 +#define TMT_CONTENTALIGNMENT 4006 +#define TMT_VALIGN 4007 +#define TMT_OFFSETTYPE 4008 +#define TMT_ICONEFFECT 4009 +#define TMT_TEXTSHADOWTYPE 4010 +#define TMT_IMAGELAYOUT 4011 +#define TMT_GLYPHTYPE 4012 +#define TMT_IMAGESELECTTYPE 4013 +#define TMT_GLYPHFONTSIZINGTYPE 4014 +#define TMT_TRUESIZESCALINGTYPE 4015 +#define TMT_USERPICTURE 5001 +#define TMT_DEFAULTPANESIZE 5002 +#define TMT_BLENDCOLOR 5003 +#define TMT_CUSTOMSPLITRECT 5004 +#define TMT_ANIMATIONBUTTONRECT 5005 +#define TMT_ANIMATIONDURATION 5006 +#define TMT_TRANSITIONDURATIONS 6000 +#define TMT_SCALEDBACKGROUND 7001 +#define TMT_ATLASIMAGE 8000 +#define TMT_ATLASINPUTIMAGE 8001 +#define TMT_ATLASRECT 8002 + + +// +// LINK class parts and states +// +#define VSCLASS_LINK L"LINK" + +enum LINKPARTS { + LP_HYPERLINK = 1, +}; + +enum HYPERLINKSTATES { + HLS_NORMALTEXT = 1, + HLS_LINKTEXT = 2, +}; + + +// +// EMPTYMARKUP class parts and states +// +#define VSCLASS_EMPTYMARKUP L"EMPTYMARKUP" + +enum EMPTYMARKUPPARTS { + EMP_MARKUPTEXT = 1, +}; + +enum MARKUPTEXTSTATES { + EMT_NORMALTEXT = 1, + EMT_LINKTEXT = 2, +}; + + +// +// STATIC class parts and states +// +#define VSCLASS_STATIC L"STATIC" + +enum STATICPARTS { + STAT_TEXT = 1, +}; + + +// +// PAGE class parts and states +// +#define VSCLASS_PAGE L"PAGE" + +enum PAGEPARTS { + PGRP_UP = 1, + PGRP_DOWN = 2, + PGRP_UPHORZ = 3, + PGRP_DOWNHORZ = 4, +}; + + +// +// MONTHCAL class parts and states +// +#define VSCLASS_MONTHCAL L"MONTHCAL" + +enum MONTHCALPARTS { + MC_BACKGROUND = 1, + MC_BORDERS = 2, + MC_GRIDBACKGROUND = 3, + MC_COLHEADERSPLITTER = 4, + MC_GRIDCELLBACKGROUND = 5, + MC_GRIDCELL = 6, + MC_GRIDCELLUPPER = 7, + MC_TRAILINGGRIDCELL = 8, + MC_TRAILINGGRIDCELLUPPER = 9, + MC_NAVNEXT = 10, + MC_NAVPREV = 11, +}; + +enum GRIDCELLBACKGROUNDSTATES { + MCGCB_SELECTED = 1, + MCGCB_HOT = 2, + MCGCB_SELECTEDHOT = 3, + MCGCB_SELECTEDNOTFOCUSED = 4, + MCGCB_TODAY = 5, +}; + +enum GRIDCELLSTATES { + MCGC_HOT = 1, + MCGC_HASSTATE = 2, + MCGC_HASSTATEHOT = 3, + MCGC_TODAY = 4, +}; + +enum GRIDCELLUPPERSTATES { + MCGCU_HOT = 1, + MCGCU_HASSTATE = 2, + MCGCU_HASSTATEHOT = 3, +}; + +enum TRAILINGGRIDCELLSTATES { + MCTGC_HOT = 1, + MCTGC_HASSTATE = 2, + MCTGC_HASSTATEHOT = 3, + MCTGC_TODAY = 4, +}; + +enum TRAILINGGRIDCELLUPPERSTATES { + MCTGCU_HOT = 1, + MCTGCU_HASSTATE = 2, + MCTGCU_HASSTATEHOT = 3, +}; + +enum NAVNEXTSTATES { + MCNN_NORMAL = 1, + MCNN_HOT = 2, + MCNN_PRESSED = 3, + MCNN_DISABLED = 4, +}; + +enum NAVPREVSTATES { + MCNP_NORMAL = 1, + MCNP_HOT = 2, + MCNP_PRESSED = 3, + MCNP_DISABLED = 4, +}; + + +// +// CLOCK class parts and states +// +#define VSCLASS_CLOCK L"CLOCK" + +enum CLOCKPARTS { + CLP_TIME = 1, +}; + +enum CLOCKSTATES { + CLS_NORMAL = 1, + CLS_HOT = 2, + CLS_PRESSED = 3, +}; + + +// +// TRAYNOTIFY class parts and states +// +#define VSCLASS_TRAYNOTIFY L"TRAYNOTIFY" + +enum TRAYNOTIFYPARTS { + TNP_BACKGROUND = 1, + TNP_ANIMBACKGROUND = 2, +}; + + +// +// TASKBAR class parts and states +// +#define VSCLASS_TASKBAR L"TASKBAR" + +enum TASKBARPARTS { + TBP_BACKGROUNDBOTTOM = 1, + TBP_BACKGROUNDRIGHT = 2, + TBP_BACKGROUNDTOP = 3, + TBP_BACKGROUNDLEFT = 4, + TBP_SIZINGBARBOTTOM = 5, + TBP_SIZINGBARRIGHT = 6, + TBP_SIZINGBARTOP = 7, + TBP_SIZINGBARLEFT = 8, +}; + + +// +// TASKBAND class parts and states +// +#define VSCLASS_TASKBAND L"TASKBAND" + +enum TASKBANDPARTS { + TDP_GROUPCOUNT = 1, + TDP_FLASHBUTTON = 2, + TDP_FLASHBUTTONGROUPMENU = 3, +}; + + +// +// STARTPANEL class parts and states +// +#define VSCLASS_STARTPANEL L"STARTPANEL" + +enum STARTPANELPARTS { + SPP_USERPANE = 1, + SPP_MOREPROGRAMS = 2, + SPP_MOREPROGRAMSARROW = 3, + SPP_PROGLIST = 4, + SPP_PROGLISTSEPARATOR = 5, + SPP_PLACESLIST = 6, + SPP_PLACESLISTSEPARATOR = 7, + SPP_LOGOFF = 8, + SPP_LOGOFFBUTTONS = 9, + SPP_USERPICTURE = 10, + SPP_PREVIEW = 11, + SPP_MOREPROGRAMSTAB = 12, + SPP_NSCHOST = 13, + SPP_SOFTWAREEXPLORER = 14, + SPP_OPENBOX = 15, + SPP_SEARCHVIEW = 16, + SPP_MOREPROGRAMSARROWBACK = 17, + SPP_TOPMATCH = 18, + SPP_LOGOFFSPLITBUTTONDROPDOWN = 19, +}; + +enum MOREPROGRAMSTABSTATES { + SPMPT_NORMAL = 1, + SPMPT_HOT = 2, + SPMPT_SELECTED = 3, + SPMPT_DISABLED = 4, + SPMPT_FOCUSED = 5, +}; + +enum SOFTWAREEXPLORERSTATES { + SPSE_NORMAL = 1, + SPSE_HOT = 2, + SPSE_SELECTED = 3, + SPSE_DISABLED = 4, + SPSE_FOCUSED = 5, +}; + +enum OPENBOXSTATES { + SPOB_NORMAL = 1, + SPOB_HOT = 2, + SPOB_SELECTED = 3, + SPOB_DISABLED = 4, + SPOB_FOCUSED = 5, +}; + +enum MOREPROGRAMSARROWSTATES { + SPS_NORMAL = 1, + SPS_HOT = 2, + SPS_PRESSED = 3, +}; + +enum MOREPROGRAMSARROWBACKSTATES { + SPSB_NORMAL = 1, + SPSB_HOT = 2, + SPSB_PRESSED = 3, +}; + +enum LOGOFFBUTTONSSTATES { + SPLS_NORMAL = 1, + SPLS_HOT = 2, + SPLS_PRESSED = 3, +}; + + +// +// MENUBAND class parts and states +// +#define VSCLASS_MENUBAND L"MENUBAND" + +enum MENUBANDPARTS { + MDP_NEWAPPBUTTON = 1, + MDP_SEPERATOR = 2, +}; + +enum MENUBANDSTATES { + MDS_NORMAL = 1, + MDS_HOT = 2, + MDS_PRESSED = 3, + MDS_DISABLED = 4, + MDS_CHECKED = 5, + MDS_HOTCHECKED = 6, +}; + + +#endif //__VSSYM32_H__ + diff --git a/plugins/Clist_nicer/src/alphablend.cpp b/plugins/Clist_nicer/src/alphablend.cpp new file mode 100644 index 0000000000..f81c029bad --- /dev/null +++ b/plugins/Clist_nicer/src/alphablend.cpp @@ -0,0 +1,545 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 "commonheaders.h" + +extern int g_hottrack, g_hottrack_done; +extern BOOL g_inCLCpaint; +extern BYTE saved_alpha; +extern DWORD savedCORNER; +extern StatusItems_t *StatusItems; +extern ImageItem *g_glyphItem; + +BYTE __forceinline percent_to_byte(UINT32 percent) +{ + return(BYTE) ((FLOAT) (((FLOAT) percent) / 100) * 255); +} + +COLORREF __forceinline revcolref(COLORREF colref) +{ + return RGB(GetBValue(colref), GetGValue(colref), GetRValue(colref)); +} + +DWORD __forceinline argb_from_cola(COLORREF col, UINT32 alpha) +{ + return((BYTE) percent_to_byte(alpha) << 24 | col); +} + + +void __forceinline DrawBorderStyle(HDC hdcwnd, RECT *rc, DWORD BORDERSTYLE) +{ + if(BORDERSTYLE >= 0) { + HPEN hPenOld = 0; + POINT pt; + + switch(BORDERSTYLE) { + case BDR_RAISEDOUTER: // raised + MoveToEx(hdcwnd, rc->left, rc->bottom - 1, &pt); + hPenOld = reinterpret_cast(SelectObject(hdcwnd, cfg::dat.hPen3DBright)); + LineTo(hdcwnd, rc->left, rc->top); + LineTo(hdcwnd, rc->right, rc->top); + SelectObject(hdcwnd, cfg::dat.hPen3DDark); + MoveToEx(hdcwnd, rc->right - 1, rc->top + 1, &pt); + LineTo(hdcwnd, rc->right - 1, rc->bottom - 1); + LineTo(hdcwnd, rc->left - 1, rc->bottom - 1); + break; + case BDR_SUNKENINNER: + MoveToEx(hdcwnd, rc->left, rc->bottom - 1, &pt); + hPenOld = reinterpret_cast(SelectObject(hdcwnd, cfg::dat.hPen3DDark)); + LineTo(hdcwnd, rc->left, rc->top); + LineTo(hdcwnd, rc->right, rc->top); + MoveToEx(hdcwnd, rc->right - 1, rc->top + 1, &pt); + SelectObject(hdcwnd, cfg::dat.hPen3DBright); + LineTo(hdcwnd, rc->right - 1, rc->bottom - 1); + LineTo(hdcwnd, rc->left, rc->bottom - 1); + break; + default: + DrawEdge(hdcwnd, rc, BORDERSTYLE, BF_RECT | BF_SOFT); + break; + } + if(hPenOld) + SelectObject(hdcwnd, hPenOld); + } +} +void DrawAlpha(HDC hdcwnd, PRECT rc, DWORD basecolor, int alpha, DWORD basecolor2, BOOL transparent, BYTE FLG_GRADIENT, BYTE FLG_CORNER, DWORD BORDERSTYLE, ImageItem *imageItem) +{ + HBRUSH BrMask; + HBRUSH holdbrush; + HDC hdc; + BLENDFUNCTION bf; + HBITMAP hbitmap; + HBITMAP holdbitmap; + BITMAPINFO bmi; + VOID *pvBits; + UINT32 x, y; + ULONG ulBitmapWidth, ulBitmapHeight; + UCHAR ubAlpha = 0xFF; + UCHAR ubRedFinal = 0xFF; + UCHAR ubGreenFinal = 0xFF; + UCHAR ubBlueFinal = 0xFF; + UCHAR ubRed; + UCHAR ubGreen; + UCHAR ubBlue; + UCHAR ubRed2; + UCHAR ubGreen2; + UCHAR ubBlue2; + + int realx; + + FLOAT fAlphaFactor; + LONG realHeight = (rc->bottom - rc->top); + LONG realWidth = (rc->right - rc->left); + LONG realHeightHalf = realHeight >> 1; + + if (g_hottrack && g_inCLCpaint) { + StatusItems_t *ht = &StatusItems[ID_EXTBKHOTTRACK - ID_STATUS_OFFLINE]; + if (ht->IGNORED == 0) { + basecolor = ht->COLOR; + basecolor2 = ht->COLOR2; + alpha = ht->ALPHA; + FLG_GRADIENT = ht->GRADIENT; + transparent = ht->COLOR2_TRANSPARENT; + BORDERSTYLE = ht->BORDERSTYLE; + imageItem = ht->imageItem; + } + g_hottrack_done = 1; + } + + if(imageItem) { + IMG_RenderImageItem(hdcwnd, imageItem, rc); + return; + } + + if (rc == NULL) + return; + + if (rc->right < rc->left || rc->bottom < rc->top || (realHeight <= 0) || (realWidth <= 0)) + return; + + if(cfg::dat.bUseFastGradients && !(FLG_CORNER & CORNER_ACTIVE)) { + GRADIENT_RECT grect; + TRIVERTEX tvtx[2]; + int orig = 1, dest = 0; + + if (!(FLG_GRADIENT & GRADIENT_ACTIVE)) { + tvtx[0].Red = tvtx[1].Red = (COLOR16)GetRValue(basecolor) << 8; + tvtx[0].Blue = tvtx[1].Blue = (COLOR16)GetBValue(basecolor) << 8; + tvtx[0].Green = tvtx[1].Green = (COLOR16)GetGValue(basecolor) << 8; + tvtx[0].Alpha = tvtx[1].Alpha = 0; + } + else { + if(FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_TB) { + orig = 0; + dest = 1; + } + + tvtx[orig].Red = (COLOR16)GetRValue(basecolor) << 8; + tvtx[orig].Blue = (COLOR16)GetBValue(basecolor) << 8; + tvtx[orig].Green = (COLOR16)GetGValue(basecolor) << 8; + tvtx[orig].Alpha = (COLOR16)0; + + tvtx[dest].Red = (COLOR16)GetRValue(basecolor2) << 8; + tvtx[dest].Blue = (COLOR16)GetBValue(basecolor2) << 8; + tvtx[dest].Green = (COLOR16)GetGValue(basecolor2) << 8; + tvtx[dest].Alpha = (COLOR16)0; + } + grect.UpperLeft = 0; + grect.LowerRight = 1; + + saved_alpha = (UCHAR) (basecolor >> 24); + + if(alpha < 100) { + BLENDFUNCTION bf; + HDC hdc; + HBITMAP hbm, hbmOld; + LONG width = rc->right - rc->left, height = rc->bottom - rc->top; + + tvtx[0].x = tvtx[0].y = 0; + tvtx[1].x = width; + tvtx[1].y = height; + + basecolor = argb_from_cola(revcolref(basecolor), alpha); + basecolor2 = argb_from_cola(revcolref(basecolor2), alpha); + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = percent_to_byte((UINT32)alpha); + bf.AlphaFormat = 0; // so it will use our specified alpha value + hdc = CreateCompatibleDC(hdcwnd); + if (!hdc) + return; + hbm = CreateCompatibleBitmap(hdcwnd, width, height); + hbmOld = reinterpret_cast(SelectObject(hdc, hbm)); + API::pfnGradientFill(hdc, tvtx, 2, &grect, 1, (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT) ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H); + API::pfnAlphaBlend(hdcwnd, rc->left, rc->top, width, height, hdc, 0, 0, width, height, bf); + + SelectObject(hdc, hbmOld); + DeleteObject(hbm); + DeleteDC(hdc); + } + else { + tvtx[0].x = rc->left; + tvtx[0].y = rc->top; + tvtx[1].x = rc->right; + tvtx[1].y = rc->bottom; + API::pfnGradientFill(hdcwnd, tvtx, 2, &grect, 1, (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT) ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H); + } + DrawBorderStyle(hdcwnd, rc, BORDERSTYLE); + //_DebugPopup(0, "using gradient fill"); + return; + } + + hdc = CreateCompatibleDC(hdcwnd); + if (!hdc) + return; + + ZeroMemory(&bmi, sizeof(BITMAPINFO)); + + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + if (FLG_GRADIENT & GRADIENT_ACTIVE && (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL)) { + bmi.bmiHeader.biWidth = ulBitmapWidth = realWidth; + bmi.bmiHeader.biHeight = ulBitmapHeight = 1; + } else if (FLG_GRADIENT & GRADIENT_ACTIVE && (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT)) { + bmi.bmiHeader.biWidth = ulBitmapWidth = 1; + bmi.bmiHeader.biHeight = ulBitmapHeight = realHeight; + } else { + bmi.bmiHeader.biWidth = ulBitmapWidth = 1; + bmi.bmiHeader.biHeight = ulBitmapHeight = 1; + } + + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4; + + if (ulBitmapWidth <= 0 || ulBitmapHeight <= 0) + return; + + hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0); + if (hbitmap == NULL || pvBits == NULL) { + DeleteDC(hdc); + return; + } + + holdbitmap = reinterpret_cast(SelectObject(hdc, hbitmap)); + + // convert basecolor to RGB and then merge alpha so its ARGB + basecolor = argb_from_cola(revcolref(basecolor), alpha); + basecolor2 = argb_from_cola(revcolref(basecolor2), alpha); + + ubRed = (UCHAR) (basecolor >> 16); + ubGreen = (UCHAR) (basecolor >> 8); + ubBlue = (UCHAR) basecolor; + + ubRed2 = (UCHAR) (basecolor2 >> 16); + ubGreen2 = (UCHAR) (basecolor2 >> 8); + ubBlue2 = (UCHAR) basecolor2; + + //DRAW BASE - make corner space 100% transparent + for (y = 0; y < ulBitmapHeight; y++) { + for (x = 0 ; x < ulBitmapWidth ; x++) { + if (FLG_GRADIENT & GRADIENT_ACTIVE) { + if (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL) { + realx = x + realHeightHalf; + realx = (ULONG) realx > ulBitmapWidth ? ulBitmapWidth : realx; + gradientHorizontal(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapWidth, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, realx, &ubAlpha); + } else if (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT) + gradientVertical(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapHeight, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, y, &ubAlpha); + + fAlphaFactor = (float) ubAlpha / (float) 0xff; + ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor)); + } else { + ubAlpha = percent_to_byte(alpha); + ubRedFinal = ubRed; + ubGreenFinal = ubGreen; + ubBlueFinal = ubBlue; + fAlphaFactor = (float) ubAlpha / (float) 0xff; + + ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor)); + } + } + } + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = (UCHAR) (basecolor >> 24); + bf.AlphaFormat = AC_SRC_ALPHA; // so it will use our specified alpha value + + API::pfnAlphaBlend(hdcwnd, rc->left + realHeightHalf, rc->top, (realWidth - realHeightHalf * 2), realHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf); + + SelectObject(hdc, holdbitmap); + DeleteObject(hbitmap); + + saved_alpha = (UCHAR) (basecolor >> 24); + + // corners + BrMask = CreateSolidBrush(RGB(0xFF, 0x00, 0xFF)); + { + bmi.bmiHeader.biWidth = ulBitmapWidth = realHeightHalf; + bmi.bmiHeader.biHeight = ulBitmapHeight = realHeight; + bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4; + + if (ulBitmapWidth <= 0 || ulBitmapHeight <= 0) { + DeleteDC(hdc); + DeleteObject(BrMask); + return; + } + + // TL+BL CORNER + hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0); + + if(hbitmap == 0 || pvBits == NULL) { + DeleteObject(BrMask); + DeleteDC(hdc); + return; + } + + holdbrush = reinterpret_cast(SelectObject(hdc, BrMask)); + holdbitmap = reinterpret_cast(SelectObject(hdc, hbitmap)); + RoundRect(hdc, -1, -1, ulBitmapWidth * 2 + 1, (realHeight + 1), cfg::dat.cornerRadius << 1, cfg::dat.cornerRadius << 1); + + for (y = 0; y < ulBitmapHeight; y++) { + for (x = 0; x < ulBitmapWidth; x++) { + if (((((UINT32 *) pvBits)[x + y * ulBitmapWidth]) << 8) == 0xFF00FF00 || (y< ulBitmapHeight >> 1 && !(FLG_CORNER & CORNER_BL && FLG_CORNER & CORNER_ACTIVE)) || (y > ulBitmapHeight >> 2 && !(FLG_CORNER & CORNER_TL && FLG_CORNER & CORNER_ACTIVE))) { + if (FLG_GRADIENT & GRADIENT_ACTIVE) { + if (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL) + gradientHorizontal(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, realWidth, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, x, &ubAlpha); + else if (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT) + gradientVertical(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapHeight, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, y, &ubAlpha); + + fAlphaFactor = (float) ubAlpha / (float) 0xff; + ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor)); + } else { + ubAlpha = percent_to_byte(alpha); + ubRedFinal = ubRed; + ubGreenFinal = ubGreen; + ubBlueFinal = ubBlue; + fAlphaFactor = (float) ubAlpha / (float) 0xff; + + ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor)); + } + } + } + } + API::pfnAlphaBlend(hdcwnd, rc->left, rc->top, ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf); + SelectObject(hdc, holdbitmap); + DeleteObject(hbitmap); + + // TR+BR CORNER + hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0); + + //SelectObject(hdc, BrMask); // already BrMask? + holdbitmap = reinterpret_cast(SelectObject(hdc, hbitmap)); + RoundRect(hdc, -1 - ulBitmapWidth, -1, ulBitmapWidth + 1, (realHeight + 1), cfg::dat.cornerRadius << 1, cfg::dat.cornerRadius << 1); + + for (y = 0; y < ulBitmapHeight; y++) { + for (x = 0; x < ulBitmapWidth; x++) { + if (((((UINT32 *) pvBits)[x + y * ulBitmapWidth]) << 8) == 0xFF00FF00 || (y< ulBitmapHeight >> 1 && !(FLG_CORNER & CORNER_BR && FLG_CORNER & CORNER_ACTIVE)) || (y > ulBitmapHeight >> 1 && !(FLG_CORNER & CORNER_TR && FLG_CORNER & CORNER_ACTIVE))) { + if (FLG_GRADIENT & GRADIENT_ACTIVE) { + if (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL) { + realx = x + realWidth; + realx = realx > realWidth ? realWidth : realx; + gradientHorizontal(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, realWidth, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, realx, &ubAlpha); + } else if (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT) + gradientVertical(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapHeight, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, y, &ubAlpha); + + fAlphaFactor = (float) ubAlpha / (float) 0xff; + ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor)); + } else { + ubAlpha = percent_to_byte(alpha); + ubRedFinal = ubRed; + ubGreenFinal = ubGreen; + ubBlueFinal = ubBlue; + fAlphaFactor = (float) ubAlpha / (float) 0xff; + + ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor)); + } + } + } + } + API::pfnAlphaBlend(hdcwnd, rc->right - realHeightHalf, rc->top, ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf); + } + DrawBorderStyle(hdcwnd, rc, BORDERSTYLE); + + SelectObject(hdc, holdbitmap); + DeleteObject(hbitmap); + SelectObject(hdc, holdbrush); + DeleteObject(BrMask); + DeleteDC(hdc); +} + +void __inline gradientHorizontal(UCHAR *ubRedFinal, UCHAR *ubGreenFinal, UCHAR *ubBlueFinal, ULONG ulBitmapWidth, UCHAR ubRed, UCHAR ubGreen, UCHAR ubBlue, UCHAR ubRed2, UCHAR ubGreen2, UCHAR ubBlue2, DWORD FLG_GRADIENT, BOOL transparent, UINT32 x, UCHAR *ubAlpha) +{ + FLOAT fSolidMulti, fInvSolidMulti; + + // solid to transparent + if (transparent) { + *ubAlpha = (UCHAR) ((float) x / (float) ulBitmapWidth * 255); + *ubAlpha = FLG_GRADIENT & GRADIENT_LR ? 0xFF - (*ubAlpha) : (*ubAlpha); + *ubRedFinal = ubRed; *ubGreenFinal = ubGreen; *ubBlueFinal = ubBlue; + } else { // solid to solid2 + if (FLG_GRADIENT & GRADIENT_LR) { + fSolidMulti = ((float) x / (float) ulBitmapWidth); + fInvSolidMulti = 1 - fSolidMulti; + } else { + fInvSolidMulti = ((float) x / (float) ulBitmapWidth); + fSolidMulti = 1 - fInvSolidMulti; + } + + *ubRedFinal = (UCHAR) (((float) ubRed * (float) fInvSolidMulti) + ((float) ubRed2 * (float) fSolidMulti)); + *ubGreenFinal = (UCHAR) (((float) ubGreen * (float) fInvSolidMulti) + ((float) ubGreen2 * (float) fSolidMulti)); + *ubBlueFinal = (UCHAR) (((float) ubBlue * (float) fInvSolidMulti) + ((float) ubBlue2 * (float) fSolidMulti)); + + *ubAlpha = 0xFF; + } +} + +void __inline gradientVertical(UCHAR *ubRedFinal, UCHAR *ubGreenFinal, UCHAR *ubBlueFinal, ULONG ulBitmapHeight, UCHAR ubRed, UCHAR ubGreen, UCHAR ubBlue, UCHAR ubRed2, UCHAR ubGreen2, UCHAR ubBlue2, DWORD FLG_GRADIENT, BOOL transparent, UINT32 y, UCHAR *ubAlpha) +{ + FLOAT fSolidMulti, fInvSolidMulti; + + // solid to transparent + if (transparent) { + *ubAlpha = (UCHAR) ((float) y / (float) ulBitmapHeight * 255); + *ubAlpha = FLG_GRADIENT & GRADIENT_BT ? 0xFF - *ubAlpha : *ubAlpha; + *ubRedFinal = ubRed; *ubGreenFinal = ubGreen; *ubBlueFinal = ubBlue; + } else { // solid to solid2 + if (FLG_GRADIENT & GRADIENT_BT) { + fSolidMulti = ((float) y / (float) ulBitmapHeight); + fInvSolidMulti = 1 - fSolidMulti; + } else { + fInvSolidMulti = ((float) y / (float) ulBitmapHeight); + fSolidMulti = 1 - fInvSolidMulti; + } + + *ubRedFinal = (UCHAR) (((float) ubRed * (float) fInvSolidMulti) + ((float) ubRed2 * (float) fSolidMulti)); + *ubGreenFinal = (UCHAR) (((float) ubGreen * (float) fInvSolidMulti) + ((float) ubGreen2 * (float) fSolidMulti)); + *ubBlueFinal = (UCHAR) (((float) ubBlue * (float) fInvSolidMulti) + ((float) ubBlue2 * (float) fSolidMulti)); + + *ubAlpha = 0xFF; + } +} + +/* + * render a skin image to the given rect. + * all parameters are in ImageItem already pre-configured + */ + +// XXX add support for more stretching options (stretch/tile divided image parts etc. + +void __fastcall IMG_RenderImageItem(HDC hdc, ImageItem *item, RECT *rc) +{ + BYTE l = item->bLeft, r = item->bRight, t = item->bTop, b = item->bBottom; + LONG width = rc->right - rc->left; + LONG height = rc->bottom - rc->top; + BOOL isGlyph = (item->dwFlags & IMAGE_GLYPH) && g_glyphItem; + HDC hdcSrc = isGlyph ? g_glyphItem->hdc : item->hdc; + LONG srcOrigX = isGlyph ? item->glyphMetrics[0] : 0; + LONG srcOrigY = isGlyph ? item->glyphMetrics[1] : 0; + + if(item->dwFlags & IMAGE_FLAG_DIVIDED) { + // top 3 items + + API::pfnAlphaBlend(hdc, rc->left, rc->top, l, t, hdcSrc, srcOrigX, srcOrigY, l, t, item->bf); + API::pfnAlphaBlend(hdc, rc->left + l, rc->top, width - l - r, t, hdcSrc, srcOrigX + l, srcOrigY, item->inner_width, t, item->bf); + API::pfnAlphaBlend(hdc, rc->right - r, rc->top, r, t, hdcSrc, srcOrigX + (item->width - r), srcOrigY, r, t, item->bf); + + // middle 3 items + + API::pfnAlphaBlend(hdc, rc->left, rc->top + t, l, height - t - b, hdcSrc, srcOrigX, srcOrigY + t, l, item->inner_height, item->bf); + + if(item->dwFlags & IMAGE_FILLSOLID && item->fillBrush) { + RECT rcFill; + rcFill.left = rc->left + l; rcFill.top = rc->top +t; + rcFill.right = rc->right - r; rcFill.bottom = rc->bottom - b; + FillRect(hdc, &rcFill, item->fillBrush); + } + else + API::pfnAlphaBlend(hdc, rc->left + l, rc->top + t, width - l - r, height - t - b, hdcSrc, srcOrigX + l, srcOrigY + t, item->inner_width, item->inner_height, item->bf); + + API::pfnAlphaBlend(hdc, rc->right - r, rc->top + t, r, height - t - b, hdcSrc, srcOrigX + (item->width - r), srcOrigY + t, r, item->inner_height, item->bf); + + // bottom 3 items + + API::pfnAlphaBlend(hdc, rc->left, rc->bottom - b, l, b, hdcSrc, srcOrigX, srcOrigY + (item->height - b), l, b, item->bf); + API::pfnAlphaBlend(hdc, rc->left + l, rc->bottom - b, width - l - r, b, hdcSrc, srcOrigX + l, srcOrigY + (item->height - b), item->inner_width, b, item->bf); + API::pfnAlphaBlend(hdc, rc->right - r, rc->bottom - b, r, b, hdcSrc, srcOrigX + (item->width - r), srcOrigY + (item->height - b), r, b, item->bf); + } + else { + switch(item->bStretch) { + case IMAGE_STRETCH_H: + // tile image vertically, stretch to width + { + LONG top = rc->top; + + do { + if(top + item->height <= rc->bottom) { + API::pfnAlphaBlend(hdc, rc->left, top, width, item->height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf); + top += item->height; + } + else { + API::pfnAlphaBlend(hdc, rc->left, top, width, rc->bottom - top, hdcSrc, srcOrigX, srcOrigY, item->width, rc->bottom - top, item->bf); + break; + } + } while (TRUE); + break; + } + case IMAGE_STRETCH_V: + // tile horizontally, stretch to height + { + LONG left = rc->left; + + do { + if(left + item->width <= rc->right) { + API::pfnAlphaBlend(hdc, left, rc->top, item->width, height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf); + left += item->width; + } + else { + API::pfnAlphaBlend(hdc, left, rc->top, rc->right - left, height, hdcSrc, srcOrigX, srcOrigY, rc->right - left, item->height, item->bf); + break; + } + } while (TRUE); + break; + } + case IMAGE_STRETCH_B: + // stretch the image in both directions... + API::pfnAlphaBlend(hdc, rc->left, rc->top, width, height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf); + break; + /* + case IMAGE_STRETCH_V: + // stretch vertically, draw 3 horizontal tiles... + AlphaBlend(hdc, rc->left, rc->top, l, height, item->hdc, 0, 0, l, item->height, item->bf); + AlphaBlend(hdc, rc->left + l, rc->top, width - l - r, height, item->hdc, l, 0, item->inner_width, item->height, item->bf); + AlphaBlend(hdc, rc->right - r, rc->top, r, height, item->hdc, item->width - r, 0, r, item->height, item->bf); + break; + case IMAGE_STRETCH_H: + // stretch horizontally, draw 3 vertical tiles... + AlphaBlend(hdc, rc->left, rc->top, width, t, item->hdc, 0, 0, item->width, t, item->bf); + AlphaBlend(hdc, rc->left, rc->top + t, width, height - t - b, item->hdc, 0, t, item->width, item->inner_height, item->bf); + AlphaBlend(hdc, rc->left, rc->bottom - b, width, b, item->hdc, 0, item->height - b, item->width, b, item->bf); + break; + */ + default: + break; + } + } +} diff --git a/plugins/Clist_nicer/src/clc.cpp b/plugins/Clist_nicer/src/clc.cpp new file mode 100644 index 0000000000..98348ca0e0 --- /dev/null +++ b/plugins/Clist_nicer/src/clc.cpp @@ -0,0 +1,806 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clc.cpp 12968 2010-10-16 20:10:55Z Michael.Kunz@s2005.TU-Chemnitz.de $ + * + */ + +#include +#include +#include +#include "../cluiframes/cluiframes.h" +#include "../coolsb/coolscroll.h" + +int DefaultImageListColorDepth = ILC_COLOR32; + +extern HPEN g_hPenCLUIFrames; +extern HANDLE hExtraImageApplying; +extern wndFrame *wndFrameCLC; +extern ButtonItem *g_ButtonItems; + +extern int during_sizing; +extern StatusItems_t *StatusItems; + +HIMAGELIST hCListImages; +extern HIMAGELIST himlExtraImages; + +HANDLE hIcoLibChanged = 0, hSvc_GetContactStatusMsg = 0; + +static HANDLE hClcSettingsChanged, hClcDBEvent = 0; + +static HRESULT(WINAPI *MyCloseThemeData)(HANDLE); + +LONG g_cxsmIcon, g_cysmIcon; + +void SetDBButtonStates(HANDLE hContact); + +HMENU BuildGroupPopupMenu(struct ClcGroup* group) +{ + return (HMENU)CallService(MS_CLIST_MENUBUILDSUBGROUP, (WPARAM)group, 0); +} + +int AvatarChanged(WPARAM wParam, LPARAM lParam) +{ + pcli->pfnClcBroadcast(INTM_AVATARCHANGED, wParam, lParam); + return 0; +} + +int __forceinline __strcmp(const char * src, const char * dst) +{ + int ret = 0 ; + + while (!(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) + ++src, ++dst; + return(ret); +} + +static int ClcEventAdded(WPARAM wParam, LPARAM lParam) +{ + DBEVENTINFO dbei = {0}; + int iEntry; + DWORD new_freq = 0; + + cfg::dat.t_now = time(NULL); + + if (wParam && lParam) { + dbei.cbSize = sizeof(dbei); + dbei.pBlob = 0; + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM)lParam, (LPARAM)&dbei); + if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { + DWORD firstTime = cfg::getDword((HANDLE)wParam, "CList", "mf_firstEvent", 0); + DWORD count = cfg::getDword((HANDLE)wParam, "CList", "mf_count", 0); + count++; + new_freq = count ? (dbei.timestamp - firstTime) / count : 0x7fffffff; + cfg::writeDword((HANDLE)wParam, "CList", "mf_freq", new_freq); + cfg::writeDword((HANDLE)wParam, "CList", "mf_count", count); + iEntry = cfg::getCache((HANDLE)wParam, NULL); + if (iEntry >= 0 && iEntry < cfg::nextCacheEntry) { + cfg::eCache[iEntry].dwLastMsgTime = dbei.timestamp; + if (new_freq) + cfg::eCache[iEntry].msgFrequency = new_freq; + pcli->pfnClcBroadcast(INTM_FORCESORT, 0, 1); + } + } + } + return 0; +} + +static int ClcSettingChanged(WPARAM wParam, LPARAM lParam) +{ + char *szProto = NULL; + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; + + if (wParam) { + if (!__strcmp(cws->szModule, "CList")) { + if (!__strcmp(cws->szSetting, "StatusMsg")) + SendMessage(pcli->hwndContactTree, INTM_STATUSMSGCHANGED, wParam, lParam); + } else if (!__strcmp(cws->szModule, "UserInfo")) { + if (!__strcmp(cws->szSetting, "ANSIcodepage")) + pcli->pfnClcBroadcast(INTM_CODEPAGECHANGED, wParam, lParam); + else if (!__strcmp(cws->szSetting, "Timezone") || !__strcmp(cws->szSetting, "TzName")) + ReloadExtraInfo((HANDLE)wParam); + } else if (wParam != 0 && (szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0)) != NULL) { + char *id = NULL; + if (!__strcmp(cws->szModule, "Protocol") && !__strcmp(cws->szSetting, "p")) { + char *szProto_s; + pcli->pfnClcBroadcast(INTM_PROTOCHANGED, wParam, lParam); + if (cws->value.type == DBVT_DELETED) + szProto_s = NULL; + else + szProto_s = cws->value.pszVal; + pcli->pfnChangeContactIcon((HANDLE) wParam, IconFromStatusMode(szProto_s, szProto_s == NULL ? ID_STATUS_OFFLINE : cfg::getWord((HANDLE) wParam, szProto_s, "Status", ID_STATUS_OFFLINE), (HANDLE) wParam, NULL), 0); + } + // something is being written to a protocol module + if (!__strcmp(szProto, cws->szModule)) { + // was a unique setting key written? + pcli->pfnInvalidateDisplayNameCacheEntry((HANDLE) wParam); + if (!__strcmp(cws->szSetting, "Status")) { + if (!cfg::getByte((HANDLE) wParam, "CList", "Hidden", 0)) { + if (cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT)) { + // User's state is changing, and we are hideOffline-ing + if (cws->value.wVal == ID_STATUS_OFFLINE) { + pcli->pfnChangeContactIcon((HANDLE) wParam, IconFromStatusMode(cws->szModule, cws->value.wVal, (HANDLE) wParam, NULL), 0); + CallService(MS_CLUI_CONTACTDELETED, wParam, 0); + return 0; + } + pcli->pfnChangeContactIcon((HANDLE) wParam, IconFromStatusMode(cws->szModule, cws->value.wVal, (HANDLE) wParam, NULL), 1); + } + pcli->pfnChangeContactIcon((HANDLE) wParam, IconFromStatusMode(cws->szModule, cws->value.wVal, (HANDLE) wParam, NULL), 0); + } + SendMessage(pcli->hwndContactTree, INTM_STATUSCHANGED, wParam, lParam); + return 0; + } else if (strstr("YMsg|StatusDescr|XStatusMsg", cws->szSetting)) + SendMessage(pcli->hwndContactTree, INTM_STATUSMSGCHANGED, wParam, lParam); + else if (strstr(cws->szSetting, "XStatus")) + SendMessage(pcli->hwndContactTree, INTM_XSTATUSCHANGED, wParam, lParam); + else if (!__strcmp(cws->szSetting, "Timezone") || !__strcmp(cws->szSetting, "TzName")) + ReloadExtraInfo((HANDLE)wParam); + else if (!__strcmp(cws->szSetting, "MirVer")) + NotifyEventHooks(hExtraImageApplying, wParam, 0); + + if (cfg::dat.bMetaAvail && !(cfg::dat.dwFlags & CLUI_USEMETAICONS) && !__strcmp(szProto, cfg::dat.szMetaName)) { + if ((lstrlenA(cws->szSetting) > 6 && !strncmp(cws->szSetting, "Status", 6)) || strstr("Default,ForceSend,Nick", cws->szSetting)) + pcli->pfnClcBroadcast(INTM_NAMEORDERCHANGED, wParam, lParam); + } + if (!__strcmp(cws->szSetting, "UseSound")) { + cfg::dat.soundsOff = cws->value.bVal ? 0 : 1; + ClcSetButtonState(IDC_TBSOUND, cfg::dat.soundsOff); + } + } + if (cfg::dat.bMetaAvail && cfg::dat.bMetaEnabled && !__strcmp(cws->szModule, cfg::dat.szMetaName) && !__strcmp(cws->szSetting, "IsSubcontact")) + pcli->pfnClcBroadcast(INTM_HIDDENCHANGED, wParam, lParam); + } + } else if (wParam == 0 && !__strcmp(cws->szModule, cfg::dat.szMetaName)) { + BYTE bMetaEnabled = cfg::getByte(cfg::dat.szMetaName, "Enabled", 1); + if (bMetaEnabled != (BYTE)cfg::dat.bMetaEnabled) { + cfg::dat.bMetaEnabled = bMetaEnabled; + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + } + } else if (szProto == NULL && wParam == 0) { + if (!__strcmp(cws->szSetting, "XStatusId")) + CluiProtocolStatusChanged(0, cws->szModule); + return 0; + } + return 0; +} + +static int ClcPreshutdown(WPARAM wParam, LPARAM lParam) +{ + SFL_Destroy(); + cfg::shutDown = TRUE; + if (hSvc_GetContactStatusMsg) + DestroyServiceFunction(hSvc_GetContactStatusMsg); + UnhookEvent(hClcSettingsChanged); + UnhookEvent(hClcDBEvent); + if (hIcoLibChanged) + UnhookEvent(hIcoLibChanged); + return 0; +} + +int ClcShutdown(WPARAM wParam, LPARAM lParam) +{ + if (cfg::dat.hIconInvisible) + DestroyIcon(cfg::dat.hIconInvisible); + if (cfg::dat.hIconVisible) + DestroyIcon(cfg::dat.hIconVisible); + if (cfg::dat.hIconChatactive) + DestroyIcon(cfg::dat.hIconChatactive); + + DeleteObject(cfg::dat.hPen3DBright); + DeleteObject(cfg::dat.hPen3DDark); + DeleteObject(cfg::dat.hBrushColorKey); + DeleteObject(cfg::dat.hBrushCLCBk); + DeleteObject(cfg::dat.hBrushAvatarBorder); + DestroyMenu(cfg::dat.hMenuNotify); + ClearIcons(1); + SFL_UnregisterWindowClass(); + if (cfg::eCache) { + for (int i = 0; i < cfg::nextCacheEntry; i++) { + if (cfg::eCache[i].statusMsg) + free(cfg::eCache[i].statusMsg); + if (cfg::eCache[i].status_item) { + StatusItems_t *item = cfg::eCache[i].status_item; + int j; + + free(cfg::eCache[i].status_item); + cfg::eCache[i].status_item = 0; + for (j = i; j < cfg::nextCacheEntry; j++) { // avoid duplicate free()'ing status item pointers (there are references from sub to master contacts, so compare the pointers... + if (cfg::eCache[j].status_item == item) + cfg::eCache[j].status_item = 0; + } + } + } + free(cfg::eCache); + cfg::eCache = NULL; + } + IMG_DeleteItems(); + free(StatusItems); + DeleteCriticalSection(&cfg::cachecs); + return 0; +} + +int LoadCLCModule(void) +{ + g_cxsmIcon = GetSystemMetrics(SM_CXSMICON); + g_cysmIcon = GetSystemMetrics(SM_CYSMICON); + + hCListImages = (HIMAGELIST) CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); + + hClcSettingsChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ClcSettingChanged); + hClcDBEvent = HookEvent(ME_DB_EVENT_ADDED, ClcEventAdded); + HookEvent(ME_OPT_INITIALISE, ClcOptInit); + HookEvent(ME_SYSTEM_SHUTDOWN, ClcPreshutdown); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// clist_nicer+ control window procedure + +extern LRESULT(CALLBACK *saveContactListControlWndProc)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +LRESULT CALLBACK ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct ClcData *dat; + BOOL frameHasTitlebar = FALSE; + + if (wndFrameCLC) + frameHasTitlebar = wndFrameCLC->TitleBar.ShowTitleBar; + + dat = (struct ClcData *) GetWindowLongPtr(hwnd, 0); + if (msg >= CLM_FIRST && msg < CLM_LAST) + return ProcessExternalMessages(hwnd, dat, msg, wParam, lParam); + + switch (msg) { + case WM_CREATE: + dat = (struct ClcData *)mir_alloc(sizeof(struct ClcData)); + memset(dat, 0, sizeof(struct ClcData)); + SetWindowLongPtr(hwnd, 0, (LONG_PTR) dat); + + RowHeight::Init(dat); + dat->forceScroll = 0; + dat->lastRepaint = 0; + dat->himlExtraColumns = himlExtraImages; + dat->hwndParent = GetParent(hwnd); + dat->lastSort = GetTickCount(); + dat->needsResort = FALSE; + { + CREATESTRUCT *cs = (CREATESTRUCT *)lParam; + if (cs->lpCreateParams == (LPVOID)0xff00ff00) { + dat->bisEmbedded = FALSE; + dat->bHideSubcontacts = TRUE; + cfg::clcdat = dat; + if (cfg::dat.bShowLocalTime) + SetTimer(hwnd, TIMERID_REFRESH, 65000, NULL); + } else + dat->bisEmbedded = TRUE; + } + break; + case WM_SIZE: + pcli->pfnEndRename(hwnd, dat, 1); + KillTimer(hwnd, TIMERID_INFOTIP); + KillTimer(hwnd, TIMERID_RENAME); + pcli->pfnRecalcScrollBar(hwnd, dat); +LBL_Def: + return DefWindowProc(hwnd, msg, wParam, lParam); + + case WM_NCCALCSIZE: { + return FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam, frameHasTitlebar); + } + + /* + * scroll bar handling + */ + case WM_NCPAINT: + return FrameNCPaint(hwnd, DefWindowProc, wParam, lParam, frameHasTitlebar); + case INTM_GROUPCHANGED: { + struct ClcContact *contact; + BYTE iExtraImage[MAXEXTRACOLUMNS]; + BYTE flags = 0; + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + memset(iExtraImage, 0xFF, sizeof(iExtraImage)); + else { + CopyMemory(iExtraImage, contact->iExtraImage, sizeof(iExtraImage)); + flags = contact->flags; + } + pcli->pfnDeleteItemFromTree(hwnd, (HANDLE) wParam); + if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !CLVM_GetContactHiddenStatus((HANDLE)wParam, NULL, dat)) { + NMCLISTCONTROL nm; + pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, 1, 1); + if (FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) { + CopyMemory(contact->iExtraImage, iExtraImage, sizeof(iExtraImage)); + if (flags & CONTACTF_CHECKED) + contact->flags |= CONTACTF_CHECKED; + } + nm.hdr.code = CLN_CONTACTMOVED; + nm.hdr.hwndFrom = hwnd; + nm.hdr.idFrom = GetDlgCtrlID(hwnd); + nm.flags = 0; + nm.hItem = (HANDLE) wParam; + SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) &nm); + } + dat->needsResort = TRUE; + PostMessage(hwnd, INTM_SORTCLC, 0, 1); + goto LBL_Def; + } + + case INTM_ICONCHANGED: { + struct ClcContact *contact = NULL; + struct ClcGroup *group = NULL; + int recalcScrollBar = 0, shouldShow; + WORD status = ID_STATUS_OFFLINE; + char *szProto; + int contactRemoved = 0; + HANDLE hSelItem = NULL; + struct ClcContact *selcontact = NULL; + + szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto == NULL) + status = ID_STATUS_OFFLINE; + else + status = cfg::getWord((HANDLE) wParam, szProto, "Status", ID_STATUS_OFFLINE); + + shouldShow = (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !CLVM_GetContactHiddenStatus((HANDLE)wParam, szProto, dat)) && ((cfg::dat.bFilterEffective ? TRUE : !pcli->pfnIsHiddenMode(dat, status)) || CallService(MS_CLIST_GETCONTACTICON, wParam, 0) != lParam);// XXX CLVM changed - this means an offline msg is flashing, so the contact should be shown + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL)) { + if (shouldShow && CallService(MS_DB_CONTACT_IS, wParam, 0)) { + if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1) + hSelItem = pcli->pfnContactToHItem(selcontact); + pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, 0, 0); + recalcScrollBar = 1; + FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL); + if (contact) { + contact->iImage = (WORD) lParam; + pcli->pfnNotifyNewContact(hwnd, (HANDLE) wParam); + } + } + } else { + //item in list already + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + if (contact->iImage == (WORD) lParam) + break; + if (!shouldShow && !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline || cfg::dat.bFilterEffective)) { // CLVM changed + if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1) + hSelItem = pcli->pfnContactToHItem(selcontact); + pcli->pfnRemoveItemFromGroup(hwnd, group, contact, 0); + contactRemoved = TRUE; + recalcScrollBar = 1; + } else { + contact->iImage = (WORD) lParam; + if (!pcli->pfnIsHiddenMode(dat, status)) + contact->flags |= CONTACTF_ONLINE; + else + contact->flags &= ~CONTACTF_ONLINE; + } + } + if (hSelItem) { + struct ClcGroup *selgroup; + if (pcli->pfnFindItem(hwnd, dat, hSelItem, &selcontact, &selgroup, NULL)) + dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, List_IndexOf((SortedList*) & selgroup->cl, selcontact)); + else + dat->selection = -1; + } + dat->needsResort = TRUE; + PostMessage(hwnd, INTM_SORTCLC, 0, recalcScrollBar); + PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contactRemoved ? 0 : wParam)); + if (recalcScrollBar) + pcli->pfnRecalcScrollBar(hwnd, dat); + goto LBL_Def; + } + case INTM_METACHANGED: { + struct ClcContact *contact; + if (!pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + break; + if (contact->bIsMeta && cfg::dat.bMetaAvail && !(cfg::dat.dwFlags & CLUI_USEMETAICONS)) { + contact->hSubContact = (HANDLE) CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM) contact->hContact, 0); + contact->metaProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) contact->hSubContact, 0); + contact->iImage = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) contact->hSubContact, 0); + if (contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) { + int subIndex = cfg::getCache(contact->hSubContact, contact->metaProto); + cfg::eCache[contact->extraCacheEntry].proto_status_item = GetProtocolStatusItem(contact->metaProto); + if (subIndex >= 0 && subIndex <= cfg::nextCacheEntry) { + cfg::eCache[contact->extraCacheEntry].status_item = cfg::eCache[subIndex].status_item; + CopyMemory(cfg::eCache[contact->extraCacheEntry].iExtraImage, cfg::eCache[subIndex].iExtraImage, MAXEXTRACOLUMNS); + cfg::eCache[contact->extraCacheEntry].iExtraValid = cfg::eCache[subIndex].iExtraValid; + } + } + } + SendMessage(hwnd, INTM_NAMEORDERCHANGED, wParam, lParam); + goto LBL_Def; + } + case INTM_METACHANGEDEVENT: { + struct ClcContact *contact; + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + break; + if (lParam == 0) + SendMessage(hwnd, CLM_AUTOREBUILD, 0, 0); + goto LBL_Def; + } + case INTM_NAMECHANGED: { + struct ClcContact *contact; + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + break; + lstrcpyn(contact->szText, pcli->pfnGetContactDisplayName((HANDLE)wParam, 0), safe_sizeof(contact->szText)); + + RTL_DetectAndSet(contact, 0); + + dat->needsResort = TRUE; + PostMessage(hwnd, INTM_SORTCLC, 0, 0); + goto LBL_Def; + } + + case INTM_CODEPAGECHANGED: { + struct ClcContact *contact = NULL; + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + break; + contact->codePage = cfg::getDword((HANDLE) wParam, "Tab_SRMsg", "ANSIcodepage", cfg::getDword((HANDLE)wParam, "UserInfo", "ANSIcodepage", CP_ACP)); + PostMessage(hwnd, INTM_INVALIDATE, 0, 0); + goto LBL_Def; + } + case INTM_AVATARCHANGED: { + struct avatarCacheEntry *cEntry = (struct avatarCacheEntry *)lParam; + struct ClcContact *contact = NULL; + + if (wParam == 0) { + //RemoveFromImgCache(0, cEntry); + cfg::dat.bForceRefetchOnPaint = TRUE; + RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + cfg::dat.bForceRefetchOnPaint = FALSE; + goto LBL_Def; + } + + if (!FindItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL)) + return 0; + contact->ace = cEntry; + if (cEntry == NULL) + contact->cFlags &= ~ECF_AVATAR; + else { + DWORD dwFlags; + + if (contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) + dwFlags = cfg::eCache[contact->extraCacheEntry].dwDFlags; + else + dwFlags = cfg::getDword(contact->hContact, "CList", "CLN_Flags", 0); + if (cfg::dat.dwFlags & CLUI_FRAME_AVATARS) + contact->cFlags = (dwFlags & ECF_HIDEAVATAR ? contact->cFlags & ~ECF_AVATAR : contact->cFlags | ECF_AVATAR); + else + contact->cFlags = (dwFlags & ECF_FORCEAVATAR ? contact->cFlags | ECF_AVATAR : contact->cFlags & ~ECF_AVATAR); + } + PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)contact->hContact); + goto LBL_Def; + } + case INTM_STATUSMSGCHANGED: { + struct ClcContact *contact = NULL; + int index = -1; + char *szProto = NULL; + + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + index = cfg::getCache((HANDLE)wParam, NULL); + else { + index = contact->extraCacheEntry; + szProto = contact->proto; + } + GetCachedStatusMsg(index, szProto); + PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contact ? contact->hContact : 0)); + goto LBL_Def; + } + case INTM_STATUSCHANGED: { + struct ClcContact *contact = NULL; + WORD wStatus; + + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + break; + + wStatus = cfg::getWord((HANDLE)wParam, contact->proto, "Status", ID_STATUS_OFFLINE); + if (cfg::dat.bNoOfflineAvatars && wStatus != ID_STATUS_OFFLINE && contact->wStatus == ID_STATUS_OFFLINE) { + contact->wStatus = wStatus; + if (cfg::dat.bAvatarServiceAvail && contact->ace == NULL) + LoadAvatarForContact(contact); + } + contact->wStatus = wStatus; + goto LBL_Def; + } + case INTM_PROTOCHANGED: { + DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING *) lParam; + struct ClcContact *contact = NULL; + + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + break; + contact->proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + CallService(MS_CLIST_INVALIDATEDISPLAYNAME, wParam, 0); + lstrcpyn(contact->szText, pcli->pfnGetContactDisplayName((HANDLE)wParam, 0), safe_sizeof(contact->szText)); + + RTL_DetectAndSet(contact, 0); + + dat->needsResort = TRUE; + PostMessage(hwnd, INTM_SORTCLC, 0, 0); + goto LBL_Def; + } + + case INTM_INVALIDATE: + if (!dat->bNeedPaint) { + KillTimer(hwnd, TIMERID_PAINT); + SetTimer(hwnd, TIMERID_PAINT, 100, NULL); + dat->bNeedPaint = TRUE; + } + + if (lParam && !dat->bisEmbedded) { + struct ClcContact *contact = NULL; + + if (FindItem(hwnd, dat, (HANDLE)lParam, &contact, NULL, 0)) { + if (contact && contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry && cfg::eCache[contact->extraCacheEntry].floater) + FLT_Update(dat, contact); + } + } + goto LBL_Def; + + case INTM_INVALIDATECONTACT: { + struct ClcContact *contact = 0; + struct ClcGroup *group = 0; + int iItem; + + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL)) + break; + + if (contact == 0 || group == 0) + break; + + iItem = pcli->pfnGetRowsPriorTo(&dat->list, group, List_IndexOf((SortedList*) & group->cl, contact)); + pcli->pfnInvalidateItem(hwnd, dat, iItem); + goto LBL_Def; + } + case INTM_FORCESORT: + dat->needsResort = TRUE; + return SendMessage(hwnd, INTM_SORTCLC, wParam, lParam); + case INTM_SORTCLC: + if (dat->needsResort) { + pcli->pfnSortCLC(hwnd, dat, TRUE); + dat->needsResort = FALSE; + } + if (lParam) + pcli->pfnRecalcScrollBar(hwnd, dat); + goto LBL_Def; + + case INTM_IDLECHANGED: { + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; + char *szProto; + struct ClcContact *contact = NULL; + + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + break; + szProto = (char*)cws->szModule; + if (szProto == NULL) + break; + contact->flags &= ~CONTACTF_IDLE; + if (cfg::getDword((HANDLE) wParam, szProto, "IdleTS", 0)) { + contact->flags |= CONTACTF_IDLE; + } + PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)contact->hContact); + goto LBL_Def; + } + case INTM_XSTATUSCHANGED: { + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; + char *szProto; + struct ClcContact *contact = NULL; + int index; + + szProto = (char *)cws->szModule; + + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) { + index = cfg::getCache((HANDLE)wParam, szProto); + if (!dat->bisEmbedded && cfg::dat.bMetaAvail && szProto) { // may be a subcontact, forward the xstatus + if (cfg::getByte((HANDLE)wParam, cfg::dat.szMetaName, "IsSubcontact", 0)) { + HANDLE hMasterContact = (HANDLE)cfg::getDword((HANDLE)wParam, cfg::dat.szMetaName, "Handle", 0); + if (hMasterContact && hMasterContact != (HANDLE)wParam) // avoid recursive call of settings handler + cfg::writeByte(hMasterContact, cfg::dat.szMetaName, "XStatusId", + (BYTE)cfg::getByte((HANDLE)wParam, szProto, "XStatusId", 0)); + break; + } + } + } else { + contact->xStatus = cfg::getByte((HANDLE) wParam, szProto, "XStatusId", 0); + index = contact->extraCacheEntry; + } + if (szProto == NULL) + break; + GetCachedStatusMsg(index, szProto); + PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contact ? contact->hContact : 0)); + goto LBL_Def; + } + case WM_PAINT: { + HDC hdc; + PAINTSTRUCT ps; + hdc = BeginPaint(hwnd, &ps); + if (IsWindowVisible(hwnd) && !during_sizing && !cfg::shutDown) { + PaintClc(hwnd, dat, hdc, &ps.rcPaint); + dat->bNeedPaint = FALSE; + dat->lastRepaint = GetTickCount(); + } + EndPaint(hwnd, &ps); + if (dat->selection != dat->oldSelection && !dat->bisEmbedded && g_ButtonItems != NULL) { + SetDBButtonStates(0); + dat->oldSelection = dat->selection; + } + goto LBL_Def; + } + + case WM_MOUSEWHEEL: + dat->forceScroll = TRUE; + break; + + case WM_TIMER: + if (wParam == TIMERID_PAINT) { + KillTimer(hwnd, TIMERID_PAINT); + InvalidateRect(hwnd, NULL, FALSE); + goto LBL_Def; + } + + if (wParam == TIMERID_REFRESH) { + InvalidateRect(hwnd, NULL, FALSE); + goto LBL_Def; + } + break; + + case WM_LBUTTONDBLCLK: { + struct ClcContact *contact; + DWORD hitFlags; + ReleaseCapture(); + dat->iHotTrack = -1; + pcli->pfnHideInfoTip(hwnd, dat); + KillTimer(hwnd, TIMERID_RENAME); + KillTimer(hwnd, TIMERID_INFOTIP); + dat->szQuickSearch[0] = 0; + dat->selection = HitTest(hwnd, dat, (short) LOWORD(lParam), (short) HIWORD(lParam), &contact, NULL, &hitFlags); + if (hitFlags & CLCHT_ONITEMEXTRAEX && hwnd == pcli->hwndContactTree && contact != 0) { + int column = hitFlags >> 24; + if (column-- > 0) { + if (contact->type == CLCIT_CONTACT) { + CONTACTINFO ci; + ZeroMemory(&ci,sizeof(CONTACTINFO)); + ci.cbSize = sizeof(CONTACTINFO); + ci.hContact = contact->hContact; + ci.szProto = contact->proto; + + if (column == 0) { + ci.dwFlag = CNF_EMAIL; + if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { + char buf[4096]; + mir_snprintf(buf, sizeof(buf), "mailto:%s", (LPCSTR)ci.pszVal); + mir_free(ci.pszVal); + ShellExecuteA(hwnd, "open", buf, NULL, NULL, SW_SHOW); + } + return TRUE; + } + if (column == 1) { + ci.dwFlag = CNF_HOMEPAGE; + if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { + ShellExecuteA(hwnd, "open", (LPCSTR)ci.pszVal, NULL, NULL, SW_SHOW); + mir_free(ci.pszVal); + } + return TRUE; + } + } + } + } + InvalidateRect(hwnd, NULL, FALSE); + if (dat->selection != -1) + pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0); + if (hitFlags & CLCHT_ONAVATAR && cfg::dat.bDblClkAvatars) { + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)contact->hContact, 0); + return TRUE; + } + if (hitFlags & (CLCHT_ONITEMICON | CLCHT_ONITEMLABEL | CLCHT_ONITEMSPACE)) { + UpdateWindow(hwnd); + pcli->pfnDoSelectionDefaultAction(hwnd, dat); + } + return TRUE; + } + case WM_CONTEXTMENU: { + struct ClcContact *contact; + HMENU hMenu = NULL; + POINT pt; + DWORD hitFlags; + + pcli->pfnEndRename(hwnd, dat, 1); + pcli->pfnHideInfoTip(hwnd, dat); + KillTimer(hwnd, TIMERID_RENAME); + KillTimer(hwnd, TIMERID_INFOTIP); + if (GetFocus() != hwnd) + SetFocus(hwnd); + dat->iHotTrack = -1; + dat->szQuickSearch[0] = 0; + pt.x = (short) LOWORD(lParam); + pt.y = (short) HIWORD(lParam); + if (pt.x == -1 && pt.y == -1) { + dat->selection = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, NULL); + if (dat->selection != -1) + pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0); + pt.x = dat->iconXSpace + 15; + pt.y = RowHeight::getItemTopY(dat, dat->selection) - dat->yScroll + (int)(dat->row_heights[dat->selection] * .7); + hitFlags = dat->selection == -1 ? CLCHT_NOWHERE : CLCHT_ONITEMLABEL; + } else { + ScreenToClient(hwnd, &pt); + dat->selection = HitTest(hwnd, dat, pt.x, pt.y, &contact, NULL, &hitFlags); + } + InvalidateRect(hwnd, NULL, FALSE); + if (dat->selection != -1) + pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0); + UpdateWindow(hwnd); + + if (dat->selection != -1 && hitFlags & (CLCHT_ONITEMICON | CLCHT_ONITEMCHECK | CLCHT_ONITEMLABEL)) { + if (contact->type == CLCIT_GROUP) { + hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDSUBGROUP, (WPARAM)contact->group, 0); + ClientToScreen(hwnd, &pt); + TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, pcli->hwndContactList, NULL); + CheckMenuItem(hMenu, POPUP_GROUPHIDEOFFLINE, contact->group->hideOffline ? MF_CHECKED : MF_UNCHECKED); + DestroyMenu(hMenu); + return 0; + } else if (contact->type == CLCIT_CONTACT) + hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) contact->hContact, 0); + } else { + //call parent for new group/hide offline menu + PostMessage(GetParent(hwnd), WM_CONTEXTMENU, wParam, lParam); + return 0; + } + if (hMenu != NULL) { + ClientToScreen(hwnd, &pt); + TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL); + DestroyMenu(hMenu); + } + return 0; + } + case WM_COMMAND: + if (LOWORD(wParam) == POPUP_NEWGROUP) + SendMessage(GetParent(hwnd), msg, wParam, lParam); + break; + + case WM_NCHITTEST: { + LRESULT lr = SendMessage(GetParent(hwnd), WM_NCHITTEST, wParam, lParam); + if (lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT + || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT) + return HTTRANSPARENT; + break; + } + case WM_DESTROY: { + int i; + + if (!dat->bisEmbedded) { + for (i = 0; i < cfg::nextCacheEntry; i++) { + if (cfg::eCache[i].floater && cfg::eCache[i].floater->hwnd) + DestroyWindow(cfg::eCache[i].floater->hwnd); + } + } + RowHeight::Free(dat); + break; + } + } + + { + LRESULT result = saveContactListControlWndProc(hwnd, msg, wParam, lParam); + return result; + } +} diff --git a/plugins/Clist_nicer/src/clcidents.cpp b/plugins/Clist_nicer/src/clcidents.cpp new file mode 100644 index 0000000000..1315a61f32 --- /dev/null +++ b/plugins/Clist_nicer/src/clcidents.cpp @@ -0,0 +1,102 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 + +/* the CLC uses 3 different ways to identify elements in its list, this file +contains routines to convert between them. + +1) struct ClcContact/struct ClcGroup pair. Only ever used within the duration + of a single operation, but used at some point in nearly everything +2) index integer. The 0-based number of the item from the top. Only visible + items are counted (ie not closed groups). Used for saving selection and drag + highlight +3) hItem handle. Either the hContact or (hGroup|HCONTACT_ISGROUP). Used + exclusively externally + +1->2: GetRowsPriorTo() +1->3: ContactToHItem() +3->1: FindItem() +2->1: GetRowByIndex() +*/ + +int FindItem(HWND hwnd, struct ClcData *dat, HANDLE hItem, struct ClcContact **contact, struct ClcGroup **subgroup, int *isVisible) +{ + int index = 0; + int nowVisible = 1; + struct ClcGroup *group = &dat->list; + + group->scanIndex = 0; + for (; ;) { + if (group->scanIndex == group->cl.count) { + struct ClcGroup *tgroup; + group = group->parent; + if (group == NULL) + break; + nowVisible = 1; + for (tgroup = group; tgroup; tgroup = tgroup->parent) { + if (!(group->expanded)) { + nowVisible = 0; break; + } + } + group->scanIndex++; + continue; + } + if (nowVisible) + index++; + if ((IsHContactGroup(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_GROUP && ((UINT_PTR) hItem & ~HCONTACT_ISGROUP) == group->cl.items[group->scanIndex]->groupId) || (IsHContactContact(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->hContact == hItem) || (IsHContactInfo(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->hContact == (HANDLE) ((UINT_PTR) hItem & ~HCONTACT_ISINFO))) { + if (isVisible) { + if (!nowVisible) + *isVisible = 0; + else { + int posy = RowHeight::getItemTopY(dat,index+1); + if(posyyScroll) + *isVisible=0; + //if ((index + 1) * dat->rowHeight< dat->yScroll) + // *isVisible = 0; + else { + RECT clRect; + GetClientRect(hwnd, &clRect); + //if (index * dat->rowHeight >= dat->yScroll + clRect.bottom) + if (posy >= dat->yScroll + clRect.bottom) + *isVisible = 0; + else + *isVisible = 1; + } + } + } + if (contact) + *contact = group->cl.items[group->scanIndex]; + if (subgroup) + *subgroup = group; + return 1; + } + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { + group = group->cl.items[group->scanIndex]->group; + group->scanIndex = 0; + nowVisible &= (group->expanded); + continue; + } + group->scanIndex++; + } + return 0; +} diff --git a/plugins/Clist_nicer/src/clcitems.cpp b/plugins/Clist_nicer/src/clcitems.cpp new file mode 100644 index 0000000000..b40a0a3328 --- /dev/null +++ b/plugins/Clist_nicer/src/clcitems.cpp @@ -0,0 +1,659 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clcitems.cpp 12968 2010-10-16 20:10:55Z Michael.Kunz@s2005.TU-Chemnitz.de $ + * + */ + +#include +#include + +extern HANDLE hExtraImageListRebuilding, hExtraImageApplying; + +extern int ( *saveAddContactToGroup )(struct ClcData *dat, struct ClcGroup *group, HANDLE hContact); +extern int ( *saveAddInfoItemToGroup )(struct ClcGroup *group, int flags, const TCHAR *pszText); +extern struct ClcGroup* ( *saveRemoveItemFromGroup )(HWND hwnd, struct ClcGroup *group, struct ClcContact *contact, int updateTotalCount); +extern struct ClcGroup* ( *saveAddGroup )(HWND hwnd, struct ClcData *dat, const TCHAR *szName, DWORD flags, int groupId, int calcTotalMembers); + +static void TZ_LoadTimeZone(HANDLE hContact, struct TExtraCache *c, const char *szProto); + +//routines for managing adding/removal of items in the list, including sorting + +struct ClcContact* CreateClcContact( void ) +{ + struct ClcContact* p = (struct ClcContact*)mir_alloc( sizeof( struct ClcContact )); + if ( p != NULL ) { + ZeroMemory(p, sizeof(struct ClcContact)); + //p->clientId = -1; + p->extraCacheEntry = -1; + p->avatarLeft = p->extraIconRightBegin = -1; + p->isRtl = 0; + p->ace = 0; + } + return p; +} + +int AddInfoItemToGroup(struct ClcGroup *group, int flags, const TCHAR *pszText) +{ + int i = saveAddInfoItemToGroup(group, flags, pszText); + struct ClcContact* p = group->cl.items[i]; + p->codePage = 0; + //p->clientId = -1; + p->bIsMeta = 0; + p->xStatus = 0; + p->ace = NULL; + p->extraCacheEntry = -1; + p->avatarLeft = p->extraIconRightBegin = -1; + return i; +} + +struct ClcGroup *AddGroup(HWND hwnd, struct ClcData *dat, const TCHAR *szName, DWORD flags, int groupId, int calcTotalMembers) +{ + struct ClcGroup *p = saveAddGroup( hwnd, dat, szName, flags, groupId, calcTotalMembers); + + + if ( p && p->parent ) + RTL_DetectGroupName( p->parent->cl.items[ p->parent->cl.count-1] ); + + return p; +} + +struct ClcGroup *RemoveItemFromGroup(HWND hwnd, struct ClcGroup *group, struct ClcContact *contact, int updateTotalCount) +{ + if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) { + if(cfg::eCache[contact->extraCacheEntry].floater && cfg::eCache[contact->extraCacheEntry].floater->hwnd) + ShowWindow(cfg::eCache[contact->extraCacheEntry].floater->hwnd, SW_HIDE); + } + return(saveRemoveItemFromGroup(hwnd, group, contact, updateTotalCount)); +} + +void LoadAvatarForContact(struct ClcContact *p) +{ + DWORD dwFlags; + + if(p->extraCacheEntry >= 0 && p->extraCacheEntry < cfg::nextCacheEntry) + dwFlags = cfg::eCache[p->extraCacheEntry].dwDFlags; + else + dwFlags = cfg::getDword(p->hContact, "CList", "CLN_Flags", 0); + + if(cfg::dat.dwFlags & CLUI_FRAME_AVATARS) + p->cFlags = (dwFlags & ECF_HIDEAVATAR ? p->cFlags & ~ECF_AVATAR : p->cFlags | ECF_AVATAR); + else + p->cFlags = (dwFlags & ECF_FORCEAVATAR ? p->cFlags | ECF_AVATAR : p->cFlags & ~ECF_AVATAR); + + p->ace = NULL; + if(cfg::dat.bAvatarServiceAvail && (p->cFlags & ECF_AVATAR) && (!cfg::dat.bNoOfflineAvatars || p->wStatus != ID_STATUS_OFFLINE)) { + p->ace = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)p->hContact, 0); + if (p->ace != NULL && p->ace->cbSize != sizeof(struct avatarCacheEntry)) + p->ace = NULL; + if (p->ace != NULL) + p->ace->t_lastAccess = cfg::dat.t_now; + } + if(p->ace == NULL) + p->cFlags &= ~ECF_AVATAR; +} + +int AddContactToGroup(struct ClcData *dat, struct ClcGroup *group, HANDLE hContact) +{ + int i = saveAddContactToGroup( dat, group, hContact ); + struct ClcContact* p = group->cl.items[i]; + + p->wStatus = cfg::getWord(hContact, p->proto, "Status", ID_STATUS_OFFLINE); + p->xStatus = cfg::getByte(hContact, p->proto, "XStatusId", 0); + //p->iRowHeight = -1; + + if (p->proto) + p->bIsMeta = !strcmp(p->proto, cfg::dat.szMetaName); + else + p->bIsMeta = FALSE; + if (p->bIsMeta && cfg::dat.bMetaAvail && !(cfg::dat.dwFlags & CLUI_USEMETAICONS)) { + p->hSubContact = (HANDLE) CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM) hContact, 0); + p->metaProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) p->hSubContact, 0); + p->iImage = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) p->hSubContact, 0); + } else { + p->iImage = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) hContact, 0); + p->metaProto = NULL; + } + + p->codePage = cfg::getDword(hContact, "Tab_SRMsg", "ANSIcodepage", cfg::getDword(hContact, "UserInfo", "ANSIcodepage", CP_ACP)); + p->bSecondLine = cfg::getByte(hContact, "CList", "CLN_2ndline", cfg::dat.dualRowMode); + + if(dat->bisEmbedded) + p->extraCacheEntry = -1; + else { + p->extraCacheEntry = cfg::getCache(p->hContact, p->proto); + GetExtendedInfo( p, dat); + if(p->extraCacheEntry >= 0 && p->extraCacheEntry < cfg::nextCacheEntry) { + cfg::eCache[p->extraCacheEntry].proto_status_item = GetProtocolStatusItem(p->bIsMeta ? p->metaProto : p->proto); + if(cfg::getByte(p->hContact, "CList", "floating", 0) && g_floatoptions.enabled) { + if(cfg::eCache[p->extraCacheEntry].floater == NULL) + FLT_Create(p->extraCacheEntry); + else { + ShowWindow(cfg::eCache[p->extraCacheEntry].floater->hwnd, SW_SHOWNOACTIVATE); + FLT_Update(dat, p); + } + } + } + LoadAvatarForContact(p); + // notify other plugins to re-supply their extra images (icq for xstatus, mBirthday etc...) + NotifyEventHooks(hExtraImageApplying, (WPARAM)hContact, 0); + } + + RTL_DetectAndSet( p, p->hContact); + + p->avatarLeft = p->extraIconRightBegin = -1; + p->flags |= cfg::getByte(p->hContact, "CList", "Priority", 0) ? CONTACTF_PRIORITY : 0; + + return i; +} + +void RebuildEntireList(HWND hwnd, struct ClcData *dat) +{ + char *szProto; + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + HANDLE hContact; + struct ClcGroup *group; + DBVARIANT dbv = {0}; + + RowHeight::Clear(dat); + RowHeight::getMaxRowHeight(dat, hwnd); + + dat->list.expanded = 1; + dat->list.hideOffline = cfg::getByte("CLC", "HideOfflineRoot", 0); + dat->list.cl.count = 0; + dat->list.totalMembers = 0; + dat->selection = -1; + dat->SelectMode = cfg::getByte("CLC", "SelectMode", 0); { + int i; + TCHAR *szGroupName; + DWORD groupFlags; + + for (i = 1; ; i++) { + szGroupName = pcli->pfnGetGroupName(i, &groupFlags); + if (szGroupName == NULL) + break; + pcli->pfnAddGroup(hwnd, dat, szGroupName, groupFlags, i, 0); + } + } + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) { + if (style & CLS_SHOWHIDDEN || !CLVM_GetContactHiddenStatus(hContact, NULL, dat)) { + ZeroMemory((void *)&dbv, sizeof(dbv)); + if (cfg::getTString(hContact, "CList", "Group", &dbv)) + group = &dat->list; + else { + group = pcli->pfnAddGroup(hwnd, dat, dbv.ptszVal, (DWORD) - 1, 0, 0); + mir_free(dbv.ptszVal); + } + + if (group != NULL) { + group->totalMembers++; + if (!(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline)) { + szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto == NULL) { + if (!pcli->pfnIsHiddenMode(dat, ID_STATUS_OFFLINE)) + AddContactToGroup(dat, group, hContact); + } else if (!pcli->pfnIsHiddenMode(dat, (WORD) cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE))) + AddContactToGroup(dat, group, hContact); + } else + AddContactToGroup(dat, group, hContact); + } + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + + if (style & CLS_HIDEEMPTYGROUPS) { + group = &dat->list; + group->scanIndex = 0; + for (; ;) { + if (group->scanIndex == group->cl.count) { + group = group->parent; + if (group == NULL) + break; + } else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { + if (group->cl.items[group->scanIndex]->group->cl.count == 0) { + group = pcli->pfnRemoveItemFromGroup(hwnd, group, group->cl.items[group->scanIndex], 0); + } else { + group = group->cl.items[group->scanIndex]->group; + group->scanIndex = 0; + } + continue; + } + group->scanIndex++; + } + } + pcli->pfnSortCLC(hwnd, dat, 0); + if (!dat->bisEmbedded) + FLT_SyncWithClist(); +} + +/* + * status msg in the database has changed. + * get it and store it properly formatted in the extra data cache + */ + +BYTE GetCachedStatusMsg(int iExtraCacheEntry, char *szProto) +{ + DBVARIANT dbv = {0}; + HANDLE hContact; + struct TExtraCache *cEntry; + int result; + + if(iExtraCacheEntry < 0 || iExtraCacheEntry > cfg::nextCacheEntry) + return 0; + + cEntry = &cfg::eCache[iExtraCacheEntry]; + + cEntry->bStatusMsgValid = STATUSMSG_NOTFOUND; + hContact = cEntry->hContact; + + result = cfg::getTString(hContact, "CList", "StatusMsg", &dbv); + if ( !result && lstrlen(dbv.ptszVal) > 1) + cEntry->bStatusMsgValid = STATUSMSG_CLIST; + else { + if (!szProto) + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if(szProto) { + if ( !result ) + DBFreeVariant( &dbv ); + if ( !( result = cfg::getTString(hContact, szProto, "YMsg", &dbv)) && lstrlen(dbv.ptszVal) > 1) + cEntry->bStatusMsgValid = STATUSMSG_YIM; + else if ( !(result = cfg::getTString(hContact, szProto, "StatusDescr", &dbv)) && lstrlen(dbv.ptszVal) > 1) + cEntry->bStatusMsgValid = STATUSMSG_GG; + else if ( !(result = cfg::getTString(hContact, szProto, "XStatusMsg", &dbv)) && lstrlen(dbv.ptszVal) > 1) + cEntry->bStatusMsgValid = STATUSMSG_XSTATUS; + } } + + if(cEntry->bStatusMsgValid == STATUSMSG_NOTFOUND) { // no status msg, consider xstatus name (if available) + if ( !result ) + DBFreeVariant( &dbv ); + result = cfg::getTString(hContact, szProto, "XStatusName", &dbv); + if ( !result && lstrlen(dbv.ptszVal) > 1) { + int iLen = lstrlen(dbv.ptszVal); + cEntry->bStatusMsgValid = STATUSMSG_XSTATUSNAME; + cEntry->statusMsg = (TCHAR *)realloc(cEntry->statusMsg, (iLen + 2) * sizeof(TCHAR)); + _tcsncpy(cEntry->statusMsg, dbv.ptszVal, iLen + 1); + } + else { + ICQ_CUSTOM_STATUS cst = {0}; + int xStatus; + WPARAM xStatus2; + TCHAR xStatusName[128]; + char szServiceName[128]; + + mir_snprintf(szServiceName, 128, "%s%s", szProto, PS_ICQ_GETCUSTOMSTATUSEX); + + cst.cbSize = sizeof(ICQ_CUSTOM_STATUS); + cst.flags = CSSF_MASK_STATUS; + cst.status = &xStatus; + if(ServiceExists(szServiceName) && !CallService(szServiceName, (WPARAM)hContact, (LPARAM)&cst) && xStatus > 0) { + cst.flags = CSSF_MASK_NAME | CSSF_DEFAULT_NAME | CSSF_TCHAR; + cst.wParam = &xStatus2; + cst.ptszName = xStatusName; + if (!CallService(szServiceName, (WPARAM)hContact, (LPARAM)&cst)) { + TCHAR *szwXstatusName = TranslateTS(xStatusName); + cEntry->statusMsg = (TCHAR *)realloc(cEntry->statusMsg, (lstrlen(szwXstatusName) + 2) * sizeof(TCHAR)); + _tcsncpy(cEntry->statusMsg, szwXstatusName, lstrlen(szwXstatusName) + 1); + cEntry->bStatusMsgValid = STATUSMSG_XSTATUSNAME; + } + } + } + } + if(cEntry->bStatusMsgValid > STATUSMSG_XSTATUSNAME) { + int j = 0, i; + cEntry->statusMsg = (TCHAR *)realloc(cEntry->statusMsg, (lstrlen(dbv.ptszVal) + 2) * sizeof(TCHAR)); + for (i = 0; dbv.ptszVal[i]; i++) { + if(dbv.ptszVal[i] == (TCHAR)0x0d) + continue; + cEntry->statusMsg[j] = dbv.ptszVal[i] == (wchar_t)0x0a ? (wchar_t)' ' : dbv.ptszVal[i]; + j++; + } + cEntry->statusMsg[j] = (TCHAR)0; + } + if ( !result ) + DBFreeVariant( &dbv ); + + + if(cEntry->bStatusMsgValid != STATUSMSG_NOTFOUND) { + WORD infoTypeC2[12]; + int iLen, i + ; + ZeroMemory(infoTypeC2, sizeof(WORD) * 12); + iLen = min(lstrlenW(cEntry->statusMsg), 10); + GetStringTypeW(CT_CTYPE2, cEntry->statusMsg, iLen, infoTypeC2); + cEntry->dwCFlags &= ~ECF_RTLSTATUSMSG; + for (i = 0; i < 10; i++) { + if(infoTypeC2[i] == C2_RIGHTTOLEFT) { + cEntry->dwCFlags |= ECF_RTLSTATUSMSG; + break; + } + } + } + + if(cEntry->hTimeZone == NULL) + TZ_LoadTimeZone(hContact, cEntry, szProto); + return cEntry->bStatusMsgValid;; +} + +/* + * load time zone information for the contact + * if TzName is set, use it. It has to be a standard windows time zone name + * Currently, it can only be set by using UserInfoEx plugin + * + * Fallback: use ordinary GMT offsets (incorrect, in some cases due to DST + * differences. + */ + +static void TZ_LoadTimeZone(HANDLE hContact, struct TExtraCache *c, const char *szProto) +{ + DWORD flags = 0; + if (cfg::dat.bShowLocalTimeSelective) flags |= TZF_DIFONLY; + c->hTimeZone = tmi.createByContact(hContact, flags); +} + +void ReloadExtraInfo(HANDLE hContact) +{ + if(hContact && pcli->hwndContactTree) { + int index = cfg::getCache(hContact, NULL); + if(index >= 0 && index < cfg::nextCacheEntry) { + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + + TZ_LoadTimeZone(hContact, &cfg::eCache[index], szProto); + InvalidateRect(pcli->hwndContactTree, NULL, FALSE); + } + } +} + +/* + * autodetect RTL property of the nickname, evaluates the first 10 characters of the nickname only + */ + + +void RTL_DetectAndSet(struct ClcContact *contact, HANDLE hContact) +{ + WORD infoTypeC2[12]; + int i, index; + TCHAR *szText = NULL; + DWORD iLen; + + ZeroMemory(infoTypeC2, sizeof(WORD) * 12); + + if(contact == NULL) { + szText = pcli->pfnGetContactDisplayName(hContact, 0); + index = cfg::getCache(hContact, NULL); + } + else { + szText = contact->szText; + index = contact->extraCacheEntry; + } + if(index >= 0 && index < cfg::nextCacheEntry) { + iLen = min(lstrlenW(szText), 10); + GetStringTypeW(CT_CTYPE2, szText, iLen, infoTypeC2); + cfg::eCache[index].dwCFlags &= ~ECF_RTLNICK; + for (i = 0; i < 10; i++) { + if(infoTypeC2[i] == C2_RIGHTTOLEFT) { + cfg::eCache[index].dwCFlags |= ECF_RTLNICK; + return; + } + } + } +} + +void RTL_DetectGroupName(struct ClcContact *group) +{ + WORD infoTypeC2[12]; + int i; + DWORD iLen; + + group->isRtl = 0; + + if(group->szText) { + iLen = min(lstrlenW(group->szText), 10); + GetStringTypeW(CT_CTYPE2, group->szText, iLen, infoTypeC2); + for (i = 0; i < 10; i++) { + if(infoTypeC2[i] == C2_RIGHTTOLEFT) { + group->isRtl = 1; + return; + } + } + } +} + +/* + * check for exteneded user information - email, phone numbers, homepage + * set extra icons accordingly + */ + +void GetExtendedInfo(struct ClcContact *contact, struct ClcData *dat) +{ + CONTACTINFO ci; + BOOL iCacheNew = FALSE; + int index; + + if(dat->bisEmbedded || contact == NULL) + return; + + if(contact->proto == NULL || contact->hContact == 0) + return; + + index = contact->extraCacheEntry; + + //firstTime = DBGetContactSettingDword(contact->hContact, "CList", "mf_firstEvent", 0); + //count = DBGetContactSettingDword(contact->hContact, "CList", "mf_count", 0); + //new_freq = count ? (g_CluiData.t_now - firstTime) / count : 0x7fffffff; + cfg::eCache[index].msgFrequency = cfg::getDword(contact->hContact, "CList", "mf_freq", 0x7fffffff); + //g_ExtraCache[index].msgFrequency = new_freq; + //DBWriteContactSettingDword(contact->hContact, "CList", "mf_freq", new_freq); + + if(index >= 0 && index < cfg::nextCacheEntry) { + if(cfg::eCache[index].valid) + return; + cfg::eCache[index].valid = TRUE; + } + else + return; + + cfg::eCache[index].isChatRoom = cfg::getByte(contact->hContact, contact->proto, "ChatRoom", 0); + + cfg::eCache[index].iExtraValid &= ~(EIMG_SHOW_EMAIL | EIMG_SHOW_SMS | EIMG_SHOW_WEB); + cfg::eCache[index].iExtraImage[EXTRA_ICON_EMAIL] = cfg::eCache[index].iExtraImage[EXTRA_ICON_WEB] = cfg::eCache[index].iExtraImage[EXTRA_ICON_SMS] = 0xff; + + ZeroMemory(&ci,sizeof(CONTACTINFO)); + ci.cbSize = sizeof(CONTACTINFO); + ci.hContact = contact->hContact; + ci.szProto = contact->proto; + + ci.dwFlag = CNF_EMAIL; + if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { + cfg::eCache[index].iExtraImage[EXTRA_ICON_EMAIL] = 0; + mir_free(ci.pszVal); + } + + ci.dwFlag = CNF_HOMEPAGE; + if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { + cfg::eCache[index].iExtraImage[EXTRA_ICON_WEB] = 1; + mir_free(ci.pszVal); + } + + ci.dwFlag = CNF_CELLULAR; + if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { + cfg::eCache[index].iExtraImage[EXTRA_ICON_SMS] = 2; + mir_free(ci.pszVal); + } + else { + ci.dwFlag = CNF_PHONE; + if (!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)) { + cfg::eCache[index].iExtraImage[EXTRA_ICON_SMS] = 2; + mir_free(ci.pszVal); + } + } + + // set the mask for valid extra images... + + cfg::eCache[index].iExtraValid |= ((cfg::eCache[index].iExtraImage[EXTRA_ICON_EMAIL] != 0xff ? EIMG_SHOW_EMAIL : 0) | + (cfg::eCache[index].iExtraImage[EXTRA_ICON_WEB] != 0xff ? EIMG_SHOW_WEB : 0) | + (cfg::eCache[index].iExtraImage[EXTRA_ICON_SMS] != 0xff ? EIMG_SHOW_SMS : 0)); + + +} + +void LoadSkinItemToCache(struct TExtraCache *cEntry, const char *szProto) +{ + HANDLE hContact = cEntry->hContact; + + if(cfg::getByte(hContact, "EXTBK", "VALID", 0)) { + if(cEntry->status_item == NULL) + cEntry->status_item = reinterpret_cast(malloc(sizeof(StatusItems_t))); + ZeroMemory(cEntry->status_item, sizeof(StatusItems_t)); + strcpy(cEntry->status_item->szName, "{--CONTACT--}"); // mark as "per contact" item + cEntry->status_item->IGNORED = 0; + + cEntry->status_item->TEXTCOLOR = cfg::getDword(hContact, "EXTBK", "TEXT", RGB(20, 20, 20)); + cEntry->status_item->COLOR = cfg::getDword(hContact, "EXTBK", "COLOR1", RGB(224, 224, 224)); + cEntry->status_item->COLOR2 = cfg::getDword(hContact, "EXTBK", "COLOR2", RGB(224, 224, 224)); + cEntry->status_item->ALPHA = (BYTE)cfg::getByte(hContact, "EXTBK", "ALPHA", 100); + + cEntry->status_item->MARGIN_LEFT = (DWORD)cfg::getByte(hContact, "EXTBK", "LEFT", 0); + cEntry->status_item->MARGIN_RIGHT = (DWORD)cfg::getByte(hContact, "EXTBK", "RIGHT", 0); + cEntry->status_item->MARGIN_TOP = (DWORD)cfg::getByte(hContact, "EXTBK", "TOP", 0); + cEntry->status_item->MARGIN_BOTTOM = (DWORD)cfg::getByte(hContact, "EXTBK", "BOTTOM", 0); + + cEntry->status_item->COLOR2_TRANSPARENT = (BYTE)cfg::getByte(hContact, "EXTBK", "TRANS", 1); + cEntry->status_item->BORDERSTYLE = cfg::getDword(hContact, "EXTBK", "BDR", 0); + + cEntry->status_item->CORNER = cfg::getByte(hContact, "EXTBK", "CORNER", 0); + cEntry->status_item->GRADIENT = cfg::getByte(hContact, "EXTBK", "GRAD", 0); + } + else if(cEntry->status_item) { + free(cEntry->status_item); + cEntry->status_item = NULL; + } +} + +void ReloadSkinItemsToCache() +{ + int i; + char *szProto; + + for (i = 0; i < cfg::nextCacheEntry; i++) { + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)cfg::eCache[i].hContact, 0); + if(szProto) + LoadSkinItemToCache(&cfg::eCache[i], szProto); + } +} + +DWORD CalcXMask(HANDLE hContact) +{ + DWORD dwXMask = cfg::getDword(hContact, "CList", "CLN_xmask", 0); + int i; + DWORD dwResult = cfg::dat.dwExtraImageMask, bForced, bHidden; + + for (i = 0; i <= 10; i++) { + bForced = (dwXMask & (1 << (2 * i))); + bHidden = (dwXMask & (1 << (2 * i + 1))); + if(bForced == 0 && bHidden == 0) + continue; + else if(bForced) + dwResult |= (1 << i); + else if(bHidden) + dwResult &= ~(1 << i); + } + return(dwResult); +} + +/* + * checks the currently active view mode filter and returns true, if the contact should be hidden + * if no view mode is active, it returns the CList/Hidden setting + * also cares about sub contacts (if meta is active) + */ + +int __fastcall CLVM_GetContactHiddenStatus(HANDLE hContact, char *szProto, struct ClcData *dat) +{ + int dbHidden = cfg::getByte(hContact, "CList", "Hidden", 0); // default hidden state, always respect it. + int filterResult = 1; + DBVARIANT dbv = {0}; + char szTemp[64]; + TCHAR szGroupMask[256]; + DWORD dwLocalMask; + + // always hide subcontacts (but show them on embedded contact lists) + + if(cfg::dat.bMetaAvail && dat != NULL && dat->bHideSubcontacts && cfg::dat.bMetaEnabled && cfg::getByte(hContact, cfg::dat.szMetaName, "IsSubcontact", 0)) + return 1; + + if(cfg::dat.bFilterEffective) { + if(szProto == NULL) + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + // check stickies first (priority), only if we really have stickies defined (CLVM_STICKY_CONTACTS is set). + if(cfg::dat.bFilterEffective & CLVM_STICKY_CONTACTS) { + if ((dwLocalMask = cfg::getDword(hContact, "CLVM", cfg::dat.current_viewmode, 0)) != 0) { + if(cfg::dat.bFilterEffective & CLVM_FILTER_STICKYSTATUS) { + WORD wStatus = cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); + return !((1 << (wStatus - ID_STATUS_OFFLINE)) & HIWORD(dwLocalMask)); + } + return 0; + } + } + // check the proto, use it as a base filter result for all further checks + if(cfg::dat.bFilterEffective & CLVM_FILTER_PROTOS) { + mir_snprintf(szTemp, sizeof(szTemp), "%s|", szProto); + filterResult = strstr(cfg::dat.protoFilter, szTemp) ? 1 : 0; + } + if(cfg::dat.bFilterEffective & CLVM_FILTER_GROUPS) { + if (!cfg::getTString(hContact, "CList", "Group", &dbv)) { + _sntprintf(szGroupMask, safe_sizeof(szGroupMask), _T("%s|"), &dbv.ptszVal[1]); + filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? (filterResult | (_tcsstr(cfg::dat.groupFilter, szGroupMask) ? 1 : 0)) : (filterResult & (_tcsstr(cfg::dat.groupFilter, szGroupMask) ? 1 : 0)); + mir_free(dbv.ptszVal); + } + else if(cfg::dat.filterFlags & CLVM_INCLUDED_UNGROUPED) + filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 1; + else + filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 0; + } + if(cfg::dat.bFilterEffective & CLVM_FILTER_STATUS) { + WORD wStatus = cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); + filterResult = (cfg::dat.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & cfg::dat.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & cfg::dat.statusMaskFilter ? 1 : 0)); + } + if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG) { + DWORD now; + int iEntry = cfg::getCache(hContact, szProto); + if(iEntry >= 0 && iEntry <= cfg::nextCacheEntry) { + now = cfg::dat.t_now; + now -= cfg::dat.lastMsgFilter; + if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG_OLDERTHAN) + filterResult = filterResult & (cfg::eCache[iEntry].dwLastMsgTime < now); + else if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG_NEWERTHAN) + filterResult = filterResult & (cfg::eCache[iEntry].dwLastMsgTime > now); + } + } + return (dbHidden | !filterResult); + } + else + return dbHidden; +} diff --git a/plugins/Clist_nicer/src/clcmsgs.cpp b/plugins/Clist_nicer/src/clcmsgs.cpp new file mode 100644 index 0000000000..97a4d0bb99 --- /dev/null +++ b/plugins/Clist_nicer/src/clcmsgs.cpp @@ -0,0 +1,221 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clcmsgs.cpp 12535 2010-08-29 23:48:32Z silvercircle $ + * + */ + +#include + +//processing of all the CLM_ messages incoming + +extern LRESULT ( *saveProcessExternalMessages )(HWND hwnd, struct ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam); + +LRESULT ProcessExternalMessages(HWND hwnd, struct ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case CLM_SETSTICKY: + { + struct ClcContact *contact; + struct ClcGroup *group; + + if (wParam == 0 || !FindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL)) + return 0; + if (lParam) + contact->flags |= CONTACTF_STICKY; + else + contact->flags &= ~CONTACTF_STICKY; + break; + } + + case CLM_SETEXTRAIMAGEINT: + { + struct ClcContact *contact = NULL; + int index = -1; + + if (LOWORD(lParam) >= MAXEXTRACOLUMNS || wParam == 0) + return 0; + + if (!FindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) + return 0; + + index = contact->extraCacheEntry; + + if(contact->type != CLCIT_CONTACT) // || contact->bIsMeta) + return 0; + + //if(contact->bIsMeta && LOWORD(lParam) != EIMG_EXTRA && LOWORD(lParam) != EIMG_CLIENT) + // return 0; + + /* + if(contact->hContact == 5846286) { + _DebugTraceA("set extra image %d", LOWORD(lParam)); + } + */ + if(index >= 0 && index < cfg::nextCacheEntry) { + cfg::eCache[index].iExtraImage[LOWORD(lParam)] = (BYTE)HIWORD(lParam); + cfg::eCache[index].iExtraValid = cfg::eCache[index].iExtraImage[LOWORD(lParam)] != (BYTE)0xff ? (cfg::eCache[index].iExtraValid | (1 << LOWORD(lParam))) : (cfg::eCache[index].iExtraValid & ~(1 << LOWORD(lParam))); + PostMessage(hwnd, INTM_INVALIDATE, 0, (LPARAM)(contact ? contact->hContact : 0)); + } + } + return 0; + case CLM_SETEXTRAIMAGEINTMETA: + { + HANDLE hMasterContact = 0; + int index = -1; + + if (LOWORD(lParam) >= MAXEXTRACOLUMNS) + return 0; + + index = cfg::getCache((HANDLE)wParam, NULL); + if(index >= 0 && index < cfg::nextCacheEntry) { + cfg::eCache[index].iExtraImage[LOWORD(lParam)] = (BYTE)HIWORD(lParam); + cfg::eCache[index].iExtraValid = cfg::eCache[index].iExtraImage[LOWORD(lParam)] != (BYTE)0xff ? (cfg::eCache[index].iExtraValid | (1 << LOWORD(lParam))) : (cfg::eCache[index].iExtraValid & ~(1 << LOWORD(lParam))); + } + + hMasterContact = (HANDLE)cfg::getDword((HANDLE)wParam, cfg::dat.szMetaName, "Handle", 0); + + index = cfg::getCache(hMasterContact, NULL); + if(index >= 0 && index < cfg::nextCacheEntry) { + cfg::eCache[index].iExtraImage[LOWORD(lParam)] = (BYTE)HIWORD(lParam); + cfg::eCache[index].iExtraValid = cfg::eCache[index].iExtraImage[LOWORD(lParam)] != (BYTE)0xff ? (cfg::eCache[index].iExtraValid | (1 << LOWORD(lParam))) : (cfg::eCache[index].iExtraValid & ~(1 << LOWORD(lParam))); + PostMessage(hwnd, INTM_INVALIDATE, 0, 0); + } + } + return 0; + + case CLM_GETSTATUSMSG: + { + struct ClcContact *contact = NULL; + + if (wParam == 0) + return 0; + + if (!FindItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL)) + return 0; + if(contact->type != CLCIT_CONTACT) + return 0; + if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry <= cfg::nextCacheEntry) { + if(cfg::eCache[contact->extraCacheEntry].bStatusMsgValid != STATUSMSG_NOTFOUND) + return((INT_PTR)cfg::eCache[contact->extraCacheEntry].statusMsg); + } } + return 0; + + case CLM_SETHIDESUBCONTACTS: + dat->bHideSubcontacts = (BOOL)lParam; + return 0; + + case CLM_TOGGLEPRIORITYCONTACT: + { + struct ClcContact *contact = NULL; + + if (wParam == 0) + return 0; + + if (!FindItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL)) + return 0; + if(contact->type != CLCIT_CONTACT) + return 0; + contact->flags ^= CONTACTF_PRIORITY; + cfg::writeByte(contact->hContact, "CList", "Priority", (BYTE)(contact->flags & CONTACTF_PRIORITY ? 1 : 0)); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + return 0; + } + case CLM_QUERYPRIORITYCONTACT: + { + struct ClcContact *contact = NULL; + + if (wParam == 0) + return 0; + + if (!FindItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL)) + return 0; + if(contact->type != CLCIT_CONTACT) + return 0; + return(contact->flags & CONTACTF_PRIORITY ? 1 : 0); + } + case CLM_TOGGLEFLOATINGCONTACT: + { + struct ClcContact *contact = NULL; + BYTE state; + int iEntry; + + if (wParam == 0) + return 0; + + if (!FindItem(hwnd, dat, (HANDLE)wParam, &contact, NULL, NULL)) + return 0; + if(contact->type != CLCIT_CONTACT) + return 0; + + iEntry = contact->extraCacheEntry; + + if(iEntry >= 0 && iEntry <= cfg::nextCacheEntry) { + state = !cfg::getByte(contact->hContact, "CList", "floating", 0); + if(state) { + if(cfg::eCache[iEntry].floater == NULL) + FLT_Create(iEntry); + ShowWindow(cfg::eCache[contact->extraCacheEntry].floater->hwnd, SW_SHOW); + } + else { + if(cfg::eCache[iEntry].floater && cfg::eCache[iEntry].floater->hwnd) { + DestroyWindow(cfg::eCache[iEntry].floater->hwnd); + cfg::eCache[iEntry].floater = 0; + } + } + cfg::writeByte(contact->hContact, "CList", "floating", state); + } + return 0; + } + case CLM_QUERYFLOATINGCONTACT: + { + return(cfg::getByte((HANDLE)wParam, "CList", "floating", 0)); + } + case CLM_SETEXTRAIMAGELIST: + dat->himlExtraColumns = (HIMAGELIST) lParam; + InvalidateRect(hwnd, NULL, FALSE); + return 0; + + case CLM_SETFONT: + if(HIWORD(lParam)<0 || HIWORD(lParam)>FONTID_LAST) + return 0; + dat->fontInfo[HIWORD(lParam)].hFont = (HFONT)wParam; + dat->fontInfo[HIWORD(lParam)].changed = 1; + + RowHeight::getMaxRowHeight(dat, hwnd); + + if(LOWORD(lParam)) + InvalidateRect(hwnd,NULL,FALSE); + return 0; + + case CLM_ISMULTISELECT: + return dat->isMultiSelect; + } + + return saveProcessExternalMessages(hwnd, dat, msg, wParam, lParam); +} diff --git a/plugins/Clist_nicer/src/clcopts.cpp b/plugins/Clist_nicer/src/clcopts.cpp new file mode 100644 index 0000000000..60af19554b --- /dev/null +++ b/plugins/Clist_nicer/src/clcopts.cpp @@ -0,0 +1,1620 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE done + +*/ +#include +#include "../coolsb/coolscroll.h" + +#define DBFONTF_BOLD 1 +#define DBFONTF_ITALIC 2 +#define DBFONTF_UNDERLINE 4 + +static INT_PTR CALLBACK DlgProcClcMainOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +static INT_PTR CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +//static INT_PTR CALLBACK DlgProcClcTextOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcViewModesSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcFloatingContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcCluiOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcGenOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern void ReloadExtraIcons( void ); + +extern HIMAGELIST himlExtraImages; + +struct CheckBoxToStyleEx_t { + int id; + DWORD flag; + int not_t; +} static const checkBoxToStyleEx[] = { + {IDC_DISABLEDRAGDROP,CLS_EX_DISABLEDRAGDROP,0}, {IDC_NOTEDITLABELS,CLS_EX_EDITLABELS,1}, + {IDC_SHOWSELALWAYS,CLS_EX_SHOWSELALWAYS,0}, {IDC_TRACKSELECT,CLS_EX_TRACKSELECT,0}, + {IDC_DIVIDERONOFF,CLS_EX_DIVIDERONOFF,0}, {IDC_NOTNOTRANSLUCENTSEL,CLS_EX_NOTRANSLUCENTSEL,1}, + {IDC_NOTNOSMOOTHSCROLLING,CLS_EX_NOSMOOTHSCROLLING,1} +}; + +struct CheckBoxToGroupStyleEx_t { + int id; + DWORD flag; + int not_t; +} static const checkBoxToGroupStyleEx[] = { + {IDC_SHOWGROUPCOUNTS,CLS_EX_SHOWGROUPCOUNTS,0}, {IDC_HIDECOUNTSWHENEMPTY,CLS_EX_HIDECOUNTSWHENEMPTY,0}, + {IDC_LINEWITHGROUPS,CLS_EX_LINEWITHGROUPS,0}, {IDC_QUICKSEARCHVISONLY,CLS_EX_QUICKSEARCHVISONLY,0}, + {IDC_SORTGROUPSALPHA,CLS_EX_SORTGROUPSALPHA,0} +}; + +struct CheckBoxValues_t { + DWORD style; + TCHAR *szDescr; +}; + +static const struct CheckBoxValues_t greyoutValues[] = { + {GREYF_UNFOCUS,_T("Not focused")}, {MODEF_OFFLINE,_T("Offline")}, {PF2_ONLINE,_T("Online")}, {PF2_SHORTAWAY,_T("Away")}, {PF2_LONGAWAY,_T("NA")}, {PF2_LIGHTDND,_T("Occupied")}, {PF2_HEAVYDND,_T("DND")}, {PF2_FREECHAT,_T("Free for chat")}, {PF2_INVISIBLE,_T("Invisible")}, {PF2_OUTTOLUNCH,_T("Out to lunch")}, {PF2_ONTHEPHONE,_T("On the phone")} +}; +static const struct CheckBoxValues_t offlineValues[] = { + {MODEF_OFFLINE,_T("Offline")}, {PF2_ONLINE,_T("Online")}, {PF2_SHORTAWAY,_T("Away")}, {PF2_LONGAWAY,_T("NA")}, {PF2_LIGHTDND,_T("Occupied")}, {PF2_HEAVYDND,_T("DND")}, {PF2_FREECHAT,_T("Free for chat")}, {PF2_INVISIBLE,_T("Invisible")}, {PF2_OUTTOLUNCH,_T("Out to lunch")}, {PF2_ONTHEPHONE,_T("On the phone")} +}; + +static HIMAGELIST himlCheckBoxes = 0; + +static void CreateStateImageList() +{ + HICON hIconNoTick = reinterpret_cast(LoadImage(g_hInst, MAKEINTRESOURCE(IDI_NOTICK), IMAGE_ICON, 16, 16, 0)); + HICON hIconTick = reinterpret_cast(LoadImage(g_hInst, MAKEINTRESOURCE(IDI_TICK), IMAGE_ICON, 16, 16, 0)); + + himlCheckBoxes=ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,2,2); + ImageList_AddIcon(himlCheckBoxes, hIconNoTick); + ImageList_AddIcon(himlCheckBoxes, hIconTick); + ImageList_AddIcon(himlCheckBoxes, hIconNoTick); + + DestroyIcon(hIconTick); + DestroyIcon(hIconNoTick); +} + + +static UINT sortCtrlIDs[] = {IDC_SORTPRIMARY, IDC_SORTTHEN, IDC_SORTFINALLY, 0}; + +static void FillCheckBoxTree(HWND hwndTree, const struct CheckBoxValues_t *values, int nValues, DWORD style) +{ + TVINSERTSTRUCT tvis; + int i; + + tvis.hParent = NULL; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE; + for (i = 0; i < nValues; i++) { + tvis.item.lParam = values[i].style; + tvis.item.pszText = TranslateTS(values[i].szDescr); + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.state = INDEXTOSTATEIMAGEMASK((style & tvis.item.lParam) != 0 ? 1 : 2); + TreeView_InsertItem(hwndTree, &tvis); + } +} + +static DWORD MakeCheckBoxTreeFlags(HWND hwndTree) +{ + DWORD flags = 0; + TVITEM tvi; + + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; + tvi.hItem = TreeView_GetRoot(hwndTree); + while (tvi.hItem) { + TreeView_GetItem(hwndTree, &tvi); + if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 1)) + flags |= tvi.lParam; + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } + return flags; +} + +/* + * write a display profile to the db + * p->uID must contain the (valid) identifier + */ + +static void DSP_Write(DISPLAYPROFILESET *p) +{ + char szBuf[256], szKey[256]; + int i = 0, j; + DWORD dwFlags = 0; + DISPLAYPROFILE *dp; + + _snprintf(szKey, 256, "[%u]", p->uID); + cfg::writeTString(NULL, DSP_PROFILES_MODULE, szKey, p->tszName); + + for (j = 0; j < 4; j++) { + + dp = &p->dp[i]; + i = 0; + + /* + * dword values + */ + + _snprintf(szBuf, 256, "%u,%u,%d,%u,%u", dp->dwFlags, dp->dwExtraImageMask, dp->avatarBorder, dp->clcExStyle, dp->clcOfflineModes); + szBuf[255] = 0; + _snprintf(szKey, 256, "{dw_%u_%u}", p->uID, j); + cfg::writeString(NULL, DSP_PROFILES_MODULE, szKey, szBuf); + + _snprintf(szKey, 256, "{b_%u_%u}", p->uID, j); + + /* + * byte values + */ + + szBuf[i++] = (BYTE)dp->exIconScale; + szBuf[i++] = (BYTE)dp->dualRowMode; + szBuf[i++] = (BYTE)dp->avatarRadius; + szBuf[i++] = (BYTE)dp->avatarSize; + szBuf[i++] = (BYTE)dp->sortOrder[0];szBuf[i++] = (BYTE)dp->sortOrder[1];szBuf[i++] = (BYTE)dp->sortOrder[2]; + szBuf[i++] = dp->bUseDCMirroring; + szBuf[i++] = dp->bGroupAlign; + szBuf[i++] = dp->avatarPadding; + szBuf[i++] = dp->bLeftMargin; szBuf[i++] = dp->bRightMargin; szBuf[i++] = dp->bRowSpacing; + szBuf[i++] = dp->bGroupIndent; szBuf[i++] = dp->bRowHeight; szBuf[i++] = dp->bGroupRowHeight; + szBuf[i++] = 0; + + cfg::writeString(NULL, DSP_PROFILES_MODULE, szKey, szBuf); + + /* + * bool values (convert to bitflags + */ + + _snprintf(szKey, 256, "{f_%u_%u}", p->uID, j); + dwFlags = ((dp->bCenterStatusIcons ? DSPF_CENTERSTATUSICON : 0) | + (dp->bDimIdle ? DSPF_DIMIDLE : 0) | + (dp->bNoOfflineAvatars ? DSPF_NOFFLINEAVATARS : 0) | + (dp->bShowLocalTime ? DSPF_SHOWLOCALTIME : 0) | + (dp->bShowLocalTimeSelective ? DSPF_LOCALTIMESELECTIVE : 0) | + (dp->bDontSeparateOffline ? DSPF_DONTSEPARATEOFFLINE : 0) | + (dp->bCenterGroupNames ? DSPF_CENTERGROUPNAMES : 0)); + + cfg::writeDword(NULL, DSP_PROFILES_MODULE, szKey, dwFlags); + } +} + +/* + * read a profile from the DB + * p->uID must contain the (valid) identifier + */ + +static int DSP_Read(DISPLAYPROFILESET *p) +{ + char szBuf[256], szKey[256]; + int i = 0, j; + DWORD dwFlags = 0; + DBVARIANT dbv = {0}; + DISPLAYPROFILE *dp; + + _snprintf(szKey, 256, "[%u]", p->uID); + + if (cfg::getTString(NULL, DSP_PROFILES_MODULE, szKey, &dbv)) + return 0; + + mir_sntprintf(p->tszName, 60, dbv.ptszVal); + DBFreeVariant(&dbv); + + for (j = 0; j < 4; j++) { + + dp = &p->dp[j]; + i = 0; + /* + * dword values + */ + + mir_snprintf(szKey, 256, "{dw_%u_%u}", p->uID, j); + if (!cfg::getString(NULL, DSP_PROFILES_MODULE, szKey, &dbv)) { + sscanf(dbv.pszVal, "%u,%u,%u,%u,%u", dp->dwFlags, dp->dwExtraImageMask, dp->avatarBorder, dp->clcExStyle, dp->clcOfflineModes); + DBFreeVariant(&dbv); + } + else + return 0; + + /* + * byte values + */ + + _snprintf(szKey, 256, "{b_%u_%u}", p->uID, j); + if (!cfg::getString(NULL, DSP_PROFILES_MODULE, szKey, &dbv)) { + if (lstrlenA(dbv.pszVal) >= 16) { + dp->exIconScale = (int)szBuf[i++]; + dp->dualRowMode = szBuf[i++]; + dp->avatarRadius = szBuf[i++]; + dp->avatarSize = szBuf[i++]; + dp->sortOrder[0] = szBuf[i++]; dp->sortOrder[1] = szBuf[i++]; dp->sortOrder[2] = szBuf[i++]; + dp->bUseDCMirroring = szBuf[i++]; + dp->bGroupAlign = szBuf[i++]; + dp->avatarPadding = szBuf[i++]; + dp->bLeftMargin = szBuf[i++]; dp->bRightMargin = szBuf[i++]; dp->bRowSpacing = szBuf[i++]; + dp->bGroupIndent = szBuf[i++]; dp->bRowHeight = szBuf[i++]; dp->bGroupRowHeight = szBuf[i++]; + } + else { + DBFreeVariant(&dbv); + return 0; + } + DBFreeVariant(&dbv); + } + else + return 0; + + /* + * bool values (convert to bitflags + */ + + _snprintf(szKey, 256, "{f_%u_%u}", p->uID, j); + dwFlags = cfg::getDword(DSP_PROFILES_MODULE, szKey, 0); + + dp->bCenterStatusIcons = dwFlags & DSPF_CENTERSTATUSICON ? 1 : 0; + dp->bDimIdle = dwFlags & DSPF_DIMIDLE ? 1 : 0; + dp->bNoOfflineAvatars = dwFlags & DSPF_NOFFLINEAVATARS ? 1 : 0; + dp->bShowLocalTime = dwFlags & DSPF_SHOWLOCALTIME ? 1 : 0; + dp->bShowLocalTimeSelective = dwFlags & DSPF_LOCALTIMESELECTIVE ? 1 : 0; + dp->bDontSeparateOffline = dwFlags & DSPF_DONTSEPARATEOFFLINE ? 1 : 0; + dp->bCenterGroupNames = dwFlags & DSPF_CENTERGROUPNAMES ? 1 : 0; + } + + return 1; +} + +/* + * load current values into the given profile + */ + +static void DSP_LoadFromDefaults(DISPLAYPROFILE *p) +{ + p->dwExtraImageMask = cfg::dat.dwExtraImageMask; + p->exIconScale = cfg::dat.exIconScale; + p->bCenterStatusIcons = cfg::dat.bCenterStatusIcons; + p->dwFlags = cfg::dat.dwFlags; + p->bDimIdle = cfg::getByte("CLC", "ShowIdle", CLCDEFAULT_SHOWIDLE); + p->avatarBorder = cfg::dat.avatarBorder; + p->avatarSize = cfg::dat.avatarSize; + p->avatarRadius = cfg::dat.avatarRadius; + p->dualRowMode = cfg::dat.dualRowMode; + p->bNoOfflineAvatars = cfg::dat.bNoOfflineAvatars; + p->bShowLocalTime = cfg::dat.bShowLocalTime; + p->bShowLocalTimeSelective = cfg::dat.bShowLocalTimeSelective; + p->clcExStyle = cfg::getDword("CLC", "ExStyle", pcli->pfnGetDefaultExStyle()); + p->clcOfflineModes = cfg::getDword("CLC", "OfflineModes", CLCDEFAULT_OFFLINEMODES); + p->bDontSeparateOffline = cfg::dat.bDontSeparateOffline; + p->sortOrder[0] = cfg::dat.sortOrder[0]; + p->sortOrder[1] = cfg::dat.sortOrder[1]; + p->sortOrder[2] = cfg::dat.sortOrder[2]; + p->bUseDCMirroring = cfg::dat.bUseDCMirroring; + p->bCenterGroupNames = cfg::getByte("CLCExt", "EXBK_CenterGroupnames", 0); + p->bGroupAlign = cfg::dat.bGroupAlign; + p->avatarPadding = cfg::dat.avatarPadding; + + p->bLeftMargin = cfg::getByte("CLC", "LeftMargin", CLCDEFAULT_LEFTMARGIN); + p->bRightMargin = cfg::getByte("CLC", "RightMargin", CLCDEFAULT_LEFTMARGIN); + p->bRowSpacing = cfg::dat.bRowSpacing; + p->bGroupIndent = cfg::getByte("CLC", "GroupIndent", CLCDEFAULT_GROUPINDENT); + p->bRowHeight = cfg::getByte("CLC", "RowHeight", CLCDEFAULT_ROWHEIGHT); + p->bGroupRowHeight = cfg::getByte("CLC", "GRowHeight", CLCDEFAULT_ROWHEIGHT); + CopyMemory(p->exIconOrder, cfg::dat.exIconOrder, EXICON_COUNT); +} + +/* + * apply a display profile + */ + +void DSP_Apply(DISPLAYPROFILE *p) +{ + int oldexIconScale = cfg::dat.exIconScale; + DWORD oldMask = cfg::dat.dwExtraImageMask; + int i; + DWORD exStyle; + char temp[EXICON_COUNT + 1]; + /* + * icons page + */ + cfg::dat.dwFlags &= ~(CLUI_FRAME_STATUSICONS | CLUI_SHOWVISI | CLUI_USEMETAICONS | CLUI_FRAME_USEXSTATUSASSTATUS | CLUI_FRAME_OVERLAYICONS | CLUI_FRAME_SELECTIVEICONS); + cfg::dat.dwExtraImageMask = p->dwExtraImageMask; + cfg::dat.exIconScale = p->exIconScale; + cfg::dat.bCenterStatusIcons = p->bCenterStatusIcons; + + cfg::writeDword("CLUI", "ximgmask", cfg::dat.dwExtraImageMask); + cfg::writeByte("CLC", "ExIconScale", (BYTE)cfg::dat.exIconScale); + cfg::writeByte("CLC", "si_centered", (BYTE)cfg::dat.bCenterStatusIcons); + cfg::writeByte("CLC", "ShowIdle", (BYTE)p->bDimIdle); + + CopyMemory(cfg::dat.exIconOrder, p->exIconOrder, EXICON_COUNT); + CopyMemory(temp, p->exIconOrder, EXICON_COUNT); + temp[EXICON_COUNT] = 0; + cfg::writeString(NULL, "CLUI", "exIconOrder", temp); + + /* + * advanced (avatars & 2nd row) + */ + + cfg::dat.dwFlags &= ~(CLUI_FRAME_AVATARSLEFT | CLUI_FRAME_AVATARSRIGHT | CLUI_FRAME_AVATARSRIGHTWITHNICK | + CLUI_FRAME_AVATARS | CLUI_FRAME_AVATARBORDER | CLUI_FRAME_ROUNDAVATAR | + CLUI_FRAME_ALWAYSALIGNNICK | CLUI_FRAME_SHOWSTATUSMSG | CLUI_FRAME_GDIPLUS); + + cfg::dat.avatarSize = p->avatarSize; + cfg::dat.avatarBorder = p->avatarBorder; + cfg::dat.avatarRadius = p->avatarRadius; + cfg::dat.dualRowMode = p->dualRowMode; + cfg::dat.bNoOfflineAvatars = p->bNoOfflineAvatars; + cfg::dat.bShowLocalTime = p->bShowLocalTime; + cfg::dat.bShowLocalTimeSelective = p->bShowLocalTimeSelective; + + if (cfg::dat.hBrushAvatarBorder) + DeleteObject(cfg::dat.hBrushAvatarBorder); + cfg::dat.hBrushAvatarBorder = CreateSolidBrush(cfg::dat.avatarBorder); + + /* + * items page + */ + + cfg::dat.dwFlags &= ~CLUI_STICKYEVENTS; + + cfg::dat.sortOrder[0] = p->sortOrder[0]; + cfg::dat.sortOrder[1] = p->sortOrder[1]; + cfg::dat.sortOrder[2] = p->sortOrder[2]; + cfg::dat.bDontSeparateOffline = p->bDontSeparateOffline; + cfg::writeByte("CList", "DontSeparateOffline", (BYTE)cfg::dat.bDontSeparateOffline); + cfg::writeDword("CLC", "OfflineModes", p->clcOfflineModes); + + cfg::writeDword("CList", "SortOrder", + MAKELONG(MAKEWORD(cfg::dat.sortOrder[0], cfg::dat.sortOrder[1]), + MAKEWORD(cfg::dat.sortOrder[2], 0))); + + cfg::dat.bUseDCMirroring = p->bUseDCMirroring; + cfg::writeByte("CLC", "MirrorDC", cfg::dat.bUseDCMirroring); + + /* + * groups page + */ + + cfg::dat.dwFlags &= ~CLUI_FRAME_NOGROUPICON; + cfg::dat.bGroupAlign = p->bGroupAlign; + cfg::writeByte("CLC", "GroupAlign", cfg::dat.bGroupAlign); + cfg::writeByte("CLCExt", "EXBK_CenterGroupnames", (BYTE)p->bCenterGroupNames); + + exStyle = cfg::getDword("CLC", "ExStyle", pcli->pfnGetDefaultExStyle()); + for (i = 0; i < sizeof(checkBoxToGroupStyleEx) / sizeof(checkBoxToGroupStyleEx[0]); i++) + exStyle &= ~(checkBoxToGroupStyleEx[i].flag); + + exStyle |= p->clcExStyle; + cfg::writeDword("CLC", "ExStyle", exStyle); + cfg::dat.avatarPadding = p->avatarPadding; + cfg::writeByte("CList", "AvatarPadding", cfg::dat.avatarPadding); + + cfg::dat.bRowSpacing = p->bRowSpacing; + cfg::writeByte("CLC", "RowGap", cfg::dat.bRowSpacing); + + cfg::writeByte("CLC", "LeftMargin", (BYTE)p->bLeftMargin); + cfg::writeByte("CLC", "RightMargin", (BYTE)p->bRightMargin); + cfg::writeByte("CLC", "GroupIndent", (BYTE)p->bGroupIndent); + cfg::writeByte("CLC", "RowHeight", (BYTE)p->bRowHeight); + cfg::writeByte("CLC", "GRowHeight", (BYTE)p->bGroupRowHeight); + + if (cfg::dat.sortOrder[0] == SORTBY_LASTMSG || cfg::dat.sortOrder[1] == SORTBY_LASTMSG || cfg::dat.sortOrder[2] == SORTBY_LASTMSG) { + int i; + + for (i = 0; i < cfg::nextCacheEntry; i++) + cfg::eCache[i].dwLastMsgTime = INTSORT_GetLastMsgTime(cfg::eCache[i].hContact); + } + + cfg::writeByte("CLC", "ShowLocalTime", (BYTE)cfg::dat.bShowLocalTime); + cfg::writeByte("CLC", "SelectiveLocalTime", (BYTE)cfg::dat.bShowLocalTimeSelective); + cfg::writeDword("CLC", "avatarborder", cfg::dat.avatarBorder); + cfg::writeDword("CLC", "avatarradius", cfg::dat.avatarRadius); + cfg::writeWord(NULL, "CList", "AvatarSize", (WORD)cfg::dat.avatarSize); + cfg::writeByte("CLC", "DualRowMode", cfg::dat.dualRowMode); + cfg::writeByte("CList", "NoOfflineAV", (BYTE)cfg::dat.bNoOfflineAvatars); + + KillTimer(pcli->hwndContactTree, TIMERID_REFRESH); + if (cfg::dat.bShowLocalTime) + SetTimer(pcli->hwndContactTree, TIMERID_REFRESH, 65000, NULL); + + cfg::dat.dwFlags |= p->dwFlags; + cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags); + + for (i = 0; i < cfg::nextCacheEntry; i++) + cfg::eCache[i].dwXMask = CalcXMask(cfg::eCache[i].hContact); + + if (oldexIconScale != cfg::dat.exIconScale) { + ImageList_RemoveAll(himlExtraImages); + ImageList_SetIconSize(himlExtraImages, cfg::dat.exIconScale, cfg::dat.exIconScale); + IcoLibReloadIcons(); + } + pcli->pfnClcOptionsChanged(); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); +} + +void GetDefaultFontSetting(int i, LOGFONT *lf, COLORREF *colour) +{ + SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), lf, FALSE); + *colour = GetSysColor(COLOR_WINDOWTEXT); + switch (i) { + case FONTID_GROUPS: + lf->lfWeight = FW_BOLD; + break; + case FONTID_GROUPCOUNTS: + lf->lfHeight = (int) (lf->lfHeight * .75); + *colour = GetSysColor(COLOR_3DSHADOW); + break; + case FONTID_OFFINVIS: + case FONTID_INVIS: + lf->lfItalic = !lf->lfItalic; + break; + case FONTID_DIVIDERS: + lf->lfHeight = (int) (lf->lfHeight * .75); + break; + case FONTID_NOTONLIST: + *colour = GetSysColor(COLOR_3DSHADOW); + break; +} } + +static INT_PTR CALLBACK DlgProcDspGroups(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + int i = 0; + TranslateDialogDefault(hwndDlg); + SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always Left")); + SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always Right")); + SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Automatic (RTL)")); + } + return TRUE; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_ROWHEIGHT || LOWORD(wParam) == IDC_AVATARPADDING || LOWORD(wParam) == IDC_ROWGAP || LOWORD(wParam) == IDC_RIGHTMARGIN || LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_SMOOTHTIME || LOWORD(wParam) == IDC_GROUPINDENT || LOWORD(wParam) == IDC_GROUPROWHEIGHT) + && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_USER + 100: + { + DISPLAYPROFILE *p = (DISPLAYPROFILE *)lParam; + if (p) { + DWORD exStyle = p->clcExStyle; + int i; + for (i = 0; i < sizeof(checkBoxToGroupStyleEx) / sizeof(checkBoxToGroupStyleEx[0]); i++) + CheckDlgButton(hwndDlg, checkBoxToGroupStyleEx[i].id, (exStyle & checkBoxToGroupStyleEx[i].flag) ^ (checkBoxToGroupStyleEx[i].flag * checkBoxToGroupStyleEx[i].not_t) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_NOGROUPICON, (p->dwFlags & CLUI_FRAME_NOGROUPICON) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CENTERGROUPNAMES, p->bCenterGroupNames); + SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_SETCURSEL, p->bGroupAlign, 0); + SendDlgItemMessage(hwndDlg, IDC_AVATARPADDINGSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0)); + SendDlgItemMessage(hwndDlg, IDC_AVATARPADDINGSPIN, UDM_SETPOS, 0, p->avatarPadding); + + SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETRANGE, 0, MAKELONG(64, 0)); + SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, p->bLeftMargin); + SendDlgItemMessage(hwndDlg, IDC_RIGHTMARGINSPIN, UDM_SETRANGE, 0, MAKELONG(64, 0)); + SendDlgItemMessage(hwndDlg, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, p->bRightMargin); + SendDlgItemMessage(hwndDlg, IDC_ROWGAPSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0)); + SendDlgItemMessage(hwndDlg, IDC_ROWGAPSPIN, UDM_SETPOS, 0, p->bRowSpacing); + SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETRANGE, 0, MAKELONG(50, 0)); + SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_SETPOS, 0, p->bGroupIndent); + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, 8)); + SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_SETPOS, 0, p->bRowHeight); + SendDlgItemMessage(hwndDlg, IDC_GROUPROWHEIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, 8)); + SendDlgItemMessage(hwndDlg, IDC_GROUPROWHEIGHTSPIN, UDM_SETPOS, 0, p->bGroupRowHeight); + } + } + return 0; + + case WM_USER + 200: + { + DISPLAYPROFILE *p = (DISPLAYPROFILE *)lParam; + if (p) { + int i; + DWORD exStyle = 0; + LRESULT curSel; + BOOL translated; + + for (i = 0; i < sizeof(checkBoxToGroupStyleEx) / sizeof(checkBoxToGroupStyleEx[0]); i++) { + if ((IsDlgButtonChecked(hwndDlg, checkBoxToGroupStyleEx[i].id) == 0) == checkBoxToGroupStyleEx[i].not_t) + exStyle |= checkBoxToGroupStyleEx[i].flag; + } + p->clcExStyle = exStyle; + p->dwFlags |= (IsDlgButtonChecked(hwndDlg, IDC_NOGROUPICON) ? CLUI_FRAME_NOGROUPICON : 0); + p->bCenterGroupNames = IsDlgButtonChecked(hwndDlg, IDC_CENTERGROUPNAMES) ? 1 : 0; + curSel = SendDlgItemMessage(hwndDlg, IDC_GROUPALIGN, CB_GETCURSEL, 0, 0); + if (curSel != CB_ERR) + p->bGroupAlign = (BYTE)curSel; + + p->avatarPadding = (BYTE)GetDlgItemInt(hwndDlg, IDC_AVATARPADDING, &translated, FALSE); + p->bLeftMargin = (BYTE)SendDlgItemMessage(hwndDlg, IDC_LEFTMARGINSPIN, UDM_GETPOS, 0, 0); + p->bRightMargin = (BYTE)SendDlgItemMessage(hwndDlg, IDC_RIGHTMARGINSPIN, UDM_GETPOS, 0, 0); + p->bRowSpacing = (BYTE)SendDlgItemMessage(hwndDlg, IDC_ROWGAPSPIN, UDM_GETPOS, 0, 0); + p->bGroupIndent = (BYTE)SendDlgItemMessage(hwndDlg, IDC_GROUPINDENTSPIN, UDM_GETPOS, 0, 0); + p->bRowHeight = (BYTE)SendDlgItemMessage(hwndDlg, IDC_ROWHEIGHTSPIN, UDM_GETPOS, 0, 0); + p->bGroupRowHeight = (BYTE)SendDlgItemMessage(hwndDlg, IDC_GROUPROWHEIGHTSPIN, UDM_GETPOS, 0, 0); + } + return 0; + } + + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + return TRUE; + } + break; + } + break; + } + return FALSE; +} + +static INT_PTR CALLBACK DlgProcDspItems(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + DISPLAYPROFILE *p; + + switch (msg) { + case WM_INITDIALOG: + { + int i = 0; + HIMAGELIST himlOld; + + TranslateDialogDefault(hwndDlg); + if (himlCheckBoxes == 0) + CreateStateImageList(); + + himlOld = TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), himlCheckBoxes, TVSIL_STATE); + ImageList_Destroy(himlOld); + + for (i = 0; sortCtrlIDs[i] != 0; i++) { + SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Nothing")); + SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Name")); + SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Protocol")); + SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Status")); + SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Last Message")); + SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_INSERTSTRING, -1, (LPARAM)TranslateT("Message Frequency")); + } + SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Never")); + SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always")); + SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("For RTL only")); + SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_INSERTSTRING, -1, (LPARAM)TranslateT("RTL TEXT only")); + } + return TRUE; + + case WM_COMMAND: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_USER + 100: + p = (DISPLAYPROFILE *)lParam; + if (p) { + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS), offlineValues, sizeof(offlineValues) / sizeof(offlineValues[0]), p->clcOfflineModes); + CheckDlgButton(hwndDlg, IDC_EVENTSONTOP, (p->dwFlags & CLUI_STICKYEVENTS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DONTSEPARATE, p->bDontSeparateOffline); + for (int i = 0; sortCtrlIDs[i] != 0; i++) + SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_SETCURSEL, p->sortOrder[i], 0); + + SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_SETCURSEL, p->bUseDCMirroring, 0); + } + return 0; + + case WM_USER + 200: + p = (DISPLAYPROFILE *)lParam; + if (p) { + for (int i = 0; sortCtrlIDs[i] != 0; i++) { + LRESULT curSel = SendDlgItemMessage(hwndDlg, sortCtrlIDs[i], CB_GETCURSEL, 0, 0); + if (curSel == 0 || curSel == CB_ERR) + p->sortOrder[i] = 0; + else + p->sortOrder[i] = (BYTE)curSel; + } + p->bDontSeparateOffline = IsDlgButtonChecked(hwndDlg, IDC_DONTSEPARATE) ? 1 : 0; + p->dwFlags |= IsDlgButtonChecked(hwndDlg, IDC_EVENTSONTOP) ? CLUI_STICKYEVENTS : 0; + p->clcOfflineModes = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_HIDEOFFLINEOPTS)); + p->bUseDCMirroring = (BYTE)SendDlgItemMessage(hwndDlg, IDC_CLISTALIGN, CB_GETCURSEL, 0, 0); + } + return 0; + + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_HIDEOFFLINEOPTS: + if (((LPNMHDR) lParam)->code == NM_CLICK) { + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(GetMessagePos()); + hti.pt.y = (short) HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR) lParam)->hwndFrom, &hti.pt); + if (TreeView_HitTest(((LPNMHDR) lParam)->hwndFrom, &hti)) + if (hti.flags & TVHT_ONITEMSTATEICON) { + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hti.hItem; + TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1; + TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + return TRUE; + } + break; + } + } + return FALSE; +} + +static UINT avatar_controls[] = { IDC_ALIGNMENT, IDC_AVATARSBORDER, IDC_AVATARSROUNDED, IDC_AVATARBORDERCLR, IDC_ALWAYSALIGNNICK, IDC_AVATARHEIGHT, IDC_AVATARSIZESPIN, 0 }; +static INT_PTR CALLBACK DlgProcDspAdvanced(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + DISPLAYPROFILE *p; + + switch (msg) { + case WM_INITDIALOG: + { + int i = 0; + + TranslateDialogDefault(hwndDlg); + SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Never")); + SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always")); + SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("When space allows it")); + SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("When needed")); + + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("With Nickname - left")); + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Far left")); + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Far right")); + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("With Nickname - right")); + + if (cfg::dat.bAvatarServiceAvail) { + Utils::enableDlgControl(hwndDlg, IDC_CLISTAVATARS, TRUE); + while(avatar_controls[i] != 0) + Utils::enableDlgControl(hwndDlg, avatar_controls[i++], TRUE); + } + else { + Utils::enableDlgControl(hwndDlg, IDC_CLISTAVATARS, FALSE); + while(avatar_controls[i] != 0) + Utils::enableDlgControl(hwndDlg, avatar_controls[i++], FALSE); + } + return TRUE; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_CLISTAVATARS: + if ((HWND)lParam != GetFocus()) + return 0; + break; + + case IDC_SHOWLOCALTIME: + Utils::enableDlgControl(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT, IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIME)); + break; + + case IDC_AVATARSROUNDED: + Utils::enableDlgControl(hwndDlg, IDC_RADIUS, IsDlgButtonChecked(hwndDlg, IDC_AVATARSROUNDED) ? TRUE : FALSE); + Utils::enableDlgControl(hwndDlg, IDC_RADIUSSPIN, IsDlgButtonChecked(hwndDlg, IDC_AVATARSROUNDED) ? TRUE : FALSE); + break; + + case IDC_AVATARSBORDER: + Utils::enableDlgControl(hwndDlg, IDC_AVATARBORDERCLR, IsDlgButtonChecked(hwndDlg, IDC_AVATARSBORDER) ? TRUE : FALSE); + break; + } + if ((LOWORD(wParam) == IDC_RADIUS || LOWORD(wParam) == IDC_AVATARHEIGHT) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_USER + 100: + p = (DISPLAYPROFILE *)lParam; + if (p) { + CheckDlgButton(hwndDlg, IDC_NOAVATARSOFFLINE, p->bNoOfflineAvatars); + SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_SETCURSEL, (WPARAM)p->dualRowMode, 0); + CheckDlgButton(hwndDlg, IDC_CLISTAVATARS, (p->dwFlags & CLUI_FRAME_AVATARS) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_AVATARSBORDER, (p->dwFlags & CLUI_FRAME_AVATARBORDER) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AVATARSROUNDED, (p->dwFlags & CLUI_FRAME_ROUNDAVATAR) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSALIGNNICK, (p->dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWSTATUSMSG, (p->dwFlags & CLUI_FRAME_SHOWSTATUSMSG) ? BST_CHECKED : BST_UNCHECKED); + + SendDlgItemMessage(hwndDlg, IDC_AVATARBORDERCLR, CPM_SETCOLOUR, 0, p->avatarBorder); + + SendDlgItemMessage(hwndDlg, IDC_RADIUSSPIN, UDM_SETRANGE, 0, MAKELONG(10, 2)); + SendDlgItemMessage(hwndDlg, IDC_RADIUSSPIN, UDM_SETPOS, 0, p->avatarRadius); + + SendDlgItemMessage(hwndDlg, IDC_AVATARSIZESPIN, UDM_SETRANGE, 0, MAKELONG(100, 16)); + SendDlgItemMessage(hwndDlg, IDC_AVATARSIZESPIN, UDM_SETPOS, 0, p->avatarSize); + + Utils::enableDlgControl(hwndDlg, IDC_RADIUS, IsDlgButtonChecked(hwndDlg, IDC_AVATARSROUNDED) ? TRUE : FALSE); + Utils::enableDlgControl(hwndDlg, IDC_RADIUSSPIN, IsDlgButtonChecked(hwndDlg, IDC_AVATARSROUNDED) ? TRUE : FALSE); + Utils::enableDlgControl(hwndDlg, IDC_AVATARBORDERCLR, IsDlgButtonChecked(hwndDlg, IDC_AVATARSBORDER) ? TRUE : FALSE); + + CheckDlgButton(hwndDlg, IDC_SHOWLOCALTIME, p->bShowLocalTime ? 1 : 0); + CheckDlgButton(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT, p->bShowLocalTimeSelective ? 1 : 0); + Utils::enableDlgControl(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT, IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIME)); + + if (p->dwFlags & CLUI_FRAME_AVATARSLEFT) + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 1, 0); + else if (p->dwFlags & CLUI_FRAME_AVATARSRIGHT) + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 2, 0); + else if (p->dwFlags & CLUI_FRAME_AVATARSRIGHTWITHNICK) + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 3, 0); + else + SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_SETCURSEL, 0, 0); + } + return 0; + + case WM_USER + 200: + p = (DISPLAYPROFILE *)lParam; + if (p) { + LRESULT sel = SendDlgItemMessage(hwndDlg, IDC_ALIGNMENT, CB_GETCURSEL, 0, 0); + BOOL translated; + + if (sel != CB_ERR) { + if (sel == 1) + p->dwFlags |= CLUI_FRAME_AVATARSLEFT; + else if (sel == 2) + p->dwFlags |= CLUI_FRAME_AVATARSRIGHT; + else if (sel == 3) + p->dwFlags |= CLUI_FRAME_AVATARSRIGHTWITHNICK; + } + + p->dwFlags |= ((IsDlgButtonChecked(hwndDlg, IDC_CLISTAVATARS) ? CLUI_FRAME_AVATARS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_AVATARSBORDER) ? CLUI_FRAME_AVATARBORDER : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_AVATARSROUNDED) ? CLUI_FRAME_ROUNDAVATAR : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_ALWAYSALIGNNICK) ? CLUI_FRAME_ALWAYSALIGNNICK : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSMSG) ? CLUI_FRAME_SHOWSTATUSMSG : 0)); + + p->avatarBorder = SendDlgItemMessage(hwndDlg, IDC_AVATARBORDERCLR, CPM_GETCOLOUR, 0, 0); + p->avatarRadius = GetDlgItemInt(hwndDlg, IDC_RADIUS, &translated, FALSE); + p->avatarSize = GetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, &translated, FALSE); + p->bNoOfflineAvatars = IsDlgButtonChecked(hwndDlg, IDC_NOAVATARSOFFLINE) ? TRUE : FALSE; + p->bShowLocalTime = IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIME) ? 1 : 0; + p->bShowLocalTimeSelective = IsDlgButtonChecked(hwndDlg, IDC_SHOWLOCALTIMEONLYWHENDIFFERENT) ? 1 : 0; + + p->dualRowMode = (BYTE)SendDlgItemMessage(hwndDlg, IDC_DUALROWMODE, CB_GETCURSEL, 0, 0); + if (p->dualRowMode == CB_ERR) + p->dualRowMode = 0; + } + return 0; + + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + return TRUE; + } + break; + } + return FALSE; +} + +ORDERTREEDATA OrderTreeData[]= +{ + {EXTRA_ICON_RES0, _T("Reserved, unused"), 9, TRUE, 0}, + {EXTRA_ICON_EMAIL, _T("E-mail"), 0, TRUE, 0}, + {EXTRA_ICON_RES1, _T("Reserved #1"), 7, TRUE, 0}, + {EXTRA_ICON_SMS, _T("Telephone"), 2, TRUE, 0}, + {EXTRA_ICON_ADV1, _T("Advanced #1 (ICQ X-Status)"), 3, TRUE, 0}, + {EXTRA_ICON_ADV2, _T("Advanced #2"), 4, TRUE, 0}, + {EXTRA_ICON_WEB, _T("Homepage"), 1, TRUE, 0}, + {EXTRA_ICON_CLIENT, _T("Client (fingerprint required)"), 10, TRUE, 0}, + {EXTRA_ICON_RES2, _T("Reserved #2"), 8, TRUE, 0}, + {EXTRA_ICON_ADV3, _T("Advanced #3"), 5, TRUE, 0}, + {EXTRA_ICON_ADV4, _T("Advanced #4"), 6, TRUE, 0}, +}; + +static int dragging=0; +static HTREEITEM hDragItem=NULL; + +static int FillOrderTree(HWND hwndDlg, HWND hwndTree, BYTE *exIconOrder, unsigned dwExtraImageMask) +{ + TVINSERTSTRUCT tvis = {0}; + TreeView_DeleteAllItems(hwndTree); + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + + for (int i = 0; i < EXICON_COUNT; i++) { + int iIndex = (int)(exIconOrder[i] - 1); + tvis.item.lParam=(LPARAM)(&(OrderTreeData[iIndex])); + tvis.item.pszText = TranslateTS(OrderTreeData[iIndex].Name); + OrderTreeData[iIndex].Visible = (dwExtraImageMask & (1 << OrderTreeData[iIndex].ID)) != 0; + tvis.item.iImage = tvis.item.iSelectedImage = OrderTreeData[iIndex].Visible; + TreeView_InsertItem(hwndTree, &tvis); + } + + return 0; +} + +static int SaveOrderTree(HWND hwndDlg, HWND hwndTree, DISPLAYPROFILE *p) +{ + TVITEM tvi = {0}; + tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; + + p->dwExtraImageMask = 0; + + HTREEITEM ht = TreeView_GetRoot(hwndTree); + for (int iIndex = 0; ht != NULL; iIndex++) { + tvi.hItem = ht; + TreeView_GetItem(hwndTree, &tvi); + + ORDERTREEDATA *it = (ORDERTREEDATA *)(tvi.lParam); + p->exIconOrder[iIndex] = it->ID + 1; + p->dwExtraImageMask |= (it->Visible ? (1 << it->ID) : 0); + ht = TreeView_GetNextSibling(hwndTree, ht); + } + + return 0; +} + +static INT_PTR CALLBACK DlgProcXIcons(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + DISPLAYPROFILE *p; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EXTRAORDER), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_EXTRAORDER),GWL_STYLE)|TVS_NOHSCROLL); + + if (himlCheckBoxes == 0) + CreateStateImageList(); + + TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_EXTRAORDER), himlCheckBoxes, TVSIL_NORMAL); + return TRUE; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_EXICONSCALE) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + + if (IDC_RESETXICONS == LOWORD(wParam)) { + BYTE exIconOrder[EXICON_COUNT]; + for (int i = 0; i < EXICON_COUNT; i++) { + OrderTreeData[i].Visible = TRUE; + exIconOrder[i] = i + 1; + } + FillOrderTree(hwndDlg, GetDlgItem(hwndDlg, IDC_EXTRAORDER), exIconOrder, 0xffffffff); + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_USER + 100: + p = (DISPLAYPROFILE *)lParam; + if (p) { + CheckDlgButton(hwndDlg, IDC_XSTATUSASSTATUS, p->dwFlags & CLUI_FRAME_USEXSTATUSASSTATUS ? 1 : 0); + + CheckDlgButton(hwndDlg, IDC_SHOWSTATUSICONS, (p->dwFlags & CLUI_FRAME_STATUSICONS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWVISIBILITY, (p->dwFlags & CLUI_SHOWVISI) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWMETA, (p->dwFlags & CLUI_USEMETAICONS) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_OVERLAYICONS, (p->dwFlags & CLUI_FRAME_OVERLAYICONS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SELECTIVEICONS, (p->dwFlags & CLUI_FRAME_SELECTIVEICONS) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_STATUSICONSCENTERED, p->bCenterStatusIcons ? 1 : 0); + CheckDlgButton(hwndDlg, IDC_IDLE, p->bDimIdle ? BST_CHECKED : BST_UNCHECKED); + + SendDlgItemMessage(hwndDlg, IDC_EXICONSCALESPIN, UDM_SETRANGE, 0, MAKELONG(20, 8)); + SendDlgItemMessage(hwndDlg, IDC_EXICONSCALESPIN, UDM_SETPOS, 0, (LPARAM)p->exIconScale); + FillOrderTree(hwndDlg, GetDlgItem(hwndDlg, IDC_EXTRAORDER), p->exIconOrder, p->dwExtraImageMask); + } + return 0; + + case WM_USER + 200: + p = (DISPLAYPROFILE *)lParam; + if (p) { + SaveOrderTree(hwndDlg, GetDlgItem(hwndDlg, IDC_EXTRAORDER), p); + + p->exIconScale = SendDlgItemMessage(hwndDlg, IDC_EXICONSCALESPIN, UDM_GETPOS, 0, 0); + p->exIconScale = (p->exIconScale < 8 || p->exIconScale > 20) ? 16 : p->exIconScale; + + p->dwFlags |= ((IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSICONS) ? CLUI_FRAME_STATUSICONS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SHOWVISIBILITY) ? CLUI_SHOWVISI : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SHOWMETA) ? CLUI_USEMETAICONS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_OVERLAYICONS) ? CLUI_FRAME_OVERLAYICONS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_XSTATUSASSTATUS) ? CLUI_FRAME_USEXSTATUSASSTATUS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_SELECTIVEICONS) ? CLUI_FRAME_SELECTIVEICONS : 0)); + + p->bDimIdle = IsDlgButtonChecked(hwndDlg, IDC_IDLE) ? 1 : 0; + p->bCenterStatusIcons = IsDlgButtonChecked(hwndDlg, IDC_STATUSICONSCENTERED) ? 1 : 0; + } + return 0; + + case WM_NOTIFY: + if (((LPNMHDR) lParam)->idFrom == IDC_EXTRAORDER) { + switch (((LPNMHDR)lParam)->code) { + case TVN_BEGINDRAGA: + case TVN_BEGINDRAGW: + SetCapture(hwndDlg); + dragging=1; + hDragItem=((LPNMTREEVIEWA)lParam)->itemNew.hItem; + TreeView_SelectItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hDragItem); + break; + case NM_CLICK: + { + TVHITTESTINFO hti; + hti.pt.x=(short)LOWORD(GetMessagePos()); + hti.pt.y=(short)HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR)lParam)->hwndFrom,&hti.pt); + if (TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom,&hti)) + if (hti.flags&TVHT_ONITEMICON) + { + TVITEMA tvi; + tvi.mask=TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvi.hItem=hti.hItem; + TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom,&tvi); + tvi.iImage=tvi.iSelectedImage=!tvi.iImage; + ((ORDERTREEDATA *)tvi.lParam)->Visible=tvi.iImage; + TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom,&tvi); + SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0); + } + } + } + break; + } + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + return TRUE; + } + break; + + case WM_MOUSEMOVE: + if (dragging) { + TVHITTESTINFO hti; + hti.pt.x = (short)LOWORD(lParam); + hti.pt.y = (short)HIWORD(lParam); + ClientToScreen(hwndDlg, &hti.pt); + ScreenToClient(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &hti.pt); + TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER), &hti); + if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT)) { + HTREEITEM it = hti.hItem; + hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg, IDC_EXTRAORDER)) / 2; + TreeView_HitTest(GetDlgItem(hwndDlg, IDC_EXTRAORDER), &hti); + //TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hti.hItem,1); + if (!(hti.flags & TVHT_ABOVE)) + TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_EXTRAORDER), hti.hItem, 1); + else + TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_EXTRAORDER), it, 0); + } + else { + if (hti.flags & TVHT_ABOVE) SendDlgItemMessage(hwndDlg,IDC_EXTRAORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); + if (hti.flags & TVHT_BELOW) SendDlgItemMessage(hwndDlg, IDC_EXTRAORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); + TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_EXTRAORDER), NULL, 0); + } + } + break; + + case WM_LBUTTONUP: + if (dragging) { + TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),NULL,0); + dragging=0; + ReleaseCapture(); + + TVHITTESTINFO hti; + TVITEM tvi; + hti.pt.x=(short)LOWORD(lParam); + hti.pt.y=(short)HIWORD(lParam); + ClientToScreen(hwndDlg,&hti.pt); + ScreenToClient(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti.pt); + hti.pt.y-=TreeView_GetItemHeight(GetDlgItem(hwndDlg,IDC_EXTRAORDER))/2; + TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti); + if (hDragItem==hti.hItem) break; + if (hti.flags&TVHT_ABOVE) hti.hItem=TVI_FIRST; + tvi.mask=TVIF_HANDLE|TVIF_PARAM; + tvi.hItem=hDragItem; + TreeView_GetItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvi); + if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT)||(hti.hItem==TVI_FIRST)) { + TVINSERTSTRUCT tvis; + TCHAR name[128]; + tvis.item.mask=TVIF_HANDLE|TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + tvis.item.stateMask=0xFFFFFFFF; + tvis.item.pszText=name; + tvis.item.cchTextMax=sizeof(name); + tvis.item.hItem=hDragItem; + tvis.item.iImage=tvis.item.iSelectedImage=((ORDERTREEDATA *)tvi.lParam)->Visible; + TreeView_GetItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvis.item); + TreeView_DeleteItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hDragItem); + tvis.hParent=NULL; + tvis.hInsertAfter=hti.hItem; + TreeView_SelectItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),TreeView_InsertItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvis)); + SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0); + } + } + break; + } + return FALSE; +} + +static HWND hwndList; +static DISPLAYPROFILE dsp_current; + +static INT_PTR CALLBACK DlgProcDspProfiles(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int iInit = TRUE; + static HWND hwndTab; + static int iTabCount; + + DISPLAYPROFILE *p; + TCITEM tci; + + switch(msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwnd); + { + hwndList = GetDlgItem(hwnd, IDC_PROFILELIST); + + HWND hwndBtn = GetDlgItem(hwnd, IDC_DSP_ADD); + CustomizeButton(hwndBtn, false,true, false); + SendMessage(hwndBtn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ADDCONTACT), IMAGE_ICON, 16, 16, LR_SHARED)); + SetWindowText(hwndBtn, TranslateT("Add New...")); + + hwndBtn = GetDlgItem(hwnd, IDC_DSP_DELETE); + CustomizeButton(hwndBtn, false,true, false); + SendMessage(hwndBtn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_DELETE), IMAGE_ICON, 16, 16, LR_SHARED)); + SetWindowText(hwndBtn, TranslateT("Delete")); + + hwndBtn = GetDlgItem(hwnd, IDC_DSP_RENAME); + CustomizeButton(hwndBtn, false,true, false); + SendMessage(hwndBtn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_RENAME), IMAGE_ICON, 16, 16, LR_SHARED)); + SetWindowText(hwndBtn, TranslateT("Rename...")); + + hwndBtn = GetDlgItem(hwnd, IDC_DSP_APPLY); + CustomizeButton(hwndBtn, false,true, false); + SendMessage(hwndBtn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_OPTIONS), IMAGE_ICON, 16, 16, LR_SHARED)); + SetWindowText(hwndBtn, TranslateT("Apply this profile")); + + RECT rcClient; + GetClientRect(hwnd, &rcClient); + + hwndTab = GetDlgItem(hwnd, IDC_OPTIONSTAB); + iInit = TRUE; + + TCITEM tci; + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_DSPITEMS), hwnd, DlgProcDspItems); + tci.pszText = TranslateT("Contacts"); + TabCtrl_InsertItem(hwndTab, 0, &tci); + + int oPage = cfg::getByte("CLUI", "opage_d", 0); + MoveWindow((HWND)tci.lParam,64,25,rcClient.right-128,rcClient.bottom-67,1); + ShowWindow((HWND)tci.lParam, oPage == 0 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_DSPGROUPS), hwnd, DlgProcDspGroups); + tci.pszText = TranslateT("Groups and layout"); + TabCtrl_InsertItem(hwndTab, 1, &tci); + MoveWindow((HWND)tci.lParam,64,25,rcClient.right-128,rcClient.bottom-67,1); + ShowWindow((HWND)tci.lParam, oPage == 1 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_XICONS), hwnd, DlgProcXIcons); + tci.pszText = TranslateT("Icons"); + TabCtrl_InsertItem(hwndTab, 2, &tci); + MoveWindow((HWND)tci.lParam,64,25,rcClient.right-128,rcClient.bottom-67,1); + ShowWindow((HWND)tci.lParam, oPage == 2 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_DSPADVANCED), hwnd, DlgProcDspAdvanced); + tci.pszText = TranslateT("Advanced"); + TabCtrl_InsertItem(hwndTab, 3, &tci); + MoveWindow((HWND)tci.lParam,64,25,rcClient.right-128,rcClient.bottom-67,1); + ShowWindow((HWND)tci.lParam, oPage == 3 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB), oPage); + + DISPLAYPROFILE dsp_default; + DSP_LoadFromDefaults(&dsp_default); + CopyMemory(&dsp_current, &dsp_default, sizeof(DISPLAYPROFILE)); + + iTabCount = TabCtrl_GetItemCount(hwndTab); + + SendMessage(hwnd, WM_USER + 100, 0, (LPARAM)&dsp_default); + SendMessage(hwndList, LB_INSERTSTRING, 0, (LPARAM)TranslateT("")); + + hwndList = GetDlgItem(hwnd, IDC_CLASSLIST); + SendMessage(hwndList, LB_INSERTSTRING, 0, (LPARAM)TranslateT("Default")); + SendMessage(hwndList, LB_INSERTSTRING, 1, (LPARAM)TranslateT("Offline contact")); + SendMessage(hwndList, LB_INSERTSTRING, 2, (LPARAM)TranslateT("Selected contact")); + SendMessage(hwndList, LB_INSERTSTRING, 3, (LPARAM)TranslateT("Hottracked contact")); + + iInit = FALSE; + return FALSE; + } + + /* + * distribute a WM_USER message to all child windows so they can update their pages from the + * display profile structure + * LPARAM = DISPLAYPROFILE * + */ + + case WM_USER + 100: + p = (DISPLAYPROFILE *)lParam; + if (p) { + int i; + TCITEM item = {0}; + item.mask = TCIF_PARAM; + + for (i = 0; i < iTabCount; i++) { + TabCtrl_GetItem(hwndTab, i, &item); + if (item.lParam && IsWindow((HWND)item.lParam)) + SendMessage((HWND)item.lParam, WM_USER + 100, 0, (LPARAM)p); + } + } + return 0; + + /* + * collect the settings from the pages into a DISPLAYPROFILE struct + */ + case WM_USER + 200: + p = (DISPLAYPROFILE *)lParam; + if (p) { + TCITEM item = {0}; + item.mask = TCIF_PARAM; + + for (int i = 0; i < iTabCount; i++) { + TabCtrl_GetItem(hwndTab, i, &item); + if (item.lParam && IsWindow((HWND)item.lParam)) + SendMessage((HWND)item.lParam, WM_USER + 200, 0, (LPARAM)p); + } + return 0; + } + + case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0); + if (!iInit) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + { + DISPLAYPROFILE p; + ZeroMemory(&p, sizeof(DISPLAYPROFILE)); + SendMessage(hwnd, WM_USER + 200, 0, (LPARAM)&p); + DSP_Apply(&p); + } + break; + } + break; + + case IDC_OPTIONSTAB: + switch (((LPNMHDR)lParam)->code) { + case TCN_SELCHANGING: + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_HIDE); + break; + + case TCN_SELCHANGE: + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_SHOW); + cfg::writeByte("CLUI", "opage_d", (BYTE)TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB))); + break; + } + break; + } + break; + } + return FALSE; +} + +static INT_PTR CALLBACK TabOptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TCITEM tci; + static int iInit = TRUE; + + switch(msg) { + case WM_INITDIALOG: + { + RECT rcClient; + int oPage = cfg::getByte("CLUI", "opage_m", 0); + + GetClientRect(hwnd, &rcClient); + iInit = TRUE; + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_CLIST), hwnd, DlgProcGenOpts); + tci.pszText = TranslateT("General"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 0, &tci); + MoveWindow((HWND)tci.lParam,5,25,rcClient.right-9,rcClient.bottom-30,1); + ShowWindow((HWND)tci.lParam, oPage == 0 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_CLC), hwnd, DlgProcClcMainOpts); + tci.pszText = TranslateT("List layout"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 1, &tci); + MoveWindow((HWND)tci.lParam,5,25,rcClient.right-9,rcClient.bottom-30,1); + ShowWindow((HWND)tci.lParam, oPage == 1 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_CLUI), hwnd, DlgProcCluiOpts); + tci.pszText = TranslateT("Window"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 2, &tci); + MoveWindow((HWND)tci.lParam,5,25,rcClient.right-9,rcClient.bottom-30,1); + ShowWindow((HWND)tci.lParam, oPage == 2 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_CLCBKG), hwnd, DlgProcClcBkgOpts); + tci.pszText = TranslateT("Background"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 3, &tci); + MoveWindow((HWND)tci.lParam,5,25,rcClient.right-9,rcClient.bottom-30,1); + ShowWindow((HWND)tci.lParam, oPage == 3 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_SBAR), hwnd, DlgProcSBarOpts); + tci.pszText = TranslateT("Status Bar"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 4, &tci); + MoveWindow((HWND)tci.lParam,5,25,rcClient.right-9,rcClient.bottom-30,1); + ShowWindow((HWND)tci.lParam, oPage == 4 ? SW_SHOW : SW_HIDE); + if (IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB), oPage); + iInit = FALSE; + } + return FALSE; + + case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0); + if (!iInit) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + tci.mask = TCIF_PARAM; + int count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_OPTIONSTAB)); + for (int i=0; i < count; i++) { + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),i,&tci); + SendMessage((HWND)tci.lParam,WM_NOTIFY,0,lParam); + } + break; + } + break; + + case IDC_OPTIONSTAB: + switch (((LPNMHDR)lParam)->code) { + case TCN_SELCHANGING: + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_HIDE); + break; + + case TCN_SELCHANGE: + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_SHOW); + cfg::writeByte("CLUI", "opage_m", (BYTE)TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB))); + break; + } + break; + } + break; + } + return FALSE; +} + +int ClcOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = g_hInst; + odp.pszGroup = LPGEN("Contact List"); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_DSPPROFILES); + odp.pszTitle = LPGEN("Contact rows"); + odp.pfnDlgProc = DlgProcDspProfiles; + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FLOATING); + odp.pszTitle = LPGEN("Floating contacts"); + odp.pfnDlgProc = DlgProcFloatingContacts; + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT); + odp.pszGroup = LPGEN("Skins"); + odp.pszTitle = LPGEN("Contact list"); + odp.flags = ODPF_BOLDGROUPS; + odp.pfnDlgProc = OptionsDlgProc; + Options_AddPage(wParam, &odp); + + odp.position = -1000000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONSDIALOG); + odp.pszGroup = NULL; + odp.pszTitle = LPGEN("Contact List"); + odp.pfnDlgProc = TabOptionsDlgProc; + odp.flags = ODPF_BOLDGROUPS; + odp.nIDBottomSimpleControl = 0; + Options_AddPage(wParam, &odp); + return 0; +} + +static int opt_clc_main_changed = 0; + +static INT_PTR CALLBACK DlgProcClcMainOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + opt_clc_main_changed = 0; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + { + int i; + DWORD exStyle = cfg::getDword("CLC", "ExStyle", pcli->pfnGetDefaultExStyle()); + UDACCEL accel[2] = { + {0,10}, {2,50} + }; + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETRANGE, 0, MAKELONG(999, 0)); + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETACCEL, sizeof(accel) / sizeof(accel[0]), (LPARAM) &accel); + SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CLC", "ScrollTime", CLCDEFAULT_SCROLLTIME), 0)); + + for (i = 0; i < sizeof(checkBoxToStyleEx) / sizeof(checkBoxToStyleEx[0]); i++) + CheckDlgButton(hwndDlg, checkBoxToStyleEx[i].id, (exStyle & checkBoxToStyleEx[i].flag) ^ (checkBoxToStyleEx[i].flag * checkBoxToStyleEx[i].not_t) ? BST_CHECKED : BST_UNCHECKED); + } + CheckDlgButton(hwndDlg, IDC_FULLROWSELECT, (cfg::dat.dwFlags & CLUI_FULLROWSELECT) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_DBLCLKAVATARS, cfg::dat.bDblClkAvatars); + CheckDlgButton(hwndDlg, IDC_GREYOUT, cfg::getDword("CLC", "GreyoutFlags", CLCDEFAULT_GREYOUTFLAGS) ? BST_CHECKED : BST_UNCHECKED); + Utils::enableDlgControl(hwndDlg, IDC_SMOOTHTIME, IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING)); + Utils::enableDlgControl(hwndDlg, IDC_GREYOUTOPTS, IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)); + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), greyoutValues, sizeof(greyoutValues) / sizeof(greyoutValues[0]), cfg::getDword("CLC", "FullGreyoutFlags", CLCDEFAULT_FULLGREYOUTFLAGS)); + CheckDlgButton(hwndDlg, IDC_NOSCROLLBAR, cfg::getByte("CLC", "NoVScrollBar", 0) ? BST_CHECKED : BST_UNCHECKED); + + return TRUE; + case WM_VSCROLL: + opt_clc_main_changed = 1; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_NOTNOSMOOTHSCROLLING) + Utils::enableDlgControl(hwndDlg, IDC_SMOOTHTIME, IsDlgButtonChecked(hwndDlg, IDC_NOTNOSMOOTHSCROLLING)); + if (LOWORD(wParam) == IDC_GREYOUT) + Utils::enableDlgControl(hwndDlg, IDC_GREYOUTOPTS, IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + opt_clc_main_changed = 1; + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_GREYOUTOPTS: + if (((LPNMHDR) lParam)->code == NM_CLICK) { + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(GetMessagePos()); + hti.pt.y = (short) HIWORD(GetMessagePos()); + ScreenToClient(((LPNMHDR) lParam)->hwndFrom, &hti.pt); + if (TreeView_HitTest(((LPNMHDR) lParam)->hwndFrom, &hti)) + if (hti.flags & TVHT_ONITEMSTATEICON) { + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hti.hItem; + TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1; + TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + opt_clc_main_changed = 1; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + int i; + DWORD exStyle = cfg::getDword("CLC", "ExStyle", CLCDEFAULT_EXSTYLE); + + if (!opt_clc_main_changed) + return TRUE; + + for (i = 0; i < sizeof(checkBoxToStyleEx) / sizeof(checkBoxToStyleEx[0]); i++) + exStyle &= ~(checkBoxToStyleEx[i].flag); + + for (i = 0; i < sizeof(checkBoxToStyleEx) / sizeof(checkBoxToStyleEx[0]); i++) { + if ((IsDlgButtonChecked(hwndDlg, checkBoxToStyleEx[i].id) == 0) == checkBoxToStyleEx[i].not_t) + exStyle |= checkBoxToStyleEx[i].flag; + } + cfg::writeDword("CLC", "ExStyle", exStyle); + } { + DWORD fullGreyoutFlags = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS)); + cfg::writeDword("CLC", "FullGreyoutFlags", fullGreyoutFlags); + if (IsDlgButtonChecked(hwndDlg, IDC_GREYOUT)) + cfg::writeDword("CLC", "GreyoutFlags", fullGreyoutFlags); + else + cfg::writeDword("CLC", "GreyoutFlags", 0); + } + cfg::writeWord("CLC", "ScrollTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_SMOOTHTIMESPIN, UDM_GETPOS, 0, 0)); + cfg::writeByte("CLC", "NoVScrollBar", (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_NOSCROLLBAR) ? 1 : 0)); + cfg::dat.dwFlags = IsDlgButtonChecked(hwndDlg, IDC_FULLROWSELECT) ? cfg::dat.dwFlags | CLUI_FULLROWSELECT : cfg::dat.dwFlags & ~CLUI_FULLROWSELECT; + cfg::dat.bDblClkAvatars = IsDlgButtonChecked(hwndDlg, IDC_DBLCLKAVATARS) ? TRUE : FALSE; + cfg::writeByte("CLC", "dblclkav", (BYTE)cfg::dat.bDblClkAvatars); + cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags); + + pcli->pfnClcOptionsChanged(); + CoolSB_SetupScrollBar(); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + opt_clc_main_changed = 0; + return TRUE; + } + break; + } + break; + case WM_DESTROY: + ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_GREYOUTOPTS), TVSIL_STATE)); + break; + } + return FALSE; +} + +static int opt_clc_bkg_changed = 0; + +static INT_PTR CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + opt_clc_bkg_changed = 0; + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_BITMAP, cfg::getByte("CLC", "UseBitmap", CLCDEFAULT_USEBITMAP) ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndDlg, WM_USER + 10, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, CLCDEFAULT_BKCOLOUR); + SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0, cfg::getDword("CLC", "BkColour", CLCDEFAULT_BKCOLOUR)); + CheckDlgButton(hwndDlg, IDC_WINCOLOUR, cfg::getByte("CLC", "UseWinColours", 0)); + CheckDlgButton(hwndDlg, IDC_SKINMODE, cfg::dat.bWallpaperMode); + SendMessage(hwndDlg, WM_USER + 11, 0, 0); + { + DBVARIANT dbv; + + if (!cfg::getTString(NULL, "CLC", "BkBitmap", &dbv)) { + TCHAR szPath[MAX_PATH]; + if (CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM) dbv.ptszVal, (LPARAM)szPath)) + SetDlgItemText(hwndDlg, IDC_FILENAME, szPath); + + DBFreeVariant(&dbv); + } + + WORD bmpUse = cfg::getWord("CLC", "BkBmpUse", CLCDEFAULT_BKBMPUSE); + CheckDlgButton(hwndDlg, IDC_STRETCHH, bmpUse & CLB_STRETCHH ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_STRETCHV, bmpUse & CLB_STRETCHV ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TILEH, bmpUse & CLBF_TILEH ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TILEV, bmpUse & CLBF_TILEV ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SCROLL, bmpUse & CLBF_SCROLL ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROPORTIONAL, bmpUse & CLBF_PROPORTIONAL ? BST_CHECKED : BST_UNCHECKED); + + HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND, DWORD); + MySHAutoComplete = (HRESULT(STDAPICALLTYPE *)(HWND, DWORD))GetProcAddress(GetModuleHandleA("shlwapi"), "SHAutoComplete"); + if (MySHAutoComplete) + MySHAutoComplete(GetDlgItem(hwndDlg, IDC_FILENAME), 1); + } + return TRUE; + + case WM_USER+10: + Utils::enableDlgControl(hwndDlg, IDC_FILENAME, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + Utils::enableDlgControl(hwndDlg, IDC_BROWSE, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + Utils::enableDlgControl(hwndDlg, IDC_STRETCHH, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + Utils::enableDlgControl(hwndDlg, IDC_STRETCHV, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + Utils::enableDlgControl(hwndDlg, IDC_TILEH, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + Utils::enableDlgControl(hwndDlg, IDC_TILEV, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + Utils::enableDlgControl(hwndDlg, IDC_SCROLL, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + Utils::enableDlgControl(hwndDlg, IDC_PROPORTIONAL, IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); + break; + case WM_USER+11: + { + BOOL b = IsDlgButtonChecked(hwndDlg, IDC_WINCOLOUR); + Utils::enableDlgControl(hwndDlg, IDC_BKGCOLOUR, !b); + break; + } + case WM_COMMAND: + if (LOWORD(wParam) == IDC_BROWSE) { + char str[MAX_PATH]; + OPENFILENAMEA ofn = { 0 }; + char filter[512]; + + GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, sizeof(str)); + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwndDlg; + ofn.hInstance = NULL; + CallService(MS_UTILS_GETBITMAPFILTERSTRINGS, sizeof(filter), (LPARAM) filter); + ofn.lpstrFilter = filter; + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.nMaxFile = sizeof(str); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = "bmp"; + if (!GetOpenFileNameA(&ofn)) + break; + SetDlgItemTextA(hwndDlg, IDC_FILENAME, str); + } + else if (LOWORD(wParam) == IDC_FILENAME && HIWORD(wParam) != EN_CHANGE) + break; + + if (LOWORD(wParam) == IDC_BITMAP) + SendMessage(hwndDlg, WM_USER + 10, 0, 0); + if (LOWORD(wParam) == IDC_WINCOLOUR) + SendMessage(hwndDlg, WM_USER + 11, 0, 0); + if (LOWORD(wParam) == IDC_FILENAME && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + opt_clc_bkg_changed = 1; + break; + + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + if (!opt_clc_bkg_changed) + return TRUE; + + cfg::writeByte("CLC", "UseBitmap", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_BITMAP)); { + COLORREF col; + col = SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0); + if (col == CLCDEFAULT_BKCOLOUR) + DBDeleteContactSetting(NULL, "CLC", "BkColour"); + else + cfg::writeDword("CLC", "BkColour", col); + cfg::writeByte("CLC", "UseWinColours", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_WINCOLOUR)); + } { + char str[MAX_PATH], strrel[MAX_PATH]; + + GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, sizeof(str)); + if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM) str, (LPARAM) strrel)) + cfg::writeString(NULL, "CLC", "BkBitmap", strrel); + else + cfg::writeString(NULL, "CLC", "BkBitmap", str); + } { + WORD flags = 0; + if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHH)) + flags |= CLB_STRETCHH; + if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHV)) + flags |= CLB_STRETCHV; + if (IsDlgButtonChecked(hwndDlg, IDC_TILEH)) + flags |= CLBF_TILEH; + if (IsDlgButtonChecked(hwndDlg, IDC_TILEV)) + flags |= CLBF_TILEV; + if (IsDlgButtonChecked(hwndDlg, IDC_SCROLL)) + flags |= CLBF_SCROLL; + if (IsDlgButtonChecked(hwndDlg, IDC_PROPORTIONAL)) + flags |= CLBF_PROPORTIONAL; + cfg::writeWord("CLC", "BkBmpUse", flags); + cfg::dat.bWallpaperMode = IsDlgButtonChecked(hwndDlg, IDC_SKINMODE) ? 1 : 0; + cfg::writeByte("CLUI", "UseBkSkin", (BYTE)cfg::dat.bWallpaperMode); + } + pcli->pfnClcOptionsChanged(); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + opt_clc_bkg_changed = 0; + return TRUE; + } + break; + } + break; + } + return FALSE; +} diff --git a/plugins/Clist_nicer/src/clcpaint.cpp b/plugins/Clist_nicer/src/clcpaint.cpp new file mode 100644 index 0000000000..c9b11d07b3 --- /dev/null +++ b/plugins/Clist_nicer/src/clcpaint.cpp @@ -0,0 +1,1674 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clcpaint.cpp 12909 2010-10-06 14:53:00Z silvercircle $ + * + */ + +#include "commonheaders.h" + +extern struct avatarCache *g_avatarCache; +extern int g_curAvatar; + +extern ImageItem *g_glyphItem; + +extern int hClcProtoCount; +extern ORDERTREEDATA OrderTreeData[]; + +extern HIMAGELIST hCListImages; +static BYTE divide3[765] = {255}; +extern char *im_clients[]; +extern HICON im_clienthIcons[]; +extern HICON overlayicons[]; + +extern TCHAR *statusNames[]; + +extern LONG g_cxsmIcon, g_cysmIcon; +extern StatusItems_t *StatusItems; + +int g_hottrack, g_center, g_ignoreselforgroups, g_selectiveIcon, g_exIconSpacing, g_hottrack_done; +HWND g_focusWnd; +BYTE selBlend; +BYTE saved_alpha; +int my_status; + +BOOL g_inCLCpaint = FALSE; +int g_list_avatars = 0; + +HFONT __fastcall ChangeToFont(HDC hdc, struct ClcData *dat, int id, int *fontHeight) +{ + HFONT hOldFont = 0; + /* + hOldFont = SelectObject(hdc, dat->fontInfo[id].hFont); + SetTextColor(hdc, dat->fontInfo[id].colour); + if (fontHeight) + *fontHeight = dat->fontInfo[id].fontHeight; + */ + hOldFont = reinterpret_cast(SelectObject(hdc, cfg::clcdat->fontInfo[id].hFont)); + SetTextColor(hdc, cfg::clcdat->fontInfo[id].colour); + if (fontHeight) + *fontHeight = cfg::clcdat->fontInfo[id].fontHeight; + + dat->currentFontID = id; + return hOldFont; +} + +static void __inline SetHotTrackColour(HDC hdc, struct ClcData *dat) +{ + if (dat->gammaCorrection) { + COLORREF oldCol, newCol; + int oldLum, newLum; + + oldCol = GetTextColor(hdc); + oldLum = (GetRValue(oldCol) * 30 + GetGValue(oldCol) * 59 + GetBValue(oldCol) * 11) / 100; + newLum = (GetRValue(dat->hotTextColour) * 30 + GetGValue(dat->hotTextColour) * 59 + GetBValue(dat->hotTextColour) * 11) / 100; + if (newLum == 0) { + SetTextColor(hdc, dat->hotTextColour); + return; + } + if (newLum >= oldLum + 20) { + oldLum += 20; + newCol = RGB(GetRValue(dat->hotTextColour) * oldLum / newLum, GetGValue(dat->hotTextColour) * oldLum / newLum, GetBValue(dat->hotTextColour) * oldLum / newLum); + } else if (newLum <= oldLum) { + int r, g, b; + r = GetRValue(dat->hotTextColour) * oldLum / newLum; + g = GetGValue(dat->hotTextColour) * oldLum / newLum; + b = GetBValue(dat->hotTextColour) * oldLum / newLum; + if (r > 255) { + g +=(r-255)*3 / 7; + b +=(r-255)*3 / 7; + r = 255; + } + if (g > 255) { + r +=(g-255)*59 / 41; + if (r > 255) + r = 255; + b +=(g-255)*59 / 41; + g = 255; + } + if (b > 255) { + r +=(b-255)*11 / 89; + if (r > 255) + r = 255; + g +=(b-255)*11 / 89; + if (g > 255) + g = 255; + b = 255; + } + newCol = RGB(r, g, b); + } else + newCol = dat->hotTextColour; + SetTextColor(hdc, newCol); + } else + SetTextColor(hdc, dat->hotTextColour); +} + +int __fastcall GetStatusOnlineness(int status) +{ + if(status >= ID_STATUS_CONNECTING && status < ID_STATUS_OFFLINE) + return 120; + + switch (status) { + case ID_STATUS_FREECHAT: + return 110; + case ID_STATUS_ONLINE: + return 100; + case ID_STATUS_OCCUPIED: + return 60; + case ID_STATUS_ONTHEPHONE: + return 50; + case ID_STATUS_DND: + return 40; + case ID_STATUS_AWAY: + return 30; + case ID_STATUS_OUTTOLUNCH: + return 20; + case ID_STATUS_NA: + return 10; + case ID_STATUS_INVISIBLE: + return 5; + } + return 0; +} + +static int __fastcall GetGeneralisedStatus(void) +{ + int i, status, thisStatus, statusOnlineness, thisOnlineness; + + status = ID_STATUS_OFFLINE; + statusOnlineness = 0; + + for (i = 0; i < pcli->hClcProtoCount; i++) { + thisStatus = pcli->clcProto[i].dwStatus; + if (thisStatus == ID_STATUS_INVISIBLE) + return ID_STATUS_INVISIBLE; + thisOnlineness = GetStatusOnlineness(thisStatus); + if (thisOnlineness > statusOnlineness) { + status = thisStatus; + statusOnlineness = thisOnlineness; + } + } + return status; +} + +static int __fastcall GetRealStatus(struct ClcContact *contact, int status) +{ + int i; + char *szProto = contact->proto; + if (!szProto) + return status; + for (i = 0; i < pcli->hClcProtoCount; i++) { + if (!lstrcmpA(pcli->clcProto[i].szProto, szProto)) { + return pcli->clcProto[i].dwStatus; + } + } + return status; +} + +int GetBasicFontID(struct ClcContact * contact) +{ + switch (contact->type) + { + case CLCIT_GROUP: + return FONTID_GROUPS; + break; + case CLCIT_INFO: + if(contact->flags & CLCIIF_GROUPFONT) + return FONTID_GROUPS; + else + return FONTID_CONTACTS; + break; + case CLCIT_DIVIDER: + return FONTID_DIVIDERS; + break; + case CLCIT_CONTACT: + if (contact->flags & CONTACTF_NOTONLIST) + return FONTID_NOTONLIST; + else if ((contact->flags&CONTACTF_INVISTO && GetRealStatus(contact, ID_STATUS_OFFLINE) != ID_STATUS_INVISIBLE) + || (contact->flags&CONTACTF_VISTO && GetRealStatus(contact, ID_STATUS_OFFLINE) == ID_STATUS_INVISIBLE)) + return contact->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS; + else + return contact->flags & CONTACTF_ONLINE ? FONTID_CONTACTS : FONTID_OFFLINE; + break; + default: + return FONTID_CONTACTS; + } +} + +void PaintNotifyArea(HDC hDC, RECT *rc) +{ + struct ClcData *dat = (struct ClcData *) GetWindowLongPtr(pcli->hwndContactTree, 0); + int iCount; + static int ev_lastIcon = 0; + + rc->left += 26; // button + iCount = GetMenuItemCount(cfg::dat.hMenuNotify); + if (cfg::dat.hUpdateContact != 0) { + TCHAR *szName = pcli->pfnGetContactDisplayName(cfg::dat.hUpdateContact, 0); + int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) cfg::dat.hUpdateContact, 0); + + ImageList_DrawEx(hCListImages, iIcon, hDC, rc->left, (rc->bottom + rc->top - g_cysmIcon) / 2, g_cxsmIcon, g_cysmIcon, CLR_NONE, CLR_NONE, ILD_NORMAL); + rc->left += 18; + DrawText(hDC, szName, -1, rc, DT_VCENTER | DT_SINGLELINE); + ImageList_DrawEx(hCListImages, (int)cfg::dat.hIconNotify, hDC, 4, (rc->bottom + rc->top - 16) / 2, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL); + ev_lastIcon = cfg::dat.hIconNotify; + } else if (iCount > 0) { + MENUITEMINFO mii = {0}; + struct NotifyMenuItemExData *nmi; + TCHAR *szName; + int iIcon; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA; + GetMenuItemInfo(cfg::dat.hMenuNotify, iCount - 1, TRUE, &mii); + nmi = (struct NotifyMenuItemExData *) mii.dwItemData; + szName = pcli->pfnGetContactDisplayName(nmi->hContact, 0); + iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0); + ImageList_DrawEx(hCListImages, iIcon, hDC, rc->left, (rc->bottom + rc->top - g_cysmIcon) / 2, g_cxsmIcon, g_cysmIcon, CLR_NONE, CLR_NONE, ILD_NORMAL); + rc->left += 18; + ImageList_DrawEx(hCListImages, nmi->iIcon, hDC, 4, (rc->bottom + rc->top) / 2 - 8, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL); + DrawText(hDC, szName, -1, rc, DT_VCENTER | DT_SINGLELINE); + ev_lastIcon = (int)nmi->hIcon; + } else { + HICON hIcon = reinterpret_cast(LoadImage(g_hInst, MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 16, 16, 0)); + DrawText(hDC, cfg::dat.szNoEvents, lstrlen(cfg::dat.szNoEvents), rc, DT_VCENTER | DT_SINGLELINE); + DrawIconEx(hDC, 4, (rc->bottom + rc->top - 16) / 2, hIcon, 16, 16, 0, 0, DI_NORMAL | DI_COMPAT); + DestroyIcon(hIcon); + } +} + +static BLENDFUNCTION bf = {0, 0, AC_SRC_OVER, 0}; +static BOOL avatar_done = FALSE; +HDC g_HDC; +static BOOL g_RTL; +HDC hdcTempAV; +HBITMAP hbmTempAV, hbmTempOldAV; + +HDC hdcAV; + +LONG g_maxAV_X = 200, g_maxAV_Y = 200; + +static int __fastcall DrawAvatar(HDC hdcMem, RECT *rc, struct ClcContact *contact, int y, struct ClcData *dat, WORD cstatus, int rowHeight, DWORD dwFlags) +{ + float dScale = 0.; + float newHeight, newWidth; + HDC hdcAvatar = hdcAV; + //HBITMAP hbmMem; + DWORD topoffset = 0, leftoffset = 0; + LONG bmWidth, bmHeight; + float dAspect; + HBITMAP hbm, hbmOldAV; + HRGN rgn = 0; + int avatar_size = cfg::dat.avatarSize; + DWORD av_saved_left; + StatusItems_t *item = contact->wStatus == ID_STATUS_OFFLINE ? &StatusItems[ID_EXTBKAVATARFRAMEOFFLINE - ID_STATUS_OFFLINE] : &StatusItems[ID_EXTBKAVATARFRAME - ID_STATUS_OFFLINE]; + int skinMarginX, skinMarginY; + BOOL fOverlay = (cfg::dat.dwFlags & CLUI_FRAME_OVERLAYICONS); + + contact->avatarLeft = -1; + if (!cfg::dat.bAvatarServiceAvail || dat->bisEmbedded) + return 0; + + if(contact->ace != NULL && contact->ace->cbSize == sizeof(struct avatarCacheEntry)) { + if(contact->ace->dwFlags & AVS_HIDEONCLIST) { + if (cfg::dat.dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) + return avatar_size + 2; + else + return 0; + } + bmHeight = contact->ace->bmHeight; + bmWidth = contact->ace->bmWidth; + if(bmWidth != 0) + dAspect = (float)bmHeight / (float)bmWidth; + else + dAspect = 1.0; + hbm = contact->ace->hbmPic; + contact->ace->t_lastAccess = cfg::dat.t_now; + } + else if (cfg::dat.dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) + return avatar_size + 2; + else + return 0; + + if(bmHeight == 0 || bmWidth == 0 || hbm == 0) + return 0; + + g_maxAV_X = max(bmWidth, g_maxAV_X); + g_maxAV_Y = max(bmHeight, g_maxAV_Y); + + if(dAspect >= 1.0) { // height > width + skinMarginY = item->IGNORED ? 0 : (item->MARGIN_TOP + item->MARGIN_BOTTOM); + skinMarginX = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + + dScale = (float)(avatar_size - 2) / (float)bmHeight; + newHeight = (float)(avatar_size - skinMarginY - 2); + newWidth = (float)(bmWidth * dScale) - skinMarginX; + } + else { + skinMarginY = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + skinMarginX = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + + newWidth = (float)(avatar_size - 2) - skinMarginX; + dScale = (float)(avatar_size - 2) / (float)bmWidth; + newHeight = (float)(bmHeight * dScale) - skinMarginY; + } + topoffset = rowHeight > (int)newHeight ? (rowHeight - (int)newHeight) / 2 : 0; + if (!item->IGNORED) { + //topoffset += item->MARGIN_TOP; + leftoffset = item->MARGIN_LEFT; + } + // create the region for the avatar border - use the same region for clipping, if needed. + + av_saved_left = rc->left; + if(cfg::dat.bCenterStatusIcons && newWidth < newHeight) + rc->left += (((avatar_size - 2) - ((int)newWidth + skinMarginX)) / 2); + + if(cfg::dat.dwFlags & CLUI_FRAME_ROUNDAVATAR) + rgn = CreateRoundRectRgn(leftoffset + rc->left, y + topoffset, leftoffset + rc->left + (int)newWidth + 1, y + topoffset + (int)newHeight + 1, 2 * cfg::dat.avatarRadius, 2 * cfg::dat.avatarRadius); + else + rgn = CreateRectRgn(leftoffset + rc->left, y + topoffset, leftoffset + rc->left + (int)newWidth, y + topoffset + (int)newHeight); + + hbmOldAV = reinterpret_cast(SelectObject(hdcAV, hbm)); + bf.SourceConstantAlpha = 255; //(g_CluiData.dwFlags & CLUI_FRAME_TRANSPARENTAVATAR && (UCHAR)saved_alpha > 20) ? (UCHAR)saved_alpha : 255; + bf.AlphaFormat = contact->ace->dwFlags & AVS_PREMULTIPLIED ? AC_SRC_ALPHA : 0; + + /* + if(dat->showIdle && contact->flags & CONTACTF_IDLE) + bf.SourceConstantAlpha -= (bf.SourceConstantAlpha > 100 ? 50 : 0); + */ + + SelectClipRgn(hdcMem, rgn); + SetStretchBltMode(hdcMem, HALFTONE); + if(bf.SourceConstantAlpha == 255 && bf.AlphaFormat == 0) { + StretchBlt(hdcMem, leftoffset + rc->left - (g_RTL ? 1 : 0), y + topoffset, (int)newWidth, (int)newHeight, hdcAvatar, 0, 0, bmWidth, bmHeight, SRCCOPY); + } + else { + /* + * get around SUCKY AlphaBlend() rescaling quality... + */ + SetStretchBltMode(hdcTempAV, HALFTONE); + StretchBlt(hdcTempAV, 0, 0, bmWidth, bmHeight, hdcMem, leftoffset + rc->left, y + topoffset, (int)newWidth, (int)newHeight, SRCCOPY); + API::pfnAlphaBlend(hdcTempAV, 0, 0, bmWidth, bmHeight, hdcAvatar, 0, 0, bmWidth, bmHeight, bf); + StretchBlt(hdcMem, leftoffset + rc->left - (g_RTL ? 1 : 0), y + topoffset, (int)newWidth, (int)newHeight, hdcTempAV, 0, 0, bmWidth, bmHeight, SRCCOPY); + } + SelectObject(hdcAV, hbmOldAV); + + if(cfg::dat.dwFlags & CLUI_FRAME_AVATARBORDER) { + if(g_RTL) + OffsetRgn(rgn, -1 , 0); + FrameRgn(hdcMem, rgn, cfg::dat.hBrushAvatarBorder, 1, 1); + } + + if(fOverlay) + fOverlay = (dwFlags & ECF_HIDEOVERLAY) ? 0 : 1; + else + fOverlay = (dwFlags & ECF_FORCEOVERLAY) ? 1 : 0; + + if(fOverlay && cstatus && (int)newHeight >= g_cysmIcon) + DrawIconEx(hdcMem, rc->left + (int)newWidth - 15, y + topoffset + (int)newHeight - 15, overlayicons[cstatus - ID_STATUS_OFFLINE], g_cxsmIcon, g_cysmIcon, 0, 0, DI_NORMAL | DI_COMPAT); + + SelectClipRgn(hdcMem, NULL); + DeleteObject(rgn); + + if (!item->IGNORED) { + RECT rcFrame; + BOOL inClCPaint_save = g_inCLCpaint; + HDC hdcTemp = 0, hdcSaved = 0; + HBITMAP hbmOld, hbmTemp; + + g_inCLCpaint = FALSE; + rcFrame.left = rc->left; + rcFrame.top = y + topoffset - item->MARGIN_TOP; + rcFrame.right = rcFrame.left + (int)newWidth + item->MARGIN_RIGHT + item->MARGIN_LEFT; + rcFrame.bottom = rcFrame.top + (int)newHeight + item->MARGIN_BOTTOM + item->MARGIN_TOP; + if(g_RTL) { + RECT rcTemp; + + OffsetRect(&rcFrame, 1, 0); + rcTemp.left = rcTemp.top = 0; + rcTemp.right = rcFrame.right - rcFrame.left; + rcTemp.bottom = rcFrame.bottom - rcFrame.top; + hdcTemp = CreateCompatibleDC(g_HDC); + hbmTemp = CreateCompatibleBitmap(g_HDC, rcTemp.right, rcTemp.bottom); + hbmOld = reinterpret_cast(SelectObject(hdcTemp, hbmTemp)); + API::pfnSetLayout(hdcTemp, LAYOUT_RTL); + BitBlt(hdcTemp, 0, 0, rcTemp.right, rcTemp.bottom, + hdcMem, rcFrame.left, rcFrame.top, SRCCOPY); + API::pfnSetLayout(hdcTemp, 0); + DrawAlpha(hdcTemp, &rcTemp, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, item->GRADIENT, + item->CORNER, item->BORDERSTYLE, item->imageItem); + BitBlt(hdcMem, rcFrame.left, rcFrame.top, rcFrame.right - rcFrame.left, rcFrame.bottom - rcFrame.top, + hdcTemp, 0, 0, SRCCOPY); + SelectObject(hdcTemp, hbmOld); + DeleteObject(hbmTemp); + DeleteDC(hdcTemp); + } else + DrawAlpha(hdcMem, &rcFrame, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, item->GRADIENT, + item->CORNER, item->BORDERSTYLE, item->imageItem); + g_inCLCpaint = inClCPaint_save; + } + contact->avatarLeft = rc->left; + avatar_done = TRUE; + rc->left = av_saved_left; + return avatar_size + 2; + +} + +static BOOL pi_avatar = FALSE; +static RECT rcContent; +static BOOL pi_selectiveIcon; + +static BOOL av_left, av_right, av_rightwithnick; +static BOOL mirror_rtl, mirror_always, mirror_rtltext; + +BYTE savedCORNER = -1; +int g_padding_y = 0; + +void __inline PaintItem(HDC hdcMem, struct ClcGroup *group, struct ClcContact *contact, int indent, int y, struct ClcData *dat, int index, HWND hwnd, DWORD style, RECT *clRect, BOOL *bFirstNGdrawn, int groupCountsFontTopShift, int rowHeight) +{ + RECT rc; + int iImage = -1; + int selected; + SIZE textSize, countsSize, spaceSize; + int width, checkboxWidth; + char *szCounts; + int fontHeight; + BOOL twoRows = FALSE; + WORD cstatus; + DWORD leftOffset = 0, rightOffset = 0; + int iconXSpace = dat->iconXSpace; + //BOOL xStatusValid = 0; + HFONT hPreviousFont = 0; + BYTE type; + BYTE flags; + COLORREF oldGroupColor = -1; + DWORD qLeft = 0; + int leftX = dat->leftMargin + indent * dat->groupIndent; + int bg_indent_r = 0; + int bg_indent_l = 0; + int rightIcons = 0; + DWORD dt_nickflags = 0, dt_2ndrowflags = 0; + struct TExtraCache *cEntry = NULL; + DWORD dwFlags = cfg::dat.dwFlags; + int scanIndex; + BOOL check_selected, av_local_wanted, fLocalTime; + + rowHeight -= cfg::dat.bRowSpacing; + savedCORNER = -1; + + if(group == NULL || contact == NULL) + return; + + g_RTL = FALSE; + scanIndex = group->scanIndex; + av_local_wanted = (g_list_avatars > 0); + + type = contact->type; + flags = contact->flags; + selected = index == dat->selection && (dat->showSelAlways || dat->exStyle &CLS_EX_SHOWSELALWAYS || g_focusWnd == hwnd) && type != CLCIT_DIVIDER; + avatar_done = FALSE; + if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) + cEntry = &cfg::eCache[contact->extraCacheEntry]; + else + cEntry = cfg::eCache; + + + if(dat->bisEmbedded) + goto set_bg_l; + + if(type == CLCIT_CONTACT && (cEntry->dwCFlags & ECF_RTLNICK || mirror_always)) { + if(API::pfnSetLayout != NULL && (mirror_rtl || mirror_always)) { + g_RTL = TRUE; + bg_indent_r = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else if(mirror_rtltext) { + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + dt_nickflags = DT_RTLREADING | DT_RIGHT; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else if(type == CLCIT_GROUP && API::pfnSetLayout != NULL) { + if ((contact->isRtl && cfg::dat.bGroupAlign == CLC_GROUPALIGN_AUTO) || cfg::dat.bGroupAlign == CLC_GROUPALIGN_RIGHT) { + g_RTL = TRUE; + bg_indent_r = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + +set_bg_l: + + + g_hottrack = dat->exStyle & CLS_EX_TRACKSELECT && type == CLCIT_CONTACT && dat->iHotTrack == index; + if (g_hottrack == selected) + g_hottrack = 0; + + saved_alpha = 0; + + //setup + if (type == CLCIT_GROUP) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else if (type == CLCIT_INFO) { + if (flags & CLCIIF_GROUPFONT) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + } else if (type == CLCIT_DIVIDER) { + ChangeToFont(hdcMem, dat, FONTID_DIVIDERS, &fontHeight); + GetTextExtentPoint32(hdcMem, contact->szText, lstrlen(contact->szText), &textSize); + } + else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) + ChangeToFont(hdcMem, dat, FONTID_NOTONLIST, &fontHeight); + else if (type == CLCIT_CONTACT && ((flags & CONTACTF_INVISTO && GetRealStatus(contact, my_status) != ID_STATUS_INVISIBLE) || (flags & CONTACTF_VISTO && GetRealStatus(contact, my_status) == ID_STATUS_INVISIBLE))) { + // the contact is in the always visible list and the proto is invisible + // the contact is in the always invisible and the proto is in any other mode + ChangeToFont(hdcMem, dat, flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS, &fontHeight); + } else if (type == CLCIT_CONTACT && !(flags & CONTACTF_ONLINE)) + ChangeToFont(hdcMem, dat, FONTID_OFFLINE, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + + if (type == CLCIT_GROUP) { + GetTextExtentPoint32(hdcMem, contact->szText, lstrlen(contact->szText), &textSize); + width = textSize.cx; + szCounts = pcli->pfnGetGroupCountsText(dat, contact); + if (szCounts[0]) { + GetTextExtentPoint32(hdcMem, _T(" "), 1, &spaceSize); + ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &fontHeight); + GetTextExtentPoint32A(hdcMem, szCounts, lstrlenA(szCounts), &countsSize); + width += spaceSize.cx + countsSize.cx; + } + } + if ((style & CLS_CHECKBOXES && type == CLCIT_CONTACT) || (style & CLS_GROUPCHECKBOXES && type == CLCIT_GROUP) || (type == CLCIT_INFO && flags & CLCIIF_CHECKBOX)) + checkboxWidth = dat->checkboxSize + 2; + else + checkboxWidth = 0; + + rc.left = 0; + cstatus = contact->wStatus; + + /***** BACKGROUND DRAWING *****/ + // contacts + + g_hottrack_done = 0; + check_selected = (!selected || selBlend); + + if(dat->bisEmbedded) { + rc.left = bg_indent_l; + rc.top = y; + rc.right = clRect->right - bg_indent_r; + rc.bottom = y + rowHeight; + if (selected) { + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); + SetTextColor(hdcMem, dat->selTextColour); + } + else { + FillRect(hdcMem, &rc, cfg::dat.hBrushCLCBk); + if(g_hottrack) + SetHotTrackColour(hdcMem,dat); + } + goto bgskipped; + } + + if (type == CLCIT_CONTACT || type == CLCIT_DIVIDER) { + StatusItems_t *sitem, *sfirstitem, *ssingleitem, *slastitem, *slastitem_NG, + *sfirstitem_NG, *ssingleitem_NG, *sevencontact_pos, *soddcontact_pos, *pp_item; + + if (cstatus >= ID_STATUS_OFFLINE && cstatus <= ID_STATUS_OUTTOLUNCH) { + BYTE perstatus_ignored; + + if ((flags & CONTACTF_IDLE) && !StatusItems[ID_EXTBKIDLE - ID_STATUS_OFFLINE].IGNORED) + sitem = &StatusItems[ID_EXTBKIDLE - ID_STATUS_OFFLINE]; + else + sitem = &StatusItems[cstatus - ID_STATUS_OFFLINE]; + + if (!dat->bisEmbedded) { + pp_item = cEntry->status_item ? cEntry->status_item : cEntry->proto_status_item; + + if (!(perstatus_ignored = sitem->IGNORED) && !(flags & CONTACTF_NOTONLIST)) + SetTextColor(hdcMem, sitem->TEXTCOLOR); + + if(cfg::dat.bUsePerProto && pp_item && !pp_item->IGNORED) { + sitem = pp_item; + if ((perstatus_ignored || cfg::dat.bOverridePerStatusColors) && sitem->TEXTCOLOR != -1) + SetTextColor(hdcMem, sitem->TEXTCOLOR); + } + } + else if (!sitem->IGNORED) + SetTextColor(hdcMem, sitem->TEXTCOLOR); + + sevencontact_pos = &StatusItems[ID_EXTBKEVEN_CNTCTPOS - ID_STATUS_OFFLINE]; + soddcontact_pos = &StatusItems[ID_EXTBKODD_CNTCTPOS - ID_STATUS_OFFLINE]; + sfirstitem = &StatusItems[ID_EXTBKFIRSTITEM - ID_STATUS_OFFLINE]; + ssingleitem = &StatusItems[ID_EXTBKSINGLEITEM - ID_STATUS_OFFLINE]; + slastitem = &StatusItems[ID_EXTBKLASTITEM - ID_STATUS_OFFLINE]; + + sfirstitem_NG = &StatusItems[ID_EXTBKFIRSTITEM_NG - ID_STATUS_OFFLINE]; + ssingleitem_NG = &StatusItems[ID_EXTBKSINGLEITEM_NG - ID_STATUS_OFFLINE]; + slastitem_NG = &StatusItems[ID_EXTBKLASTITEM_NG - ID_STATUS_OFFLINE]; + + rc.left = sitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + sitem->MARGIN_TOP; + rc.right = clRect->right - sitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sitem->MARGIN_BOTTOM; + + // check for special cases (first item, single item, last item) + // this will only change the shape for this status. Color will be blended over with ALPHA value + if (!ssingleitem->IGNORED && scanIndex == 0 && group->cl.count == 1 && group->parent != NULL) { + rc.left = ssingleitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + ssingleitem->MARGIN_TOP; + rc.right = clRect->right - ssingleitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - ssingleitem->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, ssingleitem->CORNER, ssingleitem->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, ssingleitem->CORNER, ssingleitem->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, ssingleitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = ssingleitem->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, ssingleitem->COLOR, ssingleitem->ALPHA, ssingleitem->COLOR2, ssingleitem->COLOR2_TRANSPARENT, ssingleitem->GRADIENT, ssingleitem->CORNER, ssingleitem->BORDERSTYLE, ssingleitem->imageItem); + } else if (scanIndex == 0 && group->cl.count > 1 && !sfirstitem->IGNORED && group->parent != NULL) { + rc.left = sfirstitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + sfirstitem->MARGIN_TOP; + rc.right = clRect->right - sfirstitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sfirstitem->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, sfirstitem->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, sfirstitem->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, sfirstitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = sfirstitem->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, sfirstitem->COLOR, sfirstitem->ALPHA, sfirstitem->COLOR2, sfirstitem->COLOR2_TRANSPARENT, sfirstitem->GRADIENT, sfirstitem->CORNER, sfirstitem->BORDERSTYLE, sfirstitem->imageItem); + } else if (scanIndex == group->cl.count - 1 && !slastitem->IGNORED && group->parent != NULL) { + // last item of group + rc.left = slastitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + slastitem->MARGIN_TOP; + rc.right = clRect->right - slastitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - slastitem->MARGIN_BOTTOM; + rc.bottom = y + rowHeight - slastitem->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, slastitem->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, slastitem->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, slastitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = slastitem->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, slastitem->COLOR, slastitem->ALPHA, slastitem->COLOR2, slastitem->COLOR2_TRANSPARENT, slastitem->GRADIENT, slastitem->CORNER, slastitem->BORDERSTYLE, slastitem->imageItem); + } else + // - - - Non-grouped items - - - + if (type != CLCIT_GROUP // not a group + && group->parent == NULL // not grouped + && !sfirstitem_NG->IGNORED && scanIndex != group->cl.count - 1 && !(*bFirstNGdrawn)) { + // first NON-grouped + *bFirstNGdrawn = TRUE; + rc.left = sfirstitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + sfirstitem_NG->MARGIN_TOP; + rc.right = clRect->right - sfirstitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sfirstitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, sfirstitem_NG->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, sfirstitem_NG->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, sfirstitem_NG->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = sfirstitem_NG->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, sfirstitem_NG->COLOR, sfirstitem_NG->ALPHA, sfirstitem_NG->COLOR2, sfirstitem_NG->COLOR2_TRANSPARENT, sfirstitem_NG->GRADIENT, sfirstitem_NG->CORNER, sfirstitem->BORDERSTYLE, sfirstitem->imageItem); + } else if (type != CLCIT_GROUP // not a group + && group->parent == NULL && !slastitem_NG->IGNORED && scanIndex == group->cl.count - 1 && (*bFirstNGdrawn)) { + // last item of list (NON-group) + // last NON-grouped + rc.left = slastitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + slastitem_NG->MARGIN_TOP; + rc.right = clRect->right - slastitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - slastitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, slastitem_NG->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, slastitem_NG->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, slastitem_NG->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = slastitem_NG->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, slastitem_NG->COLOR, slastitem_NG->ALPHA, slastitem_NG->COLOR2, slastitem_NG->COLOR2_TRANSPARENT, slastitem_NG->GRADIENT, slastitem_NG->CORNER, slastitem->BORDERSTYLE, slastitem->imageItem); + } else if (type != CLCIT_GROUP // not a group + && group->parent == NULL && !slastitem_NG->IGNORED && !(*bFirstNGdrawn)) { + // single item of NON-group + // single NON-grouped + rc.left = ssingleitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + ssingleitem_NG->MARGIN_TOP; + rc.right = clRect->right - ssingleitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - ssingleitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, ssingleitem_NG->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, ssingleitem_NG->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, ssingleitem_NG->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = ssingleitem_NG->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, ssingleitem_NG->COLOR, ssingleitem_NG->ALPHA, ssingleitem_NG->COLOR2, ssingleitem_NG->COLOR2_TRANSPARENT, ssingleitem_NG->GRADIENT, ssingleitem_NG->CORNER, ssingleitem->BORDERSTYLE, ssingleitem->imageItem); + } else if (!sitem->IGNORED) { + // draw default grouped + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, sitem->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, sitem->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, sitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = sitem->CORNER; + } + } + } + if (type == CLCIT_GROUP) { + StatusItems_t *sempty = &StatusItems[ID_EXTBKEMPTYGROUPS - ID_STATUS_OFFLINE]; + StatusItems_t *sexpanded = &StatusItems[ID_EXTBKEXPANDEDGROUP - ID_STATUS_OFFLINE]; + StatusItems_t *scollapsed = &StatusItems[ID_EXTBKCOLLAPSEDDGROUP - ID_STATUS_OFFLINE]; + + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + if (contact->group->cl.count == 0) { + if (!sempty->IGNORED) { + rc.left = sempty->MARGIN_LEFT + bg_indent_l; + rc.top = y + sempty->MARGIN_TOP; + rc.right = clRect->right - sempty->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sempty->MARGIN_BOTTOM; + DrawAlpha(hdcMem, &rc, sempty->COLOR, sempty->ALPHA, sempty->COLOR2, sempty->COLOR2_TRANSPARENT, sempty->GRADIENT, sempty->CORNER, sempty->BORDERSTYLE, sempty->imageItem); + savedCORNER = sempty->CORNER; + oldGroupColor = SetTextColor(hdcMem, sempty->TEXTCOLOR); + } + } else if (contact->group->expanded) { + if (!sexpanded->IGNORED) { + rc.left = sexpanded->MARGIN_LEFT + bg_indent_l; + rc.top = y + sexpanded->MARGIN_TOP; + rc.right = clRect->right - sexpanded->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - (char) sexpanded->MARGIN_BOTTOM; + DrawAlpha(hdcMem, &rc, sexpanded->COLOR, sexpanded->ALPHA, sexpanded->COLOR2, sexpanded->COLOR2_TRANSPARENT, sexpanded->GRADIENT, sexpanded->CORNER, sexpanded->BORDERSTYLE, sexpanded->imageItem); + savedCORNER = sexpanded->CORNER; + oldGroupColor = SetTextColor(hdcMem, sexpanded->TEXTCOLOR); + } + } else { + if (!scollapsed->IGNORED) { + // collapsed but not empty + rc.left = scollapsed->MARGIN_LEFT + bg_indent_l; + rc.top = y + scollapsed->MARGIN_TOP; + rc.right = clRect->right - scollapsed->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - scollapsed->MARGIN_BOTTOM; + DrawAlpha(hdcMem, &rc, scollapsed->COLOR, scollapsed->ALPHA, scollapsed->COLOR2, scollapsed->COLOR2_TRANSPARENT, scollapsed->GRADIENT, scollapsed->CORNER, scollapsed->BORDERSTYLE, scollapsed->imageItem); + savedCORNER = scollapsed->CORNER; + oldGroupColor = SetTextColor(hdcMem, scollapsed->TEXTCOLOR); + } + } + } + if (selected) { + StatusItems_t *sselected = &StatusItems[ID_EXTBKSELECTION - ID_STATUS_OFFLINE]; + + if (!g_ignoreselforgroups || type != CLCIT_GROUP) { + if (!sselected->IGNORED) { + rc.left = sselected->MARGIN_LEFT + bg_indent_l; + rc.top = y + sselected->MARGIN_TOP; + rc.right = clRect->right - sselected->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sselected->MARGIN_BOTTOM; + if (cfg::getByte("CLCExt", "EXBK_EqualSelection", 0) == 1 && savedCORNER != -1) { + DrawAlpha(hdcMem, &rc, sselected->COLOR, sselected->ALPHA, sselected->COLOR2, sselected->COLOR2_TRANSPARENT, sselected->GRADIENT, savedCORNER, sselected->BORDERSTYLE, sselected->imageItem); + } else { + DrawAlpha(hdcMem, &rc, sselected->COLOR, sselected->ALPHA, sselected->COLOR2, sselected->COLOR2_TRANSPARENT, sselected->GRADIENT, sselected->CORNER, sselected->BORDERSTYLE, sselected->imageItem); + } + SetTextColor(hdcMem, sselected->TEXTCOLOR); + } + else { + rc.left = bg_indent_l; + rc.top = y; + rc.right = clRect->right - bg_indent_r; + rc.bottom = y + rowHeight; + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); + SetTextColor(hdcMem, dat->selTextColour); + } + } + } + else if (g_hottrack) { + StatusItems_t *ht = &StatusItems[ID_EXTBKHOTTRACK - ID_STATUS_OFFLINE]; + + SetHotTrackColour(hdcMem,dat); + if(ht->IGNORED == 0) + SetTextColor(hdcMem, ht->TEXTCOLOR); + if (!g_hottrack_done) { + if (ht->IGNORED == 0) { + DrawAlpha(hdcMem, &rc, ht->COLOR, ht->ALPHA, ht->COLOR2, ht->COLOR2_TRANSPARENT, ht->GRADIENT, + ht->CORNER, ht->BORDERSTYLE, ht->imageItem); + } + } + } + + if(g_RTL) + API::pfnSetLayout(hdcMem, LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED); +bgskipped: + + rcContent.top = y + g_padding_y; + rcContent.bottom = y + rowHeight - (2 * g_padding_y); + rcContent.left = leftX; + rcContent.right = clRect->right - dat->rightMargin; + twoRows = ((dat->fontInfo[FONTID_STATUS].fontHeight + fontHeight <= rowHeight + 1) && (contact->bSecondLine != MULTIROW_NEVER)) && !dat->bisEmbedded; + + pi_avatar = !dat->bisEmbedded && type == CLCIT_CONTACT && (contact->cFlags & ECF_AVATAR) && contact->ace != 0 && !(contact->ace->dwFlags & AVS_HIDEONCLIST); + + //checkboxes + if (checkboxWidth) { + RECT rc; + HANDLE hTheme = 0; + + if (IS_THEMED) + hTheme = API::pfnOpenThemeData(hwnd, L"BUTTON"); + + rc.left = leftX; + rc.right = rc.left + dat->checkboxSize; + rc.top = y + ((rowHeight - dat->checkboxSize) >> 1); + rc.bottom = rc.top + dat->checkboxSize; + if (hTheme) { + API::pfnDrawThemeBackground(hTheme, hdcMem, BP_CHECKBOX, flags & CONTACTF_CHECKED ? (g_hottrack ? CBS_CHECKEDHOT : CBS_CHECKEDNORMAL) : (g_hottrack ? CBS_UNCHECKEDHOT : CBS_UNCHECKEDNORMAL), &rc, &rc); + API::pfnCloseThemeData(hTheme); + hTheme = 0; + } + else + DrawFrameControl(hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT | (flags & CONTACTF_CHECKED ? DFCS_CHECKED : 0) | (g_hottrack ? DFCS_HOT : 0)); + rcContent.left += checkboxWidth; + leftX += checkboxWidth; + } + + if (type == CLCIT_GROUP) + iImage = (contact->group->expanded) ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; + else if (type == CLCIT_CONTACT) + iImage = contact->iImage; + + + if(pi_avatar && (av_left || av_right)) { + RECT rc; + + rc.left = rcContent.left; + rc.right = clRect->right; + rc.top = y; + rc.bottom = rc.top + rowHeight; + + if(av_left) { + leftOffset += DrawAvatar(hdcMem, &rc, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + rcContent.left += leftOffset; + leftX += leftOffset; + } + else { + rc.left = (rcContent.right - cfg::dat.avatarSize) + 1; + rightOffset += DrawAvatar(hdcMem, &rc, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + rcContent.right -= (rightOffset); + } + } + else if(type == CLCIT_CONTACT && !dat->bisEmbedded && !g_selectiveIcon && (dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) && av_local_wanted && (av_left || av_right)) { + if(av_right) + rcContent.right -= (cfg::dat.avatarSize + 2); + if(av_left) + rcContent.left += (cfg::dat.avatarSize + 2); + } + //icon + + // skip icon for groups if the option is enabled... + + if(type == CLCIT_GROUP && dwFlags & CLUI_FRAME_NOGROUPICON) { + iconXSpace = 0; + goto text; + } + if (iImage != -1) { + // this doesnt use CLS_CONTACTLIST since the colour prolly wont match anyway + COLORREF colourFg = dat->selBkColour; + //int clientId = contact->clientId; + int mode = ILD_NORMAL; + pi_selectiveIcon = g_selectiveIcon && (type == CLCIT_CONTACT); + + if ((dwFlags & CLUI_FRAME_STATUSICONS && !pi_selectiveIcon) || type != CLCIT_CONTACT || (pi_selectiveIcon && !avatar_done)) { + HIMAGELIST hImgList = 0; + if (!dat->bisEmbedded && type == CLCIT_CONTACT && cEntry && (dwFlags & CLUI_FRAME_USEXSTATUSASSTATUS) && cEntry->iExtraImage[EXTRA_ICON_ADV1] != 0xff) { + if(pcli->pfnIconFromStatusMode(contact->proto, contact->wStatus, contact->hContact) == iImage) { + hImgList = dat->himlExtraColumns; + iImage = cEntry->iExtraImage[EXTRA_ICON_ADV1]; + } + else hImgList = hCListImages; + } + else + hImgList = hCListImages; + + if (g_hottrack) { + colourFg = dat->hotTextColour; + } else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; + mode = ILD_BLEND50; + } + if (type == CLCIT_CONTACT && dat->showIdle && (flags & CONTACTF_IDLE) && contact->wStatus != ID_STATUS_OFFLINE) + mode = ILD_SELECTED; + + if(pi_selectiveIcon && av_right) { + ImageList_DrawEx(hImgList, iImage, hdcMem, rcContent.right - 18, (twoRows && type == CLCIT_CONTACT && !cfg::dat.bCenterStatusIcons) ? y + 2 : y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + rcContent.right -= 18; + } + else { + LONG offset = 0; + BOOL centered = FALSE; + offset += (type != CLCIT_CONTACT || avatar_done || !(av_local_wanted) ? 20 : dwFlags & CLUI_FRAME_ALWAYSALIGNNICK && av_left && g_selectiveIcon ? cfg::dat.avatarSize + 2 : 20); + centered = (cfg::dat.bCenterStatusIcons && offset == cfg::dat.avatarSize + 2); + ImageList_DrawEx(hImgList, iImage, hdcMem, centered ? rcContent.left + offset / 2 - 10 : rcContent.left, (twoRows && type == CLCIT_CONTACT && !cfg::dat.bCenterStatusIcons) ? y + 2 : y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + rcContent.left += offset; + } + } + else + iconXSpace = 0; + if (type == CLCIT_CONTACT && !dat->bisEmbedded) { + BYTE bApparentModeDontCare = !((flags & CONTACTF_VISTO) ^ (flags & CONTACTF_INVISTO)); + contact->extraIconRightBegin = 0; + if(cEntry && (contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry && cEntry->iExtraValid)) { + int i, iIndex, id; + DWORD dwOldMask = cEntry->dwXMask; + if(dwFlags & CLUI_FRAME_USEXSTATUSASSTATUS) + cEntry->dwXMask &= ~EIMG_SHOW_ADV1; + + for (i = EXICON_COUNT - 1; i >= 0; i--) { + iIndex = cfg::dat.exIconOrder[i] - 1; + if(iIndex >= 0 && iIndex < EXICON_COUNT) { + id = OrderTreeData[iIndex].ID; + if(cEntry->iExtraImage[id] != 0xff && ((1 << id) & cEntry->dwXMask)) { + if(contact->extraIconRightBegin == 0 && i != (EXICON_COUNT - 1)) + contact->extraIconRightBegin = rcContent.right; + ImageList_DrawEx(dat->himlExtraColumns, cEntry->iExtraImage[id], hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + rcContent.right -= g_exIconSpacing; + rightIcons++; + } + } + } + cEntry->dwXMask = dwOldMask; + } + if (!bApparentModeDontCare && (dwFlags & CLUI_SHOWVISI) && contact->proto) { + BOOL fVisi; + + if(dwFlags & CLUI_SHOWVISI) + fVisi = cEntry->dwDFlags & ECF_HIDEVISIBILITY ? 0 : 1; + else + fVisi = cEntry->dwDFlags & ECF_FORCEVISIBILITY ? 1 : 0; + + if(fVisi) { + if(cEntry->isChatRoom) + DrawIconEx(hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + cfg::dat.hIconChatactive, cfg::dat.exIconScale, cfg::dat.exIconScale, 0, 0, DI_NORMAL | DI_COMPAT); + else + DrawIconEx(hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + flags & CONTACTF_VISTO ? cfg::dat.hIconVisible : cfg::dat.hIconInvisible, cfg::dat.exIconScale, cfg::dat.exIconScale, 0, 0, DI_NORMAL | DI_COMPAT); + rcContent.right -= g_exIconSpacing; + rightIcons++; + } + } + } + } + //text +text: + if (type == CLCIT_DIVIDER) { + RECT rc; + rc.top = y + ((rowHeight) >> 1); rc.bottom = rc.top + 2; + rc.left = rcContent.left; + rc.right = rc.left - dat->rightMargin + ((clRect->right - rc.left - textSize.cx) >> 1) - 3; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + TextOut(hdcMem, rc.right + 3, y + ((rowHeight - fontHeight) >> 1), contact->szText, lstrlen(contact->szText)); + rc.left = rc.right + 6 + textSize.cx; + rc.right = clRect->right - dat->rightMargin; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } else if (type == CLCIT_GROUP) { + RECT rc; + int leftMargin = 0, countStart = 0, leftLineEnd, rightLineStart; + fontHeight = dat->fontInfo[FONTID_GROUPS].fontHeight; + rc.top = y + ((rowHeight - fontHeight) >> 1) + cfg::dat.group_padding; + rc.bottom = rc.top + textSize.cy; + if (szCounts[0]) { + int required, labelWidth, offset = 0; + int height = 0; + COLORREF clr = GetTextColor(hdcMem); + + ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &height); + if(oldGroupColor != -1) + SetTextColor(hdcMem, clr); + + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + iconXSpace; + rc.right = clRect->right - dat->rightMargin; + + if(indent == 0 && iconXSpace == 0) + rc.left += 2; + + required = textSize.cx + countsSize.cx + spaceSize.cx; + + if(required > rc.right - rc.left) + textSize.cx = (rc.right - rc.left) - countsSize.cx - spaceSize.cx; + + labelWidth = textSize.cx + countsSize.cx + spaceSize.cx; + if(g_center) + offset = ((rc.right - rc.left) - labelWidth) / 2; + + + TextOutA(hdcMem, rc.left + offset + textSize.cx + spaceSize.cx, rc.top + groupCountsFontTopShift, szCounts, lstrlenA(szCounts)); + rightLineStart = rc.left + offset + textSize.cx + spaceSize.cx + countsSize.cx + 2; + + if (selected && !g_ignoreselforgroups) + SetTextColor(hdcMem, dat->selTextColour); + else + SetTextColor(hdcMem, clr); + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &height); + SetTextColor(hdcMem, clr); + rc.left += offset; + rc.right = rc.left + textSize.cx; + leftLineEnd = rc.left - 2; + qLeft = rc.left; + DrawText(hdcMem, contact->szText, -1, &rc, DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS); + } else if (g_center && !szCounts[0]) { + int offset; + + rc.left = rcContent.left; + rc.right = clRect->right - dat->rightMargin; + if(textSize.cx >= rc.right - rc.left) + textSize.cx = rc.right - rc.left; + + offset = ((rc.right - rc.left) - textSize.cx) / 2; + rc.left += offset; + rc.right = rc.left + textSize.cx; + leftLineEnd = rc.left - 2; + rightLineStart = rc.right + 2; + DrawText(hdcMem, contact->szText, -1, &rc, DT_CENTER | DT_NOPREFIX | DT_SINGLELINE); + qLeft = rc.left; + } else { + qLeft = rcContent.left + (indent == 0 && iconXSpace == 0 ? 2 : 0);; + rc.left = qLeft; + rc.right = min(rc.left + textSize.cx, clRect->right - dat->rightMargin);; + DrawText(hdcMem, contact->szText, -1, &rc, DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS); + rightLineStart = qLeft + textSize.cx + 2; + } + + if (dat->exStyle & CLS_EX_LINEWITHGROUPS) { + if (!g_center) { + rc.top = y + ((rowHeight) >> 1); rc.bottom = rc.top + 2; + rc.left = rightLineStart; + rc.right = clRect->right - 1 - dat->extraColumnSpacing * dat->extraColumnsCount - dat->rightMargin; + if (rc.right - rc.left > 1) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + else { + rc.top = y + ((rowHeight) >> 1); rc.bottom = rc.top + 2; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + iconXSpace; + rc.right = leftLineEnd; + if (rc.right > rc.left) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + rc.right = clRect->right - dat->rightMargin; + rc.left = rightLineStart; + if (rc.right > rc.left) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + } + } else { + TCHAR *szText = contact->szText; + + rcContent.top = y + ((rowHeight - fontHeight) >> 1); + + // avatar + + if (!dat->bisEmbedded) { + if(av_local_wanted && !avatar_done && pi_avatar) { + if(av_rightwithnick) { + RECT rcAvatar = rcContent; + + rcAvatar.left = rcContent.right - (cfg::dat.avatarSize - 1); + DrawAvatar(hdcMem, &rcAvatar, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + rcContent.right -= (cfg::dat.avatarSize + 2); + } + else + rcContent.left += DrawAvatar(hdcMem, &rcContent, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + } + else if(dwFlags & CLUI_FRAME_ALWAYSALIGNNICK && !avatar_done && av_local_wanted) + rcContent.left += (dwFlags & (CLUI_FRAME_AVATARSLEFT | CLUI_FRAME_AVATARSRIGHT | CLUI_FRAME_AVATARSRIGHTWITHNICK) ? 0 : cfg::dat.avatarSize + 2); + } + + // nickname + if (!twoRows) { + if(dt_nickflags) + DrawText(hdcMem, szText, -1, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE | dt_nickflags); + else + DrawText(hdcMem, szText, -1, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + else { + int statusFontHeight; + DWORD dtFlags = DT_WORD_ELLIPSIS | DT_NOPREFIX | DT_NOCLIP | DT_SINGLELINE; + DWORD saved_right = rcContent.right; + BOOL verticalfit = FALSE; + + rcContent.top = y + cfg::dat.avatarPadding / 2; + + if(cfg::dat.bShowLocalTime) + fLocalTime = cEntry->dwDFlags & ECF_HIDELOCALTIME ? 0 : 1; + else + fLocalTime = cEntry->dwDFlags & ECF_FORCELOCALTIME ? 1 : 0; + + if (cEntry->hTimeZone && fLocalTime) { + int idOldFont; + DWORD now = cfg::dat.t_now; + SIZE szTime; + RECT rc = rcContent; + COLORREF oldColor; + int fHeight = 0; + + + TCHAR szResult[80]; + if (tmi.printDateTime(cEntry->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0)) + goto nodisplay; + + oldColor = GetTextColor(hdcMem); + idOldFont = dat->currentFontID; + ChangeToFont(hdcMem, dat, FONTID_TIMESTAMP, &fHeight); + GetTextExtentPoint32(hdcMem, szResult, lstrlen(szResult), &szTime); + verticalfit = (rowHeight - fHeight >= cfg::dat.exIconScale + 1); + + if(av_right) { + if(verticalfit) + rc.left = rcContent.right + (rightIcons * g_exIconSpacing) - szTime.cx - 2; + else + rc.left = rcContent.right - szTime.cx - 2; + } + else if(av_rightwithnick) { + if(verticalfit && rightIcons * g_exIconSpacing >= szTime.cx) + rc.left = clRect->right - dat->rightMargin - szTime.cx; + else if(verticalfit && !avatar_done) + rc.left = clRect->right - dat->rightMargin - szTime.cx; + else { + rc.left = rcContent.right - szTime.cx - 2; + rcContent.right = rc.left - 2; + } + } + else { + if(verticalfit) + rc.left = clRect->right - dat->rightMargin - szTime.cx; + else + rc.left = rcContent.right - szTime.cx - 2; + } + DrawText(hdcMem, szResult, -1, &rc, DT_NOPREFIX | DT_NOCLIP | DT_SINGLELINE); + ChangeToFont(hdcMem, dat, idOldFont, 0); + SetTextColor(hdcMem, oldColor); + + verticalfit = (rowHeight - fontHeight >= cfg::dat.exIconScale + 1); + if(verticalfit && av_right) + rcContent.right = min(clRect->right - cfg::dat.avatarSize - 2, rc.left - 2); + else if(verticalfit && !av_rightwithnick) + rcContent.right = min(clRect->right - dat->rightMargin, rc.left - 3); + } + else { +nodisplay: + verticalfit = (rowHeight - fontHeight >= cfg::dat.exIconScale + 1); + if(avatar_done) { + if(verticalfit && av_right) + rcContent.right = clRect->right - cfg::dat.avatarSize - 2; + else if(verticalfit && !av_rightwithnick) + rcContent.right = clRect->right - dat->rightMargin; + } + } + DrawText(hdcMem, szText, -1, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE | dt_nickflags); + + rcContent.right = saved_right; + rcContent.top += (fontHeight - 1); + hPreviousFont = ChangeToFont(hdcMem, dat, FONTID_STATUS, &statusFontHeight); + //if(selected) + // SetTextColor(hdcMem, dat->selTextColour); + rcContent.bottom = y + rowHeight; + + if(cstatus >= ID_STATUS_OFFLINE && cstatus <= ID_STATUS_OUTTOLUNCH) { + TCHAR *szText = NULL; + BYTE smsgValid = cEntry->bStatusMsgValid; + + if ((dwFlags & CLUI_FRAME_SHOWSTATUSMSG && smsgValid > STATUSMSG_XSTATUSID) || smsgValid == STATUSMSG_XSTATUSNAME) + szText = cEntry->statusMsg; + else + + szText = &statusNames[cstatus - ID_STATUS_OFFLINE][0]; + + if(cEntry->dwCFlags & ECF_RTLSTATUSMSG && cfg::dat.bUseDCMirroring == 3) + dt_2ndrowflags |= (DT_RTLREADING | DT_RIGHT); + + if(rightIcons == 0) { + if ((rcContent.bottom - rcContent.top) >= (2 * statusFontHeight)) { + dtFlags &= ~(DT_SINGLELINE | DT_BOTTOM | DT_NOCLIP); + dtFlags |= DT_WORDBREAK; + rcContent.bottom -= ((rcContent.bottom - rcContent.top) % statusFontHeight); + } + DrawText(hdcMem, szText, -1, &rcContent, dtFlags | dt_2ndrowflags); + } + else { + if ((rcContent.bottom - rcContent.top) < (2 * statusFontHeight) - 2) + DrawText(hdcMem, szText, -1, &rcContent, dtFlags | dt_2ndrowflags); + else { + DRAWTEXTPARAMS dtp = {0}; + LONG rightIconsTop = rcContent.bottom - g_exIconSpacing; + LONG old_right = rcContent.right; + ULONG textCounter = 0; + ULONG ulLen = lstrlen(szText); + LONG old_bottom = rcContent.bottom; + DWORD i_dtFlags = DT_WORDBREAK | DT_NOPREFIX | dt_2ndrowflags; + dtp.cbSize = sizeof(dtp); + rcContent.right = clRect->right - dat->rightMargin - rightOffset; + do { + if(rcContent.top + (statusFontHeight - 1) > rightIconsTop + 1) + rcContent.right = old_right; + dtp.uiLengthDrawn = 0; + rcContent.bottom = rcContent.top + statusFontHeight - 1; + if(rcContent.bottom + statusFontHeight >= old_bottom) + i_dtFlags |= DT_END_ELLIPSIS; + DrawTextEx(hdcMem, &szText[textCounter], -1, &rcContent, i_dtFlags, &dtp); + rcContent.top += statusFontHeight; + textCounter += dtp.uiLengthDrawn; + } while (textCounter <= ulLen && dtp.uiLengthDrawn && rcContent.top + statusFontHeight <= old_bottom); + } + } + } + } + } + if (selected) { + if (type != CLCIT_DIVIDER) { + TCHAR *szText = contact->szText; + RECT rc; + int qlen = lstrlen(dat->szQuickSearch); + if(hPreviousFont) + SelectObject(hdcMem, hPreviousFont); + SetTextColor(hdcMem, dat->quickSearchColour); + if(type == CLCIT_CONTACT) { + rc.left = rcContent.left; + rc.top = y + ((rowHeight - fontHeight) >> 1); + rc.right = clRect->right - rightOffset; + rc.right = rcContent.right; + rc.bottom = rc.top; + if(twoRows) + rc.top = y; + } + else { + rc.left = qLeft; + rc.top = y + ((rowHeight - fontHeight) >> 1); + rc.right = clRect->right - rightOffset; + rc.bottom = rc.top; + } + if (qlen) + DrawText(hdcMem, szText, qlen, &rc, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + } + //extra icons + for (iImage = 0; iImage< dat->extraColumnsCount; iImage++) { + COLORREF colourFg = dat->selBkColour; + int mode = ILD_NORMAL; + if (contact->iExtraImage[iImage] == 0xFF) + continue; + if (selected) + mode = ILD_SELECTED; + else if (g_hottrack) { + mode = ILD_FOCUS; colourFg = dat->hotTextColour; + } else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; mode = ILD_BLEND50; + } + ImageList_DrawEx(dat->himlExtraColumns, contact->iExtraImage[iImage], hdcMem, clRect->right - rightOffset - dat->extraColumnSpacing * (dat->extraColumnsCount - iImage), y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + } + if(g_RTL) + API::pfnSetLayout(hdcMem, 0); +} + +void SkinDrawBg(HWND hwnd, HDC hdc) +{ + RECT rcCl; + POINT ptTest = {0}; + + ClientToScreen(hwnd, &ptTest); + GetClientRect(hwnd, &rcCl); + + BitBlt(hdc, 0, 0, rcCl.right - rcCl.left, rcCl.bottom - rcCl.top, cfg::dat.hdcBg, ptTest.x - cfg::dat.ptW.x, ptTest.y - cfg::dat.ptW.y, SRCCOPY); +} + +void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint) +{ + HDC hdcMem; + RECT clRect; + int y,indent,index,fontHeight; + struct ClcGroup *group; + HBITMAP hBmpOsb, hOldBitmap; + HFONT hOldFont; + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + int grey = 0,groupCountsFontTopShift; + BOOL bFirstNGdrawn = FALSE; + int line_num = -1; + COLORREF tmpbkcolour = style & CLS_CONTACTLIST ? (dat->useWindowsColours ? GetSysColor(COLOR_3DFACE) : dat->bkColour) : dat->bkColour; + DWORD done, now = GetTickCount(); + selBlend = cfg::getByte("CLCExt", "EXBK_SelBlend", 1); + g_inCLCpaint = TRUE; + g_focusWnd = GetFocus(); + my_status = GetGeneralisedStatus(); + g_HDC = hdc; + + /* + * temporary DC for avatar drawing + */ + + g_padding_y = 0; + + hdcTempAV = CreateCompatibleDC(g_HDC); + hdcAV = CreateCompatibleDC(g_HDC); + hbmTempAV = CreateCompatibleBitmap(g_HDC, g_maxAV_X, g_maxAV_Y); + hbmTempOldAV = reinterpret_cast(SelectObject(hdcTempAV, hbmTempAV)); + + cfg::dat.t_now = time(NULL); + GetSystemTime(&cfg::dat.st); + SystemTimeToFileTime(&cfg::dat.st, &cfg::dat.ft); + + cfg::dat.bUseFastGradients = cfg::dat.bWantFastGradients && (API::pfnGradientFill != 0); + + av_left = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSLEFT); + av_right = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSRIGHT); + av_rightwithnick = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSRIGHTWITHNICK); + + mirror_rtl = (cfg::dat.bUseDCMirroring == 2); + mirror_always = (cfg::dat.bUseDCMirroring == 1); + mirror_rtltext = (cfg::dat.bUseDCMirroring == 3); + + g_center = cfg::getByte("CLCExt", "EXBK_CenterGroupnames", 0) && !dat->bisEmbedded; + g_ignoreselforgroups = cfg::getByte("CLC", "IgnoreSelforGroups", 0); + g_exIconSpacing = cfg::dat.exIconScale + 2; + + if (dat->greyoutFlags & pcli->pfnClcStatusToPf2(my_status) || style & WS_DISABLED) + grey = 1; + else if (GetFocus() != hwnd && dat->greyoutFlags & GREYF_UNFOCUS) + grey = 1; + GetClientRect(hwnd, &clRect); + if (rcPaint == NULL) + rcPaint = &clRect; + if (IsRectEmpty(rcPaint)) { + SelectObject(hdcTempAV, hbmTempOldAV); + DeleteObject(hbmTempAV); + DeleteDC(hdcTempAV); + + DeleteDC(hdcAV); + return; + } + y = -dat->yScroll; + hdcMem = CreateCompatibleDC(hdc); + hBmpOsb = CreateBitmap(clRect.right, clRect.bottom, 1, GetDeviceCaps(hdc, BITSPIXEL), NULL); + + hOldBitmap = reinterpret_cast(SelectObject(hdcMem, hBmpOsb)); + { + TEXTMETRIC tm; + hOldFont = reinterpret_cast(SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPS].hFont)); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift = tm.tmAscent; + SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift -= tm.tmAscent; + } + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + + SetBkMode(hdcMem, TRANSPARENT); { + HBRUSH hBrush, hoBrush; + + hBrush = CreateSolidBrush(tmpbkcolour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRect(hdcMem, rcPaint, hBrush); + + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + + if(1) { + if(cfg::dat.bWallpaperMode && !dat->bisEmbedded) { + SkinDrawBg(hwnd, hdcMem); + goto bgdone; + } + if (dat->hBmpBackground) { + BITMAP bmp; + HDC hdcBmp; + int x, y; + int bitx, bity; + int maxx, maxy; + int destw, desth; + // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98. + SetStretchBltMode(hdcMem, HALFTONE); + + GetObject(dat->hBmpBackground, sizeof(bmp), &bmp); + hdcBmp = CreateCompatibleDC(hdcMem); + SelectObject(hdcBmp, dat->hBmpBackground); + y = dat->backgroundBmpUse & CLBF_SCROLL ? -dat->yScroll : 0; + maxx = dat->backgroundBmpUse & CLBF_TILEH ? clRect.right : 1; + maxy = dat->backgroundBmpUse & CLBF_TILEV ? maxy = rcPaint->bottom : y + 1; + switch (dat->backgroundBmpUse & CLBM_TYPE) { + case CLB_STRETCH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + if (clRect.right * bmp.bmHeight < clRect.bottom * bmp.bmWidth) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } else { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } + } else { + destw = clRect.right; + desth = clRect.bottom; + } + break; + case CLB_STRETCHH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } else { + destw = clRect.right; + desth = bmp.bmHeight; + } + break; + case CLB_STRETCHV: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } else { + destw = bmp.bmWidth; + desth = clRect.bottom; + } + break; + default: + //clb_topleft + destw = bmp.bmWidth; + desth = bmp.bmHeight; + break; + } + + bitx = 0; + bity = 0; + + for (; y < maxy; y += desth) { + if (y< rcPaint->top - desth) + continue; + for (x = 0; x < maxx; x += destw) { + StretchBlt(hdcMem, x, y, destw, desth, cfg::dat.hdcPic, bitx, bity, bmp.bmWidth, bmp.bmHeight, SRCCOPY); + } + } + DeleteDC(hdcBmp); + } + } + } +bgdone: + group = &dat->list; + group->scanIndex = 0; + + if ( dat->row_heights == NULL ) + RowHeight::calcRowHeights(dat, hwnd); + + group = &dat->list; + group->scanIndex = 0; + + g_list_avatars = 0; + while(TRUE) + { + if (group->scanIndex==group->cl.count) + { + group=group->parent; + if(group==NULL) break; // Finished list + group->scanIndex++; + continue; + } + + if(group->cl.items[group->scanIndex]->cFlags & ECF_AVATAR) + g_list_avatars++; + + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) { + group=group->cl.items[group->scanIndex]->group; + group->scanIndex=0; + continue; + } + group->scanIndex++; + } + g_selectiveIcon = (g_list_avatars > 0) && (cfg::dat.dwFlags & CLUI_FRAME_SELECTIVEICONS) && !dat->bisEmbedded; + + group = &dat->list; + group->scanIndex = 0; + indent = 0; + + for (index = 0; y< rcPaint->bottom;) { + if (group->scanIndex == group->cl.count) { + group = group->parent; + indent--; + if (group == NULL) { + break; + } + group->scanIndex++; + continue; + } + + line_num++; + if(cfg::dat.bForceRefetchOnPaint) + group->cl.items[group->scanIndex]->ace = (struct avatarCacheEntry*)-1; + + if (y > rcPaint->top - dat->row_heights[line_num] && y <= rcPaint->bottom) { + if (group->cl.items[group->scanIndex]->ace == (struct avatarCacheEntry*)-1 ) + group->cl.items[group->scanIndex]->ace = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)group->cl.items[group->scanIndex]->hContact, 0); + RowHeight::getRowHeight(dat, hwnd, group->cl.items[group->scanIndex], line_num, style); + PaintItem(hdcMem, group, group->cl.items[group->scanIndex], indent, y, dat, index, hwnd, style, &clRect, &bFirstNGdrawn, groupCountsFontTopShift, dat->row_heights[line_num]); + } + index++; + y += dat->row_heights[line_num]; + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) { + group = group->cl.items[group->scanIndex]->group; + indent++; + group->scanIndex = 0; + continue; + } + group->scanIndex++; + } + + SelectObject(hdcTempAV, hbmTempOldAV); + DeleteObject(hbmTempAV); + DeleteDC(hdcTempAV); + + DeleteDC(hdcAV); + + if (dat->iInsertionMark != -1) { + //insertion mark + HBRUSH hBrush, hoBrush; + POINT pts[8]; + HRGN hRgn; + + pts[0].x=dat->leftMargin; pts[0].y = RowHeight::getItemTopY(dat, dat->iInsertionMark) - dat->yScroll - 4; + //pts[0]. x = dat->leftMargin; pts[0]. y = dat->iInsertionMark * rowHeight - dat->yScroll - 4; + pts[1]. x = pts[0].x + 2; pts[1]. y = pts[0].y + 3; + pts[2]. x = clRect.right - 4; pts[2]. y = pts[1].y; + pts[3]. x = clRect.right - 1; pts[3]. y = pts[0].y - 1; + pts[4]. x = pts[3].x; pts[4]. y = pts[0].y + 7; + pts[5]. x = pts[2].x + 1; pts[5]. y = pts[1].y + 2; + pts[6]. x = pts[1].x; pts[6]. y = pts[5].y; + pts[7]. x = pts[0].x; pts[7]. y = pts[4].y; + hRgn = CreatePolygonRgn(pts, sizeof(pts) / sizeof(pts[0]), ALTERNATE); + hBrush = CreateSolidBrush(dat->fontInfo[FONTID_CONTACTS].colour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRgn(hdcMem, hRgn, hBrush); + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + } + if (!grey) + BitBlt(hdc, rcPaint->left, rcPaint->top, rcPaint->right - rcPaint->left, rcPaint->bottom - rcPaint->top, hdcMem, rcPaint->left, rcPaint->top, SRCCOPY); + + SelectObject(hdcMem, hOldBitmap); + SelectObject(hdcMem, hOldFont); + + DeleteDC(hdcMem); + if (grey) { + PBYTE bits; + BITMAPINFOHEADER bmih = {0}; + + int i; + int greyRed, greyGreen, greyBlue; + COLORREF greyColour; + bmih.biBitCount = 32; + bmih.biSize = sizeof(bmih); + bmih.biCompression = BI_RGB; + bmih.biHeight = -clRect.bottom; + bmih.biPlanes = 1; + bmih.biWidth = clRect.right; + bits = (PBYTE) mir_alloc(4 * bmih.biWidth * -bmih.biHeight); + GetDIBits(hdc, hBmpOsb, 0, clRect.bottom, bits, (BITMAPINFO *) &bmih, DIB_RGB_COLORS); + greyColour = GetSysColor(COLOR_3DFACE); + greyRed = GetRValue(greyColour) * 2; + greyGreen = GetGValue(greyColour) * 2; + greyBlue = GetBValue(greyColour) * 2; + if (divide3[0] == 255) { + for (i = 0; i < sizeof(divide3) / sizeof(divide3[0]); i++) { + divide3[i] = (i + 1) / 3; + } + } + for (i = 4 * clRect.right *clRect.bottom - 4; i >= 0; i -= 4) { + bits[i] = divide3[bits[i] + greyBlue]; + bits[i + 1] = divide3[bits[i + 1] + greyGreen]; + bits[i + 2] = divide3[bits[i + 2] + greyRed]; + } + SetDIBitsToDevice(hdc, 0, 0, clRect.right, clRect.bottom, 0, 0, 0, clRect.bottom, bits, (BITMAPINFO *) &bmih, DIB_RGB_COLORS); + mir_free(bits); + } + DeleteObject(hBmpOsb); + g_inCLCpaint = FALSE; + done = GetTickCount(); +} diff --git a/plugins/Clist_nicer/src/clcutils.cpp b/plugins/Clist_nicer/src/clcutils.cpp new file mode 100644 index 0000000000..f41b091517 --- /dev/null +++ b/plugins/Clist_nicer/src/clcutils.cpp @@ -0,0 +1,624 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE done + +*/ +#include +#include +#include "../coolsb/coolscroll.h" + +#ifndef SPI_GETDESKWALLPAPER +#define SPI_GETDESKWALLPAPER 115 +#endif +//loads of stuff that didn't really fit anywhere else + +extern int /*g_isConnecting,*/ during_sizing; + +extern void ( *saveRecalcScrollBar )(HWND hwnd, struct ClcData *dat); + +static int MY_pathIsAbsolute(const TCHAR *path) +{ + if (!path || !(lstrlen(path) > 2)) + return 0; + if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) + return 1; + return 0; +} + +size_t MY_pathToRelative(const TCHAR *pSrc, TCHAR *pOut) +{ + if (!pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH) + return 0; + if (!MY_pathIsAbsolute(pSrc)) { + mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); + return lstrlen(pOut); + } else { + TCHAR szTmp[MAX_PATH]; + mir_sntprintf(szTmp, SIZEOF(szTmp), _T("%s"), pSrc); + _tcslwr(szTmp); + if (_tcsstr(szTmp, cfg::dat.tszProfilePath)) { + mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc + lstrlen(cfg::dat.tszProfilePath) - 1); + pOut[0]='.'; + return lstrlen(pOut); + } else { + mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); + return lstrlen(pOut); + } + } +} + +size_t MY_pathToAbsolute(const TCHAR *pSrc, TCHAR *pOut) +{ + if (!pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH) + return 0; + if (MY_pathIsAbsolute(pSrc)&&pSrc[0]!='.') + mir_sntprintf(pOut, MAX_PATH, _T("%s"), pSrc); + else if (pSrc[0]=='.') + mir_sntprintf(pOut, MAX_PATH, _T("%s\\%s"), cfg::dat.tszProfilePath, pSrc); + + return lstrlen(pOut); +} + +/* + * performs hit-testing for reversed (mirrored) contact rows when using RTL + * shares all the init stuff with HitTest() + */ + +int RTL_HitTest(HWND hwnd, struct ClcData *dat, int testx, int testy, struct ClcContact *hitcontact, DWORD *flags, int indent, int hit) +{ + RECT clRect; + int right, checkboxWidth, cxSmIcon, i, width; + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + SIZE textSize; + HDC hdc; + HFONT hFont; + + GetClientRect(hwnd, &clRect); + right = clRect.right; + + // avatar check + if(hitcontact->type == CLCIT_CONTACT && cfg::dat.dwFlags & CLUI_FRAME_AVATARS && hitcontact->ace != NULL && hitcontact->avatarLeft != -1) { + if(testx < right - hitcontact->avatarLeft && testx > right - hitcontact->avatarLeft - cfg::dat.avatarSize) { + if(flags) + *flags |= CLCHT_ONAVATAR; + } + } + if (testx > right - (dat->leftMargin + indent * dat->groupIndent)) { + if (flags) + *flags |= CLCHT_ONITEMINDENT; + return hit; + } + checkboxWidth = 0; + if (style & CLS_CHECKBOXES && hitcontact->type == CLCIT_CONTACT) + checkboxWidth = dat->checkboxSize + 2; + if (style & CLS_GROUPCHECKBOXES && hitcontact->type == CLCIT_GROUP) + checkboxWidth = dat->checkboxSize + 2; + if (hitcontact->type == CLCIT_INFO && hitcontact->flags & CLCIIF_CHECKBOX) + checkboxWidth = dat->checkboxSize + 2; + if (testx > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth)) { + if (flags) + *flags |= CLCHT_ONITEMCHECK; + return hit; + } + if (testx > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace)) { + if (flags) + *flags |= CLCHT_ONITEMICON; + return hit; + } + cxSmIcon = GetSystemMetrics(SM_CXSMICON); + for (i = 0; i< dat->extraColumnsCount; i++) { + if (hitcontact->iExtraImage[i] == 0xFF) + continue; + if (testx >= dat->extraColumnSpacing * (dat->extraColumnsCount - i) && testx < dat->extraColumnSpacing * (dat->extraColumnsCount - i) + cxSmIcon) { + if (flags) + *flags |= CLCHT_ONITEMEXTRA | (i << 24); + return hit; + } + } + if(hitcontact->extraCacheEntry >= 0 && hitcontact->extraCacheEntry < cfg::nextCacheEntry && cfg::eCache[hitcontact->extraCacheEntry].iExtraValid) { + int rightOffset = hitcontact->extraIconRightBegin; + int images_present = 0; + + for (i = 5; i >= 0; i--) { + if (cfg::eCache[hitcontact->extraCacheEntry].iExtraImage[i] == 0xFF) + continue; + if (!((1 << i) & cfg::eCache[hitcontact->extraCacheEntry].dwXMask)) + continue; + images_present++; + if (testx < right - (rightOffset - (cfg::dat.exIconScale + 2) * images_present) && testx > right - (rightOffset - (cfg::dat.exIconScale + 2) * images_present + (cfg::dat.exIconScale))) { + if (flags) + *flags |= (CLCHT_ONITEMEXTRAEX | ((i + 1) << 24)); + return hit; + } + } + } + + hdc = GetDC(hwnd); + if (hitcontact->type == CLCIT_GROUP) + hFont = reinterpret_cast(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont)); + else + hFont = reinterpret_cast(SelectObject(hdc, dat->fontInfo[FONTID_CONTACTS].hFont)); + GetTextExtentPoint32(hdc, hitcontact->szText, lstrlen(hitcontact->szText), &textSize); + width = textSize.cx; + if (hitcontact->type == CLCIT_GROUP) { + char *szCounts; + szCounts = pcli->pfnGetGroupCountsText(dat, hitcontact); + if (szCounts[0]) { + GetTextExtentPoint32A(hdc, " ", 1, &textSize); + width += textSize.cx; + SelectObject(hdc, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); + GetTextExtentPoint32A(hdc, szCounts, lstrlenA(szCounts), &textSize); + width += textSize.cx; + } + } + SelectObject(hdc, hFont); + ReleaseDC(hwnd, hdc); + if (testx > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0))) { + if (flags) + *flags |= CLCHT_ONITEMLABEL; + return hit; + } + if (cfg::dat.dwFlags & CLUI_FULLROWSELECT && !(GetKeyState(VK_SHIFT) & 0x8000) && testx < right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0))) { + if (flags) + *flags |= CLCHT_ONITEMSPACE; + return hit; + } + if (flags) + *flags |= CLCHT_NOWHERE; + return -1; +} + +int HitTest(HWND hwnd, struct ClcData *dat, int testx, int testy, struct ClcContact **contact, struct ClcGroup **group, DWORD *flags) +{ + struct ClcContact *hitcontact; + struct ClcGroup *hitgroup; + int hit, indent, width, i, cxSmIcon; + int checkboxWidth; + SIZE textSize; + HDC hdc; + RECT clRect; + HFONT hFont; + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + BYTE mirror_mode = cfg::dat.bUseDCMirroring; + + if (flags) + *flags = 0; + GetClientRect(hwnd, &clRect); + if (testx < 0 || testy < 0 || testy >= clRect.bottom || testx >= clRect.right) { + if (flags) { + if (testx < 0) + *flags |= CLCHT_TOLEFT; + else if (testx >= clRect.right) + *flags |= CLCHT_TORIGHT; + if (testy < 0) + *flags |= CLCHT_ABOVE; + else if (testy >= clRect.bottom) + *flags |= CLCHT_BELOW; + } + return -1; + } + if (testx< dat->leftMargin) { + if (flags) + *flags |= CLCHT_INLEFTMARGIN | CLCHT_NOWHERE; + return -1; + } + hit = RowHeight::hitTest(dat, dat->yScroll + testy); + if (hit != -1) + hit = pcli->pfnGetRowByIndex(dat, hit, &hitcontact, &hitgroup); + + if (hit == -1) { + if (flags) + *flags |= CLCHT_NOWHERE | CLCHT_BELOWITEMS; + return -1; + } + if (contact) + *contact = hitcontact; + if (group) + *group = hitgroup; + + for (indent = 0; hitgroup->parent; indent++,hitgroup = hitgroup->parent) { + ; + } + + if (!dat->bisEmbedded) { + if(hitcontact->type == CLCIT_CONTACT) { + if(mirror_mode == 1 || (mirror_mode == 2 && cfg::eCache[hitcontact->extraCacheEntry].dwCFlags & ECF_RTLNICK)) + return RTL_HitTest(hwnd, dat, testx, testy, hitcontact, flags, indent, hit); + } + else if(hitcontact->type == CLCIT_GROUP) { + if(cfg::dat.bGroupAlign == CLC_GROUPALIGN_RIGHT || (hitcontact->isRtl && cfg::dat.bGroupAlign == CLC_GROUPALIGN_AUTO)) + return RTL_HitTest(hwnd, dat, testx, testy, hitcontact, flags, indent, hit); + } + } + + // avatar check + if(hitcontact->type == CLCIT_CONTACT && cfg::dat.dwFlags & CLUI_FRAME_AVATARS && hitcontact->ace != NULL && hitcontact->avatarLeft != -1) { + if(testx >hitcontact->avatarLeft && testx < hitcontact->avatarLeft + cfg::dat.avatarSize) { + if(flags) + *flags |= CLCHT_ONAVATAR; + } + } + if (testx< dat->leftMargin + indent * dat->groupIndent) { + if (flags) + *flags |= CLCHT_ONITEMINDENT; + return hit; + } + checkboxWidth = 0; + if (style & CLS_CHECKBOXES && hitcontact->type == CLCIT_CONTACT) + checkboxWidth = dat->checkboxSize + 2; + if (style & CLS_GROUPCHECKBOXES && hitcontact->type == CLCIT_GROUP) + checkboxWidth = dat->checkboxSize + 2; + if (hitcontact->type == CLCIT_INFO && hitcontact->flags & CLCIIF_CHECKBOX) + checkboxWidth = dat->checkboxSize + 2; + if (testx< dat->leftMargin + indent * dat->groupIndent + checkboxWidth) { + if (flags) + *flags |= CLCHT_ONITEMCHECK; + return hit; + } + if (testx< dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace) { + if (flags) + *flags |= CLCHT_ONITEMICON; + return hit; + } + cxSmIcon = GetSystemMetrics(SM_CXSMICON); + for (i = 0; i< dat->extraColumnsCount; i++) { + if (hitcontact->iExtraImage[i] == 0xFF) + continue; + if (testx >= clRect.right - dat->extraColumnSpacing * (dat->extraColumnsCount - i) && testx< clRect.right - dat->extraColumnSpacing * (dat->extraColumnsCount - i) + cxSmIcon) { + if (flags) + *flags |= CLCHT_ONITEMEXTRA | (i << 24); + return hit; + } + } + if(hitcontact->extraCacheEntry >= 0 && hitcontact->extraCacheEntry < cfg::nextCacheEntry && cfg::eCache[hitcontact->extraCacheEntry].iExtraValid) { + //int rightOffset = clRect.right; + int rightOffset = hitcontact->extraIconRightBegin; + int images_present = 0; + + for (i = 5; i >= 0; i--) { + if (cfg::eCache[hitcontact->extraCacheEntry].iExtraImage[i] == 0xFF) + continue; + if (!((1 << i) & cfg::eCache[hitcontact->extraCacheEntry].dwXMask)) + continue; + images_present++; + if (testx > (rightOffset - (cfg::dat.exIconScale + 2) * images_present) && testx < (rightOffset - (cfg::dat.exIconScale + 2) * images_present + (cfg::dat.exIconScale))) { + if (flags) + *flags |= (CLCHT_ONITEMEXTRAEX | ((i + 1) << 24)); + return hit; + } + } + } + hdc = GetDC(hwnd); + if (hitcontact->type == CLCIT_GROUP) + hFont = reinterpret_cast(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont)); + else + hFont = reinterpret_cast(SelectObject(hdc, dat->fontInfo[FONTID_CONTACTS].hFont)); + GetTextExtentPoint32(hdc, hitcontact->szText, lstrlen(hitcontact->szText), &textSize); + width = textSize.cx; + if (hitcontact->type == CLCIT_GROUP) { + char *szCounts; + szCounts = pcli->pfnGetGroupCountsText(dat, hitcontact); + if (szCounts[0]) { + GetTextExtentPoint32A(hdc, " ", 1, &textSize); + width += textSize.cx; + SelectObject(hdc, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); + GetTextExtentPoint32A(hdc, szCounts, lstrlenA(szCounts), &textSize); + width += textSize.cx; + } + } + SelectObject(hdc, hFont); + ReleaseDC(hwnd, hdc); + if (cfg::dat.dwFlags & CLUI_FULLROWSELECT && !(GetKeyState(VK_SHIFT) & 0x8000) && testx > dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) { + if (flags) + *flags |= CLCHT_ONITEMSPACE; + return hit; + } + if (testx< dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) { + if (flags) + *flags |= CLCHT_ONITEMLABEL; + return hit; + } + if (flags) + *flags |= CLCHT_NOWHERE; + return -1; +} + +void ScrollTo(HWND hwnd, struct ClcData *dat, int desty, int noSmooth) +{ + DWORD startTick, nowTick; + int oldy = dat->yScroll; + RECT clRect, rcInvalidate; + int maxy, previousy; + + if (dat->iHotTrack != -1 && dat->yScroll != desty) { + pcli->pfnInvalidateItem(hwnd, dat, dat->iHotTrack); + dat->iHotTrack = -1; + ReleaseCapture(); + } + GetClientRect(hwnd, &clRect); + rcInvalidate = clRect; + + maxy = RowHeight::getTotalHeight(dat)-clRect.bottom; + if (desty > maxy) + desty = maxy; + if (desty < 0) + desty = 0; + if (abs(desty - dat->yScroll) < 4) + noSmooth = 1; + if (!noSmooth && dat->exStyle & CLS_EX_NOSMOOTHSCROLLING) + noSmooth = 1; + previousy = dat->yScroll; + if (!noSmooth) { + startTick = GetTickCount(); + for (; ;) { + nowTick = GetTickCount(); + if (nowTick >= startTick + dat->scrollTime) + break; + dat->yScroll = oldy + (desty - oldy) * (int) (nowTick - startTick) / dat->scrollTime; + if (dat->backgroundBmpUse & CLBF_SCROLL || dat->hBmpBackground == NULL) + ScrollWindowEx(hwnd, 0, previousy - dat->yScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE); + else + InvalidateRect(hwnd, NULL, FALSE); + previousy = dat->yScroll; + if(cfg::dat.bSkinnedScrollbar && !dat->bisEmbedded) + CoolSB_SetScrollPos(hwnd, SB_VERT, dat->yScroll, TRUE); + else + SetScrollPos(hwnd, SB_VERT, dat->yScroll, TRUE); + UpdateWindow(hwnd); + } + } + dat->yScroll = desty; + if (dat->backgroundBmpUse & CLBF_SCROLL || dat->hBmpBackground == NULL) { + if (!noSmooth) + ScrollWindowEx(hwnd, 0, previousy - dat->yScroll, NULL, NULL, NULL, NULL, SW_INVALIDATE); + else + InvalidateRect(hwnd, NULL, FALSE); + } + else + InvalidateRect(hwnd, NULL, FALSE); + + if(cfg::dat.bSkinnedScrollbar && !dat->bisEmbedded) + CoolSB_SetScrollPos(hwnd, SB_VERT, dat->yScroll, TRUE); + else + SetScrollPos(hwnd, SB_VERT, dat->yScroll, TRUE); + dat->forceScroll = 0; +} + +void RecalcScrollBar(HWND hwnd, struct ClcData *dat) +{ + SCROLLINFO si = { 0 }; + RECT clRect; + NMCLISTCONTROL nm; + + RowHeight::calcRowHeights(dat, hwnd); + + GetClientRect(hwnd, &clRect); + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + si.nMin = 0; + si.nMax = pcli->pfnGetRowTotalHeight(dat)-1; + si.nPage = clRect.bottom; + si.nPos = dat->yScroll; + + if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_CONTACTLIST) { + if (dat->noVScrollbar == 0) { + if(cfg::dat.bSkinnedScrollbar && !dat->bisEmbedded) + CoolSB_SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + else + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + } + } + else { + if(cfg::dat.bSkinnedScrollbar && !dat->bisEmbedded) + CoolSB_SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + else + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + } + ScrollTo(hwnd, dat, dat->yScroll, 1); + nm.hdr.code = CLN_LISTSIZECHANGE; + nm.hdr.hwndFrom = hwnd; + nm.hdr.idFrom = GetDlgCtrlID(hwnd); + nm.pt.y = si.nMax; + SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) & nm); + //saveRecalcScrollBar(hwnd, dat); +} + +void SetGroupExpand(HWND hwnd,struct ClcData *dat,struct ClcGroup *group,int newState) +{ + int contentCount; + int groupy; + int newy; + int posy; + RECT clRect; + NMCLISTCONTROL nm; + + if (newState == -1) + group->expanded ^= 1; + else { + if (group->expanded == (newState != 0)) + return; + group->expanded = newState != 0; + } + InvalidateRect(hwnd,NULL,FALSE); + contentCount = pcli->pfnGetGroupContentsCount(group,1); + + groupy=pcli->pfnGetRowsPriorTo(&dat->list,group,-1); + if(dat->selection>groupy && dat->selectionselection=groupy; + pcli->pfnRecalcScrollBar(hwnd,dat); + + GetClientRect(hwnd,&clRect); + newy=dat->yScroll; + posy = RowHeight::getItemBottomY(dat, groupy+contentCount); + if(posy>=newy+clRect.bottom) + newy=posy-clRect.bottom; + posy = RowHeight::getItemTopY(dat, groupy); + if(newy>posy) newy=posy; + ScrollTo(hwnd,dat,newy,0); + + nm.hdr.code=CLN_EXPANDED; + nm.hdr.hwndFrom=hwnd; + nm.hdr.idFrom=GetDlgCtrlID(hwnd); + nm.hItem=(HANDLE)group->groupId; + nm.action = (group->expanded); + SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm); +} + +static WNDPROC OldRenameEditWndProc; +static LRESULT CALLBACK RenameEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_KEYDOWN: + switch (wParam) { + case VK_RETURN: + pcli->pfnEndRename(GetParent(hwnd), (struct ClcData *) GetWindowLongPtr(GetParent(hwnd), 0), 1); + return 0; + case VK_ESCAPE: + pcli->pfnEndRename(GetParent(hwnd), (struct ClcData *) GetWindowLongPtr(GetParent(hwnd), 0), 0); + return 0; + } + break; + case WM_GETDLGCODE: + if (lParam) { + MSG *msg = (MSG *) lParam; + if (msg->message == WM_KEYDOWN && msg->wParam == VK_TAB) + return 0; + if (msg->message == WM_CHAR && msg->wParam == '\t') + return 0; + } + return DLGC_WANTMESSAGE; + case WM_KILLFOCUS: + pcli->pfnEndRename(GetParent(hwnd), (struct ClcData *) GetWindowLongPtr(GetParent(hwnd), 0), 1); + return 0; + } + return CallWindowProc(OldRenameEditWndProc, hwnd, msg, wParam, lParam); +} + +void BeginRenameSelection(HWND hwnd, struct ClcData *dat) +{ + struct ClcContact *contact; + struct ClcGroup *group; + int indent, x, y, h; + RECT clRect; + + KillTimer(hwnd, TIMERID_RENAME); + ReleaseCapture(); + dat->iHotTrack = -1; + dat->selection = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, &group); + if (dat->selection == -1) + return; + if (contact->type != CLCIT_CONTACT && contact->type != CLCIT_GROUP) + return; + for (indent = 0; group->parent; indent++,group = group->parent) { + ; + } + GetClientRect(hwnd, &clRect); + x = indent * dat->groupIndent + dat->iconXSpace - 2; + //y = dat->selection * dat->rowHeight - dat->yScroll; + y = RowHeight::getItemTopY(dat, dat->selection)-dat->yScroll; + + h=dat->row_heights[dat->selection]; + { + int i; + for (i=0; i <= FONTID_LAST; i++) + if (hfontInfo[i].fontHeight+2) h=dat->fontInfo[i].fontHeight+2; + } + + dat->hwndRenameEdit = CreateWindowEx(0, _T("RichEdit20W"),contact->szText,WS_CHILD|WS_BORDER|ES_MULTILINE|ES_AUTOHSCROLL,x,y,clRect.right-x,h,hwnd,NULL,g_hInst,NULL); + { + if ((contact->type == CLCIT_CONTACT && cfg::eCache[contact->extraCacheEntry].dwCFlags & ECF_RTLNICK) || (contact->type == CLCIT_GROUP && contact->isRtl)) { + PARAFORMAT2 pf2; + ZeroMemory((void *)&pf2, sizeof(pf2)); + pf2.cbSize = sizeof(pf2); + pf2.dwMask = PFM_RTLPARA; + pf2.wEffects = PFE_RTLPARA; + SetWindowText(dat->hwndRenameEdit, _T("")); + SendMessage(dat->hwndRenameEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + SetWindowText(dat->hwndRenameEdit, contact->szText); + } + } + + //dat->hwndRenameEdit = CreateWindow(_T("EDIT"), contact->szText, WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, x, y, clRect.right - x, dat->rowHeight, hwnd, NULL, g_hInst, NULL); + OldRenameEditWndProc = (WNDPROC) SetWindowLongPtr(dat->hwndRenameEdit, GWLP_WNDPROC, (LONG_PTR) RenameEditSubclassProc); + SendMessage(dat->hwndRenameEdit, WM_SETFONT, (WPARAM) (contact->type == CLCIT_GROUP ? dat->fontInfo[FONTID_GROUPS].hFont : dat->fontInfo[FONTID_CONTACTS].hFont), 0); + SendMessage(dat->hwndRenameEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN | EC_USEFONTINFO, 0); + SendMessage(dat->hwndRenameEdit, EM_SETSEL, 0, (LPARAM) (-1)); + ShowWindow(dat->hwndRenameEdit, SW_SHOW); + SetFocus(dat->hwndRenameEdit); +} + +extern void ( *saveLoadClcOptions )(HWND hwnd,struct ClcData *dat); + +void LoadClcOptions(HWND hwnd, struct ClcData *dat) +{ + dat->bkChanged = 0; + + saveLoadClcOptions(hwnd, dat); + + dat->min_row_heigh = (int)cfg::getByte("CLC","RowHeight",CLCDEFAULT_ROWHEIGHT); + dat->group_row_height = (int)cfg::getByte("CLC","GRowHeight",CLCDEFAULT_ROWHEIGHT); + dat->row_border = 0; + dat->rightMargin = cfg::getByte("CLC", "RightMargin", CLCDEFAULT_LEFTMARGIN); + dat->bkColour = cfg::getByte("CLC", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS) ? + GetSysColor(COLOR_3DFACE) : cfg::getDword("CLC", "BkColour", CLCDEFAULT_BKCOLOUR); + if (!dat->bkChanged) { + if(cfg::dat.hBrushCLCBk) + DeleteObject(cfg::dat.hBrushCLCBk); + cfg::dat.hBrushCLCBk = CreateSolidBrush(dat->bkColour); + if (dat->hBmpBackground) { + if(cfg::dat.hdcPic) { + SelectObject(cfg::dat.hdcPic, cfg::dat.hbmPicOld); + DeleteDC(cfg::dat.hdcPic); + cfg::dat.hdcPic = 0; + cfg::dat.hbmPicOld = 0; + } } + + cfg::dat.bmpBackground = dat->hBmpBackground; + if(cfg::dat.bmpBackground) { + HDC hdcThis = GetDC(pcli->hwndContactList); + GetObject(cfg::dat.bmpBackground, sizeof(cfg::dat.bminfoBg), &(cfg::dat.bminfoBg)); + cfg::dat.hdcPic = CreateCompatibleDC(hdcThis); + cfg::dat.hbmPicOld = reinterpret_cast(SelectObject(cfg::dat.hdcPic, cfg::dat.bmpBackground)); + ReleaseDC(pcli->hwndContactList, hdcThis); + } + } + if (cfg::getByte("CLCExt", "EXBK_FillWallpaper", 0)) { + char wpbuf[MAX_PATH]; + if (dat->hBmpBackground) + DeleteObject(dat->hBmpBackground); dat->hBmpBackground = NULL; + + SystemParametersInfoA(SPI_GETDESKWALLPAPER, MAX_PATH, wpbuf, 0); + + // we have a wallpaper string + if (strlen(wpbuf) > 0) { + dat->hBmpBackground = reinterpret_cast(LoadImageA(NULL, wpbuf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)); + } + cfg::dat.bmpBackground = dat->hBmpBackground; + if(cfg::dat.bmpBackground) { + HDC hdcThis = GetDC(pcli->hwndContactList); + GetObject(cfg::dat.bmpBackground, sizeof(cfg::dat.bminfoBg), &(cfg::dat.bminfoBg)); + cfg::dat.hdcPic = CreateCompatibleDC(hdcThis); + cfg::dat.hbmPicOld = reinterpret_cast(SelectObject(cfg::dat.hdcPic, cfg::dat.bmpBackground)); + ReleaseDC(pcli->hwndContactList, hdcThis); + } + } +} diff --git a/plugins/Clist_nicer/src/clistevents.cpp b/plugins/Clist_nicer/src/clistevents.cpp new file mode 100644 index 0000000000..93b90c34ce --- /dev/null +++ b/plugins/Clist_nicer/src/clistevents.cpp @@ -0,0 +1,397 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 +#include "../cluiframes/cluiframes.h" + +static HWND hwndEventFrame = 0; +HFONT __fastcall ChangeToFont(HDC hdc, struct ClcData *dat, int id, int *fontHeight); + +extern struct CListEvent* ( *saveAddEvent )(CLISTEVENT *cle); +extern int ( *saveRemoveEvent )(HANDLE hContact, HANDLE hDbEvent); +extern wndFrame *wndFrameEventArea; + +extern HPEN g_hPenCLUIFrames; + +extern StatusItems_t *StatusItems; + +HWND g_hwndEventArea = 0; + +struct CListEvent { + int imlIconIndex; + int flashesDone; + CLISTEVENT cle; + + int menuId; + int imlIconOverlayIndex; +}; + +struct CListImlIcon { + int index; + HICON hIcon; +}; + +static int iconsOn; +extern HIMAGELIST hCListImages; + +HANDLE hNotifyFrame = (HANDLE)-1; + +struct CListEvent* fnCreateEvent( void ) +{ + CListEvent *p = reinterpret_cast(mir_alloc(sizeof(struct CListEvent))); + if(p) + ZeroMemory(p, sizeof(struct CListEvent)); + + return p; +} + +void HideShowNotifyFrame() +{ + int dwVisible = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hNotifyFrame), 0) & F_VISIBLE; + int desired; + + if(cfg::dat.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY) + desired = cfg::dat.notifyActive ? TRUE : FALSE; + else + desired = dwVisible; + + if(desired) { + if (!dwVisible) + CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0); + } + else { + if(dwVisible) + CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0); + } +} + +static CLISTEVENT* MyGetEvent(int iSelection) +{ + int i; + + for (i = 0; i < pcli->events.count; i++) { + struct CListEvent* p = pcli->events.items[i]; + if (p->menuId == iSelection) + return &p->cle; + } + return NULL; +} + +LRESULT CALLBACK EventAreaWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_CREATE: + hwndEventFrame = hwnd; + return FALSE; + + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *lpi = (LPMEASUREITEMSTRUCT) lParam; + MENUITEMINFOA mii = {0}; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA | MIIM_ID; + if (GetMenuItemInfoA(cfg::dat.hMenuNotify, lpi->itemID, FALSE, &mii) != 0) { + if (mii.dwItemData == lpi->itemData) { + lpi->itemWidth = 8 + 16; + lpi->itemHeight = 0; + return TRUE; + } + } + break; + } + case WM_NCCALCSIZE: + return FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam, + wndFrameEventArea ? wndFrameEventArea->TitleBar.ShowTitleBar : 0); + case WM_NCPAINT: + return FrameNCPaint(hwnd, DefWindowProc, wParam, lParam, + wndFrameEventArea ? wndFrameEventArea->TitleBar.ShowTitleBar : 0); + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + + if (dis->hwndItem == (HWND) cfg::dat.hMenuNotify) { + MENUITEMINFOA mii = {0}; + + struct NotifyMenuItemExData *nmi = 0; + int iIcon; + HICON hIcon; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA; + if (GetMenuItemInfoA(cfg::dat.hMenuNotify, (UINT) dis->itemID, FALSE, &mii) != 0) { + nmi = (struct NotifyMenuItemExData *) mii.dwItemData; + if (nmi) { + iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0); + hIcon = ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL); + pcli->pfnDrawMenuItem(dis, hIcon, nmi->hIcon); + return TRUE; + } + } + } + break; + } + case WM_LBUTTONUP: + if(cfg::dat.bEventAreaEnabled) + SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0); + break; + case WM_COMMAND: + if(LOWORD(wParam) == IDC_NOTIFYBUTTON) { + int iSelection; + MENUITEMINFO mii = {0}; + POINT pt; + struct NotifyMenuItemExData *nmi = 0; + int iCount = GetMenuItemCount(cfg::dat.hMenuNotify); + BOOL result; + + GetCursorPos(&pt); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA; + if (iCount > 1) + iSelection = TrackPopupMenu(cfg::dat.hMenuNotify, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL); + else + iSelection = GetMenuItemID(cfg::dat.hMenuNotify, 0); + result = GetMenuItemInfo(cfg::dat.hMenuNotify, (UINT) iSelection, FALSE, &mii); + if (result != 0) { + nmi = (struct NotifyMenuItemExData *) mii.dwItemData; + if (nmi) { + CLISTEVENT *cle = MyGetEvent(iSelection); + if (cle) { + CLISTEVENT *cle1 = NULL; + CallService(cle->pszService, (WPARAM) NULL, (LPARAM) cle); + // re-obtain the pointer, it may already be invalid/point to another event if the + // event we're interested in was removed by the service (nasty one...) + cle1 = MyGetEvent(iSelection); + if (cle1 != NULL) + CallService(MS_CLIST_REMOVEEVENT, (WPARAM) cle->hContact, (LPARAM) cle->hDbEvent); + } + } + } + break; + } + break; + case WM_ERASEBKGND: + return TRUE; + + case WM_PAINT: + { + PAINTSTRUCT ps; + RECT rc, rcClient; + HDC hdc = BeginPaint(hwnd, &ps); + LONG dwLeft; + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hbm, hbmold; + StatusItems_t *item; + int height; + HFONT hFontOld = 0; + + GetClientRect(hwnd, &rc); + rcClient = rc; + hbm = CreateCompatibleBitmap(hdc, rc.right, rc.bottom); + hbmold = reinterpret_cast(SelectObject(hdcMem, hbm)); + SetBkMode(hdcMem, TRANSPARENT); + + if(cfg::clcdat) + hFontOld = ChangeToFont(hdcMem, cfg::clcdat, FONTID_EVENTAREA, &height); + + if(cfg::dat.bWallpaperMode) + SkinDrawBg(hwnd, hdcMem); + item = &StatusItems[ID_EXTBKEVTAREA - ID_STATUS_OFFLINE]; + if(item->IGNORED) { + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_3DFACE)); + } + else { + rc.top += item->MARGIN_TOP; rc.bottom -= item->MARGIN_BOTTOM; + rc.left += item->MARGIN_LEFT; rc.right -= item->MARGIN_RIGHT; + + DrawAlpha(hdcMem, &rc, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, + item->GRADIENT, item->CORNER, item->BORDERSTYLE, item->imageItem); + SetTextColor(hdcMem, item->TEXTCOLOR); + } + + dwLeft = rc.left; + + PaintNotifyArea(hdcMem, &rc); + if(cfg::dat.dwFlags & CLUI_FRAME_EVENTAREASUNKEN) { + rc.left = dwLeft; + InflateRect(&rc, -2, -2); + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hbmold); + if(hFontOld) + SelectObject(hdcMem, hFontOld); + DeleteObject(hbm); + DeleteDC(hdcMem); + ps.fErase = FALSE; + EndPaint(hwnd, &ps); + return 0; + } + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return TRUE; +} + +struct CListEvent* AddEvent(CLISTEVENT *cle) +{ + struct CListEvent* p = saveAddEvent(cle); + if ( p == NULL ) + return NULL; + + if (1) { + if (p->cle.hContact != 0 && p->cle.hDbEvent != (HANDLE) 1 && !(p->cle.flags & CLEF_ONLYAFEW)) { + int j; + struct NotifyMenuItemExData *nmi = 0; + char *szProto; + TCHAR *szName; + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA | MIIM_BITMAP | MIIM_ID; + if (p->cle.pszService && !strncmp("SRMsg/ReadMessage", p->cle.pszService, 17)) { + // dup check only for msg events + for (j = 0; j < GetMenuItemCount(cfg::dat.hMenuNotify); j++) { + if (GetMenuItemInfo(cfg::dat.hMenuNotify, j, TRUE, &mii) != 0) { + nmi = (struct NotifyMenuItemExData *) mii.dwItemData; + if (nmi != 0 && (HANDLE) nmi->hContact == (HANDLE) p->cle.hContact && nmi->iIcon == p->imlIconIndex) + return p; + } } } + + szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) p->cle.hContact, 0); + szName = pcli->pfnGetContactDisplayName(p->cle.hContact, 0); + if (szProto && szName) { + nmi = (struct NotifyMenuItemExData *) malloc(sizeof(struct NotifyMenuItemExData)); + if (nmi) { + TCHAR szBuffer[128]; + TCHAR* szStatus = pcli->pfnGetStatusModeDescription(cfg::getWord(p->cle.hContact, szProto, "Status", ID_STATUS_OFFLINE), 0); + + TCHAR szwProto[64]; + MultiByteToWideChar(CP_ACP, 0, szProto, -1, szwProto, 64); + szwProto[63] = 0; + _snwprintf(szBuffer, SIZEOF(szBuffer), L"%s: %s (%s)", szwProto, szName, szStatus); + + szBuffer[127] = 0; + AppendMenu(cfg::dat.hMenuNotify, MF_BYCOMMAND | MF_STRING, cfg::dat.wNextMenuID, szBuffer); + mii.hbmpItem = HBMMENU_CALLBACK; + nmi->hContact = p->cle.hContact; + nmi->iIcon = p->imlIconIndex; + nmi->hIcon = p->cle.hIcon; + nmi->hDbEvent = p->cle.hDbEvent; + mii.dwItemData = (ULONG_PTR) nmi; + mii.wID = cfg::dat.wNextMenuID; + SetMenuItemInfo(cfg::dat.hMenuNotify, cfg::dat.wNextMenuID, FALSE, &mii); + p-> menuId = cfg::dat.wNextMenuID; + cfg::dat.wNextMenuID++; + if (cfg::dat.wNextMenuID > 0x7fff) + cfg::dat.wNextMenuID = 1; + cfg::dat.hIconNotify = p->imlIconIndex; + } + } + } else if (p->cle.hContact != 0 && (p->cle.flags & CLEF_ONLYAFEW)) { + cfg::dat.hIconNotify = p->imlIconIndex; + cfg::dat.hUpdateContact = p->cle.hContact; + } + if (cfg::dat.dwFlags & CLUI_STICKYEVENTS) { + HANDLE hItem = (HANDLE) SendMessage(pcli->hwndContactTree, CLM_FINDCONTACT, (WPARAM) p->cle.hContact, 0); + if (hItem) { + SendMessage(pcli->hwndContactTree, CLM_SETSTICKY, (WPARAM) hItem, 1); + pcli->pfnClcBroadcast(INTM_PROTOCHANGED, (WPARAM) p->cle.hContact, 0); + } + } + if (pcli->events.count > 0) { + cfg::dat.bEventAreaEnabled = TRUE; + if (cfg::dat.notifyActive == 0) { + cfg::dat.notifyActive = 1; + HideShowNotifyFrame(); + } + } + InvalidateRect(hwndEventFrame, NULL, FALSE); + if(cfg::dat.bUseFloater & CLUI_USE_FLOATER && cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS) + SFL_Update(0, 0, 0, NULL, FALSE); + } + + return p; +} + +// Removes an event from the contact list's queue +// wParam=(WPARAM)(HANDLE)hContact +// lParam=(LPARAM)(HANDLE)hDbEvent +// Returns 0 if the event was successfully removed, or nonzero if the event was not found +int RemoveEvent(HANDLE hContact, HANDLE hDbEvent) +{ + HANDLE hItem; + int i; + BOOL bUnstick = TRUE; + + // Find the event that should be removed + for (i = 0; i < pcli->events.count; i++) { + if ((pcli->events.items[i]->cle.hContact == hContact) && (pcli->events.items[i]->cle.hDbEvent == hDbEvent)) { + break; + } + } + + // Event was not found + if (i == pcli->events.count) + return 1; + + // remove event from the notify menu + if (1) { + if (pcli->events.items[i]->menuId > 0) { + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA; + if (GetMenuItemInfo(cfg::dat.hMenuNotify, pcli->events.items[i]->menuId, FALSE, &mii) != 0) { + struct NotifyMenuItemExData *nmi = (struct NotifyMenuItemExData *) mii.dwItemData; + if (nmi && nmi->hContact == hContact && nmi->hDbEvent == hDbEvent) { + free(nmi); + DeleteMenu(cfg::dat.hMenuNotify, pcli->events.items[i]->menuId, MF_BYCOMMAND); + } } } } + + saveRemoveEvent(hContact, hDbEvent); + + if (pcli->events.count == 0) { + cfg::dat.bEventAreaEnabled = FALSE; + if (cfg::dat.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY) { + cfg::dat.notifyActive = 0; + HideShowNotifyFrame(); + } } + + if (bUnstick) { + // clear "sticky" (sort) status + + hItem = (HANDLE) SendMessage(pcli->hwndContactTree, CLM_FINDCONTACT, (WPARAM)hContact, 0); + if (hItem) { + SendMessage(pcli->hwndContactTree, CLM_SETSTICKY, (WPARAM) hItem, 0); + pcli->pfnClcBroadcast(INTM_PROTOCHANGED, (WPARAM)hContact, 0); + } } + + if (hContact == cfg::dat.hUpdateContact || (INT_PTR)hDbEvent == 1) + cfg::dat.hUpdateContact = 0; + + if (cfg::dat.notifyActive) { + InvalidateRect(hwndEventFrame, NULL, FALSE); + if(cfg::dat.bUseFloater & CLUI_USE_FLOATER && cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS) + SFL_Update(0, 0, 0, NULL, FALSE); + } + + return 0; +} diff --git a/plugins/Clist_nicer/src/clistmenus.cpp b/plugins/Clist_nicer/src/clistmenus.cpp new file mode 100644 index 0000000000..a1947e51a3 --- /dev/null +++ b/plugins/Clist_nicer/src/clistmenus.cpp @@ -0,0 +1,493 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 +#include +#include +#include "../CLUIFrames/cluiframes.h" + +#pragma hdrstop + +static HMENU hMainMenu, hMainStatusMenu; + +void DestroyTrayMenu(HMENU hMenu) +{ + int i, cnt; + + cnt = GetMenuItemCount(hMenu); + for (i=0; ihwndContactList); + PostQuitMessage(0); + Sleep(0); + } + + return(0); +} + +static HANDLE hWindowListIGN = 0; + +/* + * dialog procedure for handling the contact ignore dialog (available from the contact + * menu + */ + +static const UINT xImgCtrlIds[] = { + IDC_EXTRA_ICON_RES0, + IDC_EXTRA_ICON_EMAIL, + IDC_EXTRA_ICON_RES1, + IDC_EXTRA_ICON_SMS, + IDC_EXTRA_ICON_ADV1, + IDC_EXTRA_ICON_ADV2, + IDC_EXTRA_ICON_WEB, + IDC_EXTRA_ICON_CLIENT, + IDC_EXTRA_ICON_RES2, + IDC_EXTRA_ICON_ADV3, + IDC_EXTRA_ICON_ADV4 +}; + +// static UINT xImgCtrlBits[] = {6, 4, 0, 1, 2, 3, 5, 7, 8, 9, 10}; +static const UINT xImgCtrlBits[] = { + EXTRA_ICON_RES0, + EXTRA_ICON_EMAIL, + EXTRA_ICON_RES1, + EXTRA_ICON_SMS, + EXTRA_ICON_ADV1, + EXTRA_ICON_ADV2, + EXTRA_ICON_WEB, + EXTRA_ICON_CLIENT, + EXTRA_ICON_RES2, + EXTRA_ICON_ADV3, + EXTRA_ICON_ADV4 +}; + +static INT_PTR CALLBACK IgnoreDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + switch(msg) { + case WM_INITDIALOG: + { + DWORD dwMask; + struct ClcContact *contact = NULL; + int pCaps; + HWND hwndAdd; + + hContact = (HANDLE)lParam; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)hContact); + dwMask = cfg::getDword(hContact, "Ignore", "Mask1", 0); + SendMessage(hWnd, WM_USER + 100, (WPARAM)hContact, dwMask); + SendMessage(hWnd, WM_USER + 120, 0, 0); + TranslateDialogDefault(hWnd); + hwndAdd = GetDlgItem(hWnd, IDC_IGN_ADDPERMANENTLY); // CreateWindowEx(0, _T("CLCButtonClass"), _T("FOO"), WS_VISIBLE | BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, 200, 276, 106, 24, hWnd, (HMENU)IDC_IGN_ADDPERMANENTLY, g_hInst, NULL); + CustomizeButton(hwndAdd, false, true, false); + + SendMessage(hwndAdd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(210), IMAGE_ICON, 16, 16, LR_SHARED)); + SetWindowText(hwndAdd, TranslateT("Add permanently")); + EnableWindow(hwndAdd, cfg::getByte(hContact, "CList", "NotOnList", 0)); + + hwndAdd = GetDlgItem(hWnd, IDC_DSP_LOADDEFAULT); // CreateWindowEx(0, _T("CLCButtonClass"), _T("FOO"), WS_VISIBLE | BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, 200, 276, 106, 24, hWnd, (HMENU)IDC_IGN_ADDPERMANENTLY, g_hInst, NULL); + CustomizeButton(hwndAdd, false, true, false); + + SendMessage(hwndAdd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_DELETE), IMAGE_ICON, 16, 16, LR_SHARED)); + SetWindowText(hwndAdd, TranslateT("Revert to default")); + EnableWindow(hwndAdd, TRUE); + + SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Default (global setting)")); + SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Show always when available")); + SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Hide always")); + + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Default (global setting)")); + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Never")); + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Always")); + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("When space is available")); + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("When needed by status message")); + + if(cfg::clcdat) { + FindItem(pcli->hwndContactTree, cfg::clcdat, hContact, &contact, NULL, NULL); + if(contact && contact->type != CLCIT_CONTACT) { + DestroyWindow(hWnd); + return FALSE; + } + else { + TCHAR szTitle[512]; + DWORD dwFlags = cfg::getDword(hContact, "CList", "CLN_Flags", 0); + BYTE bSecondLine = cfg::getByte(hContact, "CList", "CLN_2ndline", -1); + DWORD dwXMask = cfg::getDword(hContact, "CList", "CLN_xmask", 0); + int i = 0; + + mir_sntprintf(szTitle, 512, TranslateT("Contact list display and ignore options for %s"), contact ? contact->szText : (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)); + + SetWindowText(hWnd, szTitle); + SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA)); + pCaps = CallProtoService(contact ? contact->proto : (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), PS_GETCAPS, PFLAGNUM_1, 0); + Utils::enableDlgControl(hWnd, IDC_IGN_ALWAYSONLINE, pCaps & PF1_INVISLIST ? TRUE : FALSE); + Utils::enableDlgControl(hWnd, IDC_IGN_ALWAYSOFFLINE, pCaps & PF1_VISLIST ? TRUE : FALSE); + CheckDlgButton(hWnd, IDC_IGN_PRIORITY, cfg::getByte(hContact, "CList", "Priority", 0) ? 1 : 0); + Utils::enableDlgControl(hWnd, IDC_IGN_PRIORITY, TRUE); + Utils::enableDlgControl(hWnd, IDC_AVATARDISPMODE, TRUE); + Utils::enableDlgControl(hWnd, IDC_SECONDLINEMODE, TRUE); + if(dwFlags & ECF_FORCEAVATAR) + SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 1, 0); + else if(dwFlags & ECF_HIDEAVATAR) + SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 2, 0); + else + SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 0, 0); + + if(dwFlags & ECF_FORCEOVERLAY) + SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_CHECKED, 0); + else if(dwFlags & ECF_HIDEOVERLAY) + SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_UNCHECKED, 0); + else + SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_INDETERMINATE, 0); + + if(dwFlags & ECF_FORCELOCALTIME) + SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_SETCHECK, BST_CHECKED, 0); + else if(dwFlags & ECF_HIDELOCALTIME) + SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_SETCHECK, BST_UNCHECKED, 0); + else + SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_SETCHECK, BST_INDETERMINATE, 0); + + if(dwFlags & ECF_FORCEVISIBILITY) + SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_CHECKED, 0); + else if(dwFlags & ECF_HIDEVISIBILITY) + SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_UNCHECKED, 0); + else + SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_INDETERMINATE, 0); + + while(xImgCtrlIds[i] != 0) { + if(dwXMask & (1 << (2 * xImgCtrlBits[i]))) + SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_SETCHECK, BST_CHECKED, 0); + else if(dwXMask & (1 << (2 * xImgCtrlBits[i] + 1))) + SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_SETCHECK, BST_UNCHECKED, 0); + else + SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_SETCHECK, BST_INDETERMINATE, 0); + i++; + } + + if(bSecondLine == 0xff) + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_SETCURSEL, 0, 0); + else + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_SETCURSEL, (WPARAM)(bSecondLine + 1), 0); + } + } + WindowList_Add(hWindowListIGN, hWnd, hContact); + ShowWindow(hWnd, SW_SHOWNORMAL); + } + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_IGN_PRIORITY: + SendMessage(pcli->hwndContactTree, CLM_TOGGLEPRIORITYCONTACT, (WPARAM)hContact, 0); + return 0; + case IDC_IGN_ALL: + SendMessage(hWnd, WM_USER + 100, (WPARAM)hContact, (LPARAM)0xffffffff); + return 0; + case IDC_IGN_NONE: + SendMessage(hWnd, WM_USER + 100, (WPARAM)hContact, (LPARAM)0); + return 0; + case IDC_IGN_ALWAYSONLINE: + if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSONLINE)) + CheckDlgButton(hWnd, IDC_IGN_ALWAYSOFFLINE, FALSE); + break; + case IDC_IGN_ALWAYSOFFLINE: + if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSOFFLINE)) + CheckDlgButton(hWnd, IDC_IGN_ALWAYSONLINE, FALSE); + break; + case IDC_HIDECONTACT: + cfg::writeByte(hContact, "CList", "Hidden", (BYTE)(IsDlgButtonChecked(hWnd, IDC_HIDECONTACT) ? 1 : 0)); + break; + case IDC_IGN_ADDPERMANENTLY: + { + ADDCONTACTSTRUCT acs = {0}; + + acs.handle = hContact; + acs.handleType = HANDLE_CONTACT; + acs.szProto = 0; + CallService(MS_ADDCONTACT_SHOW, (WPARAM)hWnd, (LPARAM)&acs); + Utils::enableDlgControl(hWnd, IDC_IGN_ADDPERMANENTLY, cfg::getByte(hContact, "CList", "NotOnList", 0)); + break; + } + case IDC_DSP_LOADDEFAULT: + { + int i = 0; + + SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_SETCURSEL, 0, 0); + SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_SETCURSEL, 0, 0); + while(xImgCtrlIds[i] != 0) + SendDlgItemMessage(hWnd, xImgCtrlIds[i++], BM_SETCHECK, BST_INDETERMINATE, 0); + + SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_SETCHECK, BST_INDETERMINATE, 0); + SendDlgItemMessage(hWnd, IDC_LOCALTIME, BM_SETCHECK, BST_INDETERMINATE, 0); + SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_SETCHECK, BST_INDETERMINATE, 0); + break; + } + case IDOK: + { + DWORD newMask = 0; + struct ClcContact *contact = NULL; + + SendMessage(hWnd, WM_USER + 110, 0, (LPARAM)&newMask); + cfg::writeDword(hContact, "Ignore", "Mask1", newMask); + SendMessage(hWnd, WM_USER + 130, 0, 0); + + if(cfg::clcdat) { + LRESULT iSel = SendDlgItemMessage(hWnd, IDC_AVATARDISPMODE, CB_GETCURSEL, 0, 0); + DWORD dwFlags = cfg::getDword(hContact, "CList", "CLN_Flags", 0), dwXMask = 0; + LRESULT checked = 0; + int i = 0; + + FindItem(pcli->hwndContactTree, cfg::clcdat, hContact, &contact, NULL, NULL); + if(iSel != CB_ERR) { + dwFlags &= ~(ECF_FORCEAVATAR | ECF_HIDEAVATAR); + + if(iSel == 1) + dwFlags |= ECF_FORCEAVATAR; + else if(iSel == 2) + dwFlags |= ECF_HIDEAVATAR; + if(contact) + LoadAvatarForContact(contact); + } + + dwFlags &= ~(ECF_FORCEOVERLAY | ECF_HIDEOVERLAY | ECF_FORCELOCALTIME | ECF_HIDELOCALTIME | + ECF_FORCEVISIBILITY | ECF_HIDEVISIBILITY); + + checked = SendDlgItemMessage(hWnd, IDC_OVERLAYICON, BM_GETCHECK, 0, 0); + if(checked == BST_CHECKED) + dwFlags |= ECF_FORCEOVERLAY; + else if(checked == BST_UNCHECKED) + dwFlags |= ECF_HIDEOVERLAY; + + checked = SendDlgItemMessage(hWnd, IDC_SHOWLOCALTIME1, BM_GETCHECK, 0, 0); + if(checked == BST_CHECKED) + dwFlags |= ECF_FORCELOCALTIME; + else if(checked == BST_UNCHECKED) + dwFlags |= ECF_HIDELOCALTIME; + + checked = SendDlgItemMessage(hWnd, IDC_SHOWVISIBILITY, BM_GETCHECK, 0, 0); + if(checked == BST_CHECKED) + dwFlags |= ECF_FORCEVISIBILITY; + else if(checked == BST_UNCHECKED) + dwFlags |= ECF_HIDEVISIBILITY; + + cfg::writeDword(hContact, "CList", "CLN_Flags", dwFlags); + + if ((iSel = SendDlgItemMessage(hWnd, IDC_SECONDLINEMODE, CB_GETCURSEL, 0, 0)) != CB_ERR) { + if(iSel == 0) { + DBDeleteContactSetting(hContact, "CList", "CLN_2ndline"); + if(contact) + contact->bSecondLine = cfg::dat.dualRowMode; + } + else { + DBWriteContactSettingByte(hContact, "CList", "CLN_2ndline", (BYTE)(iSel - 1)); + if(contact) + contact->bSecondLine = (BYTE)(iSel - 1); + } + } + while(xImgCtrlIds[i] != 0) { + checked = SendDlgItemMessage(hWnd, xImgCtrlIds[i], BM_GETCHECK, 0, 0); + if(checked == BST_CHECKED) + dwXMask |= (1 << (2 * xImgCtrlBits[i])); + else if(checked == BST_UNCHECKED) + dwXMask |= (1 << (2 * xImgCtrlBits[i] + 1)); + i++; + } + cfg::writeDword(hContact, "CList", "CLN_xmask", dwXMask); + if(contact) { + if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry <= cfg::nextCacheEntry) { + cfg::eCache[contact->extraCacheEntry].dwDFlags = dwFlags; + cfg::eCache[contact->extraCacheEntry].dwXMask = CalcXMask(hContact); + } + } + else { + int iIndex = cfg::getCache(hContact, NULL); + if(iIndex >= 0 && iIndex <= cfg::nextCacheEntry) { + cfg::eCache[iIndex].dwDFlags = dwFlags; + cfg::eCache[iIndex].dwXMask = CalcXMask(hContact); + } + } + cfg::writeByte(hContact, "CList", "Priority", (BYTE)(IsDlgButtonChecked(hWnd, IDC_IGN_PRIORITY) ? 1 : 0)); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + } + } + case IDCANCEL: + DestroyWindow(hWnd); + break; + } + break; + case WM_USER + 100: // fill dialog (wParam = hContact, lParam = mask) + { + CheckDlgButton(hWnd, IDC_IGN_MSGEVENTS, lParam & (1 << (IGNOREEVENT_MESSAGE - 1)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hWnd, IDC_IGN_FILEEVENTS, lParam & (1 << (IGNOREEVENT_FILE - 1)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hWnd, IDC_IGN_URLEVENTS, lParam & (1 << (IGNOREEVENT_URL - 1)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hWnd, IDC_IGN_AUTH, lParam & (1 << (IGNOREEVENT_AUTHORIZATION - 1)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hWnd, IDC_IGN_ADD, lParam & (1 << (IGNOREEVENT_YOUWEREADDED - 1)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hWnd, IDC_IGN_ONLINE, lParam & (1 << (IGNOREEVENT_USERONLINE - 1)) ? BST_CHECKED : BST_UNCHECKED); + return 0; + } + case WM_USER + 110: // retrieve value + { + DWORD *dwNewMask = (DWORD *)lParam, dwMask = 0; + + dwMask = (IsDlgButtonChecked(hWnd, IDC_IGN_MSGEVENTS) ? (1 << (IGNOREEVENT_MESSAGE - 1)) : 0) | + (IsDlgButtonChecked(hWnd, IDC_IGN_FILEEVENTS) ? (1 << (IGNOREEVENT_FILE - 1)) : 0) | + (IsDlgButtonChecked(hWnd, IDC_IGN_URLEVENTS) ? (1 << (IGNOREEVENT_URL - 1)) : 0) | + (IsDlgButtonChecked(hWnd, IDC_IGN_AUTH) ? (1 << (IGNOREEVENT_AUTHORIZATION - 1)) : 0) | + (IsDlgButtonChecked(hWnd, IDC_IGN_ADD) ? (1 << (IGNOREEVENT_YOUWEREADDED - 1)) : 0) | + (IsDlgButtonChecked(hWnd, IDC_IGN_ONLINE) ? (1 << (IGNOREEVENT_USERONLINE - 1)) : 0); + + if(dwNewMask) + *dwNewMask = dwMask; + return 0; + } + case WM_USER + 120: // set visibility status + { + struct ClcContact *contact = NULL; + + if(FindItem(pcli->hwndContactTree, cfg::clcdat, hContact, &contact, NULL, NULL)) { + if(contact) { + WORD wApparentMode = cfg::getWord(contact->hContact, contact->proto, "ApparentMode", 0); + + CheckDlgButton(hWnd, IDC_IGN_ALWAYSOFFLINE, wApparentMode == ID_STATUS_OFFLINE ? TRUE : FALSE); + CheckDlgButton(hWnd, IDC_IGN_ALWAYSONLINE, wApparentMode == ID_STATUS_ONLINE ? TRUE : FALSE); + } + } + return 0; + } + case WM_USER + 130: // update apparent mode + { + struct ClcContact *contact = NULL; + + if(FindItem(pcli->hwndContactTree, cfg::clcdat, hContact, &contact, NULL, NULL)) { + if(contact) { + WORD wApparentMode = 0, oldApparentMode = cfg::getWord(hContact, contact->proto, "ApparentMode", 0); + + if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSONLINE)) + wApparentMode = ID_STATUS_ONLINE; + else if(IsDlgButtonChecked(hWnd, IDC_IGN_ALWAYSOFFLINE)) + wApparentMode = ID_STATUS_OFFLINE; + + //DBWriteContactSettingWord(hContact, contact->proto, "ApparentMode", wApparentMode); + //if(oldApparentMode != wApparentMode) + CallContactService(hContact, PSS_SETAPPARENTMODE, (WPARAM)wApparentMode, 0); + SendMessage(hWnd, WM_USER + 120, 0, 0); + } + } + return 0; + } + case WM_DESTROY: + SetWindowLongPtr(hWnd, GWLP_USERDATA, 0); + WindowList_Remove(hWindowListIGN, hWnd); + break; + } + return FALSE; +} + +/* + * service function: Open ignore settings dialog for the contact handle in wParam + * (clist_nicer+ specific service) + * + * Servicename = CList/SetContactIgnore + * + * ensure that dialog is only opened once (the dialog proc saves the window handle of an open dialog + * of this type to the contacts database record). + * + * if dialog is already open, focus it. +*/ + +static INT_PTR SetContactIgnore(WPARAM wParam, LPARAM lParam) +{ + HWND hWnd = 0; + + if(hWindowListIGN == 0) + hWindowListIGN = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + + hWnd = WindowList_Find(hWindowListIGN, (HANDLE)wParam); + if ( wParam ) { + if ( hWnd == 0 ) + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_QUICKIGNORE), 0, IgnoreDialogProc, (LPARAM)wParam); + else if ( IsWindow( hWnd )) + SetFocus(hWnd); + } + return 0; +} + +/* + * service function: Set a contacts floating status. + * (clist_nicer+ specific service) + * + * Servicename = CList/SetContactFloating + * + * a floating contact appears as a small independent top level window anywhere on + * the desktop. +*/ + +static INT_PTR SetContactFloating(WPARAM wParam, LPARAM lParam) +{ + SendMessage(pcli->hwndContactTree, CLM_TOGGLEFLOATINGCONTACT, wParam, lParam); + return 0; +} + +int InitCustomMenus(void) +{ + CreateServiceFunction("CloseAction",CloseAction); + CreateServiceFunction("CList/SetContactFloating", SetContactFloating); + CreateServiceFunction("CList/SetContactIgnore", SetContactIgnore); + { + //FYR: Visibility and ignore item moved back to clist_nicer from core + HANDLE hIgnoreItem = 0; // FYR: moved from global it is never used globally + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof( mi ); + + if ( !hIgnoreItem ) { + mi.position = 200000; + mi.pszPopupName = ( char* )-1; + mi.pszService = "CList/SetContactIgnore"; + mi.pszName = LPGEN("&Contact list settings..."); + hIgnoreItem = Menu_AddContactMenuItem(&mi); + } + } + hMainStatusMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0); + hMainMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0); + + return 0; +} + +void UninitCustomMenus(void) +{ + +} diff --git a/plugins/Clist_nicer/src/clistmod.cpp b/plugins/Clist_nicer/src/clistmod.cpp new file mode 100644 index 0000000000..e6f88e51ee --- /dev/null +++ b/plugins/Clist_nicer/src/clistmod.cpp @@ -0,0 +1,258 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clistmod.cpp 12978 2010-10-17 06:50:51Z silvercircle $ + * + */ + +#include + +BOOL (WINAPI *MySetProcessWorkingSetSize)(HANDLE, SIZE_T, SIZE_T) = 0; + +extern int AddEvent(WPARAM wParam, LPARAM lParam); +extern int RemoveEvent(WPARAM wParam, LPARAM lParam); + +int InitCustomMenus(void); +void UninitCustomMenus(void); +INT_PTR GetContactStatusMessage(WPARAM wParam, LPARAM lParam); +void TrayIconUpdateBase(const char *szChangedProto); +int EventsProcessContactDoubleClick(HANDLE hContact); +int SetHideOffline(WPARAM wParam, LPARAM lParam); + +extern HIMAGELIST hCListImages; + +extern int g_maxStatus; +extern HANDLE hSvc_GetContactStatusMsg; +extern ImageItem *g_CLUIImageItem; + +static INT_PTR GetStatusMode(WPARAM wParam, LPARAM lParam) +{ + return(g_maxStatus == ID_STATUS_OFFLINE ? pcli->currentDesiredStatusMode : g_maxStatus); +} + +extern int ( *saveIconFromStatusMode )( const char *szProto, int status, HANDLE hContact ); + +int IconFromStatusMode(const char *szProto, int status, HANDLE hContact, HICON *phIcon) +{ + char *szFinalProto; + int finalStatus; + + if (szProto != NULL && !strcmp(szProto, cfg::dat.szMetaName) && cfg::dat.bMetaAvail && hContact != 0 && !(cfg::dat.dwFlags & CLUI_USEMETAICONS)) { + HANDLE hSubContact = (HANDLE) CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM) hContact, 0); + szFinalProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hSubContact, 0); + finalStatus = (status == 0) ? (WORD) cfg::getWord(hSubContact, szFinalProto, "Status", ID_STATUS_OFFLINE) : status; + } else { + szFinalProto = (char*) szProto; + finalStatus = status; + } + + if(status >= ID_STATUS_CONNECTING && status < ID_STATUS_OFFLINE && phIcon != NULL) { + if(szProto) { + char szBuf[128]; + mir_snprintf(szBuf, 128, "%s_conn", szProto); + *phIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szBuf); + } + } + return saveIconFromStatusMode(szFinalProto, finalStatus, hContact); +} + +static int MenuItem_LockAvatar(WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +static int ContactListShutdownProc(WPARAM wParam, LPARAM lParam) +{ + UninitCustomMenus(); + return 0; +} + +int LoadContactListModule(void) +{ + HookEvent(ME_SYSTEM_SHUTDOWN, ContactListShutdownProc); + CreateServiceFunction(MS_CLIST_GETSTATUSMODE, GetStatusMode); + + hSvc_GetContactStatusMsg = CreateServiceFunction("CList/GetContactStatusMsg", GetContactStatusMessage); + InitCustomMenus(); + MySetProcessWorkingSetSize = (BOOL(WINAPI *)(HANDLE, SIZE_T, SIZE_T))GetProcAddress(GetModuleHandleA("kernel32"), "SetProcessWorkingSetSize"); + return 0; +} + +/* +Begin of Hrk's code for bug +*/ +#define GWVS_HIDDEN 1 +#define GWVS_VISIBLE 2 +#define GWVS_COVERED 3 +#define GWVS_PARTIALLY_COVERED 4 + +int GetWindowVisibleState(HWND hWnd, int iStepX, int iStepY) +{ + RECT rc = {0}, rcUpdate = {0}; + POINT pt = {0}; + register int i = 0, j = 0, width = 0, height = 0, iCountedDots = 0, iNotCoveredDots = 0; + BOOL bPartiallyCovered = FALSE; + HWND hAux = 0; + + if (hWnd == NULL) { + SetLastError(0x00000006); //Wrong handle + return -1; + } + //Some defaults now. The routine is designed for thin and tall windows. + + if (IsIconic(hWnd) || !IsWindowVisible(hWnd)) + return GWVS_HIDDEN; + else { + HRGN rgn = 0; + POINT ptOrig; + RECT rcClient; + int clip = (int)cfg::dat.bClipBorder; + + GetClientRect(hWnd, &rcClient); + ptOrig.x = ptOrig.y = 0; + ClientToScreen(hWnd, &ptOrig); + rc.left = ptOrig.x; + rc.top = ptOrig.y; + rc.right = rc.left + rcClient.right; + rc.bottom = rc.top + rcClient.bottom; + + //GetWindowRect(hWnd, &rc); + width = rc.right - rc.left; + height = rc.bottom - rc.top; + + if (iStepX <= 0) + iStepX = 4; + if (iStepY <= 0) + iStepY = 16; + + /* + * use a rounded clip region to determine which pixels are covered + * this will avoid problems with certain XP themes which are using transparency for rounded + * window frames (reluna being one popular example). + + * the radius of 8 should be sufficient for most themes as they usually don't use bigger + * radii. + * also, clip at least 2 pixels from the border (same reason) + */ + + if(g_CLUIImageItem) + clip = 5; + else + clip = 0; + //clip = max(clip, DBGetContactSettingByte(NULL, "CLUI", "ignoreframepixels", 2)); + //rgn = CreateRoundRectRgn(rc.left + clip, rc.top + clip, rc.right - clip, rc.bottom - clip, 10 + clip, 10 + clip); + //rgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom); + //for (i = rc.top + 3 + clip; i < rc.bottom - 3 - clip; i += (height / iStepY)) { + for (i = rc.top + clip; i < rc.bottom; i += (height / iStepY)) { + pt.y = i; + //for (j = rc.left + 3 + clip; j < rc.right - 3 - clip; j += (width / iStepX)) { + for (j = rc.left + clip; j < rc.right; j += (width / iStepX)) { + /*if(rgn) { + ptTest.x = j; + ptTest.y = i; + if (!PtInRegion(rgn, ptTest.x, ptTest.y)) { + continue; + } + }*/ + pt.x = j; + hAux = WindowFromPoint(pt); + while (GetParent(hAux) != NULL) + hAux = GetParent(hAux); + if (hAux != hWnd && hAux) //There's another window! + bPartiallyCovered = TRUE; + else + iNotCoveredDots++; //Let's count the not covered dots. + iCountedDots++; //Let's keep track of how many dots we checked. + } + } + if(rgn) + DeleteObject(rgn); + + if (iNotCoveredDots == iCountedDots) //Every dot was not covered: the window is visible. + return GWVS_VISIBLE; + else if (iNotCoveredDots == 0) //They're all covered! + return GWVS_COVERED; + else //There are dots which are visible, but they are not as many as the ones we counted: it's partially covered. + return GWVS_PARTIALLY_COVERED; + } +} + +int ShowHide(WPARAM wParam, LPARAM lParam) +{ + BOOL bShow = FALSE; + + int iVisibleState = pcli->pfnGetWindowVisibleState(pcli->hwndContactList, 0, 0); + + if(IsIconic(pcli->hwndContactList)) { + SendMessage(pcli->hwndContactList, WM_SYSCOMMAND, SC_RESTORE, 0); + bShow = TRUE; + } + else { + switch (iVisibleState) { + case GWVS_PARTIALLY_COVERED: + //If we don't want to bring it to top, we can use a simple break. This goes against readability ;-) but the comment explains it. + if (!cfg::getByte("CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT)) + break; + case GWVS_COVERED: //Fall through (and we're already falling) + case GWVS_HIDDEN: + bShow = TRUE; + break; + case GWVS_VISIBLE: //This is not needed, but goes for readability. + bShow = FALSE; + break; + case -1: //We can't get here, both cli.hwndContactList and iStepX and iStepY are right. + return 0; + } + } + + if (bShow == TRUE) { + RECT rcWindow; + + SetWindowPos(pcli->hwndContactList, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOCOPYBITS); + if (!cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT)) + SetWindowPos(pcli->hwndContactList, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_NOCOPYBITS); + SetForegroundWindow(pcli->hwndContactList); + //SetActiveWindow(pcli->hwndContactList); + ShowWindow(pcli->hwndContactList, SW_SHOW); + cfg::writeByte("CList", "State", SETTING_STATE_NORMAL); + + GetWindowRect(pcli->hwndContactList, &rcWindow); + if (Utils_AssertInsideScreen(&rcWindow) == 1) + { + MoveWindow(pcli->hwndContactList, rcWindow.left, rcWindow.top, + rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE); + } + } + else { //It needs to be hidden + ShowWindow(pcli->hwndContactList, SW_HIDE); + cfg::writeByte("CList", "State", SETTING_STATE_HIDDEN); + if (MySetProcessWorkingSetSize != NULL && cfg::getByte("CList", "DisableWorkingSet", 1)) + MySetProcessWorkingSetSize(GetCurrentProcess(), -1, -1); + } + return 0; +} diff --git a/plugins/Clist_nicer/src/clistopts.cpp b/plugins/Clist_nicer/src/clistopts.cpp new file mode 100644 index 0000000000..dcb628243a --- /dev/null +++ b/plugins/Clist_nicer/src/clistopts.cpp @@ -0,0 +1,220 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE done + +*/ +#include "commonheaders.h" + +void LoadContactTree(void); +void SortContacts(void); + +static int opt_gen_opts_changed = 0; + +static void __setFlag(DWORD dwFlag, int iMode) +{ + cfg::dat.dwFlags = iMode ? cfg::dat.dwFlags | dwFlag : cfg::dat.dwFlags & ~dwFlag; +} + +INT_PTR CALLBACK DlgProcGenOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_USER+1: + { + HANDLE hContact = (HANDLE) wParam; + DBCONTACTWRITESETTING *ws = (DBCONTACTWRITESETTING *) lParam; + if (hContact == NULL && ws != NULL && ws->szModule != NULL && ws->szSetting != NULL && lstrcmpiA(ws->szModule, "CList") == 0 && lstrcmpiA(ws->szSetting, "UseGroups") == 0 && IsWindowVisible(hwndDlg)) { + CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, ws->value.bVal == 0); + } + break; + } + case WM_DESTROY: + UnhookEvent((HANDLE) GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); + break; + + case WM_INITDIALOG: + opt_gen_opts_changed = 0; + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED, hwndDlg, WM_USER + 1)); + CheckDlgButton(hwndDlg, IDC_ONTOP, cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, cfg::getByte(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_HIDEEMPTYGROUPS, cfg::getByte("CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, cfg::getByte("CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_CONFIRMDELETE, cfg::getByte("CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + { + DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0); + if (!(caps & CLUIF_HIDEEMPTYGROUPS)) + ShowWindow(GetDlgItem(hwndDlg, IDC_HIDEEMPTYGROUPS), SW_HIDE); + if (!(caps & CLUIF_DISABLEGROUPS)) + ShowWindow(GetDlgItem(hwndDlg, IDC_DISABLEGROUPS), SW_HIDE); + if (caps & CLUIF_HASONTOPOPTION) + ShowWindow(GetDlgItem(hwndDlg, IDC_ONTOP), SW_HIDE); + if (caps & CLUIF_HASAUTOHIDEOPTION) { + } + } + + CheckDlgButton(hwndDlg, IDC_SHOWBOTTOMBUTTONS, cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS); + CheckDlgButton(hwndDlg, IDC_CLISTSUNKEN, cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN); + CheckDlgButton(hwndDlg, IDC_EVENTAREAAUTOHIDE, cfg::dat.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY); + CheckDlgButton(hwndDlg, IDC_EVENTAREASUNKEN, (cfg::dat.dwFlags & CLUI_FRAME_EVENTAREASUNKEN) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(hwndDlg, IDC_ONECLK, cfg::getByte("CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSSTATUS, cfg::getByte("CList", "AlwaysStatus", SETTING_ALWAYSSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSMULTI, !cfg::getByte("CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DONTCYCLE, cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CYCLE, cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_CYCLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MULTITRAY, cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DISABLEBLINK, cfg::getByte("CList", "DisableTrayFlash", 0) == 1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ICONBLINK, cfg::getByte("CList", "NoIconBlink", 0) == 1 ? BST_CHECKED : BST_UNCHECKED); + if (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE)) { + Utils::enableDlgControl(hwndDlg, IDC_CYCLETIMESPIN, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_CYCLETIME, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_ALWAYSMULTI, FALSE); + } + if (IsDlgButtonChecked(hwndDlg, IDC_CYCLE)) { + Utils::enableDlgControl(hwndDlg, IDC_PRIMARYSTATUS, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_ALWAYSMULTI, FALSE); + } + if (IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY)) { + Utils::enableDlgControl(hwndDlg, IDC_CYCLETIMESPIN, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_CYCLETIME, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_PRIMARYSTATUS, FALSE); + } + SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETRANGE, 0, MAKELONG(120, 1)); + SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CList", "CycleTime", SETTING_CYCLETIME_DEFAULT), 0)); { + int i, count, item; + PROTOACCOUNT **accs; + DBVARIANT dbv = { + DBVT_DELETED + }; + DBGetContactSetting(NULL, "CList", "PrimaryStatus", &dbv); + ProtoEnumAccounts( &count, &accs ); + item = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) TranslateT("Global")); + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM) 0); + for (i = 0; i < count; i++) { + if ( !IsAccountEnabled(accs[i]) || CallProtoService(accs[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) == 0) + continue; + + item = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_ADDSTRING, 0, (LPARAM) accs[i]->tszAccountName); + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETITEMDATA, item, (LPARAM)accs[i] ); + if (dbv.type == DBVT_ASCIIZ && !lstrcmpA(dbv.pszVal, accs[i]->szModuleName )) + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, item, 0); + } + } + if (-1 == (int) SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0)) + SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_SETCURSEL, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETBUDDY, (WPARAM) GetDlgItem(hwndDlg, IDC_BLINKTIME), 0); // set buddy + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETRANGE, 0, MAKELONG(0x3FFF, 250)); + SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CList", "IconFlashTime", 550), 0)); + CheckDlgButton(hwndDlg, IDC_NOTRAYINFOTIPS, cfg::dat.bNoTrayTips ? 1 : 0); + CheckDlgButton(hwndDlg, IDC_APPLYLASTVIEWMODE, cfg::getByte("CList", "AutoApplyLastViewMode", 0) ? 1 : 0); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_DONTCYCLE || LOWORD(wParam) == IDC_CYCLE || LOWORD(wParam) == IDC_MULTITRAY) { + Utils::enableDlgControl(hwndDlg, IDC_PRIMARYSTATUS, IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE)); + Utils::enableDlgControl(hwndDlg, IDC_CYCLETIME, IsDlgButtonChecked(hwndDlg, IDC_CYCLE)); + Utils::enableDlgControl(hwndDlg, IDC_CYCLETIMESPIN, IsDlgButtonChecked(hwndDlg, IDC_CYCLE)); + Utils::enableDlgControl(hwndDlg, IDC_ALWAYSMULTI, IsDlgButtonChecked(hwndDlg, IDC_MULTITRAY)); + } + if ((LOWORD(wParam) == IDC_CYCLETIME) && HIWORD(wParam) != EN_CHANGE) + break; + if (LOWORD(wParam) == IDC_PRIMARYSTATUS && HIWORD(wParam) != CBN_SELCHANGE) + break; + if ((LOWORD(wParam) == IDC_CYCLETIME) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + if (LOWORD(wParam) == IDC_BLINKTIME && HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; // dont make apply enabled during buddy set crap + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + opt_gen_opts_changed = TRUE; + break; + + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + if (!opt_gen_opts_changed) + return TRUE; + + cfg::writeByte("CList", "HideOffline", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEOFFLINE)); + { + DWORD caps = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS1, 0); + if (caps & CLUIF_HIDEEMPTYGROUPS) + cfg::writeByte("CList", "HideEmptyGroups", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_HIDEEMPTYGROUPS)); + if (caps & CLUIF_DISABLEGROUPS) + cfg::writeByte("CList", "UseGroups", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_DISABLEGROUPS)); + if (!(caps & CLUIF_HASONTOPOPTION)) { + cfg::writeByte("CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP)); + SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + if (!(caps & CLUIF_HASAUTOHIDEOPTION)) { + } + } + cfg::writeByte("CList", "ConfirmDelete", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CONFIRMDELETE)); + cfg::writeByte("CList", "Tray1Click", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONECLK)); + cfg::writeByte("CList", "AlwaysStatus", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ALWAYSSTATUS)); + cfg::writeByte("CList", "AlwaysMulti", (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_ALWAYSMULTI)); + cfg::writeByte("CList", "TrayIcon", (BYTE) (IsDlgButtonChecked(hwndDlg, IDC_DONTCYCLE) ? SETTING_TRAYICON_SINGLE : (IsDlgButtonChecked(hwndDlg, IDC_CYCLE) ? SETTING_TRAYICON_CYCLE : SETTING_TRAYICON_MULTI))); + cfg::writeWord("CList", "CycleTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_CYCLETIMESPIN, UDM_GETPOS, 0, 0)); + cfg::writeWord("CList", "IconFlashTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_BLINKSPIN, UDM_GETPOS, 0, 0)); + cfg::writeByte("CList", "DisableTrayFlash", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DISABLEBLINK)); + cfg::writeByte("CList", "NoIconBlink", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ICONBLINK)); + cfg::writeByte("CList", "AutoApplyLastViewMode", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_APPLYLASTVIEWMODE)); + + __setFlag(CLUI_FRAME_EVENTAREASUNKEN, IsDlgButtonChecked(hwndDlg, IDC_EVENTAREASUNKEN)); + __setFlag(CLUI_FRAME_AUTOHIDENOTIFY, IsDlgButtonChecked(hwndDlg, IDC_EVENTAREAAUTOHIDE)); + + __setFlag(CLUI_FRAME_SHOWBOTTOMBUTTONS, IsDlgButtonChecked(hwndDlg, IDC_SHOWBOTTOMBUTTONS)); + __setFlag(CLUI_FRAME_CLISTSUNKEN, IsDlgButtonChecked(hwndDlg, IDC_CLISTSUNKEN)); + + cfg::dat.bNoTrayTips = IsDlgButtonChecked(hwndDlg, IDC_NOTRAYINFOTIPS) ? 1 : 0; + cfg::writeByte("CList", "NoTrayTips", (BYTE)cfg::dat.bNoTrayTips); + { + int cursel = SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETCURSEL, 0, 0); + PROTOACCOUNT* pa = (PROTOACCOUNT*)SendDlgItemMessage(hwndDlg, IDC_PRIMARYSTATUS, CB_GETITEMDATA, cursel, 0); + if ( !pa ) + DBDeleteContactSetting(NULL, "CList", "PrimaryStatus"); + else + cfg::writeString(NULL, "CList", "PrimaryStatus", pa->szModuleName ); + } + pcli->pfnTrayIconIconsChanged(); + cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags); + ConfigureFrame(); + ConfigureCLUIGeometry(1); + ConfigureEventArea(pcli->hwndContactList); + HideShowNotifyFrame(); + SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + LoadContactTree(); /* this won't do job properly since it only really works when changes happen */ + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + + opt_gen_opts_changed = 0; + return TRUE; + } + break; + } + break; + } + return FALSE; +} diff --git a/plugins/Clist_nicer/src/clistsettings.cpp b/plugins/Clist_nicer/src/clistsettings.cpp new file mode 100644 index 0000000000..708abb0853 --- /dev/null +++ b/plugins/Clist_nicer/src/clistsettings.cpp @@ -0,0 +1,33 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE done + +*/ +#include "commonheaders.h" + +INT_PTR GetContactStatusMessage(WPARAM wParam, LPARAM lParam) +{ + if (!cfg::shutDown) + return SendMessage(pcli->hwndContactTree, CLM_GETSTATUSMSG, wParam, lParam); + return 0; +} diff --git a/plugins/Clist_nicer/src/clisttray.cpp b/plugins/Clist_nicer/src/clisttray.cpp new file mode 100644 index 0000000000..7a20e71ce3 --- /dev/null +++ b/plugins/Clist_nicer/src/clisttray.cpp @@ -0,0 +1,171 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE done + +*/ +#include "commonheaders.h" + +#define TRAYICON_ID_BASE 100 +#define TIM_CALLBACK (WM_USER+1857) +#define TIM_CREATE (WM_USER+1858) + +extern HIMAGELIST hCListImages; + +// don't move to win2k.h, need new and old versions to work on 9x/2000/XP +#define NIF_STATE 0x00000008 +#define NIF_INFO 0x00000010 + +void TrayIconUpdateBase(const char *szChangedProto) +{ + int i,count,netProtoCount,changed = -1; + PROTOACCOUNT **accs; + int averageMode = 0; + HWND hwnd = pcli->hwndContactList; + + if (pcli->cycleTimerId) + KillTimer(NULL, pcli->cycleTimerId); pcli->cycleTimerId = 0; + + ProtoEnumAccounts( &count, &accs ); + for (i = 0,netProtoCount = 0; i < count; i++) { + if ( !pcli->pfnGetProtocolVisibility( accs[i]->szModuleName )) + continue; + netProtoCount++; + if (!lstrcmpA(szChangedProto, accs[i]->szModuleName )) + pcli->cycleStep = i; + if (averageMode == 0) + averageMode = CallProtoService( accs[i]->szModuleName, PS_GETSTATUS, 0, 0); + else if (averageMode != CallProtoService( accs[i]->szModuleName, PS_GETSTATUS, 0, 0)) { + averageMode = -1; break; + } + } + if (netProtoCount > 1) { + if (averageMode > 0) { + if (cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI) { + if (cfg::getByte("CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT)) { + HICON hIcon = 0; + int iIcon = IconFromStatusMode(szChangedProto, averageMode, 0, &hIcon); + if(hIcon) + changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), szChangedProto); + else + changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL), szChangedProto); + } + else if (pcli->trayIcon && pcli->trayIcon[0].szProto != NULL) { + pcli->pfnTrayIconDestroy(hwnd); + pcli->pfnTrayIconInit(hwnd); + } + else { + HICON hIcon = 0; + int iIcon = IconFromStatusMode(NULL, averageMode, 0, &hIcon); + + if(hIcon) + changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL); + else + changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL), NULL); + } + } else { + HICON hIcon = 0; + int iIcon = IconFromStatusMode(NULL, averageMode, 0, &hIcon); + + if(hIcon) + changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL); + else + changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL), NULL); + } + } else { + switch (cfg::getByte("CList", "TrayIcon", SETTING_TRAYICON_DEFAULT)) { + case SETTING_TRAYICON_SINGLE: + { + DBVARIANT dbv = {DBVT_DELETED}; + int iIcon = 0; + HICON hIcon = 0; + char *szProto; + if (cfg::getString(NULL, "CList", "PrimaryStatus", &dbv)) + szProto = NULL; + else + szProto = dbv.pszVal; + iIcon = IconFromStatusMode(szProto, szProto ? CallProtoService(szProto, PS_GETSTATUS, 0, 0) : CallService(MS_CLIST_GETSTATUSMODE, 0, 0), 0, &hIcon); + if(hIcon) + changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL); + else + changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL), NULL); + DBFreeVariant(&dbv); + break; + } + case SETTING_TRAYICON_CYCLE: + { + HICON hIcon = 0; + int iIcon = IconFromStatusMode(szChangedProto, CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0), 0, &hIcon); + + pcli->cycleTimerId = SetTimer(NULL, 0, cfg::getWord("CList", "CycleTime", SETTING_CYCLETIME_DEFAULT) * 1000, pcli->pfnTrayCycleTimerProc); + if(hIcon) + changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL); + else + changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL), NULL); + break; + } + case SETTING_TRAYICON_MULTI: + if ( !pcli->trayIcon ) + pcli->pfnTrayIconRemove(NULL, NULL); + else if (cfg::getByte("CList", "AlwaysMulti", SETTING_ALWAYSMULTI_DEFAULT)) { + HICON hIcon = 0; + int iIcon = IconFromStatusMode(szChangedProto, CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0), 0, &hIcon); + + if(hIcon) + changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), szChangedProto); + else + changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL), szChangedProto); + } + else { + pcli->pfnTrayIconDestroy(hwnd); + pcli->pfnTrayIconInit(hwnd); + } + break; + } + } + } else { + HICON hIcon = 0; + int iIcon = IconFromStatusMode(NULL, averageMode, 0, &hIcon); + if ( hIcon ) + changed = pcli->pfnTrayIconSetBaseInfo(CopyIcon(hIcon), NULL); + else + changed = pcli->pfnTrayIconSetBaseInfo(ImageList_GetIcon(hCListImages, iIcon, ILD_NORMAL), NULL); + } + if (changed != -1 && pcli->trayIcon[changed].isBase) + pcli->pfnTrayIconUpdate( pcli->trayIcon[changed].hBaseIcon, NULL, pcli->trayIcon[changed].szProto, 1); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +extern INT_PTR ( *saveTrayIconProcessMessage )(WPARAM wParam, LPARAM lParam); + +INT_PTR TrayIconProcessMessage(WPARAM wParam, LPARAM lParam) +{ + MSG* msg = ( MSG* )wParam; + if ( msg->message == TIM_CALLBACK && msg->lParam == WM_MOUSEMOVE ) { + if ( cfg::dat.bNoTrayTips ) { + *((LRESULT *) lParam) = 0; + return TRUE; + } } + + return saveTrayIconProcessMessage(wParam, lParam); +} diff --git a/plugins/Clist_nicer/src/clnplus.cpp b/plugins/Clist_nicer/src/clnplus.cpp new file mode 100644 index 0000000000..24c5fdddff --- /dev/null +++ b/plugins/Clist_nicer/src/clnplus.cpp @@ -0,0 +1,40 @@ +/* + * test for gdi+ + */ + +#include +#include + +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0501 + +#define _CLN_GDIP + + +#undef Translate + +void RemoveFromTaskBar(HWND hWnd) +{ + ITaskbarList *pTaskbarList = NULL; + + if (SUCCEEDED(CoCreateInstance(CLSID_TaskbarList, 0, CLSCTX_INPROC_SERVER, IID_ITaskbarList, + (void **)(&pTaskbarList))) && pTaskbarList != NULL) { + if (SUCCEEDED(pTaskbarList->HrInit())) { + pTaskbarList->DeleteTab(hWnd); + } + pTaskbarList->Release(); + } +} + +void AddToTaskBar(HWND hWnd) +{ + ITaskbarList *pTaskbarList = NULL; + + if (SUCCEEDED(CoCreateInstance(CLSID_TaskbarList, 0, CLSCTX_INPROC_SERVER, IID_ITaskbarList, + (void **)(&pTaskbarList))) && pTaskbarList != NULL) { + if (SUCCEEDED(pTaskbarList->HrInit())) { + pTaskbarList->AddTab(hWnd); + } + pTaskbarList->Release(); + } +} diff --git a/plugins/Clist_nicer/src/clui.cpp b/plugins/Clist_nicer/src/clui.cpp new file mode 100644 index 0000000000..9e5f2dbeac --- /dev/null +++ b/plugins/Clist_nicer/src/clui.cpp @@ -0,0 +1,2191 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clui.cpp 13813 2011-08-31 21:49:46Z borkra $ + * + */ + +#include +#include +#include +#include "../cluiframes/cluiframes.h" +#include "../coolsb/coolscroll.h" + +#define TM_AUTOALPHA 1 +#define TIMERID_AUTOSIZE 100 +#define MENU_MIRANDAMENU 0xFFFF1234 + +int g_fading_active = 0; + +static RECT g_PreSizeRect, g_SizingRect; +static int g_sizingmethod; +static LONG g_CLUI_x_off, g_CLUI_y_off, g_CLUI_y1_off, g_CLUI_x1_off; +static RECT rcWPC; + +static int transparentFocus = 1; +static byte oldhideoffline; +static int disableautoupd = 1; +HANDLE hFrameContactTree; +extern HIMAGELIST hCListImages; +extern PLUGININFOEX pluginInfo; +extern WNDPROC OldStatusBarProc; +extern RECT old_window_rect, new_window_rect; + +extern BOOL g_trayTooltipActive; +extern POINT tray_hover_pos; +extern HWND g_hwndViewModeFrame, g_hwndEventArea; + +extern ImageItem *g_CLUIImageItem; +extern HBRUSH g_CLUISkinnedBkColor; +extern StatusItems_t *StatusItems; +extern HWND g_hwndSFL; +extern ButtonItem *g_ButtonItems; +extern COLORREF g_CLUISkinnedBkColorRGB; +extern wndFrame *wndFrameCLC; + +HIMAGELIST himlExtraImages = 0; + +static BYTE old_cliststate, show_on_first_autosize = FALSE; + +RECT cluiPos; + +TCHAR *statusNames[12]; + +extern LRESULT CALLBACK EventAreaWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern HANDLE hNotifyFrame; + +int SortList(WPARAM wParam, LPARAM lParam); +int LoadCluiServices(void); +void InitGroupMenus(); +void ReloadExtraIcons(); +void FS_RegisterFonts(); +void LoadExtraIconModule(); +int MTG_OnmodulesLoad(WPARAM wParam, LPARAM lParam); +void RemoveFromTaskBar(HWND hWnd); +void FLT_ShowHideAll(int showCmd); +void FLT_SnapToEdges(HWND hwnd); +void DestroyTrayMenu(HMENU hMenu); + +extern LONG g_cxsmIcon, g_cysmIcon; +extern HANDLE hIcoLibChanged; +extern HANDLE hExtraImageListRebuilding, hExtraImageApplying; + +SIZE g_oldSize = {0}; +POINT g_oldPos = {0}; +int during_sizing = 0; +extern int dock_prevent_moving; + +static HDC hdcLockedPoint = 0; +static HBITMAP hbmLockedPoint = 0, hbmOldLockedPoint = 0; + +HICON overlayicons[10]; + +static struct IconDesc myIcons[] = { + { "CLN_online", LPGEN("Toggle show online/offline"), -IDI_HIDEOFFLINE }, + { "CLN_groups", LPGEN("Toggle groups"), -IDI_HIDEGROUPS }, + { "CLN_findadd", LPGEN("Find contacts"), -IDI_FINDANDADD }, + { "CLN_options", LPGEN("Open preferences"), -IDI_TBOPTIONS }, + { "CLN_sound", LPGEN("Toggle sounds"), -IDI_SOUNDSON }, + { "CLN_minimize", LPGEN("Minimize contact list"), -IDI_MINIMIZE }, + { "CLN_slist", LPGEN("Show tabSRMM session list"), -IDI_TABSRMMSESSIONLIST }, + { "CLN_menu", LPGEN("Show tabSRMM menu"), -IDI_TABSRMMMENU }, + { "CLN_soundsoff", LPGEN("Sounds are off"), -IDI_SOUNDSOFF }, + { "CLN_CLVM_select", LPGEN("Select view mode"), -IDI_CLVM_SELECT }, + { "CLN_CLVM_reset", LPGEN("Reset view mode"), -IDI_DELETE }, + { "CLN_CLVM_options", LPGEN("Configure view modes"), -IDI_CLVM_OPTIONS }, + { "CLN_topmenu", LPGEN("Show menu"), -IDI_TBTOPMENU }, + { "CLN_accounts", LPGEN("Setup accounts"), -IDI_TBACCOUNTS } +}; + +HWND hTbMenu, hTbGlobalStatus; + +/* + * simple service for testing purpose + * get the *proper* time zone offset for the given contact + * only UserInfoEx can currently set real time zones + * + * This stuff should go into the core... + * + * returns: timediff for the contact in seconds. This value has inverted sign, + * so you need to SUBTRACT it from your current time in order to get the correct + * target time. + * + * If no real time zone is set, the service falls back to ordinary GMT offsets + */ + +static void Tweak_It(COLORREF clr) +{ + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) | WS_EX_LAYERED); + API::pfnSetLayeredWindowAttributes(pcli->hwndContactList, clr, 0, LWA_COLORKEY); + cfg::dat.colorkey = clr; +} + +static void LayoutButtons(HWND hwnd, RECT *rc) +{ + RECT rect; + BYTE rightButton = 1, leftButton = 0; + BYTE left_offset = cfg::dat.bCLeft - (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? 3 : 0); + BYTE right_offset = cfg::dat.bCRight - (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? 3 : 0); + BYTE delta = left_offset + right_offset; + ButtonItem *btnItems = g_ButtonItems; + + if (rc == NULL) + GetClientRect(hwnd, &rect); + else + rect = *rc; + + rect.bottom -= cfg::dat.bCBottom; + + SetWindowPos(hTbMenu, 0, 2 + left_offset, rect.bottom - cfg::dat.statusBarHeight - 21 - 1, + 21 * 3, 21 + 1, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOREDRAW); + + SetWindowPos(hTbGlobalStatus, 0, left_offset + (3 * 21) + 3, rect.bottom - cfg::dat.statusBarHeight - 21 - 1, + rect.right - delta - (3 * 21 + 5), 21 + 1, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOREDRAW); + +} + +static int FS_FontsChanged(WPARAM wParam, LPARAM lParam) +{ + pcli->pfnClcOptionsChanged(); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return 0; +} + +/* +* create the CLC control, but not yet the frame. The frame containing the CLC should be created as the +* last frame of all. +*/ + +static HWND PreCreateCLC(HWND parent) +{ + pcli->hwndContactTree = CreateWindow(CLISTCONTROL_CLASS, _T(""), + WS_CHILD | CLS_CONTACTLIST + | (cfg::getByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) ? CLS_USEGROUPS : 0) + | CLS_HIDEOFFLINE + //|(DBGetContactSettingByte(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)?CLS_HIDEOFFLINE:0) + | (cfg::getByte(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) ? CLS_HIDEEMPTYGROUPS : 0) + | CLS_MULTICOLUMN + , 0, 0, 0, 0, parent, NULL, g_hInst, (LPVOID)0xff00ff00); + + cfg::clcdat = (struct ClcData *)GetWindowLongPtr(pcli->hwndContactTree, 0); + return pcli->hwndContactTree; +} + +/* +* create internal frames, including the last frame (actual CLC control) +*/ + +static int CreateCLC(HWND parent) +{ + ReloadExtraIcons(); + CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)oldhideoffline, 0); + disableautoupd = 0; + + { + CLISTFrame frame = {0}; + frame.cbSize = sizeof(frame); + frame.tname = _T("EventArea"); + frame.TBtname = TranslateT("Event Area"); + frame.hIcon = 0; + frame.height = 20; + frame.Flags = F_VISIBLE | F_SHOWTBTIP | F_NOBORDER | F_TCHAR; + frame.align = alBottom; + frame.hWnd = CreateWindowExA(0, "EventAreaClass", "evt", WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, pcli->hwndContactList, (HMENU) 0, g_hInst, NULL); + g_hwndEventArea = frame.hWnd; + hNotifyFrame = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM) & frame, (LPARAM)0); + CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)hNotifyFrame, FU_FMPOS); + HideShowNotifyFrame(); + CreateViewModeFrame(); + } + SetButtonToSkinned(); + + { + DWORD flags; + CLISTFrame Frame; + memset(&Frame, 0, sizeof(Frame)); + Frame.cbSize = sizeof(CLISTFrame); + Frame.hWnd = pcli->hwndContactTree; + Frame.align = alClient; + Frame.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + Frame.Flags = F_VISIBLE | F_SHOWTB | F_SHOWTBTIP | F_NOBORDER | F_TCHAR; + Frame.tname = _T("My Contacts"); + Frame.TBtname = TranslateT("My Contacts"); + Frame.height = 200; + hFrameContactTree = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM) & Frame, (LPARAM)0); + //free(Frame.name); + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_TBTIPNAME, hFrameContactTree), (LPARAM)Translate("My Contacts")); + + /* + * ugly, but working hack. Prevent that annoying little scroll bar from appearing in the "My Contacts" title bar + */ + + flags = (DWORD)CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hFrameContactTree), 0); + flags |= F_VISIBLE; + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hFrameContactTree), flags); + } + return(0); +} + +static int CluiModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + static const char *szPrefix = "clist_nicer_plus "; + + static char *component = "CList Nicer+"; + static char szCurrentVersion[30]; + static char *szVersionUrl = "http://download.miranda.or.at/clist_nicer/0.9/versionW.txt"; + static char *szUpdateUrl = "http://download.miranda.or.at/clist_nicer/0.9/clist_nicer_plusW.zip"; + + MTG_OnmodulesLoad(wParam, lParam); + FS_RegisterFonts(); + HookEvent(ME_FONT_RELOAD, FS_FontsChanged); + return 0; +} + +static HICON hIconSaved = 0; + +void ClearIcons(int mode) +{ + int i; + + for (i = IDI_OVL_OFFLINE; i <= IDI_OVL_OUTTOLUNCH; i++) { + if (overlayicons[i - IDI_OVL_OFFLINE] != 0) { + if (mode) + DestroyIcon(overlayicons[i - IDI_OVL_OFFLINE]); + overlayicons[i - IDI_OVL_OFFLINE] = 0; + } + } + hIconSaved = ImageList_GetIcon(himlExtraImages, 3, ILD_NORMAL); + ImageList_RemoveAll(himlExtraImages); +} + +static void CacheClientIcons() +{ + int i = 0; + char szBuffer[128]; + + ClearIcons(0); + + for (i = IDI_OVL_OFFLINE; i <= IDI_OVL_OUTTOLUNCH; i++) { + mir_snprintf(szBuffer, sizeof(szBuffer), "cln_ovl_%d", ID_STATUS_OFFLINE + (i - IDI_OVL_OFFLINE)); + overlayicons[i - IDI_OVL_OFFLINE] = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) szBuffer); + } + ImageList_AddIcon(himlExtraImages, (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM) "core_main_14")); + ImageList_AddIcon(himlExtraImages, (HICON)LoadSkinnedIcon(SKINICON_EVENT_URL)); + ImageList_AddIcon(himlExtraImages, (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM) "core_main_17")); + if (hIconSaved != 0) { + ImageList_AddIcon(himlExtraImages, hIconSaved); + DestroyIcon(hIconSaved); + hIconSaved = 0; + } else + ImageList_AddIcon(himlExtraImages, (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM) "core_main_17")); +} + +static void InitIcoLib() +{ + TCHAR szFilename[MAX_PATH]; + GetModuleFileName(g_hInst, szFilename, MAX_PATH); + + int i, version = 0; + char szBuffer[128]; + + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(SKINICONDESC); + sid.flags = SIDF_PATH_TCHAR; + sid.pszSection = LPGEN("CList - Nicer/Default"); + sid.ptszDefaultFile = szFilename; + for (i=0; i < SIZEOF(myIcons); i++) { + sid.pszName = myIcons[i].szName; + sid.pszDescription = myIcons[i].szDesc; + sid.iDefaultIndex = myIcons[i].uId; + Skin_AddIcon(&sid); + } + + sid.pszName = "CLN_visible"; + sid.pszDescription = LPGEN("Contact on visible list"); + sid.iDefaultIndex = -IDI_CLVISIBLE; + Skin_AddIcon(&sid); + sid.pszName = "CLN_invisible"; + sid.pszDescription = LPGEN("Contact on invisible list or blocked"); + sid.iDefaultIndex = -IDI_CLINVISIBLE; + Skin_AddIcon(&sid); + sid.pszName = "CLN_chatactive"; + sid.pszDescription = LPGEN("Chat room/IRC channel activity"); + sid.iDefaultIndex = -IDI_OVL_FREEFORCHAT; + Skin_AddIcon(&sid); + + sid.flags = SIDF_ALL_TCHAR; + sid.ptszSection = LPGENT("CList - Nicer/Overlay Icons"); + for (i = IDI_OVL_OFFLINE; i <= IDI_OVL_OUTTOLUNCH; i++) { + mir_snprintf(szBuffer, sizeof(szBuffer), "cln_ovl_%d", ID_STATUS_OFFLINE + (i - IDI_OVL_OFFLINE)); + sid.pszName = szBuffer; + sid.ptszDescription = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, ID_STATUS_OFFLINE + (i - IDI_OVL_OFFLINE), GSMDF_TCHAR); + sid.iDefaultIndex = -i; + Skin_AddIcon(&sid); + } + sid.ptszSection = LPGENT("CList - Nicer/Connecting Icons"); + + PROTOACCOUNT **accs = NULL; + int p_count = 0; + ProtoEnumAccounts( &p_count, &accs ); + for (i = 0; i < p_count; i++) { + TCHAR szDescr[128]; + if ( !IsAccountEnabled(accs[i]) || CallProtoService(accs[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) == 0) + continue; + mir_snprintf(szBuffer, 128, "%s_conn", accs[i]->szModuleName ); + sid.pszName = szBuffer; + mir_sntprintf(szDescr, 128, TranslateT("%s Connecting"), accs[i]->tszAccountName ); + sid.ptszDescription = szDescr; + sid.iDefaultIndex = -IDI_PROTOCONNECTING; + Skin_AddIcon(&sid); + } +} + +static int IcoLibChanged(WPARAM wParam, LPARAM lParam) +{ + IcoLibReloadIcons(); + return 0; +} + +void CreateButtonBar(HWND hWnd) +{ + hTbMenu = CreateWindowEx(0, MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, hWnd, (HMENU) IDC_TBMENU, g_hInst, NULL); + CustomizeButton(hTbMenu, false, false, false); + SetWindowText(hTbMenu, TranslateT("Menu")); + SendMessage(hTbMenu, BM_SETIMAGE, IMAGE_ICON, (LPARAM) LoadSkinnedIcon(SKINICON_OTHER_MIRANDA)); + SendMessage(hTbMenu, BUTTONSETASMENUACTION, 1, 0); + SendMessage(hTbMenu, BUTTONADDTOOLTIP, (WPARAM) TranslateTS(LPGENT("Open main menu")), BATF_UNICODE); + + hTbGlobalStatus = CreateWindowEx(0, MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, hWnd, (HMENU) IDC_TBGLOBALSTATUS, g_hInst, NULL); + CustomizeButton(hTbGlobalStatus, false, false, false); + SetWindowText(hTbGlobalStatus, TranslateT("Offline")); + SendMessage(hTbGlobalStatus, BM_SETIMAGE, IMAGE_ICON, (LPARAM) LoadSkinnedIcon(SKINICON_STATUS_OFFLINE)); + SendMessage(hTbGlobalStatus, BUTTONSETASMENUACTION, 1, 0); + SendMessage(hTbGlobalStatus, BUTTONADDTOOLTIP, (WPARAM) TranslateTS(LPGENT("Set status modes")), BATF_UNICODE); +} + +/* +* if mode != 0 we do first time init, otherwise only reload the extra icon stuff +*/ + +void CLN_LoadAllIcons(BOOL mode) +{ + if (mode) { + InitIcoLib(); + hIcoLibChanged = HookEvent(ME_SKIN2_ICONSCHANGED, IcoLibChanged); + cfg::dat.hIconVisible = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_visible"); + cfg::dat.hIconInvisible = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_invisible"); + cfg::dat.hIconChatactive = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_chatactive"); + } + CacheClientIcons(); +} + +void ConfigureEventArea(HWND hwnd) +{ + int iCount = GetMenuItemCount(cfg::dat.hMenuNotify); + DWORD dwFlags = cfg::dat.dwFlags; + int oldstate = cfg::dat.notifyActive; + int dwVisible = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hNotifyFrame), 0) & F_VISIBLE; + + if (dwVisible) { + if (dwFlags & CLUI_FRAME_AUTOHIDENOTIFY) + cfg::dat.notifyActive = iCount > 0 ? 1 : 0; + else + cfg::dat.notifyActive = 1; + } else + cfg::dat.notifyActive = 0; + + if (oldstate != cfg::dat.notifyActive) + HideShowNotifyFrame(); +} + +void ConfigureFrame() +{ + int show = cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS ? SW_SHOW : SW_HIDE; + ShowWindow(hTbMenu,show); + ShowWindow(hTbGlobalStatus,show); +} + +void IcoLibReloadIcons() +{ + + cfg::dat.hIconVisible = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_visible"); + cfg::dat.hIconInvisible = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_invisible"); + cfg::dat.hIconChatactive = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "CLN_chatactive"); + CacheClientIcons(); + ReloadExtraIcons(); + + // force client icons reload + { + int i; + + for (i = 0; i < cfg::nextCacheEntry; i++) { + if (cfg::eCache[i].hContact) + NotifyEventHooks(hExtraImageApplying, (WPARAM)cfg::eCache[i].hContact, 0); + } + } + // + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + SendMessage(g_hwndViewModeFrame, WM_USER + 100, 0, 0); +} + +void ConfigureCLUIGeometry(int mode) +{ + RECT rcStatus; + DWORD clmargins = cfg::getDword("CLUI", "clmargins", 0); + + cfg::dat.bCLeft = LOBYTE(LOWORD(clmargins)); + cfg::dat.bCRight = HIBYTE(LOWORD(clmargins)); + cfg::dat.bCTop = LOBYTE(HIWORD(clmargins)); + cfg::dat.bCBottom = HIBYTE(HIWORD(clmargins)); + + if (mode) { + if (cfg::dat.dwFlags & CLUI_FRAME_SBARSHOW) { + SendMessage(pcli->hwndStatus, WM_SIZE, 0, 0); + GetWindowRect(pcli->hwndStatus, &rcStatus); + cfg::dat.statusBarHeight = (rcStatus.bottom - rcStatus.top); + } else + cfg::dat.statusBarHeight = 0; + } + + cfg::dat.topOffset = cfg::dat.bCTop; + cfg::dat.bottomOffset = (cfg::dat.dwFlags & CLUI_FRAME_SHOWBOTTOMBUTTONS ? 2 + 21 : 0) + cfg::dat.bCBottom; + + if (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN) { + cfg::dat.topOffset += 2; + cfg::dat.bottomOffset += 2; + cfg::dat.bCLeft += 3; + cfg::dat.bCRight += 3; + } +} + +/* + * set the states of defined database action buttons (only if button is a toggle) +*/ + +void SetDBButtonStates(HANDLE hPassedContact) +{ + ButtonItem *buttonItem = g_ButtonItems; + HANDLE hContact = 0, hFinalContact = 0; + char *szModule, *szSetting; + int sel = cfg::clcdat ? cfg::clcdat->selection : -1; + struct ClcContact *contact = 0; + + if (sel != -1 && hPassedContact == 0) { + sel = pcli->pfnGetRowByIndex(cfg::clcdat, cfg::clcdat->selection, &contact, NULL); + if (contact && contact->type == CLCIT_CONTACT) { + hContact = contact->hContact; + } + } + + while (buttonItem) { + BOOL result = FALSE; + + if (!(buttonItem->dwFlags & BUTTON_ISTOGGLE && buttonItem->dwFlags & BUTTON_ISDBACTION)) { + buttonItem = buttonItem->nextItem; + continue; + } + szModule = buttonItem->szModule; + szSetting = buttonItem->szSetting; + if (buttonItem->dwFlags & BUTTON_DBACTIONONCONTACT || buttonItem->dwFlags & BUTTON_ISCONTACTDBACTION) { + if (hContact == 0) { + SendMessage(buttonItem->hWnd, BM_SETCHECK, BST_UNCHECKED, 0); + buttonItem = buttonItem->nextItem; + continue; + } + if (buttonItem->dwFlags & BUTTON_ISCONTACTDBACTION) + szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + hFinalContact = hContact; + } else + hFinalContact = 0; + + if (buttonItem->type == DBVT_ASCIIZ) { + DBVARIANT dbv = {0}; + + if (!cfg::getString(hFinalContact, szModule, szSetting, &dbv)) { + result = !strcmp((char *)buttonItem->bValuePush, dbv.pszVal); + DBFreeVariant(&dbv); + } + } else { + switch (buttonItem->type) { + case DBVT_BYTE: { + BYTE val = cfg::getByte(hFinalContact, szModule, szSetting, 0); + result = (val == buttonItem->bValuePush[0]); + break; + } + case DBVT_WORD: { + WORD val = cfg::getWord(hFinalContact, szModule, szSetting, 0); + result = (val == *((WORD *) & buttonItem->bValuePush)); + break; + } + case DBVT_DWORD: { + DWORD val = cfg::getDword(hFinalContact, szModule, szSetting, 0); + result = (val == *((DWORD *) & buttonItem->bValuePush)); + break; + } + } + } + SendMessage(buttonItem->hWnd, BM_SETCHECK, (WPARAM)result, 0); + buttonItem = buttonItem->nextItem; + } +} + +void BlitWallpaper(HDC hdc, RECT *rc, RECT *rcPaint, struct ClcData *dat) +{ + int x, y; + int bitx, bity; + int maxx, maxy; + int destw, desth, height, width; + BITMAP *bmp = &cfg::dat.bminfoBg; + HRGN my_rgn = 0; + LONG clip = cfg::dat.bClipBorder; + + if (dat == 0) + return; + + SetStretchBltMode(hdc, HALFTONE); + + y = rc->top; + + rc->left = max(rc->left, clip); + rc->right = min(rc->right - clip, rc->right); + rc->top = max(rc->top, clip); + rc->bottom = min(rc->bottom - clip, rc->bottom); + + width = rc->right - rc->left; + height = rc->bottom - rc->top; + my_rgn = CreateRectRgn(rc->left, rc->top, rc->right, rc->bottom); + SelectClipRgn(hdc, my_rgn); + maxx = dat->backgroundBmpUse & CLBF_TILEH ? rc->right : rc->left + 1; + maxy = dat->backgroundBmpUse & CLBF_TILEV ? maxy = rc->bottom : y + 1; + switch (dat->backgroundBmpUse & CLBM_TYPE) { + case CLB_STRETCH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + if (width * bmp->bmHeight < height * bmp->bmWidth) { + desth = height; + destw = desth * bmp->bmWidth / bmp->bmHeight; + } else { + destw = width; + desth = destw * bmp->bmHeight / bmp->bmWidth; + } + } else { + destw = width; + desth = height; + } + break; + case CLB_STRETCHH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + destw = width; + desth = destw * bmp->bmHeight / bmp->bmWidth; + } else { + destw = width; + desth = bmp->bmHeight; + } + break; + case CLB_STRETCHV: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + desth = height; + destw = desth * bmp->bmWidth / bmp->bmHeight; + } else { + destw = bmp->bmWidth; + desth = height; + } + break; + default: + //clb_topleft + destw = bmp->bmWidth; + desth = bmp->bmHeight; + break; + } + + bitx = 0; + bity = 0; + for (; y < maxy; y += desth) { + for (x = rc->left; x < maxx; x += destw) + StretchBlt(hdc, x, y, destw, desth, cfg::dat.hdcPic, bitx, bity, bmp->bmWidth, bmp->bmHeight, SRCCOPY); + } + SelectClipRgn(hdc, NULL); + DeleteObject(my_rgn); +} + +void ReloadThemedOptions() +{ + cfg::dat.bSkinnedStatusBar = cfg::getByte("CLUI", "sb_skinned", 0); + cfg::dat.bUsePerProto = cfg::getByte("CLCExt", "useperproto", 0); + cfg::dat.bOverridePerStatusColors = cfg::getByte("CLCExt", "override_status", 0); + cfg::dat.bRowSpacing = cfg::getByte("CLC", "RowGap", 0); + cfg::dat.exIconScale = cfg::getByte("CLC", "ExIconScale", 16); + cfg::dat.bApplyIndentToBg = cfg::getByte("CLCExt", "applyindentbg", 0); + cfg::dat.bWallpaperMode = cfg::getByte("CLUI", "UseBkSkin", 1); + cfg::dat.bClipBorder = cfg::getByte("CLUI", "clipborder", 0); + cfg::dat.cornerRadius = cfg::getByte("CLCExt", "CornerRad", 6); + cfg::dat.gapBetweenFrames = (BYTE)cfg::getDword("CLUIFrames", "GapBetweenFrames", 1); + cfg::dat.bUseDCMirroring = cfg::getByte("CLC", "MirrorDC", 0); + cfg::dat.bGroupAlign = cfg::getByte("CLC", "GroupAlign", 0); + if (cfg::dat.hBrushColorKey) + DeleteObject(cfg::dat.hBrushColorKey); + cfg::dat.hBrushColorKey = CreateSolidBrush(RGB(255, 0, 255)); + cfg::dat.bUseFloater = cfg::getByte("CLUI", "FloaterMode", 0); + cfg::dat.bWantFastGradients = cfg::getByte("CLCExt", "FastGradients", 0); + cfg::dat.titleBarHeight = cfg::getByte("CLCExt", "frame_height", DEFAULT_TITLEBAR_HEIGHT); + cfg::dat.group_padding = cfg::getDword("CLCExt", "grp_padding", 0); +} + +static RECT rcWindow = {0}; + +static void sttProcessResize(HWND hwnd, NMCLISTCONTROL *nmc) +{ + RECT rcTree, rcWorkArea, rcOld; + int maxHeight, newHeight; + int winstyle, skinHeight = 0; + + if (disableautoupd) + return; + + if (!cfg::getByte("CLUI", "AutoSize", 0)) + return; + + if (Docking_IsDocked(0, 0)) + return; + if (hFrameContactTree == 0) + return; + + maxHeight = cfg::getByte("CLUI", "MaxSizeHeight", 75); + rcOld = rcWindow; + + GetWindowRect(hwnd, &rcWindow); + GetWindowRect(pcli->hwndContactTree, &rcTree); + winstyle = GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE); + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, FALSE); + if (API::pfnMonitorFromWindow) + { + HMONITOR hMon = API::pfnMonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (API::pfnGetMonitorInfo(hMon, &mi)) + rcWorkArea = mi.rcWork; + } + + if (nmc->pt.y > (rcWorkArea.bottom - rcWorkArea.top)) { + nmc->pt.y = (rcWorkArea.bottom - rcWorkArea.top); + } + + if (winstyle & CLS_SKINNEDFRAME) { + BOOL hasTitleBar = wndFrameCLC ? wndFrameCLC->TitleBar.ShowTitleBar : 0; + StatusItems_t *item = &StatusItems[(hasTitleBar ? ID_EXTBKOWNEDFRAMEBORDERTB : ID_EXTBKOWNEDFRAMEBORDER) - ID_STATUS_OFFLINE]; + skinHeight = item->IGNORED ? 0 : item->MARGIN_BOTTOM + item->MARGIN_TOP; + } + + newHeight = max(nmc->pt.y, 3) + 1 + ((winstyle & WS_BORDER) ? 2 : 0) + skinHeight + (rcWindow.bottom - rcWindow.top) - (rcTree.bottom - rcTree.top); + if (newHeight == (rcWindow.bottom - rcWindow.top) && show_on_first_autosize == FALSE) + return; + + if (newHeight > (rcWorkArea.bottom - rcWorkArea.top)*maxHeight / 100) + newHeight = (rcWorkArea.bottom - rcWorkArea.top) * maxHeight / 100; + if (cfg::getByte("CLUI", "AutoSizeUpward", 0)) { + rcWindow.top = rcWindow.bottom - newHeight; + if (rcWindow.top < rcWorkArea.top) rcWindow.top = rcWorkArea.top; + } else { + rcWindow.bottom = rcWindow.top + newHeight; + if (rcWindow.bottom > rcWorkArea.bottom) rcWindow.bottom = rcWorkArea.bottom; + } + if (cfg::dat.szOldCTreeSize.cx != rcTree.right - rcTree.left) { + cfg::dat.szOldCTreeSize.cx = rcTree.right - rcTree.left; + return; + } + KillTimer(hwnd, TIMERID_AUTOSIZE); + SetTimer(hwnd, TIMERID_AUTOSIZE, 100, 0); +} + +int CustomDrawScrollBars(NMCSBCUSTOMDRAW *nmcsbcd) +{ + switch (nmcsbcd->hdr.code) { + case NM_COOLSB_CUSTOMDRAW: { + static HDC hdcScroll = 0; + static HBITMAP hbmScroll, hbmScrollOld; + static LONG scrollLeft, scrollRight, scrollHeight, scrollYmin, scrollYmax; + + switch (nmcsbcd->dwDrawStage) { + case CDDS_PREPAINT: + if (cfg::dat.bSkinnedScrollbar) // XXX fix (verify skin items to be complete, otherwise don't draw + return CDRF_SKIPDEFAULT; + else + return CDRF_DODEFAULT; + case CDDS_POSTPAINT: + return 0; + case CDDS_ITEMPREPAINT: { + HDC hdc = nmcsbcd->hdc; + StatusItems_t *item = 0, *arrowItem = 0; + UINT uItemID = ID_EXTBKSCROLLBACK; + RECT rcWindow; + POINT pt; + DWORD dfcFlags; + HRGN rgn = 0; + GetWindowRect(pcli->hwndContactTree, &rcWindow); + pt.x = rcWindow.left; + pt.y = rcWindow.top; + ScreenToClient(pcli->hwndContactList, &pt); + hdcScroll = hdc; + BitBlt(hdcScroll, nmcsbcd->rect.left, nmcsbcd->rect.top, nmcsbcd->rect.right - nmcsbcd->rect.left, + nmcsbcd->rect.bottom - nmcsbcd->rect.top, cfg::dat.hdcBg, pt.x + nmcsbcd->rect.left, pt.y + nmcsbcd->rect.top, SRCCOPY); + + switch (nmcsbcd->uItem) { + case HTSCROLL_UP: + case HTSCROLL_DOWN: + uItemID = (nmcsbcd->uState == CDIS_DEFAULT || nmcsbcd->uState == CDIS_DISABLED) ? ID_EXTBKSCROLLBUTTON : + (nmcsbcd->uState == CDIS_HOT ? ID_EXTBKSCROLLBUTTONHOVER : ID_EXTBKSCROLLBUTTONPRESSED); + break; + case HTSCROLL_PAGEGDOWN: + case HTSCROLL_PAGEGUP: + uItemID = nmcsbcd->uItem == HTSCROLL_PAGEGUP ? ID_EXTBKSCROLLBACK : ID_EXTBKSCROLLBACKLOWER;; + rgn = CreateRectRgn(nmcsbcd->rect.left, nmcsbcd->rect.top, nmcsbcd->rect.right, nmcsbcd->rect.bottom); + SelectClipRgn(hdcScroll, rgn); + break; + case HTSCROLL_THUMB: + uItemID = nmcsbcd->uState == CDIS_HOT ? ID_EXTBKSCROLLTHUMBHOVER : ID_EXTBKSCROLLTHUMB; + uItemID = nmcsbcd->uState == CDIS_SELECTED ? ID_EXTBKSCROLLTHUMBPRESSED : ID_EXTBKSCROLLTHUMB; + break; + default: + break; + } + + uItemID -= ID_STATUS_OFFLINE; + item = &StatusItems[uItemID]; + if (!item->IGNORED) { + int alpha = nmcsbcd->uState == CDIS_DISABLED ? item->ALPHA - 50 : item->ALPHA; + DrawAlpha(hdcScroll, &nmcsbcd->rect, item->COLOR, alpha, item->COLOR2, item->COLOR2_TRANSPARENT, + item->GRADIENT, item->CORNER, item->BORDERSTYLE, item->imageItem); + } + dfcFlags = DFCS_FLAT | (nmcsbcd->uState == CDIS_DISABLED ? DFCS_INACTIVE : + (nmcsbcd->uState == CDIS_HOT ? DFCS_HOT : + (nmcsbcd->uState == CDIS_SELECTED ? DFCS_PUSHED : 0))); + + if (nmcsbcd->uItem == HTSCROLL_UP) + arrowItem = &StatusItems[ID_EXTBKSCROLLARROWUP - ID_STATUS_OFFLINE]; + if (nmcsbcd->uItem == HTSCROLL_DOWN) + arrowItem = &StatusItems[ID_EXTBKSCROLLARROWDOWN - ID_STATUS_OFFLINE]; + if (arrowItem && !arrowItem->IGNORED) + DrawAlpha(hdcScroll, &nmcsbcd->rect, arrowItem->COLOR, arrowItem->ALPHA, arrowItem->COLOR2, arrowItem->COLOR2_TRANSPARENT, + arrowItem->GRADIENT, arrowItem->CORNER, arrowItem->BORDERSTYLE, arrowItem->imageItem); + else if (arrowItem) + DrawFrameControl(hdcScroll, &nmcsbcd->rect, DFC_SCROLL, (nmcsbcd->uItem == HTSCROLL_UP ? DFCS_SCROLLUP : DFCS_SCROLLDOWN) | dfcFlags); + + if (rgn) { + SelectClipRgn(hdcScroll, NULL); + DeleteObject(rgn); + } + } + default: + break; + } + } + return 0; + } + return 0; +} + +extern LRESULT(CALLBACK *saveContactListWndProc)(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +static int ServiceParamsOK(ButtonItem *item, WPARAM *wParam, LPARAM *lParam, HANDLE hContact) +{ + if (item->dwFlags & BUTTON_PASSHCONTACTW || item->dwFlags & BUTTON_PASSHCONTACTL || item->dwFlags & BUTTON_ISCONTACTDBACTION) { + if (hContact == 0) + return 0; + if (item->dwFlags & BUTTON_PASSHCONTACTW) + *wParam = (WPARAM)hContact; + else if (item->dwFlags & BUTTON_PASSHCONTACTL) + *lParam = (LPARAM)hContact; + return 1; + } + return 1; // doesn't need a paramter +} +static void ShowCLUI(HWND hwnd) +{ + int state = old_cliststate; + int onTop = cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT); + + SendMessage(hwnd, WM_SETREDRAW, FALSE, FALSE); + if (!cfg::getByte("CLUI", "ShowMainMenu", SETTING_SHOWMAINMENU_DEFAULT)) + SetMenu(pcli->hwndContactList, NULL); + if (state == SETTING_STATE_NORMAL) { + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + ShowWindow(pcli->hwndContactList, SW_SHOWNORMAL); + SendMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + } else if (state == SETTING_STATE_MINIMIZED) { + cfg::dat.forceResize = TRUE; + ShowWindow(pcli->hwndContactList, SW_HIDE); + } else if (state == SETTING_STATE_HIDDEN) { + cfg::dat.forceResize = TRUE; + ShowWindow(pcli->hwndContactList, SW_HIDE); + } + SetWindowPos(pcli->hwndContactList, onTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSENDCHANGING); + DrawMenuBar(hwnd); + if (cfg::dat.autosize) { + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0); + } + SFL_Create(); + SFL_SetState(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE ? (old_cliststate == SETTING_STATE_NORMAL ? 0 : 1) : 1); +} + +static void GetButtonRect(HWND hwnd, RECT *rc) +{ + if (hwnd) + GetWindowRect(hwnd, rc); + else { + POINT pt; + GetCursorPos(&pt); + rc->bottom = rc->top = pt.y; + rc->left = rc->right = pt.x; + } +} + +#define M_CREATECLC (WM_USER+1) +LRESULT CALLBACK ContactListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_CREATE: { + int i; + { + int flags = WS_CHILD | CCS_BOTTOM; + flags |= cfg::getByte("CLUI", "ShowSBar", 1) ? WS_VISIBLE : 0; + flags |= cfg::getByte("CLUI", "ShowGrip", 1) ? SBARS_SIZEGRIP : 0; + pcli->hwndStatus = CreateWindow(STATUSCLASSNAME, NULL, flags, 0, 0, 0, 0, hwnd, NULL, g_hInst, NULL); + if (flags & WS_VISIBLE) { + ShowWindow(pcli->hwndStatus, SW_SHOW); + SendMessage(pcli->hwndStatus, WM_SIZE, 0, 0); + } + OldStatusBarProc = (WNDPROC)SetWindowLongPtr(pcli->hwndStatus, GWLP_WNDPROC, (LONG_PTR)NewStatusBarWndProc); + SetClassLong(pcli->hwndStatus, GCL_STYLE, GetClassLong(pcli->hwndStatus, GCL_STYLE) & ~(CS_VREDRAW | CS_HREDRAW)); + } + g_oldSize.cx = g_oldSize.cy = 0; + old_cliststate = cfg::getByte("CList", "State", SETTING_STATE_NORMAL); + cfg::writeByte("CList", "State", SETTING_STATE_HIDDEN); + SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) & ~WS_VISIBLE); + SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | WS_CLIPCHILDREN); + if (!cfg::dat.bFirstRun) + ConfigureEventArea(hwnd); + CluiProtocolStatusChanged(0, 0); + ConfigureCLUIGeometry(0); + + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + statusNames[i - ID_STATUS_OFFLINE] = reinterpret_cast(CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, GSMDF_TCHAR)); + + //delay creation of CLC so that it can get the status icons right the first time (needs protocol modules loaded) + if (cfg::dat.bLayeredHack) { + SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | (WS_EX_LAYERED)); + API::SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 255, LWA_ALPHA); + } + + if (cfg::dat.isTransparent) { + SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.alpha, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + } + transparentFocus = 1; + + TranslateMenu(GetMenu(hwnd)); + PostMessage(hwnd, M_CREATECLC, 0, 0); + return FALSE; + } + case WM_NCCREATE: { + LPCREATESTRUCT p = (LPCREATESTRUCT)lParam; + p->style &= ~(CS_HREDRAW | CS_VREDRAW); + } + break; + case M_CREATECLC: { + if (cfg::getByte("CLUI", "useskin", 0)) + IMG_LoadItems(); + CreateButtonBar(hwnd); + //FYR: to be checked: otherwise it raises double xStatus items + //NotifyEventHooks(pcli->hPreBuildStatusMenuEvent, 0, 0); + SendMessage(hwnd, WM_SETREDRAW, FALSE, FALSE); + { + LONG style; + BYTE windowStyle = cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_TOOLWINDOW); + ShowWindow(pcli->hwndContactList, SW_HIDE); + style = GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE); + if (windowStyle != SETTING_WINDOWSTYLE_DEFAULT) + { + style |= WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE; + style &= ~WS_EX_APPWINDOW; + } + else + { + style &= ~(WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE); + if (cfg::getByte("CList", "AlwaysHideOnTB", 1)) + style &= ~WS_EX_APPWINDOW; + else + style |= WS_EX_APPWINDOW; + } + + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, style); + ApplyCLUIBorderStyle(pcli->hwndContactList); + + SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOACTIVATE); + } + + ConfigureFrame(); + + CreateCLC(hwnd); + cfg::clcdat = (struct ClcData *)GetWindowLongPtr(pcli->hwndContactTree, 0); + + if (API::sysConfig.isWin2KPlus && cfg::dat.bFullTransparent) { + if (g_CLUISkinnedBkColorRGB) + Tweak_It(g_CLUISkinnedBkColorRGB); + else if (cfg::dat.bClipBorder || (cfg::dat.dwFlags & CLUI_FRAME_ROUNDEDFRAME)) + Tweak_It(RGB(255, 0, 255)); + else + Tweak_It(cfg::clcdat->bkColour); + } + + cfg::writeByte("CList", "State", old_cliststate); + + if (cfg::getByte("CList", "AutoApplyLastViewMode", 0)) { + DBVARIANT dbv = {0}; + if (!DBGetContactSetting(NULL, "CList", "LastViewMode", &dbv)) { + if (lstrlenA(dbv.pszVal) > 2) { + if (cfg::getDword(NULL, CLVM_MODULE, dbv.pszVal, -1) != 0xffffffff) + ApplyViewMode((char *)dbv.pszVal); + } + DBFreeVariant(&dbv); + } + } + if (!cfg::dat.autosize) + ShowCLUI(hwnd); + else { + show_on_first_autosize = TRUE; + RecalcScrollBar(pcli->hwndContactTree, cfg::clcdat); + } + return 0; + } + case WM_ERASEBKGND: + return TRUE; + if (cfg::dat.bSkinnedButtonMode) + return TRUE; + return DefWindowProc(hwnd, msg, wParam, lParam); + case WM_PAINT: { + PAINTSTRUCT ps; + RECT rc, rcFrame, rcClient; + HDC hdc; + HRGN rgn = 0; + HDC hdcReal = BeginPaint(hwnd, &ps); + + if (during_sizing) + rcClient = rcWPC; + else + GetClientRect(hwnd, &rcClient); + CopyRect(&rc, &rcClient); + + if (!cfg::dat.hdcBg || rc.right > cfg::dat.dcSize.cx || rc.bottom + cfg::dat.statusBarHeight > cfg::dat.dcSize.cy) { + RECT rcWorkArea; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, FALSE); + if (API::pfnMonitorFromWindow) + { + HMONITOR hMon = API::pfnMonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (API::pfnGetMonitorInfo(hMon, &mi)) + rcWorkArea = mi.rcWork; + } + + cfg::dat.dcSize.cy = max(rc.bottom + cfg::dat.statusBarHeight, rcWorkArea.bottom - rcWorkArea.top); + cfg::dat.dcSize.cx = max(rc.right, (rcWorkArea.right - rcWorkArea.left) / 2); + + if (cfg::dat.hdcBg) { + SelectObject(cfg::dat.hdcBg, cfg::dat.hbmBgOld); + DeleteObject(cfg::dat.hbmBg); + DeleteDC(cfg::dat.hdcBg); + } + cfg::dat.hdcBg = CreateCompatibleDC(hdcReal); + cfg::dat.hbmBg = CreateCompatibleBitmap(hdcReal, cfg::dat.dcSize.cx, cfg::dat.dcSize.cy); + cfg::dat.hbmBgOld = reinterpret_cast(SelectObject(cfg::dat.hdcBg, cfg::dat.hbmBg)); + } + + if (cfg::shutDown) { + EndPaint(hwnd, &ps); + return 0; + } + + hdc = cfg::dat.hdcBg; + + CopyRect(&rcFrame, &rcClient); + if (g_CLUISkinnedBkColor) { + if (cfg::dat.fOnDesktop) { + HDC dc = GetDC(0); + RECT rcWin; + + GetWindowRect(hwnd, &rcWin); + BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, dc, rcWin.left, rcWin.top, SRCCOPY); + } else + FillRect(hdc, &rcClient, g_CLUISkinnedBkColor); + } + + if (cfg::dat.bClipBorder != 0 || cfg::dat.dwFlags & CLUI_FRAME_ROUNDEDFRAME) { + int docked = CallService(MS_CLIST_DOCKINGISDOCKED, 0, 0); + int clip = cfg::dat.bClipBorder; + + if (!g_CLUISkinnedBkColor) + FillRect(hdc, &rcClient, cfg::dat.hBrushColorKey); + if (cfg::dat.dwFlags & CLUI_FRAME_ROUNDEDFRAME) + rgn = CreateRoundRectRgn(clip, docked ? 0 : clip, rcClient.right - clip + 1, rcClient.bottom - (docked ? 0 : clip - 1), 8 + clip, 8 + clip); + else + rgn = CreateRectRgn(clip, docked ? 0 : clip, rcClient.right - clip, rcClient.bottom - (docked ? 0 : clip)); + SelectClipRgn(hdc, rgn); + } + + if (g_CLUIImageItem) { + IMG_RenderImageItem(hdc, g_CLUIImageItem, &rcFrame); + cfg::dat.ptW.x = cfg::dat.ptW.y = 0; + ClientToScreen(hwnd, &cfg::dat.ptW); + goto skipbg; + } + + if (cfg::dat.bWallpaperMode) + FillRect(hdc, &rcClient, cfg::dat.hBrushCLCBk); + else + FillRect(hdc, &rcClient, GetSysColorBrush(COLOR_3DFACE)); + + rcFrame.left += (cfg::dat.bCLeft - 1); + rcFrame.right -= (cfg::dat.bCRight - 1); + //if (!g_CluiData.bSkinnedButtonMode) + // rcFrame.bottom -= (g_CluiData.bottomOffset); + rcFrame.bottom++; + rcFrame.bottom -= cfg::dat.statusBarHeight; + rcFrame.top += (cfg::dat.topOffset - 1); + + //if(g_CluiData.neeedSnap) + // goto skipbg; + if (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN) { + if (cfg::dat.bWallpaperMode && cfg::clcdat != NULL) { + InflateRect(&rcFrame, -1, -1); + if (cfg::dat.bmpBackground) + BlitWallpaper(hdc, &rcFrame, &ps.rcPaint, cfg::clcdat); + cfg::dat.ptW.x = cfg::dat.ptW.y = 0; + ClientToScreen(hwnd, &cfg::dat.ptW); + } + InflateRect(&rcFrame, 1, 1); + if (cfg::dat.bSkinnedButtonMode) + rcFrame.bottom -= (cfg::dat.bottomOffset); + DrawEdge(hdc, &rcFrame, BDR_SUNKENOUTER, BF_RECT); + } else if (cfg::dat.bWallpaperMode && cfg::clcdat != NULL) { + if (cfg::dat.bmpBackground) + BlitWallpaper(hdc, &rcFrame, &ps.rcPaint, cfg::clcdat); + cfg::dat.ptW.x = cfg::dat.ptW.y = 0; + ClientToScreen(hwnd, &cfg::dat.ptW); + } +skipbg: + BitBlt(hdcReal, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdc, 0, 0, SRCCOPY); + if (rgn) { + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + } + EndPaint(hwnd, &ps); + return 0; + } + case WM_ENTERSIZEMOVE: { + RECT rc; + POINT pt = {0}; + + GetWindowRect(hwnd, &g_PreSizeRect); + GetClientRect(hwnd, &rc); + ClientToScreen(hwnd, &pt); + g_CLUI_x_off = pt.x - g_PreSizeRect.left; + g_CLUI_y_off = pt.y - g_PreSizeRect.top; + pt.x = rc.right; + ClientToScreen(hwnd, &pt); + g_CLUI_x1_off = g_PreSizeRect.right - pt.x; + pt.x = 0; + pt.y = rc.bottom; + ClientToScreen(hwnd, &pt); + g_CLUI_y1_off = g_PreSizeRect.bottom - pt.y; + //g_CluiData.neeedSnap = TRUE; + break; + } + case WM_EXITSIZEMOVE: + //g_CluiData.neeedSnap = FALSE; + PostMessage(hwnd, CLUIINTM_REDRAW, 0, 0); + //RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN); + break; + case WM_SIZING: { + RECT *szrect = (RECT *)lParam; + + break; + if (Docking_IsDocked(0, 0)) + break; + g_SizingRect = *((RECT *)lParam); + if (wParam != WMSZ_BOTTOM && wParam != WMSZ_BOTTOMRIGHT && wParam != WMSZ_BOTTOMLEFT) + szrect->bottom = g_PreSizeRect.bottom; + if (wParam != WMSZ_RIGHT && wParam != WMSZ_BOTTOMRIGHT && wParam != WMSZ_TOPRIGHT) + szrect->right = g_PreSizeRect.right; + return TRUE; + } + + case WM_WINDOWPOSCHANGED: + if (!Docking_IsDocked(0, 0)) + return(0); + else + break; + + case WM_WINDOWPOSCHANGING: { + WINDOWPOS *wp = (WINDOWPOS *)lParam; + + if (wp && wp->flags & SWP_NOSIZE) + return FALSE; + + //if (Docking_IsDocked(0, 0)) + // break; + + if (pcli->hwndContactList != NULL) { + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + during_sizing = true; + + new_window_rect.left = 0; + new_window_rect.right = wp->cx - (g_CLUI_x_off + g_CLUI_x1_off); + new_window_rect.top = 0; + new_window_rect.bottom = wp->cy - g_CLUI_y_off - g_CLUI_y1_off; + + if (cfg::dat.dwFlags & CLUI_FRAME_SBARSHOW) { + RECT rcStatus; + SetWindowPos(pcli->hwndStatus, 0, 0, new_window_rect.bottom - 20, new_window_rect.right, 20, SWP_NOZORDER); + GetWindowRect(pcli->hwndStatus, &rcStatus); + cfg::dat.statusBarHeight = (rcStatus.bottom - rcStatus.top); + if(wp->cx != g_oldSize.cx) + SendMessage(hwnd, CLUIINTM_STATUSBARUPDATE, 0, 0); + RedrawWindow(pcli->hwndStatus, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } else + cfg::dat.statusBarHeight = 0; + + SizeFramesByWindowRect(&new_window_rect); + dock_prevent_moving = 0; + LayoutButtons(hwnd, &new_window_rect); + dock_prevent_moving = 1; + g_oldPos.x = wp->x; + g_oldPos.y = wp->y; + g_oldSize.cx = wp->cx; + g_oldSize.cy = wp->cy; + rcWPC = new_window_rect; + + during_sizing = false; + } + during_sizing = false; + return(0); + } + + case WM_SIZE: { + RECT rc; + + if ((wParam == 0 && lParam == 0) || Docking_IsDocked(0, 0)) { + + if (IsZoomed(hwnd)) + ShowWindow(hwnd, SW_SHOWNORMAL); + + if (pcli->hwndContactList != 0) { + SendMessage(hwnd, WM_ENTERSIZEMOVE, 0, 0); + GetWindowRect(hwnd, &rc); + WINDOWPOS wp = {0}; + wp.cx = rc.right - rc.left; + wp.cy = rc.bottom - rc.top; + wp.x = rc.left; + wp.y = rc.top; + wp.flags = 0; + SendMessage(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&wp); + SendMessage(hwnd, WM_EXITSIZEMOVE, 0, 0); + } + } + } + case WM_MOVE: + if (!IsIconic(hwnd)) { + RECT rc; + GetWindowRect(hwnd, &rc); + + if (!Docking_IsDocked(0, 0)) { + cluiPos.bottom = (DWORD)(rc.bottom - rc.top); + cluiPos.left = rc.left; + cluiPos.top = rc.top; + } + cluiPos.right = rc.right - rc.left; + if (cfg::dat.realTimeSaving) { + RECT rc; + GetWindowRect(hwnd, &rc); + + if (!CallService(MS_CLIST_DOCKINGISDOCKED, 0, 0)) { //if docked, dont remember pos (except for width) + cfg::writeDword("CList", "Height", (DWORD)(rc.bottom - rc.top)); + cfg::writeDword("CList", "x", (DWORD) rc.left); + cfg::writeDword("CList", "y", (DWORD) rc.top); + } + cfg::writeDword("CList", "Width", (DWORD)(rc.right - rc.left)); + } + } + return TRUE; + + case WM_SETFOCUS: + SetFocus(pcli->hwndContactTree); + return 0; + case CLUIINTM_REMOVEFROMTASKBAR: { + BYTE windowStyle = cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_DEFAULT); + if (windowStyle == SETTING_WINDOWSTYLE_DEFAULT && cfg::getByte("CList", "AlwaysHideOnTB", 0)) + RemoveFromTaskBar(hwnd); + return 0; + } + case WM_ACTIVATE: + if (g_fading_active) { + if (wParam != WA_INACTIVE && cfg::dat.isTransparent) + transparentFocus = 1; + return DefWindowProc(hwnd, msg, wParam, lParam); + } + if (wParam == WA_INACTIVE) { + if ((HWND) wParam != hwnd) + if (cfg::dat.isTransparent) + if (transparentFocus) + SetTimer(hwnd, TM_AUTOALPHA, 250, NULL); + } else { + if (cfg::dat.isTransparent) { + KillTimer(hwnd, TM_AUTOALPHA); + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.alpha, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + transparentFocus = 1; + } + SetWindowPos(pcli->hwndContactList, cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOSENDCHANGING); + } + PostMessage(hwnd, CLUIINTM_REMOVEFROMTASKBAR, 0, 0); + return DefWindowProc(hwnd, msg, wParam, lParam); + + case WM_SETCURSOR: + if (cfg::dat.isTransparent) { + if (!transparentFocus && GetForegroundWindow() != hwnd) { + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.alpha, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + transparentFocus = 1; + SetTimer(hwnd, TM_AUTOALPHA, 250, NULL); + } + } + return DefWindowProc(hwnd, msg, wParam, lParam); + case WM_NCHITTEST: { + LRESULT result; + RECT r; + POINT pt; + int k = 0; + int clip = cfg::dat.bClipBorder; + + GetWindowRect(hwnd, &r); + GetCursorPos(&pt); + if (pt.y <= r.bottom && pt.y >= r.bottom - clip - 6 && !cfg::getByte("CLUI", "AutoSize", 0)) { + if (pt.x > r.left + clip + 10 && pt.x < r.right - clip - 10) + return HTBOTTOM; + if (pt.x < r.left + clip + 10) + return HTBOTTOMLEFT; + if (pt.x > r.right - clip - 10) + return HTBOTTOMRIGHT; + + } else if (pt.y >= r.top && pt.y <= r.top + 3 && !cfg::getByte("CLUI", "AutoSize", 0)) { + if (pt.x > r.left + clip + 10 && pt.x < r.right - clip - 10) + return HTTOP; + if (pt.x < r.left + clip + 10) + return HTTOPLEFT; + if (pt.x > r.right - clip - 10) + return HTTOPRIGHT; + } else if (pt.x >= r.left && pt.x <= r.left + clip + 6) + return HTLEFT; + else if (pt.x >= r.right - clip - 6 && pt.x <= r.right) + return HTRIGHT; + + result = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam); + if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT || result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT) + if (cfg::dat.autosize) + return HTCLIENT; + return result; + } + + case WM_TIMER: + if ((int) wParam == TM_AUTOALPHA) { + int inwnd; + + if (GetForegroundWindow() == hwnd) { + KillTimer(hwnd, TM_AUTOALPHA); + inwnd = 1; + } else { + POINT pt; + HWND hwndPt; + pt.x = (short) LOWORD(GetMessagePos()); + pt.y = (short) HIWORD(GetMessagePos()); + hwndPt = WindowFromPoint(pt); + inwnd = (hwndPt == hwnd || GetParent(hwndPt) == hwnd); + } + if (inwnd != transparentFocus) { + //change + transparentFocus = inwnd; + if (transparentFocus) + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.alpha, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + else + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), cfg::dat.autoalpha, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + } + if (!transparentFocus) + KillTimer(hwnd, TM_AUTOALPHA); + } else if (wParam == TIMERID_AUTOSIZE) { + KillTimer(hwnd, wParam); + SetWindowPos(hwnd, 0, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + PostMessage(hwnd, WM_SIZE, 0, 0); + PostMessage(hwnd, CLUIINTM_REDRAW, 0, 0); + } + return TRUE; + case WM_SHOWWINDOW: { + static int noRecurse = 0; + DWORD thisTick, startTick; + int sourceAlpha, destAlpha; + + if (cfg::dat.forceResize && wParam != SW_HIDE) { + cfg::dat.forceResize = FALSE; + if (0) { //!g_CluiData.fadeinout && MySetLayeredWindowAttributes && g_CluiData.bLayeredHack) { + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), 0, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + SendMessage(hwnd, WM_SIZE, 0, 0); + ShowWindow(hwnd, SW_SHOW); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), 255, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + } else { + SendMessage(hwnd, WM_SIZE, 0, 0); + PostMessage(hwnd, CLUIINTM_REDRAW, 0, 0); + } + } + PostMessage(hwnd, CLUIINTM_REMOVEFROMTASKBAR, 0, 0); + + if (g_floatoptions.enabled) { + if (wParam) + FLT_ShowHideAll(SW_HIDE); + else + FLT_ShowHideAll(SW_SHOWNOACTIVATE); + } + + if (!cfg::dat.fadeinout) + SFL_SetState(-1); + if (lParam) + return DefWindowProc(hwnd, msg, wParam, lParam); + if (noRecurse) + return DefWindowProc(hwnd, msg, wParam, lParam); + if (!cfg::dat.fadeinout || !IsWinVer2000Plus()) + return DefWindowProc(hwnd, msg, wParam, lParam); + + g_fading_active = 1; + + if (wParam) { + sourceAlpha = 0; + destAlpha = cfg::dat.isTransparent ? cfg::dat.alpha : 255; + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? (COLORREF)cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)sourceAlpha, LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + noRecurse = 1; + ShowWindow(hwnd, SW_SHOW); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); + noRecurse = 0; + } else { + sourceAlpha = cfg::dat.isTransparent ? (transparentFocus ? cfg::dat.alpha : cfg::dat.autoalpha) : 255; + destAlpha = 0; + } + for (startTick = GetTickCount(); ;) { + thisTick = GetTickCount(); + if (thisTick >= startTick + 200) { + SFL_SetState(-1); + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)(destAlpha), LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + g_fading_active = 0; + return DefWindowProc(hwnd, msg, wParam, lParam); + } + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)(sourceAlpha + (destAlpha - sourceAlpha) * (int)(thisTick - startTick) / 200), LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + } + API::SetLayeredWindowAttributes(hwnd, cfg::dat.bFullTransparent ? cfg::dat.colorkey : RGB(0, 0, 0), (BYTE)(destAlpha), LWA_ALPHA | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0)); + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + case WM_SYSCOMMAND: { + BYTE bWindowStyle = cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_DEFAULT); + if(SETTING_WINDOWSTYLE_DEFAULT == bWindowStyle) { + if(wParam == SC_RESTORE) { + CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam); + SendMessage(hwnd, WM_SIZE, 0, 0); + SendMessage(hwnd, CLUIINTM_REDRAW, 0, 0); + SendMessage(hwnd, CLUIINTM_STATUSBARUPDATE, 0, 0); + cfg::writeByte("CList", "State", SETTING_STATE_NORMAL); + break; + } + } + + if (wParam == SC_MAXIMIZE) + return 0; + else if (wParam == SC_MINIMIZE) { + if(SETTING_WINDOWSTYLE_DEFAULT == bWindowStyle && !cfg::getByte("CList", "AlwaysHideOnTB", 0)) { + cfg::writeByte("CList", "State", SETTING_STATE_MINIMIZED); + break; + } + pcli->pfnShowHide(0, 0); + return 0; + } + else if (wParam == SC_RESTORE) { + pcli->pfnShowHide(0, 0); + return(0); + } + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + case WM_COMMAND: { + DWORD dwOldFlags = cfg::dat.dwFlags; + if (HIWORD(wParam) == BN_CLICKED && lParam != 0) { + if (LOWORD(wParam) == IDC_TBFIRSTUID - 1) + break; + else if (LOWORD(wParam) >= IDC_TBFIRSTUID) { // skinnable buttons handling + ButtonItem *item = g_ButtonItems; + WPARAM wwParam = 0; + LPARAM llParam = 0; + HANDLE hContact = 0; + struct ClcContact *contact = 0; + int sel = cfg::clcdat ? cfg::clcdat->selection : -1; + int serviceFailure = FALSE; + + if (sel != -1) { + sel = pcli->pfnGetRowByIndex(cfg::clcdat, cfg::clcdat->selection, &contact, NULL); + if (contact && contact->type == CLCIT_CONTACT) { + hContact = contact->hContact; + } + } + while (item) { + if (item->uId == (DWORD)LOWORD(wParam)) { + int contactOK = ServiceParamsOK(item, &wwParam, &llParam, hContact); + + if (item->dwFlags & BUTTON_ISSERVICE) { + if (ServiceExists(item->szService) && contactOK) + CallService(item->szService, wwParam, llParam); + else if (contactOK) + serviceFailure = TRUE; + } else if (item->dwFlags & BUTTON_ISPROTOSERVICE && cfg::clcdat) { + if (contactOK) { + char szFinalService[512]; + + mir_snprintf(szFinalService, 512, "%s/%s", (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), item->szService); + if (ServiceExists(szFinalService)) + CallService(szFinalService, wwParam, llParam); + else + serviceFailure = TRUE; + } + } else if (item->dwFlags & BUTTON_ISDBACTION) { + BYTE *pValue; + char *szModule = item->szModule; + char *szSetting = item->szSetting; + HANDLE finalhContact = 0; + + if (item->dwFlags & BUTTON_ISCONTACTDBACTION || item->dwFlags & BUTTON_DBACTIONONCONTACT) { + contactOK = ServiceParamsOK(item, &wwParam, &llParam, hContact); + if (contactOK && item->dwFlags & BUTTON_ISCONTACTDBACTION) + szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + finalhContact = hContact; + } else + contactOK = 1; + + if (contactOK) { + BOOL fDelete = FALSE; + + if (item->dwFlags & BUTTON_ISTOGGLE) { + BOOL fChecked = (SendMessage(item->hWnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED); + + pValue = fChecked ? item->bValueRelease : item->bValuePush; + if (fChecked && pValue[0] == 0) + fDelete = TRUE; + } else + pValue = item->bValuePush; + + if (fDelete) { + //_DebugTraceA("delete value: %s, %s ON %d", szModule, szSetting, finalhContact); + DBDeleteContactSetting(finalhContact, szModule, szSetting); + } else { + switch (item->type) { + case DBVT_BYTE: + cfg::writeByte(finalhContact, szModule, szSetting, pValue[0]); + break; + case DBVT_WORD: + cfg::writeWord(finalhContact, szModule, szSetting, *((WORD *)&pValue[0])); + //_DebugTraceA("set WORD value: %s, %s, %d ON %d", szModule, item->szSetting, *((WORD *)&pValue[0]), finalhContact); + break; + case DBVT_DWORD: + cfg::writeDword(finalhContact, szModule, szSetting, *((DWORD *)&pValue[0])); + break; + case DBVT_ASCIIZ: + cfg::writeString(finalhContact, szModule, szSetting, (char *)pValue); + break; + } + } + } else if (item->dwFlags & BUTTON_ISTOGGLE) + SendMessage(item->hWnd, BM_SETCHECK, 0, 0); + } + if (!contactOK) + MessageBox(0, _T("The requested action requires a valid contact selection. Please select a contact from the contact list and repeat"), _T("Parameter mismatch"), MB_OK); + if (serviceFailure) { + char szError[512]; + + mir_snprintf(szError, 512, "The service %s specified by the %s button definition was not found. You may need to install additional plugins", item->szService, item->szName); + MessageBoxA(0, szError, "Service failure", MB_OK); + } + break; + } + item = item->nextItem; + } + goto buttons_done; + } + switch (LOWORD(wParam)) { + case IDC_TBMENU: + case IDC_TBTOPMENU: { + RECT rc; + HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUGETMAIN, 0, 0); + GetButtonRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc); + TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, rc.left, LOWORD(wParam) == IDC_TBMENU ? rc.top : rc.bottom, 0, hwnd, NULL); + return 0; + } + case IDC_TBTOPSTATUS: + case IDC_TBGLOBALSTATUS: { + RECT rc; + HMENU hmenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS, 0, 0); + GetButtonRect(GetDlgItem(hwnd, LOWORD(wParam)), &rc); + TrackPopupMenu(hmenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, rc.left, rc.top, 0, hwnd, NULL); + return 0; + } + + case IDC_TABSRMMSLIST: + case IDC_TABSRMMMENU: + if (ServiceExists("SRMsg_MOD/GetWindowFlags")) + CallService("SRMsg_MOD/Show_TrayMenu", 0, LOWORD(wParam) == IDC_TABSRMMSLIST ? 0 : 1); + return 0; + + case IDC_TBSOUND: + cfg::dat.soundsOff = !cfg::dat.soundsOff; + cfg::writeByte("CLUI", "NoSounds", (BYTE)cfg::dat.soundsOff); + cfg::writeByte("Skin", "UseSound", (BYTE)(cfg::dat.soundsOff ? 0 : 1)); + return 0; + + case IDC_TBSELECTVIEWMODE: + SendMessage(g_hwndViewModeFrame, WM_COMMAND, IDC_SELECTMODE, lParam); + break; + case IDC_TBCLEARVIEWMODE: + SendMessage(g_hwndViewModeFrame, WM_COMMAND, IDC_RESETMODES, lParam); + break; + case IDC_TBCONFIGUREVIEWMODE: + SendMessage(g_hwndViewModeFrame, WM_COMMAND, IDC_CONFIGUREMODES, lParam); + break; + case IDC_TBFINDANDADD: + CallService(MS_FINDADD_FINDADD, 0, 0); + return 0; + case IDC_TBACCOUNTS: + CallService(MS_PROTO_SHOWACCMGR, 0, 0); + break; + case IDC_TBOPTIONS: + CallService("Options/OptionsCommand", 0, 0); + return 0; + } + } + else if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_MAINMENU), (LPARAM)(HANDLE) NULL)) + return 0; + +buttons_done: + switch (LOWORD(wParam)) { + case ID_TRAY_EXIT: + case ID_ICQ_EXIT: + cfg::shutDown = 1; + if (CallService(MS_SYSTEM_OKTOEXIT, 0, 0)) + DestroyWindow(hwnd); + break; + case ID_TRAY_HIDE: + case IDC_TBMINIMIZE: + pcli->pfnShowHide(0, 0); + break; + case POPUP_NEWGROUP: + SendMessage(pcli->hwndContactTree, CLM_SETHIDEEMPTYGROUPS, 0, 0); + SendMessage(pcli->hwndContactTree, CLM_SETUSEGROUPS, 1, 0); + CallService(MS_CLIST_GROUPCREATE, 0, 0); + break; + case POPUP_HIDEOFFLINE: + case IDC_TBHIDEOFFLINE: + CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)(-1), 0); + break; + case POPUP_HIDEOFFLINEROOT: + SendMessage(pcli->hwndContactTree, CLM_SETHIDEOFFLINEROOT, !SendMessage(pcli->hwndContactTree, CLM_GETHIDEOFFLINEROOT, 0, 0), 0); + break; + case POPUP_HIDEEMPTYGROUPS: { + int newVal = !(GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_HIDEEMPTYGROUPS); + cfg::writeByte("CList", "HideEmptyGroups", (BYTE) newVal); + SendMessage(pcli->hwndContactTree, CLM_SETHIDEEMPTYGROUPS, newVal, 0); + break; + } + case IDC_TBHIDEGROUPS: + case POPUP_DISABLEGROUPS: { + int newVal = !(GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_USEGROUPS); + cfg::writeByte("CList", "UseGroups", (BYTE) newVal); + SendMessage(pcli->hwndContactTree, CLM_SETUSEGROUPS, newVal, 0); + CheckDlgButton(hwnd, IDC_TBHIDEGROUPS, newVal ? BST_CHECKED : BST_UNCHECKED); + break; + } + case POPUP_HIDEMIRANDA: + pcli->pfnShowHide(0, 0); + break; + case POPUP_VISIBILITY: + cfg::dat.dwFlags ^= CLUI_SHOWVISI; + break; + case POPUP_SHOWMETAICONS: + cfg::dat.dwFlags ^= CLUI_USEMETAICONS; + SendMessage(pcli->hwndContactTree, CLM_AUTOREBUILD, 0, 0); + break; + case POPUP_FRAME: + cfg::dat.dwFlags ^= CLUI_FRAME_CLISTSUNKEN; + break; + case POPUP_BUTTONS: + cfg::dat.dwFlags ^= CLUI_FRAME_SHOWBOTTOMBUTTONS; + break; + case POPUP_SHOWSTATUSICONS: + cfg::dat.dwFlags ^= CLUI_FRAME_STATUSICONS; + break; + case POPUP_FLOATER: + cfg::dat.bUseFloater ^= CLUI_USE_FLOATER; + if (cfg::dat.bUseFloater & CLUI_USE_FLOATER) { + SFL_Create(); + SFL_SetState(-1); + } else + SFL_Destroy(); + cfg::writeByte("CLUI", "FloaterMode", cfg::dat.bUseFloater); + break; + case POPUP_FLOATER_AUTOHIDE: + cfg::dat.bUseFloater ^= CLUI_FLOATER_AUTOHIDE; + SFL_SetState(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE ? (cfg::getByte("CList", "State", SETTING_STATE_NORMAL) == SETTING_STATE_NORMAL ? 0 : 1) : 1); + cfg::writeByte("CLUI", "FloaterMode", cfg::dat.bUseFloater); + break; + case POPUP_FLOATER_EVENTS: + cfg::dat.bUseFloater ^= CLUI_FLOATER_EVENTS; + SFL_SetSize(); + SFL_Update(0, 0, 0, NULL, FALSE); + cfg::writeByte("CLUI", "FloaterMode", cfg::dat.bUseFloater); + break; + } + if (dwOldFlags != cfg::dat.dwFlags) { + InvalidateRect(pcli->hwndContactTree, NULL, FALSE); + cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags); + if ((dwOldFlags & (CLUI_FRAME_SHOWBOTTOMBUTTONS | CLUI_FRAME_CLISTSUNKEN)) != (cfg::dat.dwFlags & (CLUI_FRAME_SHOWBOTTOMBUTTONS | CLUI_FRAME_CLISTSUNKEN))) { + ConfigureFrame(); + ConfigureCLUIGeometry(1); + } + ConfigureEventArea(pcli->hwndContactList); + PostMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + } + return FALSE; + } + case WM_LBUTTONDOWN: { + if (g_ButtonItems) { + POINT ptMouse, pt; + + GetCursorPos(&ptMouse); + pt = ptMouse; + return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + } + break; + } + case WM_DISPLAYCHANGE: + SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0); //forces it to send a cln_listsizechanged + break; + case WM_NOTIFY: + if (((LPNMHDR) lParam)->hwndFrom == pcli->hwndContactTree) { + switch (((LPNMHDR) lParam)->code) { + case CLN_LISTSIZECHANGE: + sttProcessResize(hwnd, (NMCLISTCONTROL*)lParam); + return FALSE; + + case NM_CLICK: { + NMCLISTCONTROL *nm = (NMCLISTCONTROL *) lParam; + DWORD hitFlags; + HANDLE hItem; + + hItem = (HANDLE)SendMessage(pcli->hwndContactTree, CLM_HITTEST, (WPARAM) & hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y)); + + if ((hitFlags & (CLCHT_NOWHERE | CLCHT_INLEFTMARGIN | CLCHT_BELOWITEMS)) == 0) + break; + if (cfg::getByte("CLUI", "ClientAreaDrag", SETTING_CLIENTDRAG_DEFAULT)) { + POINT pt; + pt = nm->pt; + ClientToScreen(pcli->hwndContactTree, &pt); + return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(pt.x, pt.y)); + } + } + return FALSE; + } + } + break; + case WM_CONTEXTMENU: { + RECT rc; + POINT pt; + + pt.x = (short) LOWORD(lParam); + pt.y = (short) HIWORD(lParam); + // x/y might be -1 if it was generated by a kb click + GetWindowRect(pcli->hwndContactTree, &rc); + if (pt.x == -1 && pt.y == -1) { + // all this is done in screen-coords! + GetCursorPos(&pt); + // the mouse isnt near the window, so put it in the middle of the window + if (!PtInRect(&rc, pt)) { + pt.x = rc.left + (rc.right - rc.left) / 2; + pt.y = rc.top + (rc.bottom - rc.top) / 2; + } + } + if (PtInRect(&rc, pt)) { + HMENU hMenu; + hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDGROUP, 0, 0); + TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL); + DestroyTrayMenu(hMenu); + return 0; + } + GetWindowRect(pcli->hwndStatus, &rc); + if (PtInRect(&rc, pt)) { + HMENU hMenu; + if (cfg::getByte("CLUI", "SBarRightClk", 0)) + hMenu = (HMENU) CallService(MS_CLIST_MENUGETMAIN, 0, 0); + else + hMenu = (HMENU) CallService(MS_CLIST_MENUGETSTATUS, 0, 0); + TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL); + return 0; + } + } + break; + + case WM_MEASUREITEM: + if (((LPMEASUREITEMSTRUCT) lParam)->itemData == MENU_MIRANDAMENU) { + ((LPMEASUREITEMSTRUCT) lParam)->itemWidth = g_cxsmIcon * 4 / 3; + ((LPMEASUREITEMSTRUCT) lParam)->itemHeight = 0; + return TRUE; + } + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + case WM_DRAWITEM: { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + + if (hbmLockedPoint == 0) { + RECT rc = {0, 0, 5, 5}; + + hdcLockedPoint = CreateCompatibleDC(dis->hDC); + hbmLockedPoint = CreateCompatibleBitmap(dis->hDC, 5, 5); + hbmOldLockedPoint = reinterpret_cast(SelectObject(hdcLockedPoint, hbmLockedPoint)); + } + if (dis->hwndItem == pcli->hwndStatus) { + ProtocolData *pd = (ProtocolData *)dis->itemData; + int nParts = SendMessage(pcli->hwndStatus, SB_GETPARTS, 0, 0); + char *szProto; + int status, x; + SIZE textSize; + BYTE showOpts = cfg::getByte("CLUI", "SBarShow", 1); + if (IsBadCodePtr((FARPROC)pd)) + return TRUE; + if (cfg::shutDown) + return TRUE; + szProto = pd->RealName; + status = CallProtoService(szProto, PS_GETSTATUS, 0, 0); + SetBkMode(dis->hDC, TRANSPARENT); + x = dis->rcItem.left; + + if (showOpts & 1) { + HICON hIcon; + + if (status >= ID_STATUS_CONNECTING && status < ID_STATUS_OFFLINE) { + char szBuffer[128]; + mir_snprintf(szBuffer, 128, "%s_conn", pd->RealName); + hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szBuffer); + } else if (cfg::dat.bShowXStatusOnSbar && status > ID_STATUS_OFFLINE) { + ICQ_CUSTOM_STATUS cst = {0}; + char szServiceName[128]; + int xStatus; + + mir_snprintf(szServiceName, 128, "%s%s", pd->RealName, PS_ICQ_GETCUSTOMSTATUSEX); + cst.cbSize = sizeof(ICQ_CUSTOM_STATUS); + cst.flags = CSSF_MASK_STATUS; + cst.status = &xStatus; + if (ServiceExists(szServiceName) && !CallService(szServiceName, 0, (LPARAM)&cst) && xStatus > 0) { + hIcon = (HICON)CallProtoService(pd->RealName, PS_ICQ_GETCUSTOMSTATUSICON, 0, LR_SHARED); // get OWN xStatus icon (if set) + } else + hIcon = LoadSkinnedProtoIcon(szProto, status); + } else + hIcon = LoadSkinnedProtoIcon(szProto, status); + + if (!(showOpts & 6) && cfg::dat.bEqualSections) + x = (dis->rcItem.left + dis->rcItem.right - 16) >> 1; + if (pd->statusbarpos == 0) + x += (cfg::dat.bEqualSections ? (cfg::dat.bCLeft / 2) : cfg::dat.bCLeft); + else if (pd->statusbarpos == nParts - 1) + x -= (cfg::dat.bCRight / 2); + DrawIconEx(dis->hDC, x, (dis->rcItem.top + dis->rcItem.bottom - 16) >> 1, hIcon, 16, 16, 0, NULL, DI_NORMAL); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); + + if (cfg::getByte("CLUI", "sbar_showlocked", 1)) { + if (cfg::getByte(szProto, "LockMainStatus", 0)) { + hIcon = LoadSkinnedIcon(SKINICON_OTHER_STATUS_LOCKED); + if (hIcon != NULL) { + DrawIconEx(dis->hDC, x, (dis->rcItem.top + dis->rcItem.bottom - 16) >> 1, hIcon, 16, 16, 0, NULL, DI_NORMAL); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); + } + } + } + x += 18; + } else { + x += 2; + if (pd->statusbarpos == 0) + x += (cfg::dat.bEqualSections ? (cfg::dat.bCLeft / 2) : cfg::dat.bCLeft); + else if (pd->statusbarpos == nParts - 1) + x -= (cfg::dat.bCRight / 2); + } + if (showOpts & 2) { + TCHAR szName[64]; + PROTOACCOUNT* pa = ProtoGetAccount( szProto ); + if ( pa ) { + lstrcpyn( szName, pa->tszAccountName, SIZEOF(szName)); + szName[ SIZEOF(szName)-1 ] = 0; + } + else szName[0] = 0; + + if (lstrlen(szName) < sizeof(szName) - 1) + lstrcat(szName, _T(" ")); + GetTextExtentPoint32(dis->hDC, szName, lstrlen(szName), &textSize); + TextOut(dis->hDC, x, (dis->rcItem.top + dis->rcItem.bottom - textSize.cy) >> 1, szName, lstrlen(szName)); + x += textSize.cx; + } + if (showOpts & 4) { + TCHAR *szStatus = pcli->pfnGetStatusModeDescription( status, 0 ); + GetTextExtentPoint32(dis->hDC, szStatus, lstrlen(szStatus), &textSize); + TextOut(dis->hDC, x, (dis->rcItem.top + dis->rcItem.bottom - textSize.cy) >> 1, szStatus, lstrlen(szStatus)); + } + } else if (dis->CtlType == ODT_MENU) { + if (dis->itemData == MENU_MIRANDAMENU) + break; + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + } + return 0; + } + + case WM_CLOSE: + if(SETTING_WINDOWSTYLE_DEFAULT == cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_DEFAULT) && !cfg::getByte("CList", "AlwaysHideOnTB", 0)) { + PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + return(0); + } + pcli->pfnShowHide(0, 0); + return(0); + + case CLUIINTM_REDRAW: + if (show_on_first_autosize) { + show_on_first_autosize = FALSE; + ShowCLUI(hwnd); + } + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN); + return 0; + case CLUIINTM_STATUSBARUPDATE: + CluiProtocolStatusChanged(0, 0); + return 0; + + case WM_THEMECHANGED: + API::updateState(); + break; + + case WM_DESTROY: + if (cfg::dat.hdcBg) { + SelectObject(cfg::dat.hdcBg, cfg::dat.hbmBgOld); + DeleteObject(cfg::dat.hbmBg); + DeleteDC(cfg::dat.hdcBg); + cfg::dat.hdcBg = NULL; + } + if (cfg::dat.bmpBackground) { + SelectObject(cfg::dat.hdcPic, cfg::dat.hbmPicOld); + DeleteDC(cfg::dat.hdcPic); + DeleteObject(cfg::dat.bmpBackground); + cfg::dat.bmpBackground = NULL; + } + FreeProtocolData(); + if (hdcLockedPoint) { + SelectObject(hdcLockedPoint, hbmOldLockedPoint); + DeleteObject(hbmLockedPoint); + DeleteDC(hdcLockedPoint); + } + /* + * if this has not yet been set, do it now. + * indicates that clist is shutting down and prevents various things + * from happening at shutdown. + */ + if (!cfg::shutDown) + cfg::shutDown = 1; + CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)hFrameContactTree, (LPARAM)0); + break; + } + return saveContactListWndProc(hwnd, msg, wParam, lParam); +} + +#ifndef CS_DROPSHADOW +#define CS_DROPSHADOW 0x00020000 +#endif + +static int MetaChanged(WPARAM wParam, LPARAM lParam) +{ + pcli->pfnClcBroadcast(INTM_METACHANGEDEVENT, wParam, lParam); + return 0; +} + +static BOOL g_AboutDlgActive = 0; + +INT_PTR CALLBACK DlgProcAbout(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HICON hIcon; + COLORREF url_visited = RGB(128, 0, 128); + COLORREF url_unvisited = RGB(0, 0, 255); + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + int h; + HFONT hFont; + LOGFONT lf; + + g_AboutDlgActive = TRUE; + hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_GETFONT, 0, 0); + GetObject(hFont, sizeof(lf), &lf); + h = lf.lfHeight; + lf.lfHeight = (int)(lf.lfHeight * 1.5); + lf.lfWeight = FW_BOLD; + hFont = CreateFontIndirect(&lf); + SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_SETFONT, (WPARAM)hFont, 0); + lf.lfHeight = h; + hFont = CreateFontIndirect(&lf); + SendDlgItemMessage(hwndDlg, IDC_VERSION, WM_SETFONT, (WPARAM)hFont, 0); + } + { + char str[64]; + DWORD v = pluginInfo.version; + mir_snprintf(str, sizeof(str), "%s %d.%d.%d.%d", Translate("Version"), HIBYTE(HIWORD(v)), LOBYTE(HIWORD(v)), HIBYTE(LOWORD(v)), LOBYTE(LOWORD(v))); + SetDlgItemTextA(hwndDlg, IDC_VERSION, str); + mir_snprintf(str, sizeof(str), Translate("Built %s %s"), __DATE__, __TIME__); + SetDlgItemTextA(hwndDlg, IDC_BUILDTIME, str); + } + hIcon = LoadIcon(GetModuleHandleA("miranda32.exe"), MAKEINTRESOURCE(102)); + SendDlgItemMessage(hwndDlg, IDC_LOGO, STM_SETICON, (WPARAM)hIcon, 0); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + DestroyIcon(hIcon); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + DestroyWindow(hwndDlg); + return TRUE; + case IDC_SUPPORT: + CallService(MS_UTILS_OPENURL, 1, (LPARAM)"http://miranda-ng.org/"); + break; + } + break; + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_WHITERECT) + || (HWND)lParam == GetDlgItem(hwndDlg, IDC_CLNICER) + || (HWND)lParam == GetDlgItem(hwndDlg, IDC_VERSION) + || (HWND)lParam == GetDlgItem(hwndDlg, IDC_BUILDTIME) + || (HWND)lParam == GetDlgItem(hwndDlg, IDC_COPYRIGHT) + || (HWND)lParam == GetDlgItem(hwndDlg, IDC_SUPPORT) + || (HWND)lParam == GetDlgItem(hwndDlg, IDC_LOGO)) { + if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_CLNICER)) + SetTextColor((HDC)wParam, RGB(180, 10, 10)); + else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_VERSION)) + SetTextColor((HDC)wParam, RGB(70, 70, 70)); + else + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetBkColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockObject(WHITE_BRUSH); + } + break; + case WM_DESTROY: { + HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_GETFONT, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_CLNICER, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0), 0); + DeleteObject(hFont); + hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_VERSION, WM_GETFONT, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_VERSION, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0), 0); + DeleteObject(hFont); + g_AboutDlgActive = FALSE; + } + break; + } + return FALSE; +} + +static INT_PTR CLN_ShowAbout(WPARAM wParam, LPARAM lParam) +{ + if (!g_AboutDlgActive) + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CLNABOUT), 0, DlgProcAbout, 0); + return 0; +} + +static INT_PTR CLN_ShowMainMenu(WPARAM wParam, LPARAM lParam) +{ + HMENU hMenu; + POINT pt; + + hMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN, 0, 0); + GetCursorPos(&pt); + TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, 0, pcli->hwndContactList, NULL); + return 0; +} + +static INT_PTR CLN_ShowStatusMenu(WPARAM wParam, LPARAM lParam) +{ + HMENU hMenu; + POINT pt; + + hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS, 0, 0); + GetCursorPos(&pt); + TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, 0, pcli->hwndContactList, NULL); + return 0; +} + +#define MS_CLUI_SHOWMAINMENU "CList/ShowMainMenu" +#define MS_CLUI_SHOWSTATUSMENU "CList/ShowStatusMenu" + +void LoadCLUIModule(void) +{ + HookEvent(ME_SYSTEM_MODULESLOADED, CluiModulesLoaded); + + WNDCLASS wndclass; + wndclass.style = 0; + wndclass.lpfnWndProc = EventAreaWndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = g_hInst; + wndclass.hIcon = 0; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE); + wndclass.lpszMenuName = 0; + wndclass.lpszClassName = _T("EventAreaClass"); + RegisterClass(&wndclass); + + SFL_RegisterWindowClass(); + + oldhideoffline = cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT); + cluiPos.left = cfg::getDword("CList", "x", 600); + cluiPos.top = cfg::getDword("CList", "y", 200); + cluiPos.right = cfg::getDword("CList", "Width", 150); + cluiPos.bottom = cfg::getDword("CList", "Height", 350); + + LoadExtraIconModule(); + LoadCLUIFramesModule(); + + CreateServiceFunction("CLN/About", CLN_ShowAbout); + CreateServiceFunction(MS_CLUI_SHOWMAINMENU, CLN_ShowMainMenu); + CreateServiceFunction(MS_CLUI_SHOWSTATUSMENU, CLN_ShowStatusMenu); +} + +void OnCreateClc() +{ + HookEvent(ME_MC_DEFAULTTCHANGED, MetaChanged); + HookEvent(ME_MC_SUBCONTACTSCHANGED, MetaChanged); + + InitGroupMenus(); + LoadExtBkSettingsFromDB(); + PreCreateCLC(pcli->hwndContactList); +} + +static struct { + UINT id; + char *name; +} _tagFSINFO[] = { + FONTID_CONTACTS, LPGEN( "Standard contacts"), + FONTID_INVIS, LPGEN( "Online contacts to whom you have a different visibility"), + FONTID_OFFLINE, LPGEN( "Offline contacts"), + FONTID_OFFINVIS, LPGEN( "Offline contacts to whom you have a different visibility" ), + FONTID_NOTONLIST, LPGEN( "Contacts which are 'not on list'"), + FONTID_GROUPS, LPGEN( "Groups"), + FONTID_GROUPCOUNTS, LPGEN( "Group member counts"), + FONTID_DIVIDERS, LPGEN( "Dividers"), + FONTID_STATUS, LPGEN("Status mode"), + FONTID_FRAMETITLE, LPGEN("Frame titles"), + FONTID_EVENTAREA, LPGEN("Event area"), + FONTID_TIMESTAMP, LPGEN("Contact list local time"), + 0, NULL +}; + +void FS_RegisterFonts() +{ + ColourID colourid; + FontID fid = {0}; + char szTemp[50]; + DBVARIANT dbv; + int j = 0; + + fid.cbSize = sizeof(fid); + strncpy(fid.group, "Contact List", sizeof(fid.group)); + strncpy(fid.dbSettingsGroup, "CLC", 5); + fid.flags = FIDF_DEFAULTVALID | FIDF_ALLOWEFFECTS | FIDF_APPENDNAME | FIDF_SAVEPOINTSIZE; + while (_tagFSINFO[j].name != 0) { + _snprintf(szTemp, sizeof(szTemp), "Font%d", _tagFSINFO[j].id); + strncpy(fid.prefix, szTemp, sizeof(fid.prefix)); + fid.order = _tagFSINFO[j].id; + strncpy(fid.name, Translate(_tagFSINFO[j].name), 60); + _snprintf(szTemp, sizeof(szTemp), "Font%dCol", _tagFSINFO[j].id); + fid.deffontsettings.colour = (COLORREF)cfg::getDword("CLC", szTemp, GetSysColor(COLOR_WINDOWTEXT)); + + _snprintf(szTemp, sizeof(szTemp), "Font%dSize", _tagFSINFO[j].id); + fid.deffontsettings.size = (BYTE)cfg::getByte("CLC", szTemp, 8); + + _snprintf(szTemp, sizeof(szTemp), "Font%dSty", _tagFSINFO[j].id); + fid.deffontsettings.style = cfg::getByte("CLC", szTemp, 0); + _snprintf(szTemp, sizeof(szTemp), "Font%dSet", _tagFSINFO[j].id); + fid.deffontsettings.charset = cfg::getByte("CLC", szTemp, DEFAULT_CHARSET); + _snprintf(szTemp, sizeof(szTemp), "Font%dName", _tagFSINFO[j].id); + if (cfg::getString(NULL, "CLC", szTemp, &dbv)) + lstrcpynA(fid.deffontsettings.szFace, "Arial", LF_FACESIZE); + else { + lstrcpynA(fid.deffontsettings.szFace, dbv.pszVal, LF_FACESIZE); + mir_free(dbv.pszVal); + } + FontRegister(&fid); + j++; + } + // and colours + colourid.cbSize = sizeof(ColourID); + colourid.order = 0; + strncpy(colourid.dbSettingsGroup, "CLC", sizeof(colourid.dbSettingsGroup)); + + strncpy(colourid.setting, "BkColour", sizeof(colourid.setting)); + strncpy(colourid.name, LPGEN("Background"), SIZEOF(colourid.name)); + strncpy(colourid.group, LPGEN("Contact List"), SIZEOF(colourid.group)); + colourid.defcolour = CLCDEFAULT_BKCOLOUR; + ColourRegister(&colourid); + + strncpy(colourid.setting, "SelTextColour", sizeof(colourid.setting)); + strncpy(colourid.name, LPGEN("Selected Text"), SIZEOF(colourid.name)); + colourid.order = 1; + colourid.defcolour = CLCDEFAULT_SELTEXTCOLOUR; + ColourRegister(&colourid); + + strncpy(colourid.setting, "HotTextColour", sizeof(colourid.setting)); + strncpy(colourid.name, LPGEN("Hottrack Text"), SIZEOF(colourid.name)); + colourid.order = 1; + colourid.defcolour = CLCDEFAULT_HOTTEXTCOLOUR; + ColourRegister(&colourid); + + strncpy(colourid.setting, "QuickSearchColour", sizeof(colourid.setting)); + strncpy(colourid.name, LPGEN("Quicksearch Text"), SIZEOF(colourid.name)); + colourid.order = 1; + colourid.defcolour = CLCDEFAULT_QUICKSEARCHCOLOUR; + ColourRegister(&colourid); +} diff --git a/plugins/Clist_nicer/src/cluiopts.cpp b/plugins/Clist_nicer/src/cluiopts.cpp new file mode 100644 index 0000000000..f836995f68 --- /dev/null +++ b/plugins/Clist_nicer/src/cluiopts.cpp @@ -0,0 +1,476 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE done + +*/ +#include "commonheaders.h" + +extern WNDPROC OldStatusBarProc; +extern HANDLE hExtraImageApplying; +extern SIZE g_oldSize; +extern POINT g_oldPos; +extern COLORREF g_CLUISkinnedBkColorRGB; +extern HPEN g_hPenCLUIFrames; + +static int opt_clui_changed = 0; + +void AddToTaskBar(HWND hWnd); + +INT_PTR CALLBACK DlgProcCluiOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + opt_clui_changed = 0; + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_BRINGTOFRONT, cfg::getByte("CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ALWAYSHIDEONTASKBAR, cfg::getByte("CList", "AlwaysHideOnTB", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONTOP, cfg::getByte("CList", "OnTop", SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWMAINMENU, cfg::getByte("CLUI", "ShowMainMenu", SETTING_SHOWMAINMENU_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CLIENTDRAG, cfg::getByte("CLUI", "ClientAreaDrag", SETTING_CLIENTDRAG_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_FADEINOUT, cfg::dat.fadeinout ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOSIZE, cfg::dat.autosize); + CheckDlgButton(hwndDlg, IDC_DROPSHADOW, cfg::getByte("CList", "WindowShadow", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONDESKTOP, cfg::getByte("CList", "OnDesktop", 0) ? BST_CHECKED : BST_UNCHECKED); + + SendDlgItemMessage(hwndDlg, IDC_BORDERSTYLE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Title bar")); + SendDlgItemMessage(hwndDlg, IDC_BORDERSTYLE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Tool Window")); + SendDlgItemMessage(hwndDlg, IDC_BORDERSTYLE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Thin border")); + SendDlgItemMessage(hwndDlg, IDC_BORDERSTYLE, CB_INSERTSTRING, -1, (LPARAM)TranslateT("No border")); + SendDlgItemMessage(hwndDlg, IDC_BORDERSTYLE, CB_SETCURSEL, cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_TOOLWINDOW), 0); + + SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + SendDlgItemMessage(hwndDlg, IDC_MAXSIZESPIN, UDM_SETPOS, 0, cfg::getByte("CLUI", "MaxSizeHeight", 75)); + + SendDlgItemMessage(hwndDlg, IDC_CLIPBORDERSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0)); + SendDlgItemMessage(hwndDlg, IDC_CLIPBORDERSPIN, UDM_SETPOS, 0, cfg::dat.bClipBorder); + + SendDlgItemMessage(hwndDlg, IDC_CLEFTSPIN, UDM_SETRANGE, 0, MAKELONG(255, 0)); + SendDlgItemMessage(hwndDlg, IDC_CRIGHTSPIN, UDM_SETRANGE, 0, MAKELONG(255, 0)); + SendDlgItemMessage(hwndDlg, IDC_CTOPSPIN, UDM_SETRANGE, 0, MAKELONG(255, 0)); + SendDlgItemMessage(hwndDlg, IDC_CBOTTOMSPIN, UDM_SETRANGE, 0, MAKELONG(255, 0)); + + SendDlgItemMessage(hwndDlg, IDC_CLUIFRAMESBDR, CPM_SETCOLOUR, 0, cfg::getDword("CLUI", "clr_frameborder", RGB(40, 40, 40))); + + SendDlgItemMessage(hwndDlg, IDC_CLEFTSPIN, UDM_SETPOS, 0, cfg::dat.bCLeft - (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? 3 : 0)); + SendDlgItemMessage(hwndDlg, IDC_CRIGHTSPIN, UDM_SETPOS, 0, cfg::dat.bCRight - (cfg::dat.dwFlags & CLUI_FRAME_CLISTSUNKEN ? 3 : 0)); + SendDlgItemMessage(hwndDlg, IDC_CTOPSPIN, UDM_SETPOS, 0, cfg::dat.bCTop); + SendDlgItemMessage(hwndDlg, IDC_CBOTTOMSPIN, UDM_SETPOS, 0, cfg::dat.bCBottom); + + CheckDlgButton(hwndDlg, IDC_AUTOSIZEUPWARD, cfg::getByte("CLUI", "AutoSizeUpward", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOHIDE, cfg::getByte("CList", "AutoHide", SETTING_AUTOHIDE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETRANGE, 0, MAKELONG(900, 1)); + SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_SETPOS, 0, MAKELONG(cfg::getWord("CList", "HideTime", SETTING_HIDETIME_DEFAULT), 0)); + Utils::enableDlgControl(hwndDlg, IDC_HIDETIME, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + Utils::enableDlgControl(hwndDlg, IDC_HIDETIMESPIN, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + Utils::enableDlgControl(hwndDlg, IDC_STATIC01, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + if (!IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)) { + Utils::enableDlgControl(hwndDlg, IDC_STATIC21, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_STATIC22, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_MAXSIZEHEIGHT, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_MAXSIZESPIN, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_AUTOSIZEUPWARD, FALSE); + } { + DBVARIANT dbv; + if (!cfg::getTString(NULL, "CList", "TitleText", &dbv)) { + SetDlgItemText(hwndDlg, IDC_TITLETEXT, dbv.ptszVal); + DBFreeVariant(&dbv); + } else + SetDlgItemTextA(hwndDlg, IDC_TITLETEXT, MIRANDANAME); + } + + if (!API::sysConfig.isWin2KPlus) { + Utils::enableDlgControl(hwndDlg, IDC_FADEINOUT, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_TRANSPARENT, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_DROPSHADOW, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_FULLTRANSPARENT, FALSE); + } else { + CheckDlgButton(hwndDlg, IDC_TRANSPARENT, cfg::dat.isTransparent ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_FULLTRANSPARENT, cfg::dat.bFullTransparent ? BST_CHECKED : BST_UNCHECKED); + } + if (!IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)) { + Utils::enableDlgControl(hwndDlg, IDC_STATIC11, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_STATIC12, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_TRANSACTIVE, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_TRANSINACTIVE, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_ACTIVEPERC, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_INACTIVEPERC, FALSE); + } + SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_SETPOS, TRUE, cfg::dat.alpha); + SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_SETPOS, TRUE, cfg::dat.autoalpha); + SendMessage(hwndDlg, WM_HSCROLL, 0x12345678, 0); + + CheckDlgButton(hwndDlg, IDC_ROUNDEDBORDER, cfg::dat.dwFlags & CLUI_FRAME_ROUNDEDFRAME); + SendDlgItemMessage(hwndDlg, IDC_FRAMEGAPSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0)); + SendDlgItemMessage(hwndDlg, IDC_FRAMEGAPSPIN, UDM_SETPOS, 0, (LPARAM)cfg::dat.gapBetweenFrames); + + return TRUE; + } + case WM_COMMAND: + if (LOWORD(wParam) == IDC_AUTOHIDE) { + Utils::enableDlgControl(hwndDlg, IDC_HIDETIME, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + Utils::enableDlgControl(hwndDlg, IDC_HIDETIMESPIN, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + Utils::enableDlgControl(hwndDlg, IDC_STATIC01, IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + } else if (LOWORD(wParam) == IDC_TRANSPARENT) { + Utils::enableDlgControl(hwndDlg, IDC_STATIC11, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + Utils::enableDlgControl(hwndDlg, IDC_STATIC12, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + Utils::enableDlgControl(hwndDlg, IDC_TRANSACTIVE, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + Utils::enableDlgControl(hwndDlg, IDC_TRANSINACTIVE, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + Utils::enableDlgControl(hwndDlg, IDC_ACTIVEPERC, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + Utils::enableDlgControl(hwndDlg, IDC_INACTIVEPERC, IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + } else if (LOWORD(wParam) == IDC_AUTOSIZE) { + Utils::enableDlgControl(hwndDlg, IDC_STATIC21, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + Utils::enableDlgControl(hwndDlg, IDC_STATIC22, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + Utils::enableDlgControl(hwndDlg, IDC_MAXSIZEHEIGHT, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + Utils::enableDlgControl(hwndDlg, IDC_MAXSIZESPIN, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + Utils::enableDlgControl(hwndDlg, IDC_AUTOSIZEUPWARD, IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + } + if ((LOWORD(wParam) == IDC_FRAMEGAP || LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_CLIPBORDER || LOWORD(wParam) == IDC_ROWGAP || LOWORD(wParam) == IDC_TITLETEXT || + LOWORD(wParam) == IDC_MAXSIZEHEIGHT || LOWORD(wParam) == IDC_CLEFT || LOWORD(wParam) == IDC_CRIGHT || LOWORD(wParam) == IDC_CTOP + || LOWORD(wParam) == IDC_CBOTTOM) && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + opt_clui_changed = 1; + break; + + case WM_HSCROLL: + { + char str[10]; + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_INACTIVEPERC, str); + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_ACTIVEPERC, str); + } + if (wParam != 0x12345678) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + opt_clui_changed = 1; + } + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + BOOL translated; + BYTE oldFading; + BYTE windowStyle = (BYTE)SendDlgItemMessage(hwndDlg, IDC_BORDERSTYLE, CB_GETCURSEL, 0, 0); + COLORREF clr_cluiframes; + + if (!opt_clui_changed) + return TRUE; + + cfg::writeByte("CLUI", "FadeInOut", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_FADEINOUT)); + cfg::dat.fadeinout = IsDlgButtonChecked(hwndDlg, IDC_FADEINOUT) ? 1 : 0; + oldFading = cfg::dat.fadeinout; + cfg::dat.fadeinout = FALSE; + + cfg::writeByte("CLUI", "WindowStyle", windowStyle); + cfg::dat.gapBetweenFrames = GetDlgItemInt(hwndDlg, IDC_FRAMEGAP, &translated, FALSE); + + cfg::writeDword("CLUIFrames", "GapBetweenFrames", cfg::dat.gapBetweenFrames); + cfg::writeByte("CList", "OnTop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONTOP)); + SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg, IDC_ONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + cfg::dat.bCLeft = (BYTE)SendDlgItemMessage(hwndDlg, IDC_CLEFTSPIN, UDM_GETPOS, 0, 0); + cfg::dat.bCRight = (BYTE)SendDlgItemMessage(hwndDlg, IDC_CRIGHTSPIN, UDM_GETPOS, 0, 0); + cfg::dat.bCTop = (BYTE)SendDlgItemMessage(hwndDlg, IDC_CTOPSPIN, UDM_GETPOS, 0, 0); + cfg::dat.bCBottom = (BYTE)SendDlgItemMessage(hwndDlg, IDC_CBOTTOMSPIN, UDM_GETPOS, 0, 0); + + cfg::writeDword("CLUI", "clmargins", MAKELONG(MAKEWORD(cfg::dat.bCLeft, cfg::dat.bCRight), MAKEWORD(cfg::dat.bCTop, cfg::dat.bCBottom))); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + + cfg::writeByte("CList", "BringToFront", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_BRINGTOFRONT)); + cfg::writeByte("CList", "AlwaysHideOnTB", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_ALWAYSHIDEONTASKBAR)); + + if (windowStyle != SETTING_WINDOWSTYLE_DEFAULT) { + LONG style; + // Window must be hidden to dynamically remove the taskbar button. + // See http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_programming/taskbar.asp + WINDOWPLACEMENT p; + p.length = sizeof(p); + GetWindowPlacement(pcli->hwndContactList, &p); + ShowWindow(pcli->hwndContactList, SW_HIDE); + + style = GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE); + style |= WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE; + style &= ~WS_EX_APPWINDOW; + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, style); + + SetWindowPlacement(pcli->hwndContactList, &p); + ShowWindow(pcli->hwndContactList, SW_SHOW); + } + else + { + LONG style; + style = GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE); + style &= ~(WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE); + if (cfg::getByte("CList", "AlwaysHideOnTB", 1)) + style &= ~WS_EX_APPWINDOW; + else + { + style |= WS_EX_APPWINDOW; + AddToTaskBar(pcli->hwndContactList); + } + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, style); + } + + cfg::dat.bClipBorder = (BYTE)GetDlgItemInt(hwndDlg, IDC_CLIPBORDER, &translated, FALSE); + cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags); + cfg::writeByte("CLUI", "clipborder", cfg::dat.bClipBorder); + + cfg::writeByte("CLUI", "ShowMainMenu", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWMAINMENU)); + cfg::writeByte("CLUI", "ClientAreaDrag", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CLIENTDRAG)); + + clr_cluiframes = (COLORREF)SendDlgItemMessage(hwndDlg, IDC_CLUIFRAMESBDR, CPM_GETCOLOUR, 0, 0); + + if(g_hPenCLUIFrames) + DeleteObject(g_hPenCLUIFrames); + g_hPenCLUIFrames = CreatePen(PS_SOLID, 1, clr_cluiframes); + cfg::writeDword("CLUI", "clr_frameborder", clr_cluiframes); + + ApplyCLUIBorderStyle(pcli->hwndContactList); + + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWMAINMENU)) + SetMenu(pcli->hwndContactList, NULL); + else + SetMenu(pcli->hwndContactList, pcli->hMenuMain); + + { + TCHAR title[256]; + GetDlgItemText(hwndDlg, IDC_TITLETEXT, title, SIZEOF(title)); + cfg::writeTString(NULL, "CList", "TitleText", title); + SetWindowText(pcli->hwndContactList, title); + } + cfg::dat.dwFlags = IsDlgButtonChecked(hwndDlg, IDC_ROUNDEDBORDER) ? cfg::dat.dwFlags | CLUI_FRAME_ROUNDEDFRAME : cfg::dat.dwFlags & ~CLUI_FRAME_ROUNDEDFRAME; + cfg::writeByte("CLUI", "AutoSize", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE)); + + if ((cfg::dat.autosize = IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZE) ? 1 : 0)) { + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0); + } + + cfg::writeByte("CLUI", "MaxSizeHeight", (BYTE) GetDlgItemInt(hwndDlg, IDC_MAXSIZEHEIGHT, NULL, FALSE)); + cfg::writeByte("CLUI", "AutoSizeUpward", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZEUPWARD)); + cfg::writeByte("CList", "AutoHide", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOHIDE)); + cfg::writeWord("CList", "HideTime", (WORD) SendDlgItemMessage(hwndDlg, IDC_HIDETIMESPIN, UDM_GETPOS, 0, 0)); + + cfg::writeByte("CList", "Transparent", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT)); + cfg::dat.isTransparent = IsDlgButtonChecked(hwndDlg, IDC_TRANSPARENT) ? 1 : 0; + cfg::writeByte("CList", "Alpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0)); + cfg::dat.alpha = (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSACTIVE, TBM_GETPOS, 0, 0); + cfg::writeByte("CList", "AutoAlpha", (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0)); + cfg::dat.autoalpha = (BYTE) SendDlgItemMessage(hwndDlg, IDC_TRANSINACTIVE, TBM_GETPOS, 0, 0); + cfg::writeByte("CList", "WindowShadow", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DROPSHADOW)); + cfg::writeByte("CList", "OnDesktop", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_ONDESKTOP)); + cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags); + cfg::dat.bFullTransparent = IsDlgButtonChecked(hwndDlg, IDC_FULLTRANSPARENT) ? 1 : 0; + cfg::writeByte("CLUI", "fulltransparent", (BYTE)cfg::dat.bFullTransparent); + + if (cfg::dat.bLayeredHack) + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) | WS_EX_LAYERED); + + if(g_CLUISkinnedBkColorRGB) + cfg::dat.colorkey = g_CLUISkinnedBkColorRGB; + else if(cfg::dat.bClipBorder == 0 && !(cfg::dat.dwFlags & CLUI_FRAME_ROUNDEDFRAME)) + cfg::dat.colorkey = cfg::getDword("CLC", "BkColour", CLCDEFAULT_BKCOLOUR); + else { + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + cfg::dat.colorkey = RGB(255, 0, 255); + } + if (cfg::dat.isTransparent || cfg::dat.bFullTransparent) { + if(API::sysConfig.isWin2KPlus) { + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) & ~WS_EX_LAYERED); + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) | WS_EX_LAYERED); + API::SetLayeredWindowAttributes(pcli->hwndContactList, 0, 255, LWA_ALPHA | LWA_COLORKEY); + API::SetLayeredWindowAttributes(pcli->hwndContactList, + (COLORREF)(cfg::dat.bFullTransparent ? cfg::dat.colorkey : 0), + (BYTE)(cfg::dat.isTransparent ? cfg::dat.autoalpha : 255), + (DWORD)((cfg::dat.isTransparent ? LWA_ALPHA : 0L) | (cfg::dat.bFullTransparent ? LWA_COLORKEY : 0L))); + } + } else { + API::SetLayeredWindowAttributes(pcli->hwndContactList, RGB(0, 0, 0), (BYTE)255, LWA_ALPHA); + if (!cfg::dat.bLayeredHack) + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) & ~WS_EX_LAYERED); + } + + ConfigureCLUIGeometry(1); + ShowWindow(pcli->hwndContactList, SW_SHOW); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); + cfg::dat.fadeinout = oldFading; + SFL_SetState(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE ? (cfg::getByte("CList", "State", SETTING_STATE_NORMAL) == SETTING_STATE_NORMAL ? 0 : 1) : 1); + opt_clui_changed = 0; + return TRUE; + } + } + break; + } + return FALSE; +} + +static int opt_sbar_changed = 0; + +INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + opt_sbar_changed = 0; + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_SHOWSBAR, cfg::getByte("CLUI", "ShowSBar", 1) ? BST_CHECKED : BST_UNCHECKED); { + BYTE showOpts = cfg::getByte("CLUI", "SBarShow", 1); + CheckDlgButton(hwndDlg, IDC_SHOWICON, showOpts & 1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWPROTO, showOpts & 2 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWSTATUS, showOpts & 4 ? BST_CHECKED : BST_UNCHECKED); + } + CheckDlgButton(hwndDlg, IDC_RIGHTSTATUS, cfg::getByte("CLUI", "SBarRightClk", 0) ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_RIGHTMIRANDA, !IsDlgButtonChecked(hwndDlg, IDC_RIGHTSTATUS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_EQUALSECTIONS, cfg::dat.bEqualSections ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SBPANELBEVEL, cfg::getByte("CLUI", "SBarBevel", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWGRIP, cfg::getByte("CLUI", "ShowGrip", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SKINBACKGROUND, cfg::dat.bSkinnedStatusBar); + CheckDlgButton(hwndDlg, IDC_SHOWXSTATUS, cfg::dat.bShowXStatusOnSbar); + CheckDlgButton(hwndDlg, IDC_MARKLOCKED, cfg::getByte("CLUI", "sbar_showlocked", 1)); + + if (!IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) { + Utils::enableDlgControl(hwndDlg, IDC_SHOWICON, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_SHOWPROTO, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_SHOWSTATUS, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_RIGHTSTATUS, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_RIGHTMIRANDA, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_EQUALSECTIONS, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_SBPANELBEVEL, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_SHOWGRIP, FALSE); + Utils::enableDlgControl(hwndDlg, IDC_SKINBACKGROUND, FALSE); + } + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_SHOWSBAR) { + Utils::enableDlgControl(hwndDlg, IDC_SHOWICON, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_SHOWPROTO, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_SHOWSTATUS, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_RIGHTSTATUS, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_RIGHTMIRANDA, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_EQUALSECTIONS, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_SBPANELBEVEL, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_SHOWGRIP, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + Utils::enableDlgControl(hwndDlg, IDC_SKINBACKGROUND, IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + opt_sbar_changed = 1; + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + if (!opt_sbar_changed) + return TRUE; + + cfg::writeByte("CLUI", "ShowSBar", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)); + cfg::writeByte("CLUI", "SBarShow", (BYTE) ((IsDlgButtonChecked(hwndDlg, IDC_SHOWICON) ? 1 : 0) | (IsDlgButtonChecked(hwndDlg, IDC_SHOWPROTO) ? 2 : 0) | (IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS) ? 4 : 0))); + cfg::writeByte("CLUI", "SBarRightClk", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_RIGHTMIRANDA)); + cfg::writeByte("CLUI", "EqualSections", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_EQUALSECTIONS)); + cfg::writeByte("CLUI", "sb_skinned", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SKINBACKGROUND)); + cfg::writeByte("CLUI", "sbar_showlocked", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_MARKLOCKED)); + + cfg::dat.bEqualSections = IsDlgButtonChecked(hwndDlg, IDC_EQUALSECTIONS) ? 1 : 0; + cfg::dat.bSkinnedStatusBar = IsDlgButtonChecked(hwndDlg, IDC_SKINBACKGROUND) ? 1 : 0; + cfg::dat.bShowXStatusOnSbar = IsDlgButtonChecked(hwndDlg, IDC_SHOWXSTATUS) ? 1 : 0; + cfg::writeByte("CLUI", "xstatus_sbar", (BYTE)cfg::dat.bShowXStatusOnSbar); + cfg::writeByte("CLUI", "SBarBevel", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SBPANELBEVEL)); + if (cfg::getByte("CLUI", "ShowGrip", 1) != (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWGRIP)) { + HWND parent = GetParent(pcli->hwndStatus); + int flags = WS_CHILD | CCS_BOTTOM; + cfg::writeByte("CLUI", "ShowGrip", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWGRIP)); + ShowWindow(pcli->hwndStatus, SW_HIDE); + SetWindowLongPtr(pcli->hwndStatus, GWLP_WNDPROC, (LONG_PTR)OldStatusBarProc); + DestroyWindow(pcli->hwndStatus); + flags |= cfg::getByte("CLUI", "ShowSBar", 1) ? WS_VISIBLE : 0; + flags |= cfg::getByte("CLUI", "ShowGrip", 1) ? SBARS_SIZEGRIP : 0; + pcli->hwndStatus = CreateWindow(STATUSCLASSNAME, NULL, flags, 0, 0, 0, 0, parent, NULL, g_hInst, NULL); + OldStatusBarProc = (WNDPROC)SetWindowLongPtr(pcli->hwndStatus, GWLP_WNDPROC, (LONG_PTR)NewStatusBarWndProc); + } + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWSBAR)) { + ShowWindow(pcli->hwndStatus, SW_SHOW); + SendMessage(pcli->hwndStatus, WM_SIZE, 0, 0); + cfg::dat.dwFlags |= CLUI_FRAME_SBARSHOW; + } else { + ShowWindow(pcli->hwndStatus, SW_HIDE); + cfg::dat.dwFlags &= ~CLUI_FRAME_SBARSHOW; + } + cfg::writeDword("CLUI", "Frameflags", cfg::dat.dwFlags); + ConfigureCLUIGeometry(1); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + CluiProtocolStatusChanged(0, 0); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + opt_sbar_changed = 0; + return TRUE; + } + break; + } + return FALSE; +} + +DWORD GetCLUIWindowStyle(BYTE style) +{ + DWORD dwBasic = WS_CLIPCHILDREN; + + if(style == SETTING_WINDOWSTYLE_THINBORDER) + return dwBasic | WS_BORDER; + else if(style == SETTING_WINDOWSTYLE_TOOLWINDOW || style == 0) + return dwBasic | (WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME); + else if(style == SETTING_WINDOWSTYLE_NOBORDER) + return dwBasic; + + return dwBasic; +} + +void ApplyCLUIBorderStyle(HWND hwnd) +{ + BYTE windowStyle = cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_TOOLWINDOW); + WINDOWPLACEMENT p; + bool minToTray = TRUE; + + p.length = sizeof(p); + GetWindowPlacement(pcli->hwndContactList, &p); + ShowWindow(pcli->hwndContactList, SW_HIDE); + + if (windowStyle == SETTING_WINDOWSTYLE_DEFAULT || windowStyle == SETTING_WINDOWSTYLE_TOOLWINDOW) { + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME); + if(SETTING_WINDOWSTYLE_DEFAULT == windowStyle) { + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) & ~(WS_MAXIMIZEBOX/* | WS_MINIMIZEBOX*/)); + minToTray = FALSE; + } + } else if(windowStyle == SETTING_WINDOWSTYLE_THINBORDER) { + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME)); + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) | WS_BORDER | WS_CLIPCHILDREN); + } + else { + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_THICKFRAME)); + SetWindowLongPtr(pcli->hwndContactList, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_STYLE) | WS_CLIPCHILDREN); + } + p.showCmd = SW_HIDE; + SetWindowPlacement(pcli->hwndContactList, &p); + + cfg::writeByte(0, "CList", "Min2Tray", minToTray); +} diff --git a/plugins/Clist_nicer/src/cluiservices.cpp b/plugins/Clist_nicer/src/cluiservices.cpp new file mode 100644 index 0000000000..d446872f16 --- /dev/null +++ b/plugins/Clist_nicer/src/cluiservices.cpp @@ -0,0 +1,261 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +UNICODE done + +*/ +#include +#include "../cluiframes/cluiframes.h" +#include + +extern HIMAGELIST hCListImages, himlExtraImages;; +extern ButtonItem *g_ButtonItems; +extern PLUGININFOEX pluginInfo; + +static INT_PTR GetClistVersion(WPARAM wParam, LPARAM lParam) +{ + static char g_szVersionString[256]; + + mir_snprintf(g_szVersionString, 256, "%s, %d.%d.%d.%d", pluginInfo.shortName, HIBYTE(HIWORD(pluginInfo.version)), LOBYTE(HIWORD(pluginInfo.version)), HIBYTE(LOWORD(pluginInfo.version)), LOBYTE(LOBYTE(pluginInfo.version))); + if (!IsBadWritePtr((LPVOID)lParam, 4)) + *((DWORD *)lParam) = pluginInfo.version; + + return (INT_PTR)g_szVersionString; +} + + +void FreeProtocolData( void ) +{ + //free protocol data + int nPanel; + int nParts=SendMessage(pcli->hwndStatus,SB_GETPARTS,0,0); + for (nPanel=0;nPanelhwndStatus,SB_GETTEXT,(WPARAM)nPanel,(LPARAM)0); + if (PD!=NULL&&!IsBadCodePtr((FARPROC)PD)) + { + SendMessage(pcli->hwndStatus,SB_SETTEXT,(WPARAM)nPanel|SBT_OWNERDRAW,(LPARAM)0); + if (PD->RealName) mir_free(PD->RealName); + if (PD) mir_free(PD); +} } } + +int g_maxStatus = ID_STATUS_OFFLINE; +char g_maxProto[100] = ""; + +void CluiProtocolStatusChanged( int parStatus, const char* szProto ) +{ + int protoCount,i; + PROTOACCOUNT **accs; + int *partWidths,partCount; + int borders[3]; + int status; + int toshow; + TCHAR *szStatus = NULL; + char *szMaxProto = NULL; + int maxOnline = 0, onlineness = 0; + WORD maxStatus = ID_STATUS_OFFLINE, wStatus; + DBVARIANT dbv = {0}; + int iIcon = 0; + HICON hIcon = 0; + int rdelta = cfg::dat.bCLeft + cfg::dat.bCRight; + BYTE windowStyle; + + if (pcli->hwndStatus == 0 || cfg::shutDown) + return; + + ProtoEnumAccounts( &protoCount, &accs ); + if (protoCount == 0) + return; + + FreeProtocolData(); + g_maxStatus = ID_STATUS_OFFLINE; + g_maxProto[0] = 0; + + SendMessage(pcli->hwndStatus,SB_GETBORDERS,0,(LPARAM)&borders); + + partWidths=(int*)_alloca(( protoCount+1)*sizeof(int)); + + if (cfg::dat.bEqualSections) { + RECT rc; + int part; + //SendMessage(pcli->hwndStatus,WM_SIZE,0,0); // XXX fix (may break status bar geometry) + GetClientRect(pcli->hwndStatus,&rc); + rc.right-=borders[0]*2; + toshow=0; + for ( i=0; i < protoCount; i++ ) + if ( pcli->pfnGetProtocolVisibility( accs[i]->szModuleName )) + toshow++; + + if ( toshow > 0 ) { + for ( part=0, i=0; i < protoCount; i++ ) { + if ( !pcli->pfnGetProtocolVisibility( accs[i]->szModuleName )) + continue; + + partWidths[ part ] = ((rc.right-rc.left-rdelta)/toshow)*(part+1) + cfg::dat.bCLeft; + if ( part == toshow-1 ) + partWidths[ part ] += cfg::dat.bCRight; + part++; + } } + + partCount=toshow; + } + else { + HDC hdc; + SIZE textSize; + BYTE showOpts = cfg::getByte("CLUI","SBarShow",1); + int x; + HFONT hofont; + TCHAR szName[32]; + PROTOACCOUNT* pa; + + hdc=GetDC(NULL); + hofont = reinterpret_cast(SelectObject(hdc,(HFONT)SendMessage(pcli->hwndStatus,WM_GETFONT,0,0))); + + for ( partCount=0,i=0; i < protoCount; i++ ) { //count down since built in ones tend to go at the end + int idx = pcli->pfnGetAccountIndexByPos( i ); + if ( idx == -1 ) + continue; + + pa = accs[idx]; + if ( !pcli->pfnGetProtocolVisibility( pa->szModuleName )) + continue; + + x=2; + if (showOpts & 1) + x += 16; + if (showOpts & 2) { + lstrcpyn( szName, pa->tszAccountName, SIZEOF(szName)); + szName[ SIZEOF(szName)-1 ] = 0; + if (( showOpts & 4 ) && lstrlen(szName) < sizeof(szName)-1 ) + lstrcat( szName, _T(" ")); + GetTextExtentPoint32( hdc, szName, lstrlen(szName), &textSize ); + x += textSize.cx + GetSystemMetrics(SM_CXBORDER) * 4; // The SB panel doesnt allocate enough room + } + if (showOpts & 4) { + TCHAR* modeDescr = pcli->pfnGetStatusModeDescription( CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0 ), 0 ); + GetTextExtentPoint32(hdc, modeDescr, lstrlen(modeDescr), &textSize ); + x += textSize.cx + GetSystemMetrics(SM_CXBORDER) * 4; // The SB panel doesnt allocate enough room + } + partWidths[partCount]=(partCount?partWidths[partCount-1]:cfg::dat.bCLeft)+ x + 2; + partCount++; + } + SelectObject(hdc,hofont); + ReleaseDC(NULL,hdc); + } + if (partCount==0) { + SendMessage(pcli->hwndStatus,SB_SIMPLE,TRUE,0); + return; + } + SendMessage(pcli->hwndStatus,SB_SIMPLE,FALSE,0); + + partWidths[partCount-1]=-1; + windowStyle = cfg::getByte("CLUI", "WindowStyle", 0); + SendMessage(pcli->hwndStatus,SB_SETMINHEIGHT, 18 + cfg::dat.bClipBorder + ((windowStyle == SETTING_WINDOWSTYLE_THINBORDER || windowStyle == SETTING_WINDOWSTYLE_NOBORDER) ? 3 : 0), 0); + SendMessage(pcli->hwndStatus, SB_SETPARTS, partCount, (LPARAM)partWidths); + + for ( partCount=0, i=0; i < protoCount; i++ ) { //count down since built in ones tend to go at the end + ProtocolData *PD; + PROTOACCOUNT *pa; + int caps1, caps2; + + int idx = pcli->pfnGetAccountIndexByPos( i ); + if ( idx == -1 ) + continue; + + pa = accs[idx]; + if ( !pcli->pfnGetProtocolVisibility( pa->szModuleName )) + continue; + + status = CallProtoService( pa->szModuleName,PS_GETSTATUS,0,0); + PD = ( ProtocolData* )mir_alloc(sizeof(ProtocolData)); + PD->RealName = mir_strdup( pa->szModuleName ); + PD->statusbarpos = partCount; + { + int flags; + flags = SBT_OWNERDRAW; + if ( cfg::getByte("CLUI","SBarBevel", 1)==0 ) + flags |= SBT_NOBORDERS; + SendMessageA( pcli->hwndStatus, SB_SETTEXTA, partCount|flags,(LPARAM)PD ); + } + caps2 = CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0); + caps1 = CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0); + if ((caps1 & PF1_IM) && (caps2 & (PF2_LONGAWAY | PF2_SHORTAWAY))) { + onlineness = GetStatusOnlineness(status); + if(onlineness > maxOnline) { + maxStatus = status; + maxOnline = onlineness; + szMaxProto = pa->szModuleName; + } + } + partCount++; + } + // update the clui button + + if (!DBGetContactSetting(NULL, "CList", "PrimaryStatus", &dbv)) { + if (dbv.type == DBVT_ASCIIZ && lstrlenA(dbv.pszVal) > 1) { + wStatus = (WORD) CallProtoService(dbv.pszVal, PS_GETSTATUS, 0, 0); + iIcon = IconFromStatusMode(dbv.pszVal, (int) wStatus, 0, &hIcon); + } + mir_free(dbv.pszVal); + } else { + wStatus = maxStatus; + iIcon = IconFromStatusMode((wStatus >= ID_STATUS_CONNECTING && wStatus < ID_STATUS_OFFLINE) ? szMaxProto : NULL, (int) wStatus, 0, &hIcon); + g_maxStatus = (int)wStatus; + if(szMaxProto) { + lstrcpynA(g_maxProto, szMaxProto, 100); + g_maxProto[99] = 0; + } + } + /* + * this is used globally (actually, by the clist control only) to determine if + * any protocol is "in connection" state. If true, then the clist discards redraws + * and uses timer based sort and redraw handling. This can improve performance + * when connecting multiple protocols significantly. + */ + //g_isConnecting = (wStatus >= ID_STATUS_CONNECTING && wStatus < ID_STATUS_OFFLINE); + szStatus = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) wStatus, GSMDF_TCHAR); + + /* + * set the global status icon and display the global (most online) status mode on the + * status mode button + */ + + if (szStatus) { + if(pcli->hwndContactList && IsWindow(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS)) && IsWindow(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS))) { + SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), WM_SETTEXT, 0, (LPARAM) szStatus); + if (!hIcon) { + SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), BUTTONSETIMLICON, (WPARAM) hCListImages, (LPARAM) iIcon); + if(g_ButtonItems == NULL) + SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS), BUTTONSETIMLICON, (WPARAM) hCListImages, (LPARAM) iIcon); + } + else { + SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), BM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon); + if(g_ButtonItems == NULL) + SendMessage(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS), BM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon); + } + InvalidateRect(GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), NULL, TRUE); + InvalidateRect(GetDlgItem(pcli->hwndContactList, IDC_TBTOPSTATUS), NULL, TRUE); + SFL_Update(hIcon, iIcon, hCListImages, szStatus, TRUE); + } } + return; +} diff --git a/plugins/Clist_nicer/src/commonheaders.cpp b/plugins/Clist_nicer/src/commonheaders.cpp new file mode 100644 index 0000000000..b317365c87 --- /dev/null +++ b/plugins/Clist_nicer/src/commonheaders.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/plugins/Clist_nicer/src/config.cpp b/plugins/Clist_nicer/src/config.cpp new file mode 100644 index 0000000000..85994a922c --- /dev/null +++ b/plugins/Clist_nicer/src/config.cpp @@ -0,0 +1,482 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: config.cpp 12887 2010-10-04 03:58:32Z borkra $ + * + */ + +#include + +TCluiData cfg::dat = {0}; +ClcData* cfg::clcdat = 0; +TExtraCache* cfg::eCache = 0; +int cfg::nextCacheEntry = 0, cfg::maxCacheEntry = 0; + +CRITICAL_SECTION cfg::cachecs = {0}; + +bool cfg::shutDown = false; + +pfnSetLayeredWindowAttributes_t API::pfnSetLayeredWindowAttributes = 0; +pfnUpdateLayeredWindow_t API::pfnUpdateLayeredWindow = 0; +pfnMonitorFromPoint_t API::pfnMonitorFromPoint = 0; +pfnMonitorFromWindow_t API::pfnMonitorFromWindow = 0; +pfnGetMonitorInfo_t API::pfnGetMonitorInfo = 0; +pfnTrackMouseEvent_t API::pfnTrackMouseEvent = 0; +//pfnDrawAlpha_t API::pfnDrawAlpha = 0; +PGF API::pfnGradientFill = 0; +pfnSetLayout_t API::pfnSetLayout = 0; +pfnAlphaBlend_t API::pfnAlphaBlend = 0; + +TSysConfig API::sysConfig = {0}; +TSysState API::sysState = {0}; + +pfnIsThemeActive_t API::pfnIsThemeActive = 0; +pfnOpenThemeData_t API::pfnOpenThemeData = 0; +pfnDrawThemeBackground_t API::pfnDrawThemeBackground = 0; +pfnCloseThemeData_t API::pfnCloseThemeData = 0; +pfnDrawThemeText_t API::pfnDrawThemeText = 0; +pfnDrawThemeTextEx_t API::pfnDrawThemeTextEx = 0; +pfnIsThemeBackgroundPartiallyTransparent_t API::pfnIsThemeBackgroundPartiallyTransparent = 0; +pfnDrawThemeParentBackground_t API::pfnDrawThemeParentBackground = 0; +pfnGetThemeBackgroundContentRect_t API::pfnGetThemeBackgroundContentRect = 0; +pfnEnableThemeDialogTexture_t API::pfnEnableThemeDialogTexture = 0; + +pfnDwmExtendFrameIntoClientArea_t API::pfnDwmExtendFrameIntoClientArea = 0; +pfnDwmIsCompositionEnabled_t API::pfnDwmIsCompositionEnabled = 0; + +EXCEPTION_RECORD API::exRecord = {0}; +CONTEXT API::exCtx = {0}; +LRESULT API::exLastResult = 0; +char API::exSzFile[MAX_PATH] = ""; +TCHAR API::exReason[256] = _T(""); +int API::exLine = 0; +bool API::exAllowContinue = false; +HMODULE API::hUxTheme = 0, API::hDwm = 0; + +void cfg::init() +{ + InitializeCriticalSection(&cachecs); +} + +DWORD cfg::getDword(const HANDLE hContact = 0, const char *szModule = 0, const char *szSetting = 0, DWORD uDefault = 0) +{ + return((DWORD)DBGetContactSettingDword(hContact, szModule, szSetting, uDefault)); +} + +/* + * read a setting from our default module (Tab_SRMSG) + */ + +DWORD cfg::getDword(const char *szSetting = 0, DWORD uDefault = 0) +{ + return((DWORD)DBGetContactSettingDword(0, DEFAULT_MODULE, szSetting, uDefault)); +} + +/* + * read a setting from module only + */ + +DWORD cfg::getDword(const char *szModule, const char *szSetting, DWORD uDefault) +{ + return((DWORD)DBGetContactSettingDword(0, szModule, szSetting, uDefault)); +} + + +WORD cfg::getWord(const HANDLE hContact = 0, const char *szModule = 0, const char *szSetting = 0, WORD uDefault = 0) +{ + return((WORD)DBGetContactSettingWord(hContact, szModule, szSetting, uDefault)); +} + +/* + * read a setting from our default module (Tab_SRMSG) + */ + +WORD cfg::getWord(const char *szSetting = 0, WORD uDefault = 0) +{ + return((WORD)DBGetContactSettingWord(0, DEFAULT_MODULE, szSetting, uDefault)); +} + +/* + * read a setting from module only + */ + +WORD cfg::getWord(const char *szModule, const char *szSetting, WORD uDefault) +{ + return((WORD)DBGetContactSettingWord(0, szModule, szSetting, uDefault)); +} + +/* + * same for bytes now + */ +int cfg::getByte(const HANDLE hContact = 0, const char *szModule = 0, const char *szSetting = 0, int uDefault = 0) +{ + return(DBGetContactSettingByte(hContact, szModule, szSetting, uDefault)); +} + +int cfg::getByte(const char *szSetting = 0, int uDefault = 0) +{ + return(DBGetContactSettingByte(0, DEFAULT_MODULE, szSetting, uDefault)); +} + +int cfg::getByte(const char *szModule, const char *szSetting, int uDefault) +{ + return(DBGetContactSettingByte(0, szModule, szSetting, uDefault)); +} + +INT_PTR cfg::getTString(const HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) +{ + return(DBGetContactSettingTString(hContact, szModule, szSetting, dbv)); +} + +INT_PTR cfg::getString(const HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) +{ + return(DBGetContactSettingString(hContact, szModule, szSetting, dbv)); +} + +/* + * writer functions + */ + +INT_PTR cfg::writeDword(const HANDLE hContact = 0, const char *szModule = 0, const char *szSetting = 0, DWORD value = 0) +{ + return(DBWriteContactSettingDword(hContact, szModule, szSetting, value)); +} + +INT_PTR cfg::writeDword(const char *szModule = 0, const char *szSetting = 0, DWORD value = 0) +{ + return(DBWriteContactSettingDword(0, szModule, szSetting, value)); +} + +INT_PTR cfg::writeWord(const HANDLE hContact = 0, const char *szModule = 0, const char *szSetting = 0, WORD value = 0) +{ + return(DBWriteContactSettingWord(hContact, szModule, szSetting, value)); +} + +INT_PTR cfg::writeWord(const char *szModule = 0, const char *szSetting = 0, WORD value = 0) +{ + return(DBWriteContactSettingWord(0, szModule, szSetting, value)); +} + +INT_PTR cfg::writeByte(const HANDLE hContact = 0, const char *szModule = 0, const char *szSetting = 0, BYTE value = 0) +{ + return(DBWriteContactSettingByte(hContact, szModule, szSetting, value)); +} + +INT_PTR cfg::writeByte(const char *szModule = 0, const char *szSetting = 0, BYTE value = 0) +{ + return(DBWriteContactSettingByte(0, szModule, szSetting, value)); +} + +INT_PTR cfg::writeTString(const HANDLE hContact, const char *szModule = 0, const char *szSetting = 0, const TCHAR *str = 0) +{ + return(DBWriteContactSettingTString(hContact, szModule, szSetting, str)); +} + +INT_PTR cfg::writeString(const HANDLE hContact, const char *szModule = 0, const char *szSetting = 0, const char *str = 0) +{ + return(DBWriteContactSettingString(hContact, szModule, szSetting, str)); +} + +int cfg::getCache(const HANDLE hContact, const char *szProto) +{ + int i, iFound = -1; + + for (i = 0; i < nextCacheEntry; i++) { + if(eCache[i].hContact == hContact) { + iFound = i; + break; + } + } + if(iFound == -1) { + EnterCriticalSection(&cachecs); + if(nextCacheEntry == maxCacheEntry) { + maxCacheEntry += 100; + cfg::eCache = (TExtraCache *)realloc(cfg::eCache, maxCacheEntry * sizeof(TExtraCache)); + } + memset(&cfg::eCache[nextCacheEntry], 0, sizeof(TExtraCache)); + cfg::eCache[nextCacheEntry].hContact = hContact; + memset(cfg::eCache[nextCacheEntry].iExtraImage, 0xff, MAXEXTRACOLUMNS); + cfg::eCache[nextCacheEntry].iExtraValid = 0; + cfg::eCache[nextCacheEntry].valid = FALSE; + cfg::eCache[nextCacheEntry].bStatusMsgValid = 0; + cfg::eCache[nextCacheEntry].statusMsg = NULL; + cfg::eCache[nextCacheEntry].status_item = NULL; + LoadSkinItemToCache(&cfg::eCache[nextCacheEntry], szProto); + cfg::eCache[nextCacheEntry].dwCFlags = 0; + cfg::eCache[nextCacheEntry].dwDFlags = DBGetContactSettingDword(hContact, "CList", "CLN_Flags", 0); + cfg::eCache[nextCacheEntry].dwXMask = CalcXMask(hContact); + GetCachedStatusMsg(nextCacheEntry, const_cast(szProto)); + cfg::eCache[nextCacheEntry].dwLastMsgTime = INTSORT_GetLastMsgTime(hContact); + iFound = nextCacheEntry++; + LeaveCriticalSection(&cachecs); + } + return iFound; +} + +void API::onInit() +{ + HMODULE hUserDll = 0; + + pfnSetLayout = (DWORD ( WINAPI *)(HDC, DWORD))GetProcAddress( GetModuleHandleA( "GDI32.DLL" ), "SetLayout" ); + + hUserDll = GetModuleHandleA("user32.dll"); + if (hUserDll) { + pfnMonitorFromPoint = ( pfnMonitorFromPoint_t )GetProcAddress(hUserDll, "MonitorFromPoint"); + pfnMonitorFromWindow = ( pfnMonitorFromWindow_t )GetProcAddress(hUserDll, "MonitorFromWindow"); + pfnGetMonitorInfo = ( pfnGetMonitorInfo_t )GetProcAddress(hUserDll, "GetMonitorInfoA"); + pfnSetLayeredWindowAttributes = ( pfnSetLayeredWindowAttributes_t )GetProcAddress(hUserDll, "SetLayeredWindowAttributes"); + pfnUpdateLayeredWindow = ( pfnUpdateLayeredWindow_t )GetProcAddress(hUserDll, "UpdateLayeredWindow"); + pfnTrackMouseEvent = ( pfnTrackMouseEvent_t )GetProcAddress(hUserDll, "TrackMouseEvent"); + } + + pfnAlphaBlend = (pfnAlphaBlend_t) GetProcAddress(GetModuleHandleA("gdi32"), "GdiAlphaBlend"); + pfnGradientFill = (PGF) GetProcAddress(GetModuleHandleA("gdi32"), "GdiGradientFill"); + if (0 == pfnAlphaBlend) { + HMODULE hMsImgDll = LoadLibraryA("msimg32.dll"); + pfnAlphaBlend = (pfnAlphaBlend_t)GetProcAddress(hMsImgDll, "AlphaBlend"); + pfnGradientFill = (PGF) GetProcAddress(hMsImgDll, "GradientFill"); + } + + sysConfig.isVistaPlus = (IsWinVerVistaPlus() ? true : false); + sysConfig.isSevenPlus = (IsWinVer7Plus() ? true : false); + sysConfig.isXPPlus = (IsWinVerXPPlus() ? true : false); + sysConfig.isWin2KPlus = (IsWinVer2000Plus() ? true : false); + + if(sysConfig.isXPPlus) { + if ((hUxTheme = Utils::loadSystemLibrary(_T("\\uxtheme.dll")), true) != 0) { + pfnIsThemeActive = (pfnIsThemeActive_t)GetProcAddress(hUxTheme, "IsThemeActive"); + pfnOpenThemeData = (pfnOpenThemeData_t)GetProcAddress(hUxTheme, "OpenThemeData"); + pfnDrawThemeBackground = (pfnDrawThemeBackground_t)GetProcAddress(hUxTheme, "DrawThemeBackground"); + pfnCloseThemeData = (pfnCloseThemeData_t)GetProcAddress(hUxTheme, "CloseThemeData"); + pfnDrawThemeText = (pfnDrawThemeText_t)GetProcAddress(hUxTheme, "DrawThemeText"); + pfnIsThemeBackgroundPartiallyTransparent = (pfnIsThemeBackgroundPartiallyTransparent_t)GetProcAddress(hUxTheme, "IsThemeBackgroundPartiallyTransparent"); + pfnDrawThemeParentBackground = (pfnDrawThemeParentBackground_t)GetProcAddress(hUxTheme, "DrawThemeParentBackground"); + pfnGetThemeBackgroundContentRect = (pfnGetThemeBackgroundContentRect_t)GetProcAddress(hUxTheme, "GetThemeBackgroundContentRect"); + pfnEnableThemeDialogTexture = (pfnEnableThemeDialogTexture_t)GetProcAddress(hUxTheme, "EnableThemeDialogTexture"); + + if (pfnIsThemeActive != 0 && pfnOpenThemeData != 0 && pfnDrawThemeBackground != 0 && pfnCloseThemeData != 0 + && pfnDrawThemeText != 0 && pfnIsThemeBackgroundPartiallyTransparent != 0 && pfnDrawThemeParentBackground != 0 + && pfnGetThemeBackgroundContentRect != 0) { + sysConfig.uxThemeValid = true; + } + } + } + if(sysConfig.isVistaPlus) { + if ((hDwm = Utils::loadSystemLibrary(_T("\\dwmapi.dll")), true) != 0) { + pfnDwmIsCompositionEnabled = (pfnDwmIsCompositionEnabled_t)GetProcAddress(hDwm, "DwmIsCompositionEnabled"); + pfnDwmExtendFrameIntoClientArea = (pfnDwmExtendFrameIntoClientArea_t)GetProcAddress(hDwm,"DwmExtendFrameIntoClientArea"); + } + } + + updateState(); +} + +void API::onUnload() +{ + if(hUxTheme) + FreeLibrary(hUxTheme); +} + +/** + * update system's state (theme status, aero status, DWM check... + * + * called when windows broadcasts things like WM_THEMECHANGED or + * WM_DWMCOMPOSITIONCHANGED + */ +void API::updateState() +{ + BOOL result = FALSE; + + ::ZeroMemory(&sysState, sizeof(TSysState)); + + if(sysConfig.uxThemeValid) + sysState.isThemed = pfnIsThemeActive() ? true : false; + + if(sysConfig.isVistaPlus) { + sysState.isDwmActive = (pfnDwmIsCompositionEnabled && (pfnDwmIsCompositionEnabled(&result) == S_OK) && result) ? true : false; + sysState.isAero = /* (CSkin::m_skinEnabled == false) && */ cfg::getByte("CLUI", "useAero", 1) /* && CSkin::m_fAeroSkinsValid */ && sysState.isDwmActive; + } +} + +BOOL API::SetLayeredWindowAttributes(HWND hWnd, COLORREF clr, BYTE alpha, DWORD dwFlags) +{ + if(sysConfig.isWin2KPlus) + return(pfnSetLayeredWindowAttributes(hWnd, clr, alpha, dwFlags)); + + return(FALSE); +} + +/** + * exception handling for SEH exceptions + */ + +/** + * exception handling - copy error message to clip board + * @param hWnd: window handle of the edit control containing the error message + */ +void API::Ex_CopyEditToClipboard(HWND hWnd) +{ + SendMessage(hWnd, EM_SETSEL, 0, 65535L); + SendMessage(hWnd, WM_COPY, 0 , 0); + SendMessage(hWnd, EM_SETSEL, 0, 0); +} + +INT_PTR CALLBACK API::Ex_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WORD wNotifyCode, wID; + + switch(uMsg) { + case WM_INITDIALOG: { + char szBuffer[2048]; +#ifdef _WIN64 + sprintf(szBuffer, + "Exception %16.16X at address %16.16X occured in %s at line %d.\r\n\r\nEAX=%16.16X EBX=%16.16X ECX=%16.16X\r\nEDX=%16.16X ESI=%16.16X EDI=%16.16X\r\nEBP=%16.16X ESP=%16.16X EIP=%16.16X", + exRecord.ExceptionCode, exRecord.ExceptionAddress, exSzFile, exLine, + exCtx.Rax,exCtx.Rbx, exCtx.Rcx, exCtx.Rdx, + exCtx.Rsi, exCtx.Rdi, exCtx.Rbp, exCtx.Rsp, exCtx.Rip); +#else + sprintf(szBuffer, + "Exception %8.8X at address %8.8X occured in %s at line %d.\r\n\r\nEAX=%8.8X EBX=%8.8X ECX=%8.8X\r\nEDX=%8.8X ESI=%8.8X EDI=%8.8X\r\nEBP=%8.8X ESP=%8.8X EIP=%8.8X", + exRecord.ExceptionCode, exRecord.ExceptionAddress, exSzFile, exLine, + exCtx.Eax,exCtx.Ebx, exCtx.Ecx, exCtx.Edx, + exCtx.Esi, exCtx.Edi, exCtx.Ebp, exCtx.Esp, exCtx.Eip); +#endif + SetDlgItemTextA(hwndDlg, IDC_EXCEPTION_DETAILS, szBuffer); + SetFocus(GetDlgItem(hwndDlg, IDC_EXCEPTION_DETAILS)); + SendDlgItemMessage(hwndDlg, IDC_EXCEPTION_DETAILS, WM_SETFONT, (WPARAM)GetStockObject(OEM_FIXED_FONT), 0); + SetDlgItemText(hwndDlg, IDC_EX_REASON, exReason); + Utils::enableDlgControl(hwndDlg, IDOK, exAllowContinue ? TRUE : FALSE); + } + break; + + case WM_COMMAND: + wNotifyCode = HIWORD(wParam); + wID = LOWORD(wParam); + if (wNotifyCode == BN_CLICKED) + { + if (wID == IDOK || wID == IDCANCEL) + EndDialog(hwndDlg, wID); + + if (wID == IDC_COPY_EXCEPTION) + Ex_CopyEditToClipboard(GetDlgItem(hwndDlg, IDC_EXCEPTION_DETAILS)); + } + + break; + } + return FALSE; +} + +void API::Ex_Handler() +{ + if (exLastResult == IDCANCEL) + ExitProcess(1); +} + +int API::Ex_ShowDialog(EXCEPTION_POINTERS *ep, const char *szFile, int line, TCHAR* szReason, bool fAllowContinue) +{ + char szDrive[MAX_PATH], szDir[MAX_PATH], szName[MAX_PATH], szExt[MAX_PATH]; + + _splitpath(szFile, szDrive, szDir, szName, szExt); + memcpy(&exRecord, ep->ExceptionRecord, sizeof(EXCEPTION_RECORD)); + memcpy(&exCtx, ep->ContextRecord, sizeof(CONTEXT)); + + _snprintf(exSzFile, MAX_PATH, "%s%s", szName, szExt); + mir_sntprintf(exReason, 256, _T("An application error has occured: %s"), szReason); + exLine = line; + exLastResult = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EXCEPTION), 0, Ex_DlgProc, 0); + exAllowContinue = fAllowContinue; + if(IDCANCEL == exLastResult) + ExitProcess(1); + return 1; +} + + +/** + * enable or disable a dialog control + */ +void TSAPI Utils::enableDlgControl(const HWND hwnd, UINT id, BOOL fEnable) +{ + ::EnableWindow(::GetDlgItem(hwnd, id), fEnable); +} + +/** + * show or hide a dialog control + */ +void TSAPI Utils::showDlgControl(const HWND hwnd, UINT id, int showCmd) +{ + ::ShowWindow(::GetDlgItem(hwnd, id), showCmd); +} + +/** + * load a system library from the Windows system path and return its module + * handle. + * + * return 0 and throw an exception if something goes wrong. + */ +HMODULE Utils::loadSystemLibrary(const TCHAR* szFilename, bool useGetHandle) +{ + TCHAR sysPathName[MAX_PATH + 2]; + HMODULE _h = 0; + + try { + if(0 == ::GetSystemDirectory(sysPathName, MAX_PATH)) + throw(CRTException("Error while loading system library", szFilename)); + + sysPathName[MAX_PATH - 1] = 0; + if(_tcslen(sysPathName) + _tcslen(szFilename) >= MAX_PATH) + throw(CRTException("Error while loading system library", szFilename)); + + lstrcat(sysPathName, szFilename); + if(useGetHandle) + _h = ::GetModuleHandle(sysPathName); + else + _h = LoadLibrary(sysPathName); + if(0 == _h) + throw(CRTException("Error while loading system library", szFilename)); + } + catch(CRTException& ex) { + ex.display(); + return(0); + } + return(_h); +} + +CRTException::CRTException(const char *szMsg, const TCHAR *szParam) : std::runtime_error(std::string(szMsg)) +{ + mir_sntprintf(m_szParam, MAX_PATH, szParam); +} + +void CRTException::display() const +{ + TCHAR* tszMsg = mir_a2t(what()); + TCHAR tszBoxMsg[500]; + + mir_sntprintf(tszBoxMsg, 500, _T("%s\n\n(%s)"), tszMsg, m_szParam); + ::MessageBox(0, tszBoxMsg, _T("TabSRMM runtime error"), MB_OK | MB_ICONERROR); + mir_free(tszMsg); +} diff --git a/plugins/Clist_nicer/src/contact.cpp b/plugins/Clist_nicer/src/contact.cpp new file mode 100644 index 0000000000..f51672e52c --- /dev/null +++ b/plugins/Clist_nicer/src/contact.cpp @@ -0,0 +1,333 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: contact.cpp 12535 2010-08-29 23:48:32Z silvercircle $ + * + */ + +#include + +struct { + int status,order; +} statusModeOrder[]={ + {ID_STATUS_OFFLINE,500}, + {ID_STATUS_ONLINE,10}, + {ID_STATUS_AWAY,200}, + {ID_STATUS_DND,110}, + {ID_STATUS_NA,450}, + {ID_STATUS_OCCUPIED,100}, + {ID_STATUS_FREECHAT,0}, + {ID_STATUS_INVISIBLE,20}, + {ID_STATUS_ONTHEPHONE,150}, + {ID_STATUS_OUTTOLUNCH,425} +}; + +static int GetContactStatus(HANDLE hContact) +{ + char *szProto; + + szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto == NULL) + return ID_STATUS_OFFLINE; + return cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); +} + +int __forceinline GetStatusModeOrdering(int statusMode) +{ + int i; + for (i = 0; i < sizeof(statusModeOrder) / sizeof(statusModeOrder[0]); i++) { + if (statusModeOrder[i].status == statusMode) + return statusModeOrder[i].order; + } + return 1000; +} + +int mf_updatethread_running = TRUE; +HANDLE hThreadMFUpdate = 0; + +static void MF_CalcFrequency(HANDLE hContact, DWORD dwCutoffDays, int doSleep) +{ + DWORD curTime = time(NULL); + DWORD frequency, eventCount; + DBEVENTINFO dbei = {0}; + HANDLE hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0); + DWORD firstEventTime = 0, lastEventTime = 0; + + eventCount = 0; + dbei.cbSize = sizeof(dbei); + dbei.timestamp = 0; + + while(hEvent) { + dbei.cbBlob = 0; + dbei.pBlob = NULL; + CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei); + + if(dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { // record time of last event + eventCount++; + } + if(eventCount >= 100 || dbei.timestamp < curTime - (dwCutoffDays * 86400)) + break; + hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hEvent, 0); + if(doSleep && mf_updatethread_running == FALSE) + return; + if(doSleep) + Sleep(100); + } + + if(eventCount == 0) { + frequency = 0x7fffffff; + cfg::writeDword(hContact, "CList", "mf_firstEvent", curTime - (dwCutoffDays * 86400)); + } + else { + frequency = (curTime - dbei.timestamp) / eventCount; + cfg::writeDword(hContact, "CList", "mf_firstEvent", dbei.timestamp); + } + + cfg::writeDword(hContact, "CList", "mf_freq", frequency); + cfg::writeDword(hContact, "CList", "mf_count", eventCount); +} + +extern TCHAR g_ptszEventName[]; + +DWORD WINAPI MF_UpdateThread(LPVOID p) +{ + HANDLE hContact; + HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, g_ptszEventName); + + WaitForSingleObject(hEvent, 20000); + ResetEvent(hEvent); + + while(mf_updatethread_running) { + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact != NULL && mf_updatethread_running) { + MF_CalcFrequency(hContact, 50, 1); + if(mf_updatethread_running) + WaitForSingleObject(hEvent, 5000); + ResetEvent(hEvent); + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + if(mf_updatethread_running) + WaitForSingleObject(hEvent, 1000000); + ResetEvent(hEvent); + } + CloseHandle(hEvent); + return 0; +} + +static BOOL mc_hgh_removed = FALSE; + +void LoadContactTree(void) +{ + HANDLE hContact; + int i, status, hideOffline; + BOOL mc_disablehgh = ServiceExists(MS_MC_DISABLEHIDDENGROUP); + DBVARIANT dbv = {0}; + BYTE bMsgFrequency = cfg::getByte("CList", "fhistdata", 0); + + CallService(MS_CLUI_LISTBEGINREBUILD, 0, 0); + for (i = 1; ; i++) { + if (pcli->pfnGetGroupName(i, NULL) == NULL) + break; + CallService(MS_CLUI_GROUPADDED, i, 0); + } + + hideOffline = cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT); + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact != NULL) { + status = GetContactStatus(hContact); + if ((!hideOffline || status != ID_STATUS_OFFLINE) && !CLVM_GetContactHiddenStatus(hContact, NULL, NULL)) + pcli->pfnChangeContactIcon(hContact, IconFromStatusMode((char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0), status, hContact, NULL), 1); + + if(mc_disablehgh && !mc_hgh_removed) { + if (!DBGetContactSetting(hContact, "CList", "Group", &dbv)) { + if (!strcmp(dbv.pszVal, "MetaContacts Hidden Group")) + DBDeleteContactSetting(hContact, "CList", "Group"); + mir_free(dbv.pszVal); + } + } + + // build initial data for message frequency + if (!bMsgFrequency) + MF_CalcFrequency(hContact, 100, 0); + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + cfg::writeByte("CList", "fhistdata", 1); + mc_hgh_removed = TRUE; + CallService(MS_CLUI_SORTLIST, 0, 0); + CallService(MS_CLUI_LISTENDREBUILD, 0, 0); +} + +DWORD INTSORT_GetLastMsgTime(HANDLE hContact) +{ + HANDLE hDbEvent; + DBEVENTINFO dbei = {0}; + + hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0); + while(hDbEvent) { + dbei.cbSize = sizeof(dbei); + dbei.pBlob = 0; + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei); + if(dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) + return dbei.timestamp; + hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0); + } + return 0; +} + +int __forceinline GetProtoIndex(char * szName) +{ + if ( !szName ) + return -1; + else { + PROTOACCOUNT* pa = ProtoGetAccount( szName ); + return ( pa == NULL ) ? -1 : pa->iOrder; + } +} + +int __forceinline INTSORT_CompareContacts(const struct ClcContact* c1, const struct ClcContact* c2, UINT bywhat) +{ + TCHAR *namea, *nameb; + int statusa, statusb; + char *szProto1, *szProto2; + int rc; + + if (c1 == 0 || c2 == 0) + return 0; + + szProto1 = c1->proto; + szProto2 = c2->proto; + statusa = c1->wStatus; + statusb = c2->wStatus; + // make sure, sticky contacts are always at the beginning of the group/list + + if ((c1->flags & CONTACTF_STICKY) != (c2->flags & CONTACTF_STICKY)) + return 2 * (c2->flags & CONTACTF_STICKY) - 1; + + if(bywhat == SORTBY_PRIOCONTACTS) { + if ((cfg::clcdat->exStyle & CLS_EX_DIVIDERONOFF) && ((c1->flags & CONTACTF_ONLINE) != (c2->flags & CONTACTF_ONLINE))) + return 0; + if ((c1->flags & CONTACTF_PRIORITY) != (c2->flags & CONTACTF_PRIORITY)) + return 2 * (c2->flags & CONTACTF_PRIORITY) - 1; + else + return 0; + } + + if (bywhat == SORTBY_STATUS) { + int ordera, orderb; + + ordera = GetStatusModeOrdering(statusa); + orderb = GetStatusModeOrdering(statusb); + if (ordera != orderb) + return ordera - orderb; + else + return 0; + } + + // separate contacts treated as "offline" + if ( !cfg::dat.bDontSeparateOffline && ((statusa == ID_STATUS_OFFLINE) != (statusb == ID_STATUS_OFFLINE ))) + return 2 * (statusa == ID_STATUS_OFFLINE) - 1; + + switch( bywhat ) { + case SORTBY_NAME: + namea = (TCHAR *)c1->szText; + nameb = (TCHAR *)c2->szText; + return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, namea, -1, nameb, -1) - 2; + + case SORTBY_LASTMSG: + if(c1->extraCacheEntry >= 0 && c1->extraCacheEntry < cfg::nextCacheEntry && + c2->extraCacheEntry >= 0 && c2->extraCacheEntry < cfg::nextCacheEntry) + return(cfg::eCache[c2->extraCacheEntry].dwLastMsgTime - cfg::eCache[c1->extraCacheEntry].dwLastMsgTime); + else { + DWORD timestamp1 = INTSORT_GetLastMsgTime(c1->hContact); + DWORD timestamp2 = INTSORT_GetLastMsgTime(c2->hContact); + return timestamp2 - timestamp1; + } + + case SORTBY_FREQUENCY: + if ( c1->extraCacheEntry >= 0 && c1->extraCacheEntry < cfg::nextCacheEntry && + c2->extraCacheEntry >= 0 && c2->extraCacheEntry < cfg::nextCacheEntry ) + return(cfg::eCache[c1->extraCacheEntry].msgFrequency - cfg::eCache[c2->extraCacheEntry].msgFrequency); + break; + + case SORTBY_PROTO: + if(c1->bIsMeta) + szProto1 = c1->metaProto ? c1->metaProto : c1->proto; + if(c2->bIsMeta) + szProto2 = c2->metaProto ? c2->metaProto : c2->proto; + + rc = GetProtoIndex(szProto1) - GetProtoIndex(szProto2); + + if (rc != 0 && (szProto1 != NULL && szProto2 != NULL)) + return rc; + } + return 0; +} + +int CompareContacts(const struct ClcContact* c1, const struct ClcContact* c2) +{ + int i, result; + + result = INTSORT_CompareContacts(c1, c2, SORTBY_PRIOCONTACTS); + if(result) + return result; + + for (i = 0; i <= 2; i++) { + if(cfg::dat.sortOrder[i]) { + result = INTSORT_CompareContacts(c1, c2, cfg::dat.sortOrder[i]); + if(result != 0) + return result; + } + } + return 0; +} + +#undef SAFESTRING + +static int resortTimerId = 0; +static VOID CALLBACK SortContactsTimer(HWND hwnd, UINT message, UINT idEvent, DWORD dwTime) +{ + KillTimer(NULL, resortTimerId); + resortTimerId = 0; + CallService(MS_CLUI_SORTLIST, 0, 0); +} + +int SetHideOffline(WPARAM wParam, LPARAM lParam) +{ + switch ((int) wParam) { + case 0: + cfg::writeByte("CList", "HideOffline", 0); break; + case 1: + cfg::writeByte("CList", "HideOffline", 1); break; + case -1: + cfg::writeByte("CList", "HideOffline", (BYTE) ! cfg::getByte("CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT)); break; + } + LoadContactTree(); + return 0; +} diff --git a/plugins/Clist_nicer/src/extBackg.cpp b/plugins/Clist_nicer/src/extBackg.cpp new file mode 100644 index 0000000000..972ba79b1f --- /dev/null +++ b/plugins/Clist_nicer/src/extBackg.cpp @@ -0,0 +1,1859 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 +#include "../coolsb/coolscroll.h" + +extern int g_hottrack; + +extern HWND g_hwndViewModeFrame; +extern HIMAGELIST himlExtraImages; + +StatusItems_t *StatusItems = NULL; +ImageItem *g_ImageItems = NULL, *g_glyphItem = NULL; +ButtonItem *g_ButtonItems = NULL; +ImageItem *g_CLUIImageItem = NULL; +HBRUSH g_CLUISkinnedBkColor = 0; +COLORREF g_CLUISkinnedBkColorRGB = 0; + +int ID_EXTBK_LAST = ID_EXTBK_LAST_D; + +//void SetTBSKinned(int mode); +void ReloadThemedOptions(); +void ReloadExtraIcons(); +static void SaveCompleteStructToDB(void); + +static StatusItems_t _StatusItems[] = { + {"Offline", "EXBK_Offline", ID_STATUS_OFFLINE, + CLCDEFAULT_GRADIENT, CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Online", "EXBK_Online", ID_STATUS_ONLINE, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Away", "EXBK_Away", ID_STATUS_AWAY, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"DND", "EXBK_Dnd", ID_STATUS_DND, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"NA", "EXBK_NA", ID_STATUS_NA, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Occupied", "EXBK_Occupied", ID_STATUS_OCCUPIED, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Free for chat", "EXBK_FFC", ID_STATUS_FREECHAT, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Invisible", "EXBK_Invisible", ID_STATUS_INVISIBLE, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"On the phone", "EXBK_OTP", ID_STATUS_ONTHEPHONE, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Out to lunch", "EXBK_OTL", ID_STATUS_OUTTOLUNCH, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Idle", "EXBK_IDLE", ID_EXTBKIDLE, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"{-}Expanded Group", "EXBK_EXPANDEDGROUPS", ID_EXTBKEXPANDEDGROUP, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Collapsed Group", "EXBK_COLLAPSEDGROUP", ID_EXTBKCOLLAPSEDDGROUP, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Empty Group", "EXBK_EMPTYGROUPS", ID_EXTBKEMPTYGROUPS, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"{-}First contact of a group", "EXBK_FIRSTITEM", ID_EXTBKFIRSTITEM, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Single item in group", "EXBK_SINGLEITEM", ID_EXTBKSINGLEITEM, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Last contact of a group", "EXBK_LASTITEM", ID_EXTBKLASTITEM, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"{-}First contact of NON-group", "EXBK_FIRSTITEM_NG", ID_EXTBKFIRSTITEM_NG, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Single item in NON-group", "EXBK_SINGLEITEM_NG", ID_EXTBKSINGLEITEM_NG, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Last contact of NON-group", "EXBK_LASTITEM_NG", ID_EXTBKLASTITEM_NG, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, 0, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"{-}Even Contact Positions", "EXBK_EVEN_CNTC_POS", ID_EXTBKEVEN_CNTCTPOS, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Odd Contact Positions", "EXBK_ODD_CNTC_POS", ID_EXTBKODD_CNTCTPOS, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"{-}Selection", "EXBK_SELECTION", ID_EXTBKSELECTION, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Hottracked Item", "EXBK_HOTTRACK", ID_EXTBKHOTTRACK, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"{-}Frame titlebars", "EXBK_FRAMETITLE", ID_EXTBKFRAMETITLE, + CLCDEFAULT_GRADIENT, CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 0 + }, {"Event area", "EXBK_EVTAREA", ID_EXTBKEVTAREA, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 0 + }, {"Status Bar", "EXBK_STATUSBAR", ID_EXTBKSTATUSBAR, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Tool bar", "EXBK_TOOLBAR", ID_EXTBKBUTTONBAR, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 0 + }, {"{-}UI Button - pressed", "EXBK_BUTTONSPRESSED", ID_EXTBKBUTTONSPRESSED, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"UI Button - not pressed", "EXBK_BUTTONSNPRESSED", ID_EXTBKBUTTONSNPRESSED, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"UI Button - mouseover", "EXBK_BUTTONSMOUSEOVER", ID_EXTBKBUTTONSMOUSEOVER, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Toolbar button - pressed", "EXBK_TBBUTTONSPRESSED", ID_EXTBKTBBUTTONSPRESSED, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Toolbar button - not pressed", "EXBK_TBBUTTONSNPRESSED", ID_EXTBKTBBUTTONSNPRESSED, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"Toolbar button - mouseover", "EXBK_TBBUTTONMOUSEOVER", ID_EXTBKTBBUTTONMOUSEOVER, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"{-}Status floater", "EXBK_STATUSFLOATER", ID_EXTBKSTATUSFLOATER, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE + }, {"{-}Frame border - no titlebar", "EXBK_OWNEDFRAMEBORDER", ID_EXTBKOWNEDFRAMEBORDER, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, 1, + 1, 1, 1, CLCDEFAULT_IGNORE + }, {"Frame border - with titlebar", "EXBK_OWNEDFRAMEBORDERTB", ID_EXTBKOWNEDFRAMEBORDERTB, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, 1, + CLCDEFAULT_MRGN_TOP, 1, 1, CLCDEFAULT_IGNORE + }, {"{-}Avatarframe", "EXBK_AVATARFRAME", ID_EXTBKAVATARFRAME, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Avatarframe offline", "EXBK_AVATARFRAMEOFFLINE", ID_EXTBKAVATARFRAMEOFFLINE, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"{-}Scrollbar backgroundupper", "EXBK_SCROLLBACK", ID_EXTBKSCROLLBACK, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar backgroundlower", "EXBK_SCROLLBACKLOWER", ID_EXTBKSCROLLBACKLOWER, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar thumb", "EXBK_SCROLLTHUMB", ID_EXTBKSCROLLTHUMB, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar thumb hovered", "EXBK_SCROLLTHUMBHOVER", ID_EXTBKSCROLLTHUMBHOVER, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar thumb pressed", "EXBK_SCROLLTHUMBPRESSED", ID_EXTBKSCROLLTHUMBPRESSED, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar button", "EXBK_SCROLLBUTTON", ID_EXTBKSCROLLBUTTON, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar button hovered", "EXBK_SCROLLBUTTONHOVER", ID_EXTBKSCROLLBUTTONHOVER, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar button pressed", "EXBK_SCROLLBUTTONPRESSED", ID_EXTBKSCROLLBUTTONPRESSED, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar arrow up", "EXBK_SCROLLARROWUP", ID_EXTBKSCROLLARROWUP, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + }, {"Scrollbar arrow down", "EXBK_SCROLLARROWDOWN", ID_EXTBKSCROLLARROWDOWN, + CLCDEFAULT_GRADIENT,CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, CLCDEFAULT_TEXTCOLOR, CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, + CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, CLCDEFAULT_MRGN_BOTTOM, 1 + } +}; + +BOOL __forceinline GetItemByStatus(int status, StatusItems_t *retitem) +{ + status = (status >= ID_STATUS_OFFLINE && status <= ID_EXTBK_LAST) ? status : ID_STATUS_OFFLINE; // better check the index... + *retitem = StatusItems[status - ID_STATUS_OFFLINE]; + if(g_hottrack && status != ID_EXTBKHOTTRACK) // allow hottracking for ignored items, unless hottrack item itself should be ignored + retitem->IGNORED = FALSE; + return TRUE; +} + +StatusItems_t *GetProtocolStatusItem(const char *szProto) +{ + int i; + + if(szProto == NULL) + return NULL; + + for (i = ID_EXTBK_LAST_D - ID_STATUS_OFFLINE + 1; i <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; i++) { + if (!strcmp(StatusItems[i].szName[0] == '{' ? &StatusItems[i].szName[3] : StatusItems[i].szName, szProto)) + return &StatusItems[i]; + } + return NULL; +} + +// fills the struct with the settings in the database +void LoadExtBkSettingsFromDB() +{ + DWORD ret; + int n; + char buffer[255]; + int protoCount = 0, i; + PROTOACCOUNT **accs = 0; + DBVARIANT dbv = {0}; + + ProtoEnumAccounts( &protoCount, &accs ); + + StatusItems = (StatusItems_t *)malloc(sizeof(StatusItems_t) * ((ID_EXTBK_LAST - ID_STATUS_OFFLINE) + protoCount + 2)); + CopyMemory(StatusItems, _StatusItems, sizeof(_StatusItems)); + + for (i = 0; i < protoCount; i++) { + ID_EXTBK_LAST++; + CopyMemory(&StatusItems[ID_EXTBK_LAST - ID_STATUS_OFFLINE], &StatusItems[0], sizeof(StatusItems_t)); + mir_snprintf(StatusItems[ID_EXTBK_LAST - ID_STATUS_OFFLINE].szDBname, 30, "EXBK_%s", accs[i]->szModuleName ); + if(i == 0) { + lstrcpynA(StatusItems[ID_EXTBK_LAST - ID_STATUS_OFFLINE].szName, "{-}", 30); + strncat(StatusItems[ID_EXTBK_LAST - ID_STATUS_OFFLINE].szName, accs[i]->szModuleName, 30); + } + else + lstrcpynA(StatusItems[ID_EXTBK_LAST - ID_STATUS_OFFLINE].szName, accs[i]->szModuleName, 30); + StatusItems[ID_EXTBK_LAST - ID_STATUS_OFFLINE].statusID = ID_EXTBK_LAST; + } + for (n = 0; n <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; n++) { + if (StatusItems[n].statusID != ID_EXTBKSEPARATOR) { + StatusItems[n].imageItem = 0; + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_IGNORE"); + ret = cfg::getByte("CLCExt", buffer, StatusItems[n].IGNORED); + StatusItems[n]. IGNORED = (BYTE) ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_GRADIENT"); + ret = cfg::getDword("CLCExt", buffer, StatusItems[n].GRADIENT); + StatusItems[n]. GRADIENT = (BYTE) ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_CORNER"); + ret = cfg::getDword("CLCExt", buffer, StatusItems[n].CORNER); + StatusItems[n]. CORNER = (BYTE) ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR"); + ret = cfg::getDword("CLCExt", buffer, StatusItems[n].COLOR); + StatusItems[n]. COLOR = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2"); + ret = cfg::getDword(NULL, "CLCExt", buffer, StatusItems[n].COLOR2); + StatusItems[n]. COLOR2 = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2_TRANSPARENT"); + ret = cfg::getByte("CLCExt", buffer, StatusItems[n].COLOR2_TRANSPARENT); + StatusItems[n]. COLOR2_TRANSPARENT = (BYTE) ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_TEXTCOLOR"); + ret = cfg::getDword("CLCExt", buffer, StatusItems[n].TEXTCOLOR); + StatusItems[n]. TEXTCOLOR = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_ALPHA"); + ret = cfg::getByte("CLCExt", buffer, StatusItems[n].ALPHA); + StatusItems[n]. ALPHA = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_LEFT"); + ret = cfg::getByte("CLCExt", buffer, StatusItems[n].MARGIN_LEFT); + StatusItems[n]. MARGIN_LEFT = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_TOP"); + ret = cfg::getByte("CLCExt", buffer, StatusItems[n].MARGIN_TOP); + StatusItems[n]. MARGIN_TOP = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_RIGHT"); + ret = cfg::getByte("CLCExt", buffer, StatusItems[n].MARGIN_RIGHT); + StatusItems[n]. MARGIN_RIGHT = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_BOTTOM"); + ret = cfg::getByte("CLCExt", buffer, StatusItems[n].MARGIN_BOTTOM); + StatusItems[n]. MARGIN_BOTTOM = ret; + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_BDRSTYLE"); + ret = cfg::getDword("CLCExt", buffer, StatusItems[n].BORDERSTYLE); + StatusItems[n]. BORDERSTYLE = ret; + } + } + if(cfg::dat.bFirstRun) { + StatusItems_t *item = &StatusItems[ID_EXTBKBUTTONBAR - ID_STATUS_OFFLINE]; + + item->COLOR = GetSysColor(COLOR_3DFACE); + item->COLOR2 = GetSysColor(COLOR_3DFACE); + + item = &StatusItems[ID_EXTBKEVTAREA - ID_STATUS_OFFLINE]; + item->COLOR = item->COLOR2 = GetSysColor(COLOR_WINDOW); + item->BORDERSTYLE = EDGE_ETCHED; + SaveCompleteStructToDB(); + } +} + +// writes whole struct to the database +static void SaveCompleteStructToDB(void) +{ + int n; + char buffer[255]; + + for (n = 0; n <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; n++) { + if (StatusItems[n].statusID != ID_EXTBKSEPARATOR) { + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_IGNORE"); + cfg::writeByte("CLCExt", buffer, StatusItems[n].IGNORED); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_GRADIENT"); + cfg::writeDword("CLCExt", buffer, StatusItems[n].GRADIENT); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_CORNER"); + cfg::writeDword("CLCExt", buffer, StatusItems[n].CORNER); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR"); + cfg::writeDword("CLCExt", buffer, StatusItems[n].COLOR); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2"); + cfg::writeDword("CLCExt", buffer, StatusItems[n].COLOR2); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2_TRANSPARENT"); + cfg::writeByte("CLCExt", buffer, StatusItems[n].COLOR2_TRANSPARENT); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_TEXTCOLOR"); + cfg::writeDword("CLCExt", buffer, StatusItems[n].TEXTCOLOR); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_ALPHA"); + cfg::writeByte("CLCExt", buffer, (BYTE)StatusItems[n].ALPHA); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_LEFT"); + cfg::writeByte("CLCExt", buffer, (BYTE)StatusItems[n].MARGIN_LEFT); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_TOP"); + cfg::writeByte("CLCExt", buffer, (BYTE)StatusItems[n].MARGIN_TOP); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_RIGHT"); + cfg::writeByte("CLCExt", buffer, (BYTE)StatusItems[n].MARGIN_RIGHT); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MRGN_BOTTOM"); + cfg::writeByte("CLCExt", buffer, (BYTE)StatusItems[n].MARGIN_BOTTOM); + + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_BDRSTYLE"); + cfg::writeDword("CLCExt", buffer, StatusItems[n].BORDERSTYLE); + } + } +} + +void SetButtonToSkinned() +{ + bool bSkinned = (cfg::dat.bSkinnedButtonMode = cfg::getByte("CLCExt", "bskinned", 0)) != 0; + CustomizeButton( GetDlgItem(pcli->hwndContactList, IDC_TBMENU), bSkinned, !bSkinned, bSkinned); + CustomizeButton( GetDlgItem(pcli->hwndContactList, IDC_TBGLOBALSTATUS), bSkinned, !bSkinned, bSkinned); + SendMessage(g_hwndViewModeFrame, WM_USER + 100, 0, 0); +} + +void Reload3dBevelColors() +{ + if(cfg::dat.hPen3DBright) + DeleteObject(cfg::dat.hPen3DBright); + if(cfg::dat.hPen3DDark) + DeleteObject(cfg::dat.hPen3DDark); + + cfg::dat.hPen3DBright = CreatePen(PS_SOLID, 1, cfg::getDword("CLCExt", "3dbright", GetSysColor(COLOR_3DLIGHT))); + cfg::dat.hPen3DDark = CreatePen(PS_SOLID, 1, cfg::getDword("CLCExt", "3ddark", GetSysColor(COLOR_3DSHADOW))); +} + +// Save Non-StatusItems Settings +void SaveNonStatusItemsSettings(HWND hwndDlg) +{ + BOOL translated; + + cfg::writeByte("CLCExt", "EXBK_EqualSelection", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_EQUALSELECTION)); + cfg::writeByte("CLCExt", "EXBK_SelBlend", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SELBLEND)); + + cfg::dat.cornerRadius = GetDlgItemInt(hwndDlg, IDC_CORNERRAD, &translated, FALSE); + cfg::dat.bApplyIndentToBg = IsDlgButtonChecked(hwndDlg, IDC_APPLYINDENTBG) ? 1 : 0; + cfg::dat.bUsePerProto = IsDlgButtonChecked(hwndDlg, IDC_USEPERPROTO) ? 1 : 0; + cfg::dat.bWantFastGradients = IsDlgButtonChecked(hwndDlg, IDC_FASTGRADIENT) ? 1 : 0; + cfg::dat.bOverridePerStatusColors = IsDlgButtonChecked(hwndDlg, IDC_OVERRIDEPERSTATUSCOLOR) ? 1 : 0; + cfg::dat.titleBarHeight = (BYTE)GetDlgItemInt(hwndDlg, IDC_LASTITEMPADDING, &translated, FALSE); + cfg::dat.group_padding = GetDlgItemInt(hwndDlg, IDC_GRPTOPPADDING, &translated, FALSE); + + cfg::writeByte("CLCExt", "CornerRad", cfg::dat.cornerRadius); + cfg::writeByte("CLCExt", "applyindentbg", (BYTE)cfg::dat.bApplyIndentToBg); + cfg::writeByte("CLCExt", "useperproto", (BYTE)cfg::dat.bUsePerProto); + cfg::writeByte("CLCExt", "override_status", (BYTE)cfg::dat.bOverridePerStatusColors); + cfg::writeByte("CLCExt", "bskinned", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_SETALLBUTTONSKINNED) ? 1 : 0)); + cfg::writeByte("CLCExt", "FastGradients", cfg::dat.bWantFastGradients); + cfg::writeByte("CLC", "IgnoreSelforGroups", (BYTE) IsDlgButtonChecked(hwndDlg, IDC_IGNORESELFORGROUPS)); + + cfg::writeDword("CLCExt", "grp_padding", cfg::dat.group_padding); + cfg::writeByte("CLCExt", "frame_height", cfg::dat.titleBarHeight); + + Reload3dBevelColors(); + SetButtonToSkinned(); +} + +/* +* skin/theme related settings which are exported to/imported from the .ini style .clist file +*/ + +struct {char *szModule; char *szSetting; unsigned int size; int defaultval;} _tagSettings[] = { + "CLCExt", "3dbright", 4, RGB(224, 225, 225), + "CLCExt", "3ddark", 4, RGB(224, 225, 225), + "CLCExt", "bskinned", 1, 0, + "CLCExt", "CornerRad", 1, 0, + "CLCExt", "applyindentbg", 1, 0, + "CLCExt", "override_status", 1, 0, + "CLCExt", "useperproto", 1, 0, + "CLUI", "sb_skinned", 1, 0, + "CLC", "RowGap", 1, 0, + "CLC", "ExIconScale", 1, 0, + "CLUI", "UseBkSkin", 1, 0, + "CLUI", "clipborder", 1, 0, + "CLUIFrames", "GapBetweenFrames", 4, 0, + "CLC", "BkColour", 4, RGB(224, 224, 224), + "CLCExt", "EXBK_CenterGroupnames", 1, 0, + "CLC", "BkBmpUse", 2, 0, + "CLUI", "clmargins", 4, 0, + // frame stuff + + "WorldTime", "BgColour", 4, 0, + "WorldTime", "FontCol", 4, 0, + NULL, NULL, 0, 0 +}; + +void extbk_export(char *file) +{ + int n, i; + char buffer[255]; + char szSection[255]; + char szKey[255]; + DBVARIANT dbv = {0}; + DWORD data; + + data = 3; + + WritePrivateProfileStructA("Global", "Version", &data, 4, file); + for (n = 0; n <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; n++) { + if (StatusItems[n].statusID != ID_EXTBKSEPARATOR) { + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_ALPHA"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].ALPHA), sizeof(StatusItems[n].ALPHA), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].COLOR), sizeof(StatusItems[n].COLOR), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].COLOR2), sizeof(StatusItems[n].COLOR2), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2_TRANSPARENT"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].COLOR2_TRANSPARENT), sizeof(StatusItems[n].COLOR2_TRANSPARENT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_TEXTCOLOR"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].TEXTCOLOR), sizeof(StatusItems[n].TEXTCOLOR), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_CORNER"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].CORNER), sizeof(StatusItems[n].CORNER), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_GRADIENT"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].GRADIENT), sizeof(StatusItems[n].GRADIENT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_IGNORED"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].IGNORED), sizeof(StatusItems[n].IGNORED), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_BOTTOM"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_BOTTOM), sizeof(StatusItems[n].MARGIN_BOTTOM), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_LEFT"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_LEFT), sizeof(StatusItems[n].MARGIN_LEFT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_RIGHT"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_RIGHT), sizeof(StatusItems[n].MARGIN_RIGHT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_TOP"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_TOP), sizeof(StatusItems[n].MARGIN_TOP), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_BORDERSTYLE"); + WritePrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].BORDERSTYLE), sizeof(StatusItems[n].BORDERSTYLE), file); + } + } + for (n = 0; n <= FONTID_LAST; n++) { + mir_snprintf(szSection, 255, "Font%d", n); + + mir_snprintf(szKey, 255, "Font%dName", n); + if (!cfg::getString(NULL, "CLC", szKey, &dbv)) { + WritePrivateProfileStringA(szSection, "Name", dbv.pszVal, file); + mir_free(dbv.pszVal); + } + mir_snprintf(szKey, 255, "Font%dSize", n); + data = (DWORD)cfg::getByte("CLC", szKey, 8); + WritePrivateProfileStructA(szSection, "Size", &data, 1, file); + + mir_snprintf(szKey, 255, "Font%dSty", n); + data = (DWORD)cfg::getByte("CLC", szKey, 8); + WritePrivateProfileStructA(szSection, "Style", &data, 1, file); + + mir_snprintf(szKey, 255, "Font%dSet", n); + data = (DWORD)cfg::getByte("CLC", szKey, 8); + WritePrivateProfileStructA(szSection, "Set", &data, 1, file); + + mir_snprintf(szKey, 255, "Font%dCol", n); + data = cfg::getDword("CLC", szKey, 8); + WritePrivateProfileStructA(szSection, "Color", &data, 4, file); + + mir_snprintf(szKey, 255, "Font%dFlags", n); + data = (DWORD)cfg::getDword("CLC", szKey, 8); + WritePrivateProfileStructA(szSection, "Flags", &data, 4, file); + + mir_snprintf(szKey, 255, "Font%dAs", n); + data = (DWORD)cfg::getWord("CLC", szKey, 8); + WritePrivateProfileStructA(szSection, "SameAs", &data, 2, file); + } + i = 0; + while(_tagSettings[i].szModule != NULL) { + data = 0; + switch(_tagSettings[i].size) { + case 1: + data = (DWORD)cfg::getByte( _tagSettings[i].szModule, _tagSettings[i].szSetting, (BYTE)_tagSettings[i].defaultval); + break; + case 2: + data = (DWORD)cfg::getWord( _tagSettings[i].szModule, _tagSettings[i].szSetting, (DWORD)_tagSettings[i].defaultval); + break; + case 4: + data = (DWORD)cfg::getDword( _tagSettings[i].szModule, _tagSettings[i].szSetting, (DWORD)_tagSettings[i].defaultval); + break; + } + WritePrivateProfileStructA("Global", _tagSettings[i].szSetting, &data, _tagSettings[i].size, file); + i++; + } + if (!cfg::getString(NULL, "CLC", "BkBitmap", &dbv)) { + WritePrivateProfileStringA("Global", "BkBitmap", dbv.pszVal, file); + DBFreeVariant(&dbv); + } +} + +DWORD __fastcall HexStringToLong(const char *szSource) +{ + char *stopped; + COLORREF clr = strtol(szSource, &stopped, 16); + if(clr == -1) + return clr; + return(RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr))); +} + +static StatusItems_t default_item = { + "{--Contact--}", "", 0, + CLCDEFAULT_GRADIENT, CLCDEFAULT_CORNER, + CLCDEFAULT_COLOR, CLCDEFAULT_COLOR2, CLCDEFAULT_COLOR2_TRANSPARENT, -1, + CLCDEFAULT_ALPHA, CLCDEFAULT_MRGN_LEFT, CLCDEFAULT_MRGN_TOP, CLCDEFAULT_MRGN_RIGHT, + CLCDEFAULT_MRGN_BOTTOM, CLCDEFAULT_IGNORE +}; + + +static void PreMultiply(HBITMAP hBitmap, int mode) +{ + BYTE *p = NULL; + DWORD dwLen; + int width, height, x, y; + BITMAP bmp; + BYTE alpha; + + GetObject(hBitmap, sizeof(bmp), &bmp); + width = bmp.bmWidth; + height = bmp.bmHeight; + dwLen = width * height * 4; + p = (BYTE *)malloc(dwLen); + if(p) { + GetBitmapBits(hBitmap, dwLen, p); + for (y = 0; y < height; ++y) { + BYTE *px = p + width * 4 * y; + + for (x = 0; x < width; ++x) { + if(mode) { + alpha = px[3]; + px[0] = px[0] * alpha/255; + px[1] = px[1] * alpha/255; + px[2] = px[2] * alpha/255; + } + else + px[3] = 255; + px += 4; + } + } + dwLen = SetBitmapBits(hBitmap, dwLen, p); + free(p); + } +} + +static void CorrectBitmap32Alpha(HBITMAP hBitmap) +{ + BITMAP bmp; + DWORD dwLen; + BYTE *p; + int x, y; + BOOL fixIt = TRUE; + + GetObject(hBitmap, sizeof(bmp), &bmp); + + if (bmp.bmBitsPixel != 32) + return; + + dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); + p = (BYTE *)malloc(dwLen); + if (p == NULL) + return; + memset(p, 0, dwLen); + + GetBitmapBits(hBitmap, dwLen, p); + + for (y = 0; y < bmp.bmHeight; ++y) { + BYTE *px = p + bmp.bmWidth * 4 * y; + + for (x = 0; x < bmp.bmWidth; ++x) + { + if (px[3] != 0) + { + fixIt = FALSE; + } + else + { + px[3] = 255; + } + + px += 4; + } + } + + if (fixIt) + { + SetBitmapBits(hBitmap, bmp.bmWidth * bmp.bmHeight * 4, p); + } + + free(p); +} + +static HBITMAP LoadPNG(const char *szFilename, ImageItem *item) +{ + HBITMAP hBitmap = 0; + + hBitmap = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (LPARAM)szFilename); + if(hBitmap != 0) + CorrectBitmap32Alpha(hBitmap); + + return hBitmap; +} + +static void IMG_CreateItem(ImageItem *item, const char *fileName, HDC hdc) +{ + HBITMAP hbm = LoadPNG(fileName, item); + BITMAP bm; + + if(hbm) { + item->hbm = hbm; + item->bf.BlendFlags = 0; + item->bf.BlendOp = AC_SRC_OVER; + item->bf.AlphaFormat = 0; + + GetObject(hbm, sizeof(bm), &bm); + if(bm.bmBitsPixel == 32) { + PreMultiply(hbm, 1); + item->dwFlags |= IMAGE_PERPIXEL_ALPHA; + item->bf.AlphaFormat = AC_SRC_ALPHA; + } + item->width = bm.bmWidth; + item->height = bm.bmHeight; + item->inner_height = item->height - item->bTop - item->bBottom; + item->inner_width = item->width - item->bLeft - item->bRight; + if(item->bTop && item->bBottom && item->bLeft && item->bRight) { + item->dwFlags |= IMAGE_FLAG_DIVIDED; + if(item->inner_height <= 0 || item->inner_width <= 0) { + DeleteObject(hbm); + item->hbm = 0; + return; + } + } + item->hdc = CreateCompatibleDC(hdc); + item->hbmOld = reinterpret_cast(SelectObject(item->hdc, item->hbm)); + } +} + +static void IMG_DeleteItem(ImageItem *item) +{ + if (!(item->dwFlags & IMAGE_GLYPH)) { + SelectObject(item->hdc, item->hbmOld); + DeleteObject(item->hbm); + DeleteDC(item->hdc); + } + if(item->fillBrush) + DeleteObject(item->fillBrush); +} + +static void ReadItem(StatusItems_t *this_item, char *szItem, char *file) +{ + char buffer[512], def_color[20]; + COLORREF clr; + + StatusItems_t *defaults = &default_item; + GetPrivateProfileStringA(szItem, "BasedOn", "None", buffer, 400, file); + + + if(strcmp(buffer, "None")) { + int i; + + for (i = 0; i <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; i++) { + if (!_stricmp(StatusItems[i].szName[0] == '{' ? &StatusItems[i].szName[3] : StatusItems[i].szName, buffer)) { + defaults = &StatusItems[i]; + break; + } + } + } + this_item->ALPHA = (int)GetPrivateProfileIntA(szItem, "Alpha", defaults->ALPHA, file); + this_item->ALPHA = min(this_item->ALPHA, 100); + + clr = RGB(GetBValue(defaults->COLOR), GetGValue(defaults->COLOR), GetRValue(defaults->COLOR)); + _snprintf(def_color, 15, "%6.6x", clr); + GetPrivateProfileStringA(szItem, "Color1", def_color, buffer, 400, file); + this_item->COLOR = HexStringToLong(buffer); + + clr = RGB(GetBValue(defaults->COLOR2), GetGValue(defaults->COLOR2), GetRValue(defaults->COLOR2)); + _snprintf(def_color, 15, "%6.6x", clr); + GetPrivateProfileStringA(szItem, "Color2", def_color, buffer, 400, file); + this_item->COLOR2 = HexStringToLong(buffer); + + this_item->COLOR2_TRANSPARENT = (BYTE)GetPrivateProfileIntA(szItem, "COLOR2_TRANSPARENT", defaults->COLOR2_TRANSPARENT, file); + + this_item->CORNER = defaults->CORNER & CORNER_ACTIVE ? defaults->CORNER : 0; + GetPrivateProfileStringA(szItem, "Corner", "None", buffer, 400, file); + if(strstr(buffer, "tl")) + this_item->CORNER |= CORNER_TL; + if(strstr(buffer, "tr")) + this_item->CORNER |= CORNER_TR; + if(strstr(buffer, "bl")) + this_item->CORNER |= CORNER_BL; + if(strstr(buffer, "br")) + this_item->CORNER |= CORNER_BR; + if(this_item->CORNER) + this_item->CORNER |= CORNER_ACTIVE; + + this_item->GRADIENT = defaults->GRADIENT & GRADIENT_ACTIVE ? defaults->GRADIENT : 0; + GetPrivateProfileStringA(szItem, "Gradient", "None", buffer, 400, file); + if(strstr(buffer, "left")) + this_item->GRADIENT = GRADIENT_RL; + else if(strstr(buffer, "right")) + this_item->GRADIENT = GRADIENT_LR; + else if(strstr(buffer, "up")) + this_item->GRADIENT = GRADIENT_BT; + else if(strstr(buffer, "down")) + this_item->GRADIENT = GRADIENT_TB; + if(this_item->GRADIENT) + this_item->GRADIENT |= GRADIENT_ACTIVE; + + this_item->MARGIN_LEFT = GetPrivateProfileIntA(szItem, "Left", defaults->MARGIN_LEFT, file); + this_item->MARGIN_RIGHT = GetPrivateProfileIntA(szItem, "Right", defaults->MARGIN_RIGHT, file); + this_item->MARGIN_TOP = GetPrivateProfileIntA(szItem, "Top", defaults->MARGIN_TOP, file); + this_item->MARGIN_BOTTOM = GetPrivateProfileIntA(szItem, "Bottom", defaults->MARGIN_BOTTOM, file); + this_item->BORDERSTYLE = GetPrivateProfileIntA(szItem, "Borderstyle", defaults->BORDERSTYLE, file); + + GetPrivateProfileStringA(szItem, "Textcolor", "ffffffff", buffer, 400, file); + this_item->TEXTCOLOR = HexStringToLong(buffer); +} + +void IMG_ReadItem(const char *itemname, const char *szFileName) +{ + ImageItem tmpItem, *newItem = NULL; + char buffer[512], szItemNr[30]; + char szFinalName[MAX_PATH]; + HDC hdc = GetDC(pcli->hwndContactList); + int i, n; + BOOL alloced = FALSE; + char szDrive[MAX_PATH], szPath[MAX_PATH]; + + ZeroMemory(&tmpItem, sizeof(ImageItem)); + GetPrivateProfileStringA(itemname, "Glyph", "None", buffer, 500, szFileName); + if(strcmp(buffer, "None")) { + sscanf(buffer, "%d,%d,%d,%d", &tmpItem.glyphMetrics[0], &tmpItem.glyphMetrics[1], + &tmpItem.glyphMetrics[2], &tmpItem.glyphMetrics[3]); + if(tmpItem.glyphMetrics[2] > tmpItem.glyphMetrics[0] && tmpItem.glyphMetrics[3] > tmpItem.glyphMetrics[1]) { + tmpItem.dwFlags |= IMAGE_GLYPH; + tmpItem.glyphMetrics[2] = (tmpItem.glyphMetrics[2] - tmpItem.glyphMetrics[0]) + 1; + tmpItem.glyphMetrics[3] = (tmpItem.glyphMetrics[3] - tmpItem.glyphMetrics[1]) + 1; + goto done_with_glyph; + } + } + GetPrivateProfileStringA(itemname, "Image", "None", buffer, 500, szFileName); + if(strcmp(buffer, "None")) { + +done_with_glyph: + + strncpy(tmpItem.szName, &itemname[1], sizeof(tmpItem.szName)); + tmpItem.szName[sizeof(tmpItem.szName) - 1] = 0; + _splitpath(szFileName, szDrive, szPath, NULL, NULL); + mir_snprintf(szFinalName, MAX_PATH, "%s\\%s\\%s", szDrive, szPath, buffer); + tmpItem.alpha = GetPrivateProfileIntA(itemname, "Alpha", 100, szFileName); + tmpItem.alpha = min(tmpItem.alpha, 100); + tmpItem.alpha = (BYTE)((FLOAT)(((FLOAT) tmpItem.alpha) / 100) * 255); + tmpItem.bf.SourceConstantAlpha = tmpItem.alpha; + tmpItem.bLeft = GetPrivateProfileIntA(itemname, "Left", 0, szFileName); + tmpItem.bRight = GetPrivateProfileIntA(itemname, "Right", 0, szFileName); + tmpItem.bTop = GetPrivateProfileIntA(itemname, "Top", 0, szFileName); + tmpItem.bBottom = GetPrivateProfileIntA(itemname, "Bottom", 0, szFileName); + if(tmpItem.dwFlags & IMAGE_GLYPH) { + tmpItem.width = tmpItem.glyphMetrics[2]; + tmpItem.height = tmpItem.glyphMetrics[3]; + tmpItem.inner_height = tmpItem.glyphMetrics[3] - tmpItem.bTop - tmpItem.bBottom; + tmpItem.inner_width = tmpItem.glyphMetrics[2] - tmpItem.bRight - tmpItem.bLeft; + + if(tmpItem.bTop && tmpItem.bBottom && tmpItem.bLeft && tmpItem.bRight) + tmpItem.dwFlags |= IMAGE_FLAG_DIVIDED; + tmpItem.bf.BlendFlags = 0; + tmpItem.bf.BlendOp = AC_SRC_OVER; + tmpItem.bf.AlphaFormat = 0; + tmpItem.dwFlags |= IMAGE_PERPIXEL_ALPHA; + tmpItem.bf.AlphaFormat = AC_SRC_ALPHA; + if(tmpItem.inner_height <= 0 || tmpItem.inner_width <= 0) { + ReleaseDC(pcli->hwndContactList, hdc); + return; + } + } + GetPrivateProfileStringA(itemname, "Fillcolor", "None", buffer, 500, szFileName); + if(strcmp(buffer, "None")) { + COLORREF fillColor = HexStringToLong(buffer); + tmpItem.fillBrush = CreateSolidBrush(fillColor); + tmpItem.dwFlags |= IMAGE_FILLSOLID; + } + else + tmpItem.fillBrush = 0; + + GetPrivateProfileStringA(itemname, "Stretch", "None", buffer, 500, szFileName); + if(buffer[0] == 'B' || buffer[0] == 'b') + tmpItem.bStretch = IMAGE_STRETCH_B; + else if(buffer[0] == 'h' || buffer[0] == 'H') + tmpItem.bStretch = IMAGE_STRETCH_V; + else if(buffer[0] == 'w' || buffer[0] == 'W') + tmpItem.bStretch = IMAGE_STRETCH_H; + tmpItem.hbm = 0; + + if (!_stricmp(itemname, "$glyphs")) { + IMG_CreateItem(&tmpItem, szFinalName, hdc); + if(tmpItem.hbm) { + newItem = reinterpret_cast(malloc(sizeof(ImageItem))); + ZeroMemory(newItem, sizeof(ImageItem)); + *newItem = tmpItem; + g_glyphItem = newItem; + } + goto imgread_done; + } + if(itemname[0] == '@') { + if (!(tmpItem.dwFlags & IMAGE_GLYPH)) + IMG_CreateItem(&tmpItem, szFinalName, hdc); + if(tmpItem.hbm || tmpItem.dwFlags & IMAGE_GLYPH) { + ImageItem *pItem = g_ImageItems; + + newItem = reinterpret_cast(malloc(sizeof(ImageItem))); + ZeroMemory(newItem, sizeof(ImageItem)); + *newItem = tmpItem; + + if(g_ImageItems == NULL) + g_ImageItems = newItem; + else { + ImageItem *pItem = g_ImageItems; + + while(pItem->nextItem != 0) + pItem = pItem->nextItem; + pItem->nextItem = newItem; + } + } + goto imgread_done; + } + for (n = 0;;n++) { + mir_snprintf(szItemNr, 30, "Item%d", n); + GetPrivateProfileStringA(itemname, szItemNr, "None", buffer, 500, szFileName); + if (!strcmp(buffer, "None")) + break; + if (!strcmp(buffer, "CLUI")) { + if (!(tmpItem.dwFlags & IMAGE_GLYPH)) + IMG_CreateItem(&tmpItem, szFinalName, hdc); + if(tmpItem.hbm || tmpItem.dwFlags & IMAGE_GLYPH) { + COLORREF clr; + + newItem = reinterpret_cast(malloc(sizeof(ImageItem))); + ZeroMemory(newItem, sizeof(ImageItem)); + *newItem = tmpItem; + g_CLUIImageItem = newItem; + GetPrivateProfileStringA(itemname, "Colorkey", "e5e5e5", buffer, 500, szFileName); + clr = HexStringToLong(buffer); + cfg::dat.colorkey = clr; + cfg::writeDword("CLUI", "ColorKey", clr); + if(g_CLUISkinnedBkColor) + DeleteObject(g_CLUISkinnedBkColor); + g_CLUISkinnedBkColor = CreateSolidBrush(clr); + g_CLUISkinnedBkColorRGB = clr; + } + continue; + } + for (i = 0; i <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; i++) { + if (!_stricmp(StatusItems[i].szName[0] == '{' ? &StatusItems[i].szName[3] : StatusItems[i].szName, buffer)) { + if (!alloced) { + if (!(tmpItem.dwFlags & IMAGE_GLYPH)) + IMG_CreateItem(&tmpItem, szFinalName, hdc); + if(tmpItem.hbm || tmpItem.dwFlags & IMAGE_GLYPH) { + newItem = reinterpret_cast(malloc(sizeof(ImageItem))); + ZeroMemory(newItem, sizeof(ImageItem)); + *newItem = tmpItem; + StatusItems[i].imageItem = newItem; + if(g_ImageItems == NULL) + g_ImageItems = newItem; + else { + ImageItem *pItem = g_ImageItems; + + while(pItem->nextItem != 0) + pItem = pItem->nextItem; + pItem->nextItem = newItem; + } + alloced = TRUE; + } + } + else if(newItem != NULL) + StatusItems[i].imageItem = newItem; + } + } + } + } +imgread_done: + ReleaseDC(pcli->hwndContactList, hdc); +} + +void IMG_DeleteItems() +{ + ImageItem *pItem = g_ImageItems, *pNextItem; + ButtonItem *pbItem = g_ButtonItems, *pbNextItem; + + int i; + + while(pItem) { + IMG_DeleteItem(pItem); + pNextItem = pItem->nextItem; + free(pItem); + pItem = pNextItem; + } + g_ImageItems = NULL; + while(pbItem) { + DestroyWindow(pbItem->hWnd); + pbNextItem = pbItem->nextItem; + free(pbItem); + pbItem = pbNextItem; + } + g_ButtonItems = NULL; + + if(g_CLUIImageItem) { + IMG_DeleteItem(g_CLUIImageItem); + free(g_CLUIImageItem); + } + g_CLUIImageItem = NULL; + + if(g_glyphItem) { + IMG_DeleteItem(g_glyphItem); + free(g_glyphItem); + } + g_glyphItem = NULL; + + for (i = 0; i <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; i++) + StatusItems[i].imageItem = NULL; +} + +static UINT nextButtonID = IDC_TBFIRSTUID; + +static void BTN_ReadItem(char *itemName, char *file) +{ + ButtonItem tmpItem, *newItem; + char szBuffer[1024]; + ImageItem *imgItem = g_ImageItems; + + ZeroMemory(&tmpItem, sizeof(tmpItem)); + mir_snprintf(tmpItem.szName, sizeof(tmpItem.szName), "%s", &itemName[1]); + tmpItem.width = GetPrivateProfileIntA(itemName, "Width", 16, file); + tmpItem.height = GetPrivateProfileIntA(itemName, "Height", 16, file); + tmpItem.xOff = GetPrivateProfileIntA(itemName, "xoff", 0, file); + tmpItem.yOff = GetPrivateProfileIntA(itemName, "yoff", 0, file); + + tmpItem.dwFlags |= GetPrivateProfileIntA(itemName, "toggle", 0, file) ? BUTTON_ISTOGGLE : 0; + + GetPrivateProfileStringA(itemName, "Pressed", "None", szBuffer, 1000, file); + if (!_stricmp(szBuffer, "default")) + tmpItem.imgPressed = StatusItems[ID_EXTBKTBBUTTONSPRESSED - ID_STATUS_OFFLINE].imageItem; + else { + while(imgItem) { + if (!_stricmp(imgItem->szName, szBuffer)) { + tmpItem.imgPressed = imgItem; + break; + } + imgItem = imgItem->nextItem; + } + } + + imgItem = g_ImageItems; + GetPrivateProfileStringA(itemName, "Normal", "None", szBuffer, 1000, file); + if (!_stricmp(szBuffer, "default")) + tmpItem.imgNormal = StatusItems[ID_EXTBKTBBUTTONSNPRESSED - ID_STATUS_OFFLINE].imageItem; + else { + while(imgItem) { + if (!_stricmp(imgItem->szName, szBuffer)) { + tmpItem.imgNormal = imgItem; + break; + } + imgItem = imgItem->nextItem; + } + } + + imgItem = g_ImageItems; + GetPrivateProfileStringA(itemName, "Hover", "None", szBuffer, 1000, file); + if (!_stricmp(szBuffer, "default")) + tmpItem.imgHover = StatusItems[ID_EXTBKTBBUTTONMOUSEOVER - ID_STATUS_OFFLINE].imageItem; + else { + while(imgItem) { + if (!_stricmp(imgItem->szName, szBuffer)) { + tmpItem.imgHover = imgItem; + break; + } + imgItem = imgItem->nextItem; + } + } + + GetPrivateProfileStringA(itemName, "NormalGlyph", "0, 0, 0, 0", szBuffer, 1000, file); + sscanf(szBuffer, "%d,%d,%d,%d", &tmpItem.normalGlyphMetrics[0], &tmpItem.normalGlyphMetrics[1], + &tmpItem.normalGlyphMetrics[2], &tmpItem.normalGlyphMetrics[3]); + tmpItem.normalGlyphMetrics[2] = (tmpItem.normalGlyphMetrics[2] - tmpItem.normalGlyphMetrics[0]) + 1; + tmpItem.normalGlyphMetrics[3] = (tmpItem.normalGlyphMetrics[3] - tmpItem.normalGlyphMetrics[1]) + 1; + + GetPrivateProfileStringA(itemName, "PressedGlyph", "0, 0, 0, 0", szBuffer, 1000, file); + sscanf(szBuffer, "%d,%d,%d,%d", &tmpItem.pressedGlyphMetrics[0], &tmpItem.pressedGlyphMetrics[1], + &tmpItem.pressedGlyphMetrics[2], &tmpItem.pressedGlyphMetrics[3]); + tmpItem.pressedGlyphMetrics[2] = (tmpItem.pressedGlyphMetrics[2] - tmpItem.pressedGlyphMetrics[0]) + 1; + tmpItem.pressedGlyphMetrics[3] = (tmpItem.pressedGlyphMetrics[3] - tmpItem.pressedGlyphMetrics[1]) + 1; + + + GetPrivateProfileStringA(itemName, "HoverGlyph", "0, 0, 0, 0", szBuffer, 1000, file); + sscanf(szBuffer, "%d,%d,%d,%d", &tmpItem.hoverGlyphMetrics[0], &tmpItem.hoverGlyphMetrics[1], + &tmpItem.hoverGlyphMetrics[2], &tmpItem.hoverGlyphMetrics[3]); + tmpItem.hoverGlyphMetrics[2] = (tmpItem.hoverGlyphMetrics[2] - tmpItem.hoverGlyphMetrics[0]) + 1; + tmpItem.hoverGlyphMetrics[3] = (tmpItem.hoverGlyphMetrics[3] - tmpItem.hoverGlyphMetrics[1]) + 1; + + tmpItem.uId = IDC_TBFIRSTUID - 1; + + GetPrivateProfileStringA(itemName, "Action", "Custom", szBuffer, 1000, file); + if (!_stricmp(szBuffer, "service")) { + tmpItem.szService[0] = 0; + GetPrivateProfileStringA(itemName, "Service", "None", szBuffer, 1000, file); + if(_stricmp(szBuffer, "None")) { + mir_snprintf(tmpItem.szService, 256, "%s", szBuffer); + tmpItem.dwFlags |= BUTTON_ISSERVICE; + tmpItem.uId = nextButtonID++; + } + } + else if (!_stricmp(szBuffer, "protoservice")) { + tmpItem.szService[0] = 0; + GetPrivateProfileStringA(itemName, "Service", "None", szBuffer, 1000, file); + if(_stricmp(szBuffer, "None")) { + mir_snprintf(tmpItem.szService, 256, "%s", szBuffer); + tmpItem.dwFlags |= BUTTON_ISPROTOSERVICE; + tmpItem.uId = nextButtonID++; + } + } + else if (!_stricmp(szBuffer, "database")) { + int n; + + GetPrivateProfileStringA(itemName, "Module", "None", szBuffer, 1000, file); + if(_stricmp(szBuffer, "None")) + mir_snprintf(tmpItem.szModule, 256, "%s", szBuffer); + GetPrivateProfileStringA(itemName, "Setting", "None", szBuffer, 1000, file); + if(_stricmp(szBuffer, "None")) + mir_snprintf(tmpItem.szSetting, 256, "%s", szBuffer); + if(GetPrivateProfileIntA(itemName, "contact", 0, file) != 0) + tmpItem.dwFlags |= BUTTON_DBACTIONONCONTACT; + + for (n = 0; n <= 1; n++) { + char szKey[20]; + BYTE *pValue; + + strcpy(szKey, n == 0 ? "dbonpush" : "dbonrelease"); + pValue = (n == 0 ? tmpItem.bValuePush : tmpItem.bValueRelease); + + GetPrivateProfileStringA(itemName, szKey, "None", szBuffer, 1000, file); + switch(szBuffer[0]) { + case 'b': + { + BYTE value = (BYTE)atol(&szBuffer[1]); + pValue[0] = value; + tmpItem.type = DBVT_BYTE; + break; + } + case 'w': + { + WORD value = (WORD)atol(&szBuffer[1]); + *((WORD *)&pValue[0]) = value; + tmpItem.type = DBVT_WORD; + break; + } + case 'd': + { + DWORD value = (DWORD)atol(&szBuffer[1]); + *((DWORD *)&pValue[0]) = value; + tmpItem.type = DBVT_DWORD; + break; + } + case 's': + { + mir_snprintf((char *)pValue, 256, &szBuffer[1]); + tmpItem.type = DBVT_ASCIIZ; + break; + } + } + } + if(tmpItem.szModule[0] && tmpItem.szSetting[0]) { + tmpItem.dwFlags |= BUTTON_ISDBACTION; + if(tmpItem.szModule[0] == '$' && (tmpItem.szModule[1] == 'c' || tmpItem.szModule[1] == 'C')) + tmpItem.dwFlags |= BUTTON_ISCONTACTDBACTION; + tmpItem.uId = nextButtonID++; + } + } + + GetPrivateProfileStringA(itemName, "PassContact", "None", szBuffer, 1000, file); + if(_stricmp(szBuffer, "None")) { + if(szBuffer[0] == 'w' || szBuffer[0] == 'W') + tmpItem.dwFlags |= BUTTON_PASSHCONTACTW; + else if(szBuffer[0] == 'l' || szBuffer[0] == 'L') + tmpItem.dwFlags |= BUTTON_PASSHCONTACTL; + } + + GetPrivateProfileStringA(itemName, "Tip", "None", szBuffer, 1000, file); + if(strcmp(szBuffer, "None")) { + + MultiByteToWideChar(cfg::dat.langPackCP, 0, szBuffer, -1, tmpItem.szTip, 256); + tmpItem.szTip[255] = 0; + + } + else + tmpItem.szTip[0] = 0; + + // create it + + newItem = (ButtonItem *)malloc(sizeof(ButtonItem)); + ZeroMemory(newItem, sizeof(ButtonItem)); + if(g_ButtonItems == NULL) { + g_ButtonItems = newItem; + *newItem = tmpItem; + newItem->nextItem = 0; + } + else { + ButtonItem *curItem = g_ButtonItems; + while(curItem->nextItem) + curItem = curItem->nextItem; + *newItem = tmpItem; + newItem->nextItem = 0; + curItem->nextItem = newItem; + } + newItem->hWnd = CreateWindowEx(0, MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 5, 5, pcli->hwndContactList, (HMENU)newItem->uId, g_hInst, NULL); + CustomizeButton(newItem->hWnd, false, false, false); + SendMessage(newItem->hWnd, BUTTONSETBTNITEM, 0, (LPARAM)newItem); + if (newItem->dwFlags & BUTTON_ISTOGGLE) + SendMessage(newItem->hWnd, BUTTONSETASPUSHBTN, TRUE, 0); + + if (newItem->szTip[0]) + SendMessage(newItem->hWnd, BUTTONADDTOOLTIP, (WPARAM)newItem->szTip, BATF_UNICODE); + return; +} + +void IMG_LoadItems() +{ + char *szSections = NULL; + char *p; + DBVARIANT dbv; + char szFileName[MAX_PATH]; + TCHAR tszFileName[MAX_PATH]; + int i = 0; + + if(cfg::getTString(NULL, "CLC", "AdvancedSkin", &dbv)) + return; + + MY_pathToAbsolute(dbv.ptszVal, tszFileName); + + /* TODO + * rewrite the skin loading in TCHAR manner + */ + + WideCharToMultiByte(CP_ACP, 0, tszFileName, MAX_PATH, szFileName, MAX_PATH, 0, 0); + + DBFreeVariant(&dbv); + + if (!PathFileExists(tszFileName)) + return; + + IMG_DeleteItems(); + + szSections = reinterpret_cast(malloc(3002)); + ZeroMemory(szSections, 3002); + p = szSections; + GetPrivateProfileSectionNamesA(szSections, 3000, szFileName); + + szSections[3001] = szSections[3000] = 0; + p = szSections; + while(lstrlenA(p) > 1) { + if(p[0] == '$' || p[0] == '@') + IMG_ReadItem(p, szFileName); + p += (lstrlenA(p) + 1); + } + nextButtonID = IDC_TBFIRSTUID; + p = szSections; + while(lstrlenA(p) > 1) { + if(p[0] == '!') + BTN_ReadItem(p, szFileName); + p += (lstrlenA(p) + 1); + } + free(szSections); + + if(g_ImageItems) { + cfg::writeByte("CLCExt", "bskinned", 1); + SetButtonToSkinned(); + } + if(g_CLUIImageItem) { + cfg::dat.bFullTransparent = TRUE; + cfg::dat.dwFlags &= ~CLUI_FRAME_CLISTSUNKEN; + cfg::writeByte("CLUI", "fulltransparent", (BYTE)cfg::dat.bFullTransparent); + cfg::writeByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_NOBORDER); + ApplyCLUIBorderStyle(pcli->hwndContactList); + SetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) | WS_EX_LAYERED); + API::SetLayeredWindowAttributes(pcli->hwndContactList, cfg::dat.colorkey, 0, LWA_COLORKEY); + } + CoolSB_SetupScrollBar(); +} + +void LoadPerContactSkins(TCHAR *tszFileName) +{ + char *p, *szProto, *uid, szItem[100]; + char *szSections = reinterpret_cast(malloc(3002)); + StatusItems_t *items = NULL, *this_item; + HANDLE hContact; + int i = 1; + + char file[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, tszFileName, MAX_PATH, file, MAX_PATH, 0, 0); + file[MAX_PATH - 1] = 0; + + + ReadItem(&default_item, "%Default", file); + ZeroMemory(szSections, 3000); + p = szSections; + GetPrivateProfileSectionNamesA(szSections, 3000, file); + szSections[3001] = szSections[3000] = 0; + p = szSections; + while(lstrlenA(p) > 1) { + if(p[0] == '%') { + p += (lstrlenA(p) + 1); + continue; + } + items = reinterpret_cast(realloc(items, i * sizeof(StatusItems_t))); + ZeroMemory(&items[i - 1], sizeof(StatusItems_t)); + this_item = &items[i - 1]; + GetPrivateProfileStringA(p, "Proto", "", this_item->szName, 40, file); + this_item->szName[39] = 0; + GetPrivateProfileStringA(p, "UIN", "", this_item->szDBname, 40, file); + this_item->szDBname[39] = 0; + this_item->IGNORED = 0; + GetPrivateProfileStringA(p, "Item", "", szItem, 100, file); + szItem[99] = 0; + //_DebugPopup(0, "Section: %s -> %s", p, szItem); + ReadItem(this_item, szItem, file); + p += (lstrlenA(p) + 1); + i++; + } + + if(items) { + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) { + char UIN[40]; + int j; + + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if(szProto) { + uid = (char *)CallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); + if ((INT_PTR) uid != CALLSERVICE_NOTFOUND && uid != NULL) { + DBVARIANT dbv = {0}; + + DBGetContactSetting(hContact, szProto, uid, &dbv); + switch(dbv.type) { + case DBVT_DWORD: + mir_snprintf(UIN, 40, "%d", dbv.dVal); + break; + case DBVT_ASCIIZ: + mir_snprintf(UIN, 40, "%s", dbv.pszVal); + DBFreeVariant(&dbv); + break; + default: + UIN[0] = 0; + break; + } + for (j = 0; j < i - 1; j++) { + if (!strcmp(szProto, items[j].szName) && !strcmp(UIN, items[j].szDBname) + && lstrlenA(szProto) == lstrlenA(items[j].szName) && lstrlenA(UIN) == lstrlenA(items[j].szDBname)) { + + //_DebugPopup(hContact, "Found: %s, %s", szProto, UIN); + cfg::writeDword(hContact, "EXTBK", "TEXT", items[j].TEXTCOLOR); + cfg::writeDword(hContact, "EXTBK", "COLOR1", items[j].COLOR); + cfg::writeDword(hContact, "EXTBK", "COLOR2", items[j].COLOR2); + cfg::writeByte(hContact, "EXTBK", "ALPHA", (BYTE)items[j].ALPHA); + + cfg::writeByte(hContact, "EXTBK", "LEFT", (BYTE)items[j].MARGIN_LEFT); + cfg::writeByte(hContact, "EXTBK", "RIGHT", (BYTE)items[j].MARGIN_RIGHT); + cfg::writeByte(hContact, "EXTBK", "TOP", (BYTE)items[j].MARGIN_TOP); + cfg::writeByte(hContact, "EXTBK", "BOTTOM", (BYTE)items[j].MARGIN_BOTTOM); + + cfg::writeByte(hContact, "EXTBK", "TRANS", items[j].COLOR2_TRANSPARENT); + cfg::writeDword(hContact, "EXTBK", "BDR", items[j].BORDERSTYLE); + + cfg::writeByte(hContact, "EXTBK", "CORNER", items[j].CORNER); + cfg::writeByte(hContact, "EXTBK", "GRAD", items[j].GRADIENT); + cfg::writeByte(hContact, "EXTBK", "TRANS", items[j].COLOR2_TRANSPARENT); + + cfg::writeByte(hContact, "EXTBK", "VALID", 1); + break; + } + } + if(j == i - 1) { // disable the db copy if it has been disabled in the skin .ini file + if(cfg::getByte(hContact, "EXTBK", "VALID", 0)) + cfg::writeByte(hContact, "EXTBK", "VALID", 0); + } + } + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + } + free(szSections); + free(items); +} + +void extbk_import(char *file, HWND hwndDlg) +{ + int n, i; + char buffer[255]; + char szKey[255], szSection[255]; + DWORD data, version = 0; + int oldexIconScale = cfg::dat.exIconScale; + + for (n = 0; n <= ID_EXTBK_LAST - ID_STATUS_OFFLINE; n++) { + if (StatusItems[n].statusID != ID_EXTBKSEPARATOR) { + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_ALPHA"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].ALPHA), sizeof(StatusItems[n].ALPHA), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].COLOR), sizeof(StatusItems[n].COLOR), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].COLOR2), sizeof(StatusItems[n].COLOR2), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_COLOR2_TRANSPARENT"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].COLOR2_TRANSPARENT), sizeof(StatusItems[n].COLOR2_TRANSPARENT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_TEXTCOLOR"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].TEXTCOLOR), sizeof(StatusItems[n].TEXTCOLOR), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_CORNER"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].CORNER), sizeof(StatusItems[n].CORNER), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_GRADIENT"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].GRADIENT), sizeof(StatusItems[n].GRADIENT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_IGNORED"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].IGNORED), sizeof(StatusItems[n].IGNORED), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_BOTTOM"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_BOTTOM), sizeof(StatusItems[n].MARGIN_BOTTOM), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_LEFT"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_LEFT), sizeof(StatusItems[n].MARGIN_LEFT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_RIGHT"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_RIGHT), sizeof(StatusItems[n].MARGIN_RIGHT), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_MARGIN_TOP"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].MARGIN_TOP), sizeof(StatusItems[n].MARGIN_TOP), file); + lstrcpyA(buffer, StatusItems[n].szDBname); lstrcatA(buffer, "_BORDERSTYLE"); + GetPrivateProfileStructA("ExtBKSettings", buffer, &(StatusItems[n].BORDERSTYLE), sizeof(StatusItems[n].BORDERSTYLE), file); + } + } + + data = 0; + GetPrivateProfileStructA("Global", "Version", &version, 4, file); + if(version >= 2) { + for (n = 0; n <= FONTID_LAST; n++) { + mir_snprintf(szSection, 255, "Font%d", n); + + mir_snprintf(szKey, 255, "Font%dName", n); + GetPrivateProfileStringA(szSection, "Name", "Arial", buffer, sizeof(buffer), file); + cfg::writeString(NULL, "CLC", szKey, buffer); + + mir_snprintf(szKey, 255, "Font%dSize", n); + data = 0; + GetPrivateProfileStructA(szSection, "Size", &data, 1, file); + cfg::writeByte("CLC", szKey, (BYTE)data); + + mir_snprintf(szKey, 255, "Font%dSty", n); + data = 0; + GetPrivateProfileStructA(szSection, "Style", &data, 1, file); + cfg::writeByte("CLC", szKey, (BYTE)data); + + mir_snprintf(szKey, 255, "Font%dSet", n); + data = 0; + GetPrivateProfileStructA(szSection, "Set", &data, 1, file); + cfg::writeByte("CLC", szKey, (BYTE)data); + + mir_snprintf(szKey, 255, "Font%dCol", n); + data = 0; + GetPrivateProfileStructA(szSection, "Color", &data, 4, file); + cfg::writeDword("CLC", szKey, data); + + mir_snprintf(szKey, 255, "Font%dFlags", n); + data = 0; + GetPrivateProfileStructA(szSection, "Flags", &data, 4, file); + cfg::writeDword("CLC", szKey, (WORD)data); + + mir_snprintf(szKey, 255, "Font%dAs", n); + data = 0; + GetPrivateProfileStructA(szSection, "SameAs", &data, 2, file); + cfg::writeDword("CLC", szKey, (WORD)data); + } + } + i = 0; + if(version >= 3) { + char szString[MAX_PATH]; + szString[0] = 0; + + while(_tagSettings[i].szModule != NULL) { + data = 0; + GetPrivateProfileStructA("Global", _tagSettings[i].szSetting, &data, _tagSettings[i].size, file); + switch(_tagSettings[i].size) { + case 1: + cfg::writeByte(NULL, _tagSettings[i].szModule, _tagSettings[i].szSetting, (BYTE)data); + break; + case 4: + cfg::writeDword(NULL, _tagSettings[i].szModule, _tagSettings[i].szSetting, data); + break; + case 2: + cfg::writeWord( _tagSettings[i].szModule, _tagSettings[i].szSetting, (WORD)data); + break; + } + i++; + } + GetPrivateProfileStringA("Global", "BkBitmap", "", szString, MAX_PATH, file); + if(lstrlenA(szString) > 0) + cfg::writeString(NULL, "CLC", "BkBitmap", szString); + } + + Reload3dBevelColors(); + ReloadThemedOptions(); + // refresh + if(hwndDlg && ServiceExists(MS_CLNSE_FILLBYCURRENTSEL)) + CallService(MS_CLNSE_FILLBYCURRENTSEL, (WPARAM)hwndDlg, 0); + pcli->pfnClcOptionsChanged(); + ConfigureCLUIGeometry(1); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN); + if(oldexIconScale != cfg::dat.exIconScale) { + ImageList_SetIconSize(himlExtraImages, cfg::dat.exIconScale, cfg::dat.exIconScale); + IcoLibReloadIcons(); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + } +} + +static void ApplyCLUISkin() +{ + DBVARIANT dbv = {0}; + TCHAR tszFinalName[MAX_PATH]; + char szFinalName[MAX_PATH]; + if (!cfg::getTString(NULL, "CLC", "AdvancedSkin", &dbv)) { + MY_pathToAbsolute(dbv.ptszVal, tszFinalName); + + WideCharToMultiByte(CP_ACP, 0, tszFinalName, MAX_PATH, szFinalName, MAX_PATH, 0, 0); + + if(cfg::getByte("CLUI", "skin_changed", 0)) { + extbk_import(szFinalName, 0); + SaveCompleteStructToDB(); + cfg::writeByte("CLUI", "skin_changed", 0); + } + IMG_LoadItems(); + ShowWindow(pcli->hwndContactList, SW_SHOWNORMAL); + SetWindowPos(pcli->hwndContactList, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + RedrawWindow(pcli->hwndContactList, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_ERASE); + DBFreeVariant(&dbv); + } +} + +static INT_PTR CALLBACK DlgProcSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + DBVARIANT dbv; + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_EQUALSELECTION, (cfg::getByte("CLCExt", "EXBK_EqualSelection", 1) == 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SELBLEND, cfg::getByte("CLCExt", "EXBK_SelBlend", 1)); + CheckDlgButton(hwndDlg, IDC_SETALLBUTTONSKINNED, cfg::getByte("CLCExt", "bskinned", 0)); + + SendDlgItemMessage(hwndDlg, IDC_CORNERSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0)); + SendDlgItemMessage(hwndDlg, IDC_CORNERSPIN, UDM_SETPOS, 0, cfg::dat.cornerRadius); + + SendDlgItemMessage(hwndDlg, IDC_GRPPADDINGSPIN, UDM_SETRANGE, 0, MAKELONG(20, 0)); + SendDlgItemMessage(hwndDlg, IDC_GRPPADDINGSPIN, UDM_SETPOS, 0, cfg::dat.group_padding); + + SendDlgItemMessage(hwndDlg, IDC_LASTITEMPADDINGSPIN, UDM_SETRANGE, 0, MAKELONG(40, 0)); + SendDlgItemMessage(hwndDlg, IDC_LASTITEMPADDINGSPIN, UDM_SETPOS, 0, cfg::dat.titleBarHeight); + + CheckDlgButton(hwndDlg, IDC_APPLYINDENTBG, cfg::dat.bApplyIndentToBg); + CheckDlgButton(hwndDlg, IDC_USEPERPROTO, cfg::dat.bUsePerProto); + CheckDlgButton(hwndDlg, IDC_OVERRIDEPERSTATUSCOLOR, cfg::dat.bOverridePerStatusColors); + CheckDlgButton(hwndDlg, IDC_FASTGRADIENT, cfg::dat.bWantFastGradients); + CheckDlgButton(hwndDlg, IDC_IGNORESELFORGROUPS, cfg::getByte("CLC", "IgnoreSelforGroups", 0) ? BST_CHECKED : BST_UNCHECKED); + + if (!cfg::getString(NULL, "CLC", "ContactSkins", &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_SKINFILE, dbv.pszVal); + DBFreeVariant(&dbv); + Utils::enableDlgControl(hwndDlg, IDC_RELOAD, TRUE); + } + else + Utils::enableDlgControl(hwndDlg, IDC_RELOAD, FALSE); + CheckDlgButton(hwndDlg, IDC_USESKIN, cfg::getByte("CLUI", "useskin", 0) ? BST_CHECKED : BST_UNCHECKED); + if (!cfg::getTString(NULL, "CLC", "AdvancedSkin", &dbv)) { + SetDlgItemText(hwndDlg, IDC_SKINFILENAME, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + SetDlgItemText(hwndDlg, IDC_SKINFILENAME, _T("")); + return TRUE; + } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_USESKIN: + { + int useskin = IsDlgButtonChecked(hwndDlg, IDC_USESKIN); + + cfg::writeByte("CLUI", "useskin", (BYTE)(useskin ? 1 : 0)); + break; + } + case IDC_UNLOAD: + IMG_DeleteItems(); + ConfigureFrame(); + SendMessage(pcli->hwndContactList, WM_SIZE, 0, 0); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + break; + case IDC_SELECTSKINFILE: + { + OPENFILENAME ofn = {0}; + TCHAR str[MAX_PATH] = _T("*.clist"), final_path[MAX_PATH]; + + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwndDlg; + ofn.hInstance = NULL; + ofn.lpstrFilter = _T("*.clist\0"); + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_DONTADDTORECENT; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = _T(""); + if (!GetOpenFileName(&ofn)) + break; + MY_pathToRelative(str, final_path); + if(PathFileExists(str)) { + int skinChanged = 0; + DBVARIANT dbv = {0}; + + if (!cfg::getTString(NULL, "CLC", "AdvancedSkin", &dbv)) { + if(_tcscmp(dbv.ptszVal, final_path)) + skinChanged = TRUE; + DBFreeVariant(&dbv); + } + else + skinChanged = TRUE; + cfg::writeTString(NULL, "CLC", "AdvancedSkin", final_path); + cfg::writeByte("CLUI", "skin_changed", (BYTE)skinChanged); + SetDlgItemText(hwndDlg, IDC_SKINFILENAME, final_path); + } + break; + } + case IDC_RELOADSKIN: + cfg::writeByte("CLUI", "skin_changed", 1); + ApplyCLUISkin(); + break; + case IDC_RELOAD: + { + TCHAR tszFilename[MAX_PATH], tszFinalPath[MAX_PATH]; + + GetDlgItemText(hwndDlg, IDC_SKINFILE, tszFilename, MAX_PATH); + tszFilename[MAX_PATH - 1] = 0; + MY_pathToAbsolute(tszFilename, tszFinalPath); + if(PathFileExists(tszFinalPath)) { + LoadPerContactSkins(tszFinalPath); + ReloadSkinItemsToCache(); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + } + break; + } + } + if ((LOWORD(wParam) == IDC_SKINFILE || LOWORD(wParam) == IDC_SKINFILENAME) + && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return 0; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + SaveNonStatusItemsSettings(hwndDlg); + pcli->pfnClcOptionsChanged(); + PostMessage(pcli->hwndContactList, CLUIINTM_REDRAW, 0, 0); + return TRUE; + } + break; + } + break; + } + return FALSE; +} + +INT_PTR CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int iInit = TRUE; + static HWND hwndSkinEdit = 0; + + switch(msg) + { + case WM_INITDIALOG: + { + TCITEM tci; + RECT rcClient; + int oPage = cfg::getByte("CLUI", "opage", 0); + SKINDESCRIPTION sd; + + TranslateDialogDefault(hwnd); + GetClientRect(hwnd, &rcClient); + iInit = TRUE; + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(g_hInst,MAKEINTRESOURCE(IDD_OPT_SKIN), hwnd, DlgProcSkinOpts); + tci.pszText = TranslateT("Load and apply"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 0, &tci); + MoveWindow((HWND)tci.lParam,5,25,rcClient.right-9,rcClient.bottom-60,1); + ShowWindow((HWND)tci.lParam, oPage == 0 ? SW_SHOW : SW_HIDE); + if(IS_THEMED) + API::pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); + + if(ServiceExists(MS_CLNSE_INVOKE)) { + ZeroMemory(&sd, sizeof(sd)); + sd.cbSize = sizeof(sd); + sd.StatusItems = StatusItems; + sd.hWndParent = hwnd; + sd.hWndTab = GetDlgItem(hwnd, IDC_OPTIONSTAB); + sd.pfnSaveCompleteStruct = SaveCompleteStructToDB; + sd.lastItem = ID_EXTBK_LAST; + sd.firstItem = ID_STATUS_OFFLINE; + sd.pfnClcOptionsChanged = pcli->pfnClcOptionsChanged; + sd.hwndCLUI = pcli->hwndContactList; + hwndSkinEdit = (HWND)CallService(MS_CLNSE_INVOKE, 0, (LPARAM)&sd); + } + + if(hwndSkinEdit) { + ShowWindow(hwndSkinEdit, oPage == 1 ? SW_SHOW : SW_HIDE); + TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB), oPage); + if(IS_THEMED) + API::pfnEnableThemeDialogTexture(hwndSkinEdit, ETDT_ENABLETAB); + } + + TabCtrl_SetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB), oPage); + Utils::enableDlgControl(hwnd, IDC_EXPORT, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0); + Utils::enableDlgControl(hwnd, IDC_IMPORT, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0); + iInit = FALSE; + return FALSE; + } + + case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0); + if (!iInit) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_EXPORT: + { + char str[MAX_PATH] = "*.clist"; + OPENFILENAMEA ofn = {0}; + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwnd; + ofn.hInstance = NULL; + ofn.lpstrFilter = "*.clist"; + ofn.lpstrFile = str; + ofn.Flags = OFN_HIDEREADONLY; + ofn.nMaxFile = sizeof(str); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = "clist"; + if (!GetSaveFileNameA(&ofn)) + break; + extbk_export(str); + break; + } + case IDC_IMPORT: + { + char str[MAX_PATH] = "*.clist"; + OPENFILENAMEA ofn = {0}; + + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = hwnd; + ofn.hInstance = NULL; + ofn.lpstrFilter = "*.clist"; + ofn.lpstrFile = str; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.nMaxFile = sizeof(str); + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = ""; + if (!GetOpenFileNameA(&ofn)) + break; + extbk_import(str, hwndSkinEdit); + SendMessage(hwndSkinEdit, WM_USER + 101, 0, 0); + break; + } + } + break; + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + { + TCITEM tci; + int i,count; + tci.mask = TCIF_PARAM; + count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_OPTIONSTAB)); + for (i=0;icode) { + case TCN_SELCHANGING: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_HIDE); + } + break; + case TCN_SELCHANGE: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_SHOW); + cfg::writeByte("CLUI", "opage", (BYTE)TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB))); + Utils::enableDlgControl(hwnd, IDC_EXPORT, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0); + Utils::enableDlgControl(hwnd, IDC_IMPORT, TabCtrl_GetCurSel(GetDlgItem(hwnd, IDC_OPTIONSTAB)) != 0); + } + break; + } + break; + + } + break; + case WM_DESTROY: + hwndSkinEdit = 0; + break; + } + return FALSE; +} + +int CoolSB_SetupScrollBar() +{ + /* + * a skinned scrollbar is only valid when ALL items are skinned with image items + * and no item is set to ignored + */ + + cfg::dat.bSkinnedScrollbar = !StatusItems[ID_EXTBKSCROLLBACK - ID_STATUS_OFFLINE].IGNORED && + !StatusItems[ID_EXTBKSCROLLBACKLOWER - ID_STATUS_OFFLINE].IGNORED && + !StatusItems[ID_EXTBKSCROLLTHUMB - ID_STATUS_OFFLINE].IGNORED && + !StatusItems[ID_EXTBKSCROLLTHUMBHOVER - ID_STATUS_OFFLINE].IGNORED && + !StatusItems[ID_EXTBKSCROLLTHUMBPRESSED - ID_STATUS_OFFLINE].IGNORED && + !StatusItems[ID_EXTBKSCROLLBUTTON - ID_STATUS_OFFLINE].IGNORED && + !StatusItems[ID_EXTBKSCROLLBUTTONHOVER - ID_STATUS_OFFLINE].IGNORED && + !StatusItems[ID_EXTBKSCROLLBUTTONPRESSED - ID_STATUS_OFFLINE].IGNORED; + + + if (!StatusItems[ID_EXTBKSCROLLBACK - ID_STATUS_OFFLINE].imageItem || + !StatusItems[ID_EXTBKSCROLLBACKLOWER - ID_STATUS_OFFLINE].imageItem || + !StatusItems[ID_EXTBKSCROLLTHUMB - ID_STATUS_OFFLINE].imageItem || + !StatusItems[ID_EXTBKSCROLLTHUMBHOVER - ID_STATUS_OFFLINE].imageItem || + !StatusItems[ID_EXTBKSCROLLTHUMBPRESSED - ID_STATUS_OFFLINE].imageItem || + !StatusItems[ID_EXTBKSCROLLBUTTON - ID_STATUS_OFFLINE].imageItem || + !StatusItems[ID_EXTBKSCROLLBUTTONHOVER - ID_STATUS_OFFLINE].imageItem || + !StatusItems[ID_EXTBKSCROLLBUTTONPRESSED - ID_STATUS_OFFLINE].imageItem) + + cfg::dat.bSkinnedScrollbar = FALSE; + + if(cfg::getByte("CLC", "NoVScrollBar", 0)) { + UninitializeCoolSB(pcli->hwndContactTree); + return 0; + } + + if(cfg::dat.bSkinnedScrollbar) { + InitializeCoolSB(pcli->hwndContactTree); + CoolSB_SetStyle(pcli->hwndContactTree, SB_VERT, CSBS_HOTTRACKED); + } + else UninitializeCoolSB(pcli->hwndContactTree); + return 0; +} diff --git a/plugins/Clist_nicer/src/init.cpp b/plugins/Clist_nicer/src/init.cpp new file mode 100644 index 0000000000..ee95e2e701 --- /dev/null +++ b/plugins/Clist_nicer/src/init.cpp @@ -0,0 +1,386 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: init.cpp 13596 2011-04-15 19:07:23Z george.hazan $ + * + */ + +#include +#include "../cluiframes/cluiframes.h" + +HINSTANCE g_hInst = 0; +CLIST_INTERFACE* pcli = NULL; +int hLangpack; + +#define DEFAULT_TB_VISIBILITY (1 | 2 | 4 | 8 | 16 | 32 | 64 | 8192) +TCHAR *szNoevents = _T("No events..."); +//extern HICON im_clienthIcons[NR_CLIENTS]; +extern HICON overlayicons[10]; + +extern int Docking_ProcessWindowMessage(WPARAM wParam, LPARAM lParam); +extern int SetHideOffline(WPARAM wParam, LPARAM lParam); + +extern DWORD g_gdiplusToken; +extern HIMAGELIST himlExtraImages; + +TIME_API tmi; + +HMENU BuildGroupPopupMenu( struct ClcGroup* group ); +struct ClcContact* CreateClcContact( void ); +struct CListEvent* fnCreateEvent( void ); +void ReloadThemedOptions(); +void TrayIconUpdateBase(const char *szChangedProto); +void RegisterCLUIFrameClasses(); +void LoadButtonModule(); + +void GetDefaultFontSetting(int i, LOGFONT *lf, COLORREF *colour); +int GetWindowVisibleState(HWND hWnd, int iStepX, int iStepY); +int ShowHide(WPARAM wParam, LPARAM lParam); +int ClcShutdown(WPARAM wParam, LPARAM lParam); + +void ( *saveLoadClcOptions )(HWND hwnd,struct ClcData *dat); +void LoadClcOptions(HWND hwnd,struct ClcData *dat); + +int ( *saveAddContactToGroup )(struct ClcData *dat, struct ClcGroup *group, HANDLE hContact); +int AddContactToGroup(struct ClcData *dat, struct ClcGroup *group, HANDLE hContact); + +struct ClcGroup* ( *saveRemoveItemFromGroup )(HWND hwnd, struct ClcGroup *group, struct ClcContact *contact, int updateTotalCount); +struct ClcGroup* RemoveItemFromGroup(HWND hwnd, struct ClcGroup *group, struct ClcContact *contact, int updateTotalCount); + +struct CListEvent* ( *saveAddEvent )(CLISTEVENT *cle); +struct CListEvent* AddEvent(CLISTEVENT *cle); + +int ( *saveAddInfoItemToGroup )(struct ClcGroup *group, int flags, const TCHAR *pszText); +int AddInfoItemToGroup(struct ClcGroup *group, int flags, const TCHAR *pszText); + +struct ClcGroup* ( *saveAddGroup )(HWND hwnd, struct ClcData *dat, const TCHAR *szName, DWORD flags, int groupId, int calcTotalMembers); +struct ClcGroup* AddGroup(HWND hwnd, struct ClcData *dat, const TCHAR *szName, DWORD flags, int groupId, int calcTotalMembers); + +LRESULT ( CALLBACK *saveContactListWndProc )(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK ContactListWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + +LRESULT ( CALLBACK *saveContactListControlWndProc )(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +int ( *saveIconFromStatusMode )( const char *szProto, int status, HANDLE hContact ); + +LRESULT ( *saveProcessExternalMessages )(HWND hwnd, struct ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT ProcessExternalMessages(HWND hwnd, struct ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam); + +int ( *saveRemoveEvent )(HANDLE hContact, HANDLE hDbEvent); +int RemoveEvent(HANDLE hContact, HANDLE hDbEvent); + +INT_PTR ( *saveTrayIconProcessMessage )(WPARAM wParam, LPARAM lParam); +INT_PTR TrayIconProcessMessage(WPARAM wParam, LPARAM lParam); + +void ( *saveRecalcScrollBar )(HWND hwnd, struct ClcData *dat); +void RecalcScrollBar(HWND hwnd, struct ClcData *dat); + +PLUGININFOEX pluginInfo = +{ + sizeof(PLUGININFOEX), + "CList Nicer+", + PLUGIN_MAKE_VERSION(0, 9, 2, 1), + "Display contacts, event notifications, protocol status", + "Pixel, egoDust, cyreve, Nightwish", + "", + "Copyright 2000-2010 Miranda-IM project", + "http://miranda-ng.org/", + UNICODE_AWARE, + // {8F79B4EE-EB48-4a03-873E-27BE6B7E9A25} + {0x8f79b4ee, 0xeb48, 0x4a03, { 0x87, 0x3e, 0x27, 0xbe, 0x6b, 0x7e, 0x9a, 0x25 }} +}; + + +void _DebugTraceW(const wchar_t *fmt, ...) +{ +#ifdef _DEBUG + wchar_t debug[2048]; + int ibsize = 2047; + va_list va; + va_start(va, fmt); + + lstrcpyW(debug, L"CLN: "); + + _vsnwprintf(&debug[5], ibsize - 10, fmt, va); + OutputDebugStringW(debug); +#endif +} + + +void _DebugTraceA(const char *fmt, ...) +{ + char debug[2048]; + int ibsize = 2047; + va_list va; + va_start(va, fmt); + + lstrcpyA(debug, "CLN: "); + _vsnprintf(&debug[5], ibsize - 10, fmt, va); +#ifdef _DEBUG + OutputDebugStringA(debug); +#else + { + char szLogFileName[MAX_PATH], szDataPath[MAX_PATH]; + FILE *f; + + CallService(MS_DB_GETPROFILEPATH, MAX_PATH, (LPARAM)szDataPath); + mir_snprintf(szLogFileName, MAX_PATH, "%s\\%s", szDataPath, "clist_nicer.log"); + f = fopen(szLogFileName, "a+"); + if(f) { + fputs(debug, f); + fputs("\n", f); + fclose(f); + } + } +#endif +} + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) +{ + g_hInst = hInstDLL; + DisableThreadLibraryCalls(g_hInst); + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX * MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_CLIST, MIID_LAST}; + +int LoadContactListModule(void); +int LoadCLCModule(void); +void LoadCLUIModule( void ); +void OnCreateClc( void ); + +static int systemModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + GetSystemTime(&cfg::dat.st); + SystemTimeToFileTime(&cfg::dat.st, &cfg::dat.ft); + cfg::dat.bMetaAvail = ServiceExists(MS_MC_GETDEFAULTCONTACT) ? TRUE : FALSE; + if(cfg::dat.bMetaAvail) + mir_snprintf(cfg::dat.szMetaName, 256, "%s", (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0)); + else + strncpy(cfg::dat.szMetaName, "MetaContacts", 255); + + if(ServiceExists(MS_MC_DISABLEHIDDENGROUP)) + CallService(MS_MC_DISABLEHIDDENGROUP, 1, 0); + cfg::dat.bMetaEnabled = cfg::getByte(cfg::dat.szMetaName, "Enabled", 1); + + cfg::dat.bAvatarServiceAvail = ServiceExists(MS_AV_GETAVATARBITMAP) ? TRUE : FALSE; + if(cfg::dat.bAvatarServiceAvail) + HookEvent(ME_AV_AVATARCHANGED, AvatarChanged); + cfg::dat.tabSRMM_Avail = ServiceExists("SRMsg_MOD/GetWindowFlags") ? TRUE : FALSE; + + ZeroMemory((void *)overlayicons, sizeof(HICON) * 10); + + CLN_LoadAllIcons(1); + return 0; +} + +static int fnIconFromStatusMode( const char* szProto, int status, HANDLE hContact ) +{ return IconFromStatusMode( szProto, status, hContact, NULL ); +} + +extern "C" int __declspec(dllexport) CListInitialise() +{ + int rc = 0; + DBVARIANT dbv; + int i; + char szProfilePath[MAX_PATH]; + + mir_getTMI(&tmi); + mir_getLP( &pluginInfo ); + + API::onInit(); + RegisterCLUIFrameClasses(); + + ZeroMemory((void*) &cfg::dat, sizeof(cfg::dat)); + + int iCount = CallService(MS_DB_CONTACT_GETCOUNT, 0, 0); + + iCount += 20; + if ( iCount < 300 ) + iCount = 300; + + cfg::eCache = reinterpret_cast(malloc(sizeof(TExtraCache) * iCount)); + ZeroMemory(cfg::eCache, sizeof(struct TExtraCache) * iCount); + cfg::nextCacheEntry = 0; + cfg::maxCacheEntry = iCount; + cfg::init(); + + cfg::dat.hMenuNotify = CreatePopupMenu(); + cfg::dat.wNextMenuID = 1; + cfg::dat.sortTimer = cfg::getDword("CLC", "SortTimer", 150); + cfg::dat.szNoEvents = TranslateTS(szNoevents); + cfg::dat.avatarBorder = (COLORREF)cfg::getDword("CLC", "avatarborder", 0); + cfg::dat.avatarRadius = (COLORREF)cfg::getDword("CLC", "avatarradius", 4); + cfg::dat.hBrushAvatarBorder = CreateSolidBrush(cfg::dat.avatarBorder); + cfg::dat.avatarSize = cfg::getWord("CList", "AvatarSize", 24); + cfg::dat.dualRowMode = cfg::getByte("CLC", "DualRowMode", 0); + cfg::dat.avatarPadding = cfg::getByte("CList", "AvatarPadding", 0); + cfg::dat.isTransparent = cfg::getByte("CList", "Transparent", 0); + cfg::dat.alpha = cfg::getByte("CList", "Alpha", SETTING_ALPHA_DEFAULT); + cfg::dat.autoalpha = cfg::getByte("CList", "AutoAlpha", SETTING_ALPHA_DEFAULT); + cfg::dat.fadeinout = cfg::getByte("CLUI", "FadeInOut", 0); + cfg::dat.autosize = cfg::getByte("CLUI", "AutoSize", 0); + cfg::dat.dwExtraImageMask = cfg::getDword("CLUI", "ximgmask", 0); + cfg::dat.bNoOfflineAvatars = cfg::getByte("CList", "NoOfflineAV", 1); + cfg::dat.bFullTransparent = cfg::getByte("CLUI", "fulltransparent", 0); + cfg::dat.bDblClkAvatars = cfg::getByte("CLC", "dblclkav", 0); + cfg::dat.bEqualSections = cfg::getByte("CLUI", "EqualSections", 0); + cfg::dat.bCenterStatusIcons = cfg::getByte("CLC", "si_centered", 1); + cfg::dat.boldHideOffline = -1; + cfg::dat.bSecIMAvail = ServiceExists("SecureIM/IsContactSecured") ? 1 : 0; + cfg::dat.bNoTrayTips = cfg::getByte("CList", "NoTrayTips", 0); + cfg::dat.bShowLocalTime = cfg::getByte("CLC", "ShowLocalTime", 1); + cfg::dat.bShowLocalTimeSelective = cfg::getByte("CLC", "SelectiveLocalTime", 1); + cfg::dat.bDontSeparateOffline = cfg::getByte("CList", "DontSeparateOffline", 0); + cfg::dat.bShowXStatusOnSbar = cfg::getByte("CLUI", "xstatus_sbar", 0); + cfg::dat.bLayeredHack = cfg::getByte("CLUI", "layeredhack", 1); + cfg::dat.bFirstRun = cfg::getByte("CLUI", "firstrun", 1); + cfg::dat.langPackCP = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); + cfg::dat.realTimeSaving = cfg::getByte("CLUI", "save_pos_always", 0); + + DWORD sortOrder = cfg::getDword("CList", "SortOrder", SORTBY_NAME); + cfg::dat.sortOrder[0] = LOBYTE(LOWORD(sortOrder)); + cfg::dat.sortOrder[1] = HIBYTE(LOWORD(sortOrder)); + cfg::dat.sortOrder[2] = LOBYTE(HIWORD(sortOrder)); + + if(cfg::dat.bFirstRun) + cfg::writeByte("CLUI", "firstrun", 0); + + if (!cfg::getString(NULL, "CLUI", "exIconOrder", &dbv)) { + if(lstrlenA(dbv.pszVal) < EXICON_COUNT) { + for (i = 1; i <= EXICON_COUNT; i++) + cfg::dat.exIconOrder[i - 1] = i; + } else { + for (i = 0; i < EXICON_COUNT; i++) + if(dbv.pszVal[i] < EXICON_COUNT+1 && dbv.pszVal[i] >0) + cfg::dat.exIconOrder[i] = dbv.pszVal[i]; + else + cfg::dat.exIconOrder[i] = i+1; + } + DBFreeVariant(&dbv); + } else { + for (i = 1; i <= EXICON_COUNT; i++) + cfg::dat.exIconOrder[i - 1] = i; + } + ReloadThemedOptions(); + FLT_ReadOptions(); + Reload3dBevelColors(); + himlExtraImages = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 30, 2); + ImageList_SetIconSize(himlExtraImages, cfg::dat.exIconScale, cfg::dat.exIconScale); + + cfg::dat.dwFlags = cfg::getDword("CLUI", "Frameflags", CLUI_FRAME_STATUSICONS | CLUI_FRAME_SHOWBOTTOMBUTTONS | + CLUI_FRAME_BUTTONSFLAT | CLUI_FRAME_CLISTSUNKEN); + cfg::dat.dwFlags |= (cfg::getByte("CLUI", "ShowSBar", 1) ? CLUI_FRAME_SBARSHOW : 0); + cfg::dat.soundsOff = cfg::getByte("CLUI", "NoSounds", 0); + + CallService(MS_DB_GETPROFILEPATH, MAX_PATH, (LPARAM)szProfilePath); + + MultiByteToWideChar(CP_ACP, 0, szProfilePath, MAX_PATH, cfg::dat.tszProfilePath, MAX_PATH); + cfg::dat.tszProfilePath[MAX_PATH - 1] = 0; + + _tcslwr(cfg::dat.tszProfilePath); + + // get the clist interface + pcli = ( CLIST_INTERFACE* )CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)g_hInst); + if ( (INT_PTR)pcli == CALLSERVICE_NOTFOUND ) { +LBL_Error: + MessageBoxA( NULL, "This plugin requires Miranda IM 0.8.0.9 or later", "Fatal error", MB_OK ); + return 1; + } + if ( pcli->version < 6 ) // don't join it with the previous if () + goto LBL_Error; + + pcli->pfnBuildGroupPopupMenu = BuildGroupPopupMenu; + pcli->pfnCluiProtocolStatusChanged = CluiProtocolStatusChanged; + pcli->pfnCompareContacts = CompareContacts; + pcli->pfnCreateClcContact = CreateClcContact; + pcli->pfnCreateEvent = fnCreateEvent; + pcli->pfnDocking_ProcessWindowMessage = Docking_ProcessWindowMessage; + pcli->pfnGetDefaultFontSetting = GetDefaultFontSetting; + pcli->pfnGetRowBottomY = RowHeight::getItemBottomY; + pcli->pfnGetRowHeight = RowHeight::getHeight; + pcli->pfnGetRowTopY = RowHeight::getItemTopY; + pcli->pfnGetRowTotalHeight = RowHeight::getTotalHeight; + pcli->pfnGetWindowVisibleState = GetWindowVisibleState; + pcli->pfnHitTest = HitTest; + pcli->pfnLoadContactTree = LoadContactTree; + pcli->pfnOnCreateClc = OnCreateClc; + pcli->pfnPaintClc = PaintClc; + pcli->pfnRebuildEntireList = RebuildEntireList; + pcli->pfnRowHitTest = RowHeight::hitTest; + pcli->pfnScrollTo = ScrollTo; + pcli->pfnTrayIconUpdateBase = TrayIconUpdateBase; + pcli->pfnSetHideOffline = SetHideOffline; + pcli->pfnShowHide = ShowHide; + + saveAddContactToGroup = pcli->pfnAddContactToGroup; pcli->pfnAddContactToGroup = AddContactToGroup; + saveRemoveItemFromGroup = pcli->pfnRemoveItemFromGroup; pcli->pfnRemoveItemFromGroup = RemoveItemFromGroup; + + saveAddEvent = pcli->pfnAddEvent; pcli->pfnAddEvent = AddEvent; + saveRemoveEvent = pcli->pfnRemoveEvent; pcli->pfnRemoveEvent = RemoveEvent; + + saveAddGroup = pcli->pfnAddGroup; pcli->pfnAddGroup = AddGroup; + saveAddInfoItemToGroup = pcli->pfnAddInfoItemToGroup; pcli->pfnAddInfoItemToGroup = AddInfoItemToGroup; + saveContactListControlWndProc = pcli->pfnContactListControlWndProc; pcli->pfnContactListControlWndProc = ContactListControlWndProc; + saveContactListWndProc = pcli->pfnContactListWndProc; pcli->pfnContactListWndProc = ContactListWndProc; + saveIconFromStatusMode = pcli->pfnIconFromStatusMode; pcli->pfnIconFromStatusMode = fnIconFromStatusMode; + saveLoadClcOptions = pcli->pfnLoadClcOptions; pcli->pfnLoadClcOptions = LoadClcOptions; + saveProcessExternalMessages = pcli->pfnProcessExternalMessages; pcli->pfnProcessExternalMessages = ProcessExternalMessages; + saveRecalcScrollBar = pcli->pfnRecalcScrollBar; pcli->pfnRecalcScrollBar = RecalcScrollBar; + saveTrayIconProcessMessage = pcli->pfnTrayIconProcessMessage; pcli->pfnTrayIconProcessMessage = TrayIconProcessMessage; + + rc = LoadContactListModule(); + if (rc == 0) + rc = LoadCLCModule(); + LoadCLUIModule(); + LoadButtonModule(); + HookEvent(ME_SYSTEM_MODULESLOADED, systemModulesLoaded); + return rc; +} + +// a plugin loader aware of CList exports will never call this. +extern "C" int __declspec(dllexport) Load(void) +{ + return 1; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + if (IsWindow(pcli->hwndContactList)) + DestroyWindow(pcli->hwndContactList); + ImageList_Destroy(himlExtraImages); + ClcShutdown(0, 0); + UnLoadCLUIFramesModule(); + return 0; +} diff --git a/plugins/Clist_nicer/src/rowheight_funcs.cpp b/plugins/Clist_nicer/src/rowheight_funcs.cpp new file mode 100644 index 0000000000..25a7b6b68d --- /dev/null +++ b/plugins/Clist_nicer/src/rowheight_funcs.cpp @@ -0,0 +1,287 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 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. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: rowheight_funcs.cpp 12484 2010-08-27 04:02:43Z silvercircle $ + * + */ + +#include +#include + +BOOL RowHeight::Init(ClcData *dat) +{ + dat->rowHeight = 0; + dat->row_heights_size = 0; + dat->row_heights_allocated = 0; + dat->row_heights = NULL; + + return TRUE; +} + +void RowHeight::Free(ClcData *dat) +{ + if (dat->row_heights != NULL) + { + free(dat->row_heights); + dat->row_heights = NULL; + } + + dat->row_heights_allocated = 0; + dat->row_heights_size = 0; +} + +void RowHeight::Clear(ClcData *dat) +{ + dat->row_heights_size = 0; +} + + +BOOL RowHeight::Alloc(ClcData *dat, int size) +{ + if (size > dat->row_heights_size) + { + if (size > dat->row_heights_allocated) { + int size_grow = size; + + size_grow += 100 - (size_grow % 100); + + if (dat->row_heights != NULL) { + int *tmp = (int *) realloc((void *)dat->row_heights, sizeof(int) * size_grow); + + if (tmp == NULL) { + Free(dat); + return FALSE; + } + + dat->row_heights = tmp; + } + else { + dat->row_heights = (int *) malloc(sizeof(int) * size_grow); + + if (dat->row_heights == NULL) { + Free(dat); + return FALSE; + } + } + dat->row_heights_allocated = size_grow; + } + dat->row_heights_size = size; + } + return TRUE; +} + +// Calc and store max row height +int RowHeight::getMaxRowHeight(ClcData *dat, const HWND hwnd) +{ + int max_height = 0, i; + DWORD style=GetWindowLongPtr(hwnd,GWL_STYLE); + + int contact_fonts[] = {FONTID_CONTACTS, FONTID_INVIS, FONTID_OFFLINE, FONTID_NOTONLIST, FONTID_OFFINVIS}; + int other_fonts[] = {FONTID_GROUPS, FONTID_GROUPCOUNTS, FONTID_DIVIDERS}; + + // Get contact font size + for (i = 0 ; i < MAX_REGS(contact_fonts) ; i++) + { + if (max_height < dat->fontInfo[contact_fonts[i]].fontHeight) + max_height = dat->fontInfo[contact_fonts[i]].fontHeight; + } + + if (cfg::dat.dualRowMode == 1 && !dat->bisEmbedded) + max_height += ROW_SPACE_BEETWEEN_LINES + dat->fontInfo[FONTID_STATUS].fontHeight; + + // Get other font sizes + for (i = 0 ; i < MAX_REGS(other_fonts) ; i++) { + if (max_height < dat->fontInfo[other_fonts[i]].fontHeight) + max_height = dat->fontInfo[other_fonts[i]].fontHeight; + } + + // Avatar size + if (cfg::dat.dwFlags & CLUI_FRAME_AVATARS && !dat->bisEmbedded) + max_height = max(max_height, cfg::dat.avatarSize + cfg::dat.avatarPadding); + + // Checkbox size + if (style&CLS_CHECKBOXES || style&CLS_GROUPCHECKBOXES) + max_height = max(max_height, dat->checkboxSize); + + //max_height += 2 * dat->row_border; + // Min size + max_height = max(max_height, dat->min_row_heigh); + max_height += cfg::dat.bRowSpacing; + + dat->rowHeight = max_height; + + return max_height; +} + +// Calc and store row height for all itens in the list +void RowHeight::calcRowHeights(ClcData *dat, HWND hwnd) +{ + int indent, subindex, line_num; + struct ClcContact *Drawing; + struct ClcGroup *group; + DWORD dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + + // Draw lines + group=&dat->list; + group->scanIndex=0; + indent=0; + //subindex=-1; + line_num = -1; + + Clear(dat); + + while(TRUE) + { + if (group->scanIndex==group->cl.count) + { + group=group->parent; + indent--; + if(group==NULL) break; // Finished list + group->scanIndex++; + continue; + } + + // Get item to draw + Drawing = group->cl.items[group->scanIndex]; + line_num++; + + // Calc row height + getRowHeight(dat, hwnd, Drawing, line_num, dwStyle); + + if(group->cl.items[group->scanIndex]->type==CLCIT_GROUP && /*!IsBadCodePtr((FARPROC)group->cl.items[group->scanIndex]->group) && */ (group->cl.items[group->scanIndex]->group->expanded & 0x0000ffff)) { + group=group->cl.items[group->scanIndex]->group; + indent++; + group->scanIndex=0; + subindex=-1; + continue; + } + group->scanIndex++; + } +} + + +// Calc item top Y (using stored data) +int RowHeight::getItemTopY(ClcData *dat, int item) +{ + int i; + int y = 0; + + if (item >= dat->row_heights_size) + return -1; + + for (i = 0 ; i < item ; i++) + { + y += dat->row_heights[i]; + } + + return y; +} + + +// Calc item bottom Y (using stored data) +int RowHeight::getItemBottomY(ClcData *dat, int item) +{ + int i; + int y = 0; + + if (item >= dat->row_heights_size) + return -1; + + for (i = 0 ; i <= item ; i++) + { + y += dat->row_heights[i]; + } + + return y; +} + + +// Calc total height of rows (using stored data) +int RowHeight::getTotalHeight(ClcData *dat) +{ + int i; + int y = 0; + + for (i = 0 ; i < dat->row_heights_size ; i++) + { + y += dat->row_heights[i]; + } + + return y; +} + +// Return the line that pos_y is at or -1 (using stored data) +int RowHeight::hitTest(ClcData *dat, int pos_y) +{ + int i; + int y = 0; + + if (pos_y < 0) + return -1; + + for (i = 0 ; i < dat->row_heights_size ; i++) + { + y += dat->row_heights[i]; + + if (pos_y < y) + return i; + } + + return -1; +} + +int RowHeight::getHeight(ClcData *dat, int item) +{ + if ( dat->row_heights == 0 ) + return 0; + + return dat->row_heights[ item ]; +} + +int RowHeight::getFloatingRowHeight(const ClcData *dat, HWND hwnd, ClcContact *contact, DWORD dwFlags) +{ + int height = 0; + + height = dat->fontInfo[GetBasicFontID(contact)].fontHeight; + + if (!dat->bisEmbedded) { + if (!(dwFlags & FLT_SIMPLE)) { + if(dwFlags & FLT_DUALROW) { + height += (dat->fontInfo[FONTID_STATUS].fontHeight + cfg::dat.avatarPadding); + } + // Avatar size + if (dwFlags & FLT_AVATARS && contact->cFlags & ECF_AVATAR && contact->type == CLCIT_CONTACT && contact->ace != NULL && !(contact->ace->dwFlags & AVS_HIDEONCLIST)) + height = max(height, cfg::dat.avatarSize + cfg::dat.avatarPadding); + } + } + + height = max(height, dat->min_row_heigh); + height += cfg::dat.bRowSpacing; + + return height; +} diff --git a/plugins/Clist_nicer/src/statusbar.cpp b/plugins/Clist_nicer/src/statusbar.cpp new file mode 100644 index 0000000000..09036b2ed7 --- /dev/null +++ b/plugins/Clist_nicer/src/statusbar.cpp @@ -0,0 +1,197 @@ +/* +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 +#include "../CLUIFrames/cluiframes.h" + +WNDPROC OldStatusBarProc = 0; + +static POINT ptMouse = {0}; +static RECT rcMouse = {0}; +static int timer_set = 0, tooltip_active = 0; +extern HANDLE hStatusBarShowToolTipEvent, hStatusBarHideToolTipEvent; +extern StatusItems_t *StatusItems; +extern HBRUSH g_CLUISkinnedBkColor; + +extern HANDLE (WINAPI *MyOpenThemeData)(HWND, LPCWSTR); +extern HRESULT (WINAPI *MyCloseThemeData)(HANDLE); +extern HRESULT (WINAPI *MyDrawThemeBackground)(HANDLE, HDC, int, int, const RECT *, const RECT *); + +#define TIMERID_HOVER 1000 + +LRESULT CALLBACK NewStatusBarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_SETCURSOR: + { + POINT pt; + + GetCursorPos(&pt); + SendMessage(GetParent(hwnd),msg,wParam,lParam); + if (pt.x == ptMouse.x && pt.y == ptMouse.y) + return 1;//return(TestCursorOnBorders()); + + ptMouse = pt; + if (tooltip_active){ + KillTimer(hwnd, TIMERID_HOVER); + if (!NotifyEventHooks(hStatusBarHideToolTipEvent, 0, 0)) + CallService("mToolTip/HideTip", 0, 0); + tooltip_active = FALSE; + } + KillTimer(hwnd, TIMERID_HOVER); + SetTimer(hwnd, TIMERID_HOVER, 750, 0); + break; + } + case WM_NCHITTEST: + { + LRESULT lr = SendMessage(GetParent(hwnd), WM_NCHITTEST, wParam, lParam); + if(lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT + || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT) + return HTTRANSPARENT; + break; + } + case WM_ERASEBKGND: + if(cfg::dat.bSkinnedStatusBar) + return 1; + return CallWindowProc(OldStatusBarProc, hwnd, msg, wParam, lParam); + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + KillTimer(hwnd, TIMERID_HOVER); + if (!NotifyEventHooks(hStatusBarHideToolTipEvent, 0, 0)) + CallService("mToolTip/HideTip", 0, 0); + tooltip_active = FALSE; + break; + + case WM_PAINT: + if(cfg::shutDown || !StatusItems) + return 0; + + if(cfg::dat.bSkinnedStatusBar) { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hbmMem, hbmOld; + RECT rcClient, rcWindow; + StatusItems_t *item = NULL; + DRAWITEMSTRUCT dis = {0}; + int nParts = 0; + int i; + HFONT hOldFont = 0; + POINT pt; + BYTE windowStyle = cfg::getByte("CLUI", "WindowStyle", SETTING_WINDOWSTYLE_DEFAULT); + LONG b_offset = cfg::dat.bClipBorder + (windowStyle == SETTING_WINDOWSTYLE_NOBORDER ? 2 : (windowStyle == SETTING_WINDOWSTYLE_THINBORDER ? 1 : 0)); + + GetClientRect(hwnd, &rcClient); + GetWindowRect(hwnd, &rcWindow); + pt.x = rcWindow.left; + pt.y = rcWindow.top; + ScreenToClient(pcli->hwndContactList, &pt); + + hbmMem = CreateCompatibleBitmap(hdc, rcClient.right, rcClient.bottom); + hbmOld = reinterpret_cast(SelectObject(hdcMem, hbmMem)); + SetBkMode(hdcMem, TRANSPARENT); + hOldFont = reinterpret_cast(SelectObject(hdcMem, GetStockObject(DEFAULT_GUI_FONT))); + BitBlt(hdcMem, 0, 0, rcClient.right, rcClient.bottom, cfg::dat.hdcBg, pt.x, pt.y, SRCCOPY); + item = &StatusItems[ID_EXTBKSTATUSBAR - ID_STATUS_OFFLINE]; + if (!item->IGNORED) { + RECT rc = rcClient; + rc.left += item->MARGIN_LEFT; + rc.right -= item->MARGIN_RIGHT; + rc.top += item->MARGIN_TOP; + rc.bottom -= item->MARGIN_BOTTOM; + DrawAlpha(hdcMem, &rc, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, item->GRADIENT, + item->CORNER, item->BORDERSTYLE, item->imageItem); + SetTextColor(hdcMem, item->TEXTCOLOR); + }else{ + SetTextColor(hdcMem, GetSysColor(COLOR_BTNTEXT)); + } + dis.hwndItem = hwnd; + dis.hDC = hdcMem; + dis.CtlType = 0; + nParts = SendMessage(hwnd, SB_GETPARTS, 0, 0); + for (i = 0; i < nParts; i++) { + SendMessage(hwnd, SB_GETRECT, i, (LPARAM)&dis.rcItem); + OffsetRect(&dis.rcItem, 0, -b_offset); + dis.itemData = SendMessage(hwnd, SB_GETTEXTA, i, 0); + SendMessage(pcli->hwndContactList, WM_DRAWITEM, 0, (LPARAM)&dis); + } + BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcMem, 0, 0, SRCCOPY); + if(hOldFont) + SelectObject(hdcMem, hOldFont); + SelectObject(hdcMem, hbmOld); + DeleteObject(hbmMem); + DeleteDC(hdcMem); + EndPaint(hwnd, &ps); + return 0; + } + break; + + case WM_DESTROY: + break; + + case WM_TIMER: + if(wParam == TIMERID_HOVER) { + POINT pt; + KillTimer(hwnd, TIMERID_HOVER); + + GetCursorPos(&pt); + if (pt.x == ptMouse.x && pt.y == ptMouse.y) { + int i,nParts; + RECT rc; + + ScreenToClient(hwnd, &pt); + nParts = SendMessage(hwnd, SB_GETPARTS, 0, 0); + for (i = 0; i < nParts; i++) { + SendMessage(hwnd, SB_GETRECT, i, (LPARAM)&rc); + if(PtInRect(&rc,pt)) { + ProtocolData *PD; + PD = (ProtocolData *)SendMessageA(hwnd, SB_GETTEXTA, i, 0); + + if(PD) { + if(NotifyEventHooks(hStatusBarShowToolTipEvent, (WPARAM)PD->RealName, 0) > 0) // a plugin handled this event + tooltip_active = TRUE; + else if(cfg::getDword("mToolTip", "ShowStatusTip", 0)) { + CLCINFOTIP ti = {0}; + BYTE isLocked = 0; + char szTipText[256], *szStatus = NULL; + WORD wStatus; + + ti.cbSize = sizeof(ti); + ti.isTreeFocused = GetFocus() == pcli->hwndContactList ? 1 : 0; + wStatus = (WORD)CallProtoService(PD->RealName, PS_GETSTATUS, 0, 0); + isLocked = cfg::getByte(PD->RealName, "LockMainStatus", 0); + szStatus = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)wStatus, 0); + mir_snprintf(szTipText, 256, "%s: %s%s", PD->RealName, szStatus, isLocked ? " (LOCKED)" : ""); + CallService("mToolTip/ShowTip", (WPARAM)szTipText, (LPARAM)&ti); + } + } + break; + } + } + } + } + break; + } + + return CallWindowProc(OldStatusBarProc, hwnd, msg, wParam, lParam); +} diff --git a/plugins/Clist_nicer/src/statusfloater.cpp b/plugins/Clist_nicer/src/statusfloater.cpp new file mode 100644 index 0000000000..d07196ee16 --- /dev/null +++ b/plugins/Clist_nicer/src/statusfloater.cpp @@ -0,0 +1,1240 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +------------------------ + +implements a simple status floater as a layered (and skinnable) window with +a minimalistic UI (change status, access main menu). It also may hold a copy +of the event area. + +Also implementes floating contacts (FLT_*() functions) + +*/ + +#include + +#define SNAP_SCREEN_TOLERANCE 10 +#define SNAP_FLT_TOLERANCE 10 +#define TOOLTIP_TIMER 1 + +#define MS_TOOLTIP_SHOWTIP "mToolTip/ShowTip" +#define MS_TOOLTIP_HIDETIP "mToolTip/HideTip" + +BYTE __forceinline percent_to_byte(UINT32 percent) +{ + return(BYTE) ((FLOAT) (((FLOAT) percent) / 100) * 255); +} + +void FLT_Update(struct ClcData *dat, struct ClcContact *contact); +void FLT_ShowHideAll(int showCmd); +void FLT_SnapToEdges(HWND hwnd); +void FLT_SnapToFloater(HWND hwnd); + +HWND g_hwndSFL = 0; +HDC g_SFLCachedDC = 0; +HBITMAP g_SFLhbmOld = 0, g_SFLhbm = 0; +struct ContactFloater *pFirstFloater = 0; +BOOL hover = FALSE; +BOOL tooltip = FALSE; +UINT_PTR hTooltipTimer = 0; +POINT start_pos; + + +extern StatusItems_t *StatusItems; +extern int g_padding_y; + +extern HIMAGELIST hCListImages; +extern HWND g_hwndEventArea; +extern HDC g_HDC; + +extern int g_list_avatars; + +FLOATINGOPTIONS g_floatoptions; + +static UINT padctrlIDs[] = { IDC_FLT_PADLEFTSPIN, IDC_FLT_PADRIGHTSPIN, IDC_FLT_PADTOPSPIN, + IDC_FLT_PADBOTTOMSPIN, 0 }; + +/* + * floating contacts support functions + * simple linked list of allocated ContactFloater* structs + */ + +static struct ContactFloater *FLT_AddToList(struct ContactFloater *pFloater) { + struct ContactFloater *pCurrent = pFirstFloater; + + if (!pFirstFloater) { + pFirstFloater = pFloater; + pFirstFloater->pNextFloater = NULL; + return pFirstFloater; + } else { + while (pCurrent->pNextFloater != 0) + pCurrent = pCurrent->pNextFloater; + pCurrent->pNextFloater = pFloater; + pFloater->pNextFloater = NULL; + return pCurrent; + } +} + +static struct ContactFloater *FLT_RemoveFromList(struct ContactFloater *pFloater) { + struct ContactFloater *pCurrent = pFirstFloater; + + if (pFloater == pFirstFloater) { + if(pFloater->pNextFloater != NULL) + pFirstFloater = pFloater->pNextFloater; + else + pFirstFloater = NULL; + return pFirstFloater; + } + + do { + if (pCurrent->pNextFloater == pFloater) { + pCurrent->pNextFloater = pCurrent->pNextFloater->pNextFloater; + return 0; + } + } while (pCurrent = pCurrent->pNextFloater); + + return NULL; +} + +void FLT_SnapToEdges(HWND hwnd) +{ + RECT dr; + MONITORINFO monInfo; + RECT rcWindow; + HMONITOR curMonitor; + + if ( API::pfnMonitorFromWindow == NULL ) + return; + + curMonitor = API::pfnMonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + + monInfo.cbSize = sizeof(monInfo); + API::pfnGetMonitorInfo(curMonitor, &monInfo); + + dr = monInfo.rcWork; + GetWindowRect(hwnd, &rcWindow); + + if (rcWindow.left < dr.left + SNAP_SCREEN_TOLERANCE){ + SetWindowPos(hwnd, HWND_TOPMOST, 0, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + GetWindowRect(hwnd, &rcWindow); + } + + if (rcWindow.top < dr.top + SNAP_SCREEN_TOLERANCE){ + SetWindowPos(hwnd, HWND_TOPMOST, rcWindow.left, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + GetWindowRect(hwnd, &rcWindow); + } + + if (rcWindow.right > dr.right - SNAP_SCREEN_TOLERANCE) + SetWindowPos(hwnd, HWND_TOPMOST, dr.right - (rcWindow.right - rcWindow.left), rcWindow.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + if (rcWindow.bottom > dr.bottom - SNAP_SCREEN_TOLERANCE) + SetWindowPos(hwnd, HWND_TOPMOST, rcWindow.left, dr.bottom - (rcWindow.bottom - rcWindow.top), 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +void FLT_SnapToFloater(HWND hwnd) +{ + struct ContactFloater *pCurrent = pFirstFloater; + RECT rcWindow, rcBase; + int minTop = 0xFFFFFF, minBottom = 0xFFFFFF, minRight = 0xFFFFFF, minLeft = 0xFFFFFF; + int posTop = 0, posBottom = 0, posRight = 0, posLeft = 0; + + GetWindowRect(hwnd, &rcBase); + + //find the closest floater + while(pCurrent) { + GetWindowRect(pCurrent->hwnd, &rcWindow); + //top + if ((rcWindow.top - rcBase.bottom > -SNAP_FLT_TOLERANCE) && (rcWindow.top - rcBase.bottom < minTop)) { + posTop = rcWindow.top; + minTop = rcWindow.top - rcBase.bottom; + } + //bottom + if ((rcBase.top - rcWindow.bottom > -SNAP_FLT_TOLERANCE) && (rcBase.top - rcWindow.bottom < minBottom)) { + posBottom = rcWindow.bottom; + minBottom = rcBase.top - rcWindow.bottom; + } + //left + if ((rcWindow.left - rcBase.right > -SNAP_FLT_TOLERANCE) && (rcWindow.left - rcBase.right < minLeft)) { + posLeft= rcWindow.left; + minLeft = rcWindow.left - rcBase.right; + } + //right + if ((rcBase.left - rcWindow.right > -SNAP_FLT_TOLERANCE) && (rcBase.left - rcWindow.right < minRight)) { + posRight= rcWindow.right; + minRight = rcBase.left - rcWindow.right; + } + pCurrent = pCurrent->pNextFloater; + } + + //snap to the closest floater if spacing is under SNAP_FLT_TOLERANCE + if (posTop && (rcBase.bottom > posTop - SNAP_FLT_TOLERANCE)) + SetWindowPos(hwnd, HWND_TOPMOST, rcBase.left, posTop - (rcBase.bottom - rcBase.top), 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + if (posBottom && (rcBase.top < posBottom + SNAP_FLT_TOLERANCE)) + SetWindowPos(hwnd, HWND_TOPMOST, rcBase.left, posBottom, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + if (posLeft && (rcBase.right > posLeft - SNAP_FLT_TOLERANCE)) + SetWindowPos(hwnd, HWND_TOPMOST, posLeft - (rcBase.right - rcBase.left), rcBase.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + if (posRight && (rcBase.left < posRight + SNAP_FLT_TOLERANCE)) + SetWindowPos(hwnd, HWND_TOPMOST, posRight, rcBase.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +/* + * dialog procedure for the floating contacts option page + */ + +INT_PTR CALLBACK DlgProcFloatingContacts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + { + DWORD dwFlags = g_floatoptions.dwFlags; + int i = 0; + + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_FLT_ENABLED, g_floatoptions.enabled); + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_ENABLED, 0); + CheckDlgButton(hwndDlg, IDC_FLT_SIMPLELAYOUT, dwFlags & FLT_SIMPLE); + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_SIMPLELAYOUT, 0); + CheckDlgButton(hwndDlg, IDC_FLT_AVATARS, dwFlags & FLT_AVATARS); + CheckDlgButton(hwndDlg, IDC_FLT_DUALROWS, dwFlags & FLT_DUALROW); + CheckDlgButton(hwndDlg, IDC_FLT_EXTRAICONS, dwFlags & FLT_EXTRAICONS); + CheckDlgButton(hwndDlg, IDC_FLT_SYNCED, dwFlags & FLT_SYNCWITHCLIST); + CheckDlgButton(hwndDlg, IDC_FLT_AUTOHIDE, dwFlags & FLT_AUTOHIDE); + CheckDlgButton(hwndDlg, IDC_FLT_SNAP, dwFlags & FLT_SNAP); + CheckDlgButton(hwndDlg, IDC_FLT_BORDER, dwFlags & FLT_BORDER); + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_BORDER, 0); + CheckDlgButton(hwndDlg, IDC_FLT_ROUNDED, dwFlags & FLT_ROUNDED); + CheckDlgButton(hwndDlg, IDC_FLT_FILLSTD, dwFlags & FLT_FILLSTDCOLOR); + + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_ROUNDED, 0); + + if (ServiceExists(MS_TOOLTIP_SHOWTIP)) + { + CheckDlgButton(hwndDlg, IDC_FLT_SHOWTOOLTIPS, dwFlags & FLT_SHOWTOOLTIPS); + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_SHOWTOOLTIPS, 0); + CheckDlgButton(hwndDlg, IDC_FLT_DEFHOVERTIME, g_floatoptions.def_hover_time); + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_FLT_DEFHOVERTIME, 0); + } + else + { + CheckDlgButton(hwndDlg, IDC_FLT_SHOWTOOLTIPS, 0); + Utils::enableDlgControl(hwndDlg, IDC_FLT_SHOWTOOLTIPS, 0); + } + + for (i = 0; padctrlIDs[i] != 0; i++) + SendDlgItemMessage(hwndDlg, padctrlIDs[i], UDM_SETRANGE, 0, MAKELONG(20, 0)); + SendDlgItemMessage(hwndDlg, IDC_FLT_WIDTHSPIN, UDM_SETRANGE, 0, MAKELONG(200, 50)); + SendDlgItemMessage(hwndDlg, IDC_FLT_RADIUSSPIN, UDM_SETRANGE, 0, MAKELONG(20, 1)); + SendDlgItemMessage(hwndDlg, IDC_FLT_HOVERTIMESPIN, UDM_SETRANGE, 0, MAKELONG(5000, 1)); + + + SendDlgItemMessage(hwndDlg, IDC_FLT_PADLEFTSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_left); + SendDlgItemMessage(hwndDlg, IDC_FLT_PADRIGHTSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_right); + SendDlgItemMessage(hwndDlg, IDC_FLT_PADTOPSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_top); + SendDlgItemMessage(hwndDlg, IDC_FLT_PADBOTTOMSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.pad_top); + SendDlgItemMessage(hwndDlg, IDC_FLT_WIDTHSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.width); + SendDlgItemMessage(hwndDlg, IDC_FLT_RADIUSSPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.radius); + SendDlgItemMessage(hwndDlg, IDC_FLT_HOVERTIMESPIN, UDM_SETPOS, 0, (LPARAM)g_floatoptions.hover_time); + + SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_SETPOS, TRUE, g_floatoptions.act_trans); + SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_SETRANGE, FALSE, MAKELONG(1, 255)); + SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_SETPOS, TRUE, g_floatoptions.trans); + SendMessage(hwndDlg, WM_HSCROLL, 0, 0); + + SendDlgItemMessage(hwndDlg, IDC_FLT_BORDERCOLOUR, CPM_SETDEFAULTCOLOUR, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_FLT_BORDERCOLOUR, CPM_SETCOLOUR, 0, g_floatoptions.border_colour); + + FLT_ShowHideAll(SW_SHOWNOACTIVATE); + + return TRUE; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_FLT_ENABLED: + { + int isEnabled = IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED); + int isSimple = IsDlgButtonChecked(hwndDlg, IDC_FLT_SIMPLELAYOUT); + int isBorder = IsDlgButtonChecked(hwndDlg, IDC_FLT_BORDER); + int isRounded = IsDlgButtonChecked(hwndDlg, IDC_FLT_ROUNDED); + int isTooltip = IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS); + int isDefHoverTime = IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME); + + Utils::enableDlgControl(hwndDlg, IDC_FLT_SIMPLELAYOUT, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_SYNCED, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_AUTOHIDE, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_SNAP, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_ACTIVEOPACITY, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_OPACITY, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_PADLEFTSPIN, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_PADRIGHTSPIN, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_PADTOPSPIN, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_PADLEFT, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_PADRIGHT, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_PADTOP, isEnabled); + //EnableWindow(GetDlgItem(hwndDlg, IDC_FLT_PADBOTTOMSPIN), isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_PADBOTTOM, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_WIDTHSPIN, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_WIDTH, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_BORDER, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_ROUNDED, isEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FLT_BORDERCOLOUR, isEnabled & isBorder); + Utils::enableDlgControl(hwndDlg, IDC_FLT_RADIUS, isEnabled & isRounded); + Utils::enableDlgControl(hwndDlg, IDC_FLT_RADIUSSPIN, isEnabled & isRounded); + Utils::enableDlgControl(hwndDlg, IDC_FLT_SHOWTOOLTIPS, isEnabled & ServiceExists(MS_TOOLTIP_SHOWTIP)); + Utils::enableDlgControl(hwndDlg, IDC_FLT_DEFHOVERTIME, isEnabled & isTooltip); + Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIME, isEnabled & isTooltip & !isDefHoverTime); + Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIMESPIN, isEnabled & isTooltip & !isDefHoverTime); + + Utils::enableDlgControl(hwndDlg, IDC_FLT_AVATARS, isEnabled & !isSimple); + Utils::enableDlgControl(hwndDlg, IDC_FLT_EXTRAICONS, isEnabled & !isSimple); + Utils::enableDlgControl(hwndDlg, IDC_FLT_DUALROWS, isEnabled & !isSimple); + } + break; + case IDC_FLT_SIMPLELAYOUT: + { + if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED)) { + int isSimple = IsDlgButtonChecked(hwndDlg, IDC_FLT_SIMPLELAYOUT); + Utils::enableDlgControl(hwndDlg, IDC_FLT_AVATARS, !isSimple); + Utils::enableDlgControl(hwndDlg, IDC_FLT_EXTRAICONS, !isSimple); + Utils::enableDlgControl(hwndDlg, IDC_FLT_DUALROWS, !isSimple); + } + } + break; + case IDC_FLT_BORDER: + { + if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED)) { + int isBorder = IsDlgButtonChecked(hwndDlg, IDC_FLT_BORDER); + Utils::enableDlgControl(hwndDlg, IDC_FLT_BORDERCOLOUR, isBorder); + } + } + break; + case IDC_FLT_ROUNDED: + { + if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED)) { + int isRounded = IsDlgButtonChecked(hwndDlg, IDC_FLT_ROUNDED); + Utils::enableDlgControl(hwndDlg, IDC_FLT_RADIUS, isRounded); + Utils::enableDlgControl(hwndDlg, IDC_FLT_RADIUSSPIN, isRounded); + } + } + break; + case IDC_FLT_SHOWTOOLTIPS: + { + if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED)) { + int isTooltip = IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS); + int isDefHoverTime = IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME); + Utils::enableDlgControl(hwndDlg, IDC_FLT_DEFHOVERTIME, isTooltip); + Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIME, isTooltip & !isDefHoverTime); + Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIMESPIN, isTooltip & !isDefHoverTime); + } + } + break; + case IDC_FLT_DEFHOVERTIME: + { + if (IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED) && IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS)) { + int isDefHoverTime = IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME); + Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIME, !isDefHoverTime); + Utils::enableDlgControl(hwndDlg, IDC_FLT_HOVERTIMESPIN, !isDefHoverTime); + } + } + break; + + case IDC_FLT_PADTOP: + { + if(HIWORD(wParam) == EN_CHANGE){ + int value = SendDlgItemMessage(hwndDlg, IDC_FLT_PADTOPSPIN, UDM_GETPOS, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_FLT_PADBOTTOMSPIN, UDM_SETPOS, 0, (LPARAM)value); + } + } + break; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_HSCROLL: + { + char str[10]; + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_FLT_ACTIVEOPACITYVALUE, str); + wsprintfA(str, "%d%%", 100 * SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_GETPOS, 0, 0) / 255); + SetDlgItemTextA(hwndDlg, IDC_FLT_OPACITYVALUE, str); + + if (lParam) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + g_floatoptions.enabled = IsDlgButtonChecked(hwndDlg, IDC_FLT_ENABLED) ? 1 : 0; + g_floatoptions.dwFlags = 0; + + if(IsDlgButtonChecked(hwndDlg, IDC_FLT_SIMPLELAYOUT)) + g_floatoptions.dwFlags = FLT_SIMPLE; + + g_floatoptions.dwFlags |= (IsDlgButtonChecked(hwndDlg, IDC_FLT_AVATARS) ? FLT_AVATARS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_DUALROWS) ? FLT_DUALROW : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_EXTRAICONS) ? FLT_EXTRAICONS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_SYNCED) ? FLT_SYNCWITHCLIST : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_AUTOHIDE) ? FLT_AUTOHIDE : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_SNAP) ? FLT_SNAP : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_BORDER) ? FLT_BORDER : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_FILLSTD) ? FLT_FILLSTDCOLOR : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_SHOWTOOLTIPS) ? FLT_SHOWTOOLTIPS : 0) | + (IsDlgButtonChecked(hwndDlg, IDC_FLT_ROUNDED) ? FLT_ROUNDED : 0); + + g_floatoptions.act_trans = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_ACTIVEOPACITY, TBM_GETPOS, 0, 0); + g_floatoptions.trans = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_OPACITY, TBM_GETPOS, 0, 0); + g_floatoptions.pad_left = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADLEFTSPIN, UDM_GETPOS, 0, 0); + g_floatoptions.pad_right = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADRIGHTSPIN, UDM_GETPOS, 0, 0); + g_floatoptions.pad_top = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADTOPSPIN, UDM_GETPOS, 0, 0); + g_floatoptions.pad_bottom = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_PADBOTTOMSPIN, UDM_GETPOS, 0, 0); + g_floatoptions.width = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_WIDTHSPIN, UDM_GETPOS, 0, 0); + g_floatoptions.radius = (BYTE)SendDlgItemMessage(hwndDlg, IDC_FLT_RADIUSSPIN, UDM_GETPOS, 0, 0); + g_floatoptions.border_colour = SendDlgItemMessage(hwndDlg, IDC_FLT_BORDERCOLOUR, CPM_GETCOLOUR, 0, 0); + + g_floatoptions.def_hover_time= IsDlgButtonChecked(hwndDlg, IDC_FLT_DEFHOVERTIME) ? 1 : 0; + if (g_floatoptions.def_hover_time) + g_floatoptions.hover_time = cfg::getWord("CLC", "InfoTipHoverTime", 200); + else + g_floatoptions.hover_time = (WORD)SendDlgItemMessage(hwndDlg, IDC_FLT_HOVERTIMESPIN, UDM_GETPOS, 0, 0); + + FLT_WriteOptions(); + FLT_RefreshAll(); + return TRUE; + } + } + break; + } + break; + } + return FALSE; +} + +void FLT_ReadOptions() +{ + DWORD dwPad; + + ZeroMemory(&g_floatoptions, sizeof(FLOATINGOPTIONS)); + + g_floatoptions.enabled = cfg::getByte("CList", "flt_enabled", 0); + g_floatoptions.dwFlags = cfg::getDword("CList", "flt_flags", FLT_SIMPLE); + dwPad = cfg::getDword("CList", "flt_padding", 0); + + g_floatoptions.pad_top = LOBYTE(LOWORD(dwPad)); + g_floatoptions.pad_right = HIBYTE(LOWORD(dwPad)); + g_floatoptions.pad_bottom = LOBYTE(HIWORD(dwPad)); + g_floatoptions.pad_left = HIBYTE(HIWORD(dwPad)); + + g_floatoptions.width = cfg::getDword("CList", "flt_width", 100); + g_floatoptions.act_trans = cfg::getByte("CList", "flt_acttrans", 255); + g_floatoptions.trans = cfg::getByte("CList", "flt_trans", 255); + g_floatoptions.radius = cfg::getByte("CList", "flt_radius", 3); + g_floatoptions.border_colour = cfg::getDword("CList", "flt_bordercolour", 0); + g_floatoptions.def_hover_time = cfg::getByte("CList", "flt_defhovertime", 1); + + if (g_floatoptions.def_hover_time) + g_floatoptions.hover_time = cfg::getWord("CLC", "InfoTipHoverTime", 200); + else + g_floatoptions.hover_time = cfg::getWord("CList", "flt_hovertime", 200); + +} + +void FLT_WriteOptions() +{ + DWORD dwPad; + + cfg::writeByte("CList", "flt_enabled", g_floatoptions.enabled); + cfg::writeDword("CList", "flt_flags", g_floatoptions.dwFlags); + dwPad = MAKELONG(MAKEWORD(g_floatoptions.pad_top, g_floatoptions.pad_right), + MAKEWORD(g_floatoptions.pad_bottom, g_floatoptions.pad_left)); + cfg::writeDword("CList", "flt_padding", dwPad); + cfg::writeDword("CList", "flt_width", g_floatoptions.width); + cfg::writeByte("CList", "flt_acttrans", g_floatoptions.act_trans); + cfg::writeByte("CList", "flt_trans", g_floatoptions.trans); + cfg::writeByte("CList", "flt_radius", g_floatoptions.radius); + cfg::writeDword("CList", "flt_bordercolour", g_floatoptions.border_colour); + cfg::writeByte("CList", "flt_defhovertime", g_floatoptions.def_hover_time); + if (!g_floatoptions.def_hover_time) + cfg::writeWord("CList", "flt_hovertime", g_floatoptions.hover_time); + +} + +LRESULT CALLBACK StatusFloaterClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_DESTROY: + Utils_SaveWindowPosition(hwnd, 0, "CLUI", "sfl"); + if(g_SFLCachedDC) { + SelectObject(g_SFLCachedDC, g_SFLhbmOld); + DeleteObject(g_SFLhbm); + DeleteDC(g_SFLCachedDC); + g_SFLCachedDC = 0; + } + break; + case WM_ERASEBKGND: + return TRUE; + case WM_PAINT: + { + HDC hdc; + PAINTSTRUCT ps; + + hdc = BeginPaint(hwnd, &ps); + ps.fErase = FALSE; + EndPaint(hwnd, &ps); + return TRUE; + } + case WM_LBUTTONDOWN: + { + POINT ptMouse; + RECT rcWindow; + + GetCursorPos(&ptMouse); + GetWindowRect(hwnd, &rcWindow); + rcWindow.right = rcWindow.left + 25; + if (!PtInRect(&rcWindow, ptMouse)) + return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(ptMouse.x, ptMouse.y)); + break; + } + case WM_LBUTTONUP: + { + HMENU hmenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS, 0, 0); + RECT rcWindow; + POINT pt; + + GetCursorPos(&pt); + GetWindowRect(hwnd, &rcWindow); + if(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS) { + if(pt.y > rcWindow.top + ((rcWindow.bottom - rcWindow.top) / 2)) + SendMessage(g_hwndEventArea, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0); + else + TrackPopupMenu(hmenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, pcli->hwndContactList, NULL); + } + else + TrackPopupMenu(hmenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, pcli->hwndContactList, NULL); + return 0; + } + case WM_CONTEXTMENU: + { + HMENU hmenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN, 0, 0); + RECT rcWindow; + + GetWindowRect(hwnd, &rcWindow); + TrackPopupMenu(hmenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, pcli->hwndContactList, NULL); + return 0; + } + + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void CALLBACK ShowTooltip(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){ + struct ContactFloater *pCurrent = pFirstFloater; + POINT pt; + CLCINFOTIP ti = {0}; + + KillTimer(hwnd, TOOLTIP_TIMER); + hTooltipTimer = 0; + + GetCursorPos(&pt); + if ((abs(pt.x - start_pos.x) > 3) && (abs(pt.y - start_pos.y) > 3)) return; + + while(pCurrent->hwnd != hwnd) + pCurrent = pCurrent->pNextFloater; + + ti.cbSize = sizeof(ti); + ti.isGroup = 0; + ti.isTreeFocused = 0; + ti.hItem = pCurrent->hContact; + ti.ptCursor = pt; + CallService(MS_TOOLTIP_SHOWTIP, 0, (LPARAM)&ti); + tooltip = TRUE; +} + +LRESULT CALLBACK ContactFloaterClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + INT_PTR iEntry = GetWindowLongPtr(hwnd, GWLP_USERDATA); + struct TExtraCache *centry = NULL; + + if(iEntry >= 0 && iEntry < cfg::nextCacheEntry) + centry = &cfg::eCache[iEntry]; + + switch(msg) { + case WM_NCCREATE: + { + CREATESTRUCT *cs = (CREATESTRUCT *)lParam; + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams); + iEntry = (int)cs->lpCreateParams; + if(iEntry >= 0 && iEntry < cfg::nextCacheEntry) + centry = &cfg::eCache[iEntry]; + return TRUE; + } + case WM_DESTROY: + if(centry) { + WINDOWPLACEMENT wp = {0}; + + SelectObject(centry->floater->hdc, centry->floater->hbmOld); + DeleteObject(centry->floater->hbm); + DeleteDC(centry->floater->hdc); + FLT_RemoveFromList(centry->floater); + free(centry->floater); + centry->floater = 0; + Utils_SaveWindowPosition(hwnd, centry->hContact, "CList", "flt"); + break; + } + case WM_ERASEBKGND: + return TRUE; + case WM_PAINT: + { + HDC hdc; + PAINTSTRUCT ps; + + hdc = BeginPaint(hwnd, &ps); + ps.fErase = FALSE; + EndPaint(hwnd, &ps); + return TRUE; + } + case WM_LBUTTONDBLCLK: + if(centry) + CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)centry->hContact, 0); + return 0; + case WM_LBUTTONDOWN: + { + POINT ptMouse; + RECT rcWindow; + + GetCursorPos(&ptMouse); + GetWindowRect(hwnd, &rcWindow); + rcWindow.right = rcWindow.left + 25; + if (!PtInRect(&rcWindow, ptMouse)) + return SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, MAKELPARAM(ptMouse.x, ptMouse.y)); + break; + } + case WM_MOUSEMOVE: + if ( API::pfnTrackMouseEvent && !hover ) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_HOVER | TME_LEAVE; + tme.hwndTrack = hwnd; + tme.dwHoverTime = 5; + API::pfnTrackMouseEvent(&tme); + hover = TRUE; + } + if ( ServiceExists( MS_TOOLTIP_SHOWTIP )) { + if ((g_floatoptions.dwFlags & FLT_SHOWTOOLTIPS) && !tooltip) { + GetCursorPos(&start_pos); + if (hTooltipTimer) KillTimer(hwnd, TOOLTIP_TIMER); + hTooltipTimer = SetTimer(hwnd, TOOLTIP_TIMER, g_floatoptions.hover_time, ShowTooltip); + } + } + + return FALSE; + + case WM_MOUSEHOVER: + { + struct ClcContact *contact = NULL; + struct ContactFloater *pCurrent = pFirstFloater; + int oldTrans = g_floatoptions.trans; + + while(pCurrent->hwnd != hwnd) + pCurrent = pCurrent->pNextFloater; + + if(FindItem(pcli->hwndContactTree, cfg::clcdat, pCurrent->hContact, &contact, NULL, 0)) { + g_floatoptions.trans = g_floatoptions.act_trans; + FLT_Update(cfg::clcdat, contact); + g_floatoptions.trans = oldTrans; + } + + break; + } + case WM_MOUSELEAVE: + { + struct ClcContact *contact = NULL; + struct ContactFloater *pCurrent = pFirstFloater; + + while(pCurrent->hwnd != hwnd) + pCurrent = pCurrent->pNextFloater; + + if(FindItem(pcli->hwndContactTree, cfg::clcdat, pCurrent->hContact, &contact, NULL, 0)) + FLT_Update(cfg::clcdat, contact); + + if (hTooltipTimer) + { + KillTimer(hwnd, TOOLTIP_TIMER); + hTooltipTimer = 0; + } + + if (tooltip) CallService(MS_TOOLTIP_HIDETIP, 0, 0); + + hover = FALSE; + tooltip = FALSE; + + + break; + } + + case WM_MOVE: + { + if (g_floatoptions.dwFlags & FLT_SNAP) + FLT_SnapToEdges(hwnd); + + if(GetKeyState(VK_CONTROL) < 0) + FLT_SnapToFloater(hwnd); + + break; + } + case WM_MEASUREITEM: + return(CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam)); + case WM_DRAWITEM: + return(CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam)); + case WM_COMMAND: + return(CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKELONG(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)centry->hContact)); + case WM_CONTEXTMENU: + { + if(centry) { + HMENU hContactMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)centry->hContact, 0); + RECT rcWindow; + + GetWindowRect(hwnd, &rcWindow); + TrackPopupMenu(hContactMenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, rcWindow.left, rcWindow.bottom, 0, hwnd, NULL); + DestroyMenu(hContactMenu); + return 0; + } + break; + } + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void SFL_RegisterWindowClass() +{ + WNDCLASS wndclass; + + wndclass.style = 0; + wndclass.lpfnWndProc = StatusFloaterClassProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = g_hInst; + wndclass.hIcon = 0; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH) (COLOR_3DFACE); + wndclass.lpszMenuName = 0; + wndclass.lpszClassName = _T("StatusFloaterClass"); + RegisterClass(&wndclass); + + wndclass.style = CS_DBLCLKS; + wndclass.lpszClassName = _T("ContactFloaterClass"); + wndclass.lpfnWndProc = ContactFloaterClassProc; + RegisterClass(&wndclass); +} + +void SFL_UnregisterWindowClass() +{ + UnregisterClass(_T("StatusFloaterClass"), g_hInst); + UnregisterClass(_T("ContactFloaterClass"), g_hInst); +} + +void SFL_Destroy() +{ + if(g_hwndSFL) + DestroyWindow(g_hwndSFL); + g_hwndSFL = 0; +} + +static HICON sfl_hIcon = (HICON)-1; +static int sfl_iIcon = -1; +static TCHAR sfl_statustext[100] = _T(""); + +void SFL_Update(HICON hIcon, int iIcon, HIMAGELIST hIml, const TCHAR *szText, BOOL refresh) +{ + RECT rcClient, rcWindow; + POINT ptDest, ptSrc = {0}; + SIZE szDest, szT; + BLENDFUNCTION bf = {0}; + HFONT hOldFont; + StatusItems_t *item = &StatusItems[ID_EXTBKSTATUSFLOATER - ID_STATUS_OFFLINE]; + RECT rcStatusArea; + LONG cy; + + if(g_hwndSFL == 0) + return; + + GetClientRect(g_hwndSFL, &rcClient); + GetWindowRect(g_hwndSFL, &rcWindow); + + ptDest.x = rcWindow.left; + ptDest.y = rcWindow.top; + szDest.cx = rcWindow.right - rcWindow.left; + szDest.cy = rcWindow.bottom - rcWindow.top; + + if(item->IGNORED) { + FillRect(g_SFLCachedDC, &rcClient, GetSysColorBrush(COLOR_3DFACE)); + SetTextColor(g_SFLCachedDC, GetSysColor(COLOR_BTNTEXT)); + } + else { + FillRect(g_SFLCachedDC, &rcClient, GetSysColorBrush(COLOR_3DFACE)); + DrawAlpha(g_SFLCachedDC, &rcClient, item->COLOR, 100, item->COLOR2, item->COLOR2_TRANSPARENT, + item->GRADIENT, item->CORNER, item->BORDERSTYLE, item->imageItem); + SetTextColor(g_SFLCachedDC, item->TEXTCOLOR); + } + bf.BlendOp = AC_SRC_OVER; + bf.AlphaFormat = 0; + bf.SourceConstantAlpha = item->IGNORED ? 255 : percent_to_byte(item->ALPHA); + + rcStatusArea = rcClient; + + if(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS) + rcStatusArea.bottom = 20; + + cy = rcStatusArea.bottom - rcStatusArea.top; + + if(szText != NULL && refresh) { + _tcsncpy(sfl_statustext, szText, 100); + sfl_statustext[99] = 0; + } + + if (!hIcon) { + HICON p_hIcon; + + if(refresh) + sfl_iIcon = iIcon; + if(sfl_iIcon != -1) { + p_hIcon = ImageList_ExtractIcon(0, hCListImages, sfl_iIcon); + DrawIconEx(g_SFLCachedDC, 5, (cy - 16) / 2, p_hIcon, 16, 16, 0, 0, DI_NORMAL); + DestroyIcon(p_hIcon); + } + } + else { + if(refresh) + sfl_hIcon = hIcon; + if(sfl_hIcon != (HICON)-1) + DrawIconEx(g_SFLCachedDC, 5, (cy - 16) / 2, sfl_hIcon, 16, 16, 0, 0, DI_NORMAL); + } + + hOldFont = reinterpret_cast(SelectObject(g_SFLCachedDC, GetStockObject(DEFAULT_GUI_FONT))); + SetBkMode(g_SFLCachedDC, TRANSPARENT); + GetTextExtentPoint32(g_SFLCachedDC, sfl_statustext, lstrlen(sfl_statustext), &szT); + TextOut(g_SFLCachedDC, 24, (cy - szT.cy) / 2, sfl_statustext, lstrlen(sfl_statustext)); + + if(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS) { + RECT rcNA = rcClient; + + rcNA.top = 18; + PaintNotifyArea(g_SFLCachedDC, &rcNA); + } + + SelectObject(g_SFLCachedDC, hOldFont); + + if(API::pfnUpdateLayeredWindow) + API::pfnUpdateLayeredWindow(g_hwndSFL, 0, &ptDest, &szDest, g_SFLCachedDC, &ptSrc, GetSysColor(COLOR_3DFACE), &bf, ULW_ALPHA | ULW_COLORKEY); +} + +/* + * set the floater + * mode = 0/1 forced hide/show + * OR -1 to set it depending on the clist state (visible/hidden) (this is actually reversed, because the function + * is called *before* the clist is shown or hidden) + */ + +void SFL_SetState(int uMode) +{ + BYTE bClistState; + + if(g_hwndSFL == 0 || !(cfg::dat.bUseFloater & CLUI_USE_FLOATER)) + return; + + if(uMode == -1) { + if(cfg::dat.bUseFloater & CLUI_FLOATER_AUTOHIDE) { + bClistState = cfg::getByte("CList", "State", SETTING_STATE_NORMAL); + ShowWindow(g_hwndSFL, bClistState == SETTING_STATE_NORMAL ? SW_SHOW : SW_HIDE); + } + else + ShowWindow(g_hwndSFL, SW_SHOW); + } + else + ShowWindow(g_hwndSFL, uMode ? SW_SHOW : SW_HIDE); +} + +// XXX improve size calculations for the floater window. + +void SFL_SetSize() +{ + HDC hdc; + LONG lWidth; + RECT rcWindow; + SIZE sz; + char *szStatusMode; + HFONT oldFont; + int i; + + GetWindowRect(g_hwndSFL, &rcWindow); + lWidth = rcWindow.right - rcWindow.left; + + hdc = GetDC(g_hwndSFL); + oldFont = reinterpret_cast(SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT))); + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) { + szStatusMode = Translate((char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, 0)); + GetTextExtentPoint32A(hdc, szStatusMode, lstrlenA(szStatusMode), &sz); + lWidth = max(lWidth, sz.cx + 16 + 8); + } + SetWindowPos(g_hwndSFL, HWND_TOPMOST, rcWindow.left, rcWindow.top, lWidth, max(cfg::dat.bUseFloater & CLUI_FLOATER_EVENTS ? 36 : 20, sz.cy + 4), SWP_SHOWWINDOW); + GetWindowRect(g_hwndSFL, &rcWindow); + + if(g_SFLCachedDC) { + SelectObject(g_SFLCachedDC, g_SFLhbmOld); + DeleteObject(g_SFLhbm); + DeleteDC(g_SFLCachedDC); + g_SFLCachedDC = 0; + } + + g_SFLCachedDC = CreateCompatibleDC(hdc); + g_SFLhbm = CreateCompatibleBitmap(hdc, lWidth, rcWindow.bottom - rcWindow.top); + g_SFLhbmOld = reinterpret_cast(SelectObject(g_SFLCachedDC, g_SFLhbm)); + + ReleaseDC(g_hwndSFL, hdc); + CluiProtocolStatusChanged(0, 0); +} + +void SFL_Create() +{ + if(g_hwndSFL == 0 && cfg::dat.bUseFloater & CLUI_USE_FLOATER && API::pfnUpdateLayeredWindow != NULL) + g_hwndSFL = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, _T("StatusFloaterClass"), _T("sfl"), WS_VISIBLE, 0, 0, 0, 0, 0, 0, g_hInst, 0); + else + return; + + SetWindowLongPtr(g_hwndSFL, GWL_STYLE, GetWindowLongPtr(g_hwndSFL, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW)); + + Utils_RestoreWindowPosition(g_hwndSFL, 0, "CLUI", "sfl"); + SFL_SetSize(); +} + +void FLT_SetSize(struct TExtraCache *centry, LONG width, LONG height) +{ + HDC hdc; + RECT rcWindow; + HFONT oldFont; + int flags = SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOACTIVATE; + + int iVis = pcli->pfnGetWindowVisibleState(pcli->hwndContactList, 0, 0); + if ((g_floatoptions.dwFlags & FLT_AUTOHIDE) && (iVis == 2 || iVis == 4)) //2 = GWVS_VISIBLE, 4 = GWVS_PARTIALLY_COVERED + flags = SWP_NOMOVE | SWP_NOACTIVATE; + + if(centry->floater) { + hdc = GetDC(centry->floater->hwnd); + oldFont = reinterpret_cast(SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT))); + + SetWindowPos(centry->floater->hwnd, HWND_TOPMOST, 0, 0, width, height, flags); + GetWindowRect(centry->floater->hwnd, &rcWindow); + + if(centry->floater->hdc) { + SelectObject(centry->floater->hdc, centry->floater->hbmOld); + DeleteObject(centry->floater->hbm); + DeleteDC(centry->floater->hdc); + centry->floater->hdc = 0; + } + + centry->floater->hdc = CreateCompatibleDC(hdc); + centry->floater->hbm = CreateCompatibleBitmap(hdc, width, rcWindow.bottom - rcWindow.top); + centry->floater->hbmOld= reinterpret_cast(SelectObject(centry->floater->hdc, centry->floater->hbm)); + + ReleaseDC(centry->floater->hwnd, hdc); + } +} + +void FLT_Create(int iEntry) +{ + struct TExtraCache *centry = NULL; + + if(iEntry >= 0 && iEntry < cfg::nextCacheEntry) { + struct ClcContact *contact = NULL; + struct ClcGroup *group = NULL; + + centry = &cfg::eCache[iEntry]; + if(centry->floater == 0 && API::pfnUpdateLayeredWindow != NULL) { + + centry->floater = (struct ContactFloater *)malloc(sizeof(struct ContactFloater)); + if(centry->floater == NULL) + return; + FLT_AddToList(centry->floater); + centry->floater->hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, _T("ContactFloaterClass"), _T("sfl"), WS_VISIBLE, 0, 0, 0, 0, 0, 0, g_hInst, (LPVOID)iEntry); + centry->floater->hContact = centry->hContact; + } + else if(centry->floater != NULL) { + ShowWindow(centry->floater->hwnd, SW_SHOWNOACTIVATE); + return; + } + + SetWindowLongPtr(centry->floater->hwnd, GWL_STYLE, GetWindowLongPtr(centry->floater->hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPEDWINDOW | WS_POPUPWINDOW)); + + if(Utils_RestoreWindowPosition(centry->floater->hwnd, centry->hContact, "CList", "flt")) + if(Utils_RestoreWindowPositionNoMove(centry->floater->hwnd, centry->hContact, "CList", "flt")) + SetWindowPos(centry->floater->hwnd, 0, 50, 50, 150, 30, SWP_NOZORDER | SWP_NOACTIVATE); + + //FLT_SetSize(centry, 100, 20); + ShowWindow(centry->floater->hwnd, SW_SHOWNOACTIVATE); + if(FindItem(pcli->hwndContactTree, cfg::clcdat, centry->hContact, &contact, &group, 0)) { + if(contact) + FLT_Update(cfg::clcdat, contact); + } + } +} + +extern HDC hdcAV; +extern HDC hdcTempAV; +extern HBITMAP hbmTempAV, hbmTempOldAV; +extern LONG g_maxAV_X, g_maxAV_Y; + +void FLT_Update(struct ClcData *dat, struct ClcContact *contact) +{ + RECT rcClient, rcWindow; + POINT ptDest, ptSrc = {0}; + SIZE szDest; + BLENDFUNCTION bf = {0}; + HWND hwnd; + HDC hdc; + BOOL firstDrawn = TRUE; + struct ClcGroup *group = NULL; + struct ClcContact *newContact = NULL; + HRGN rgn; + HBRUSH hbrBorder; + COLORREF clrKey; + HBRUSH brKey; + float greyLevel; + + if(contact == NULL || dat == NULL) + return; + + if(contact->extraCacheEntry < 0 || contact->extraCacheEntry >= cfg::nextCacheEntry) + return; + + if(cfg::eCache[contact->extraCacheEntry].floater == NULL) + return; + + FLT_SetSize(&cfg::eCache[contact->extraCacheEntry], g_floatoptions.width, RowHeight::getFloatingRowHeight(dat, pcli->hwndContactTree, contact, g_floatoptions.dwFlags) + (2*g_floatoptions.pad_top)); + + hwnd = cfg::eCache[contact->extraCacheEntry].floater->hwnd; + hdc = cfg::eCache[contact->extraCacheEntry].floater->hdc; + + if(hwnd == 0) + return; + + GetClientRect(hwnd, &rcClient); + GetWindowRect(hwnd, &rcWindow); + + ptDest.x = rcWindow.left; + ptDest.y = rcWindow.top; + szDest.cx = rcWindow.right - rcWindow.left; + szDest.cy = rcWindow.bottom - rcWindow.top; + + /* + * fill with a DESATURATED representation of the clist bg color and use this later as a color key + */ + + greyLevel = (float)(GetRValue(cfg::clcdat->bkColour) * 0.299 + GetGValue(cfg::clcdat->bkColour) * 0.587 + GetBValue(cfg::clcdat->bkColour) * 0.144); + if (greyLevel > 255) + greyLevel = 255; + + clrKey = RGB((BYTE)greyLevel, (BYTE)greyLevel, (BYTE)greyLevel); + brKey = CreateSolidBrush(clrKey); + FillRect(hdc, &rcClient, brKey); + DeleteObject(brKey); + + SetBkMode(hdc, TRANSPARENT); + + if(g_floatoptions.dwFlags & FLT_ROUNDED){ + rgn = CreateRoundRectRgn(0, 0, rcClient.right, rcClient.bottom, g_floatoptions.radius, g_floatoptions.radius); + SelectClipRgn(hdc, rgn); + if(g_floatoptions.dwFlags & FLT_FILLSTDCOLOR) { + HBRUSH br = CreateSolidBrush(cfg::clcdat->bkColour); + FillRect(hdc, &rcClient, br); + DeleteObject(br); + } + } + + if(FindItem(pcli->hwndContactTree, dat, contact->hContact, &newContact, &group, 0)) { + DWORD oldFlags = cfg::dat.dwFlags; + BYTE oldPadding = cfg::dat.avatarPadding; + DWORD oldExtraImageMask = cfg::eCache[contact->extraCacheEntry].dwXMask; + struct avatarCacheEntry *ace_old = contact->ace; + BYTE oldDualRow = contact->bSecondLine; + + int oldLeftMargin = dat->leftMargin; + int oldRightMargin = dat->rightMargin; + + if(g_floatoptions.dwFlags & FLT_SIMPLE) { + contact->ace = 0; + contact->bSecondLine = MULTIROW_NEVER; + cfg::dat.dwFlags &= ~(CLUI_SHOWCLIENTICONS | CLUI_SHOWVISI); + cfg::eCache[contact->extraCacheEntry].dwXMask = 0; + } + else{ + if (!(g_floatoptions.dwFlags & FLT_AVATARS)) { + contact->ace = 0; + g_list_avatars = 0; + } + else + g_list_avatars = 1; + + if (!(g_floatoptions.dwFlags & FLT_DUALROW)) + contact->bSecondLine = MULTIROW_NEVER; + else + contact->bSecondLine = MULTIROW_ALWAYS; + + if (!(g_floatoptions.dwFlags & FLT_EXTRAICONS)) { + cfg::dat.dwFlags &= ~(CLUI_SHOWCLIENTICONS | CLUI_SHOWVISI); + cfg::eCache[contact->extraCacheEntry].dwXMask = 0; + } + } + + //g_CluiData.avatarPadding = g_floatoptions.pad_top; + dat->leftMargin = g_floatoptions.pad_left; + dat->rightMargin = g_floatoptions.pad_right; + + g_HDC = hdc; + + hdcTempAV = CreateCompatibleDC(g_HDC); + hdcAV = CreateCompatibleDC(g_HDC); + hbmTempAV = CreateCompatibleBitmap(g_HDC, g_maxAV_X, g_maxAV_Y); + hbmTempOldAV = reinterpret_cast(SelectObject(hdcTempAV, hbmTempAV)); + + g_padding_y = g_floatoptions.pad_top; + PaintItem(hdc, group, contact, 0, 0, dat, -4, pcli->hwndContactTree, 0, &rcClient, &firstDrawn, 0, rcClient.bottom - rcClient.top); + g_padding_y = 0; + + SelectObject(hdcTempAV, hbmTempOldAV); + DeleteObject(hbmTempAV); + DeleteDC(hdcTempAV); + DeleteDC(hdcAV); + + cfg::dat.dwFlags = oldFlags; + cfg::dat.avatarPadding = oldPadding; + contact->ace = ace_old; + contact->bSecondLine = oldDualRow; + cfg::eCache[contact->extraCacheEntry].dwXMask = oldExtraImageMask; + + dat->leftMargin = oldLeftMargin; + dat->rightMargin = oldRightMargin; + } + + if(g_floatoptions.dwFlags & FLT_BORDER){ + hbrBorder = CreateSolidBrush(g_floatoptions.border_colour); + if(g_floatoptions.dwFlags & FLT_ROUNDED) + FrameRgn(hdc, rgn, hbrBorder, 1, 1); + else + FrameRect(hdc, &rcClient, hbrBorder); + + DeleteObject(hbrBorder); + } + + if(g_floatoptions.dwFlags & FLT_ROUNDED) + DeleteObject(rgn); + + bf.BlendOp = AC_SRC_OVER; + bf.AlphaFormat = 0; + bf.SourceConstantAlpha = g_floatoptions.trans; + + if(API::pfnUpdateLayeredWindow) + API::pfnUpdateLayeredWindow(hwnd, 0, &ptDest, &szDest, hdc, &ptSrc, clrKey /*GetSysColor(COLOR_3DFACE)*/, &bf, ULW_COLORKEY | ULW_ALPHA); +} + +/* + * syncs the floating contacts with clist contact visibility. + * will hide all floating contacts which are not visible on the list + * needed after a list rebuild + */ + +void FLT_SyncWithClist() +{ + struct ClcContact *contact; + struct ContactFloater *pCurrent = pFirstFloater; + HWND hwnd; + int iVis = pcli->pfnGetWindowVisibleState(pcli->hwndContactList, 0, 0); + + if(g_floatoptions.dwFlags & FLT_SYNCWITHCLIST){ + while(pCurrent) { + hwnd = pCurrent->hwnd; + if(hwnd && IsWindow(hwnd)) { + if(FindItem(pcli->hwndContactTree, cfg::clcdat, pCurrent->hContact, &contact, NULL, 0)) { + FLT_Update(cfg::clcdat, contact); + if (((g_floatoptions.dwFlags & FLT_AUTOHIDE) && (iVis == 2 || iVis == 4)) || !(g_floatoptions.dwFlags & FLT_AUTOHIDE)) + ShowWindow(hwnd, SW_SHOWNOACTIVATE); + else + ShowWindow(hwnd, SW_HIDE); + } + else + ShowWindow(hwnd, SW_HIDE); + } + pCurrent = pCurrent->pNextFloater; + } + } +} + +/* + * quickly show or hide all floating contacts + * used by autohide/show feature + */ + +void FLT_ShowHideAll(int showCmd) +{ + struct ClcContact *contact; + struct ContactFloater *pCurrent = pFirstFloater; + HWND hwnd; + + if(g_floatoptions.dwFlags & FLT_AUTOHIDE){ + while(pCurrent) { + hwnd = pCurrent->hwnd; + if(hwnd && IsWindow(hwnd)) { + if(showCmd == SW_SHOWNOACTIVATE && FindItem(pcli->hwndContactTree, cfg::clcdat, pCurrent->hContact, &contact, NULL, 0)) + ShowWindow(hwnd, SW_SHOWNOACTIVATE); + else if(showCmd != SW_SHOWNOACTIVATE) + ShowWindow(hwnd, showCmd); + } + pCurrent = pCurrent->pNextFloater; + } + } +} + +/* + * update/repaint all contact floaters + */ + +void FLT_RefreshAll() +{ + struct ClcContact *contact = NULL; + struct ContactFloater *pCurrent = pFirstFloater; + + while(pCurrent) { + if(FindItem(pcli->hwndContactTree, cfg::clcdat, pCurrent->hContact, &contact, NULL, 0)) { + HWND hwnd = pCurrent->hwnd; + if(hwnd && IsWindow(hwnd)) + FLT_Update(cfg::clcdat, contact); + } + pCurrent = pCurrent->pNextFloater; + } +} + diff --git a/plugins/Clist_nicer/src/viewmodes.cpp b/plugins/Clist_nicer/src/viewmodes.cpp new file mode 100644 index 0000000000..f9961578f8 --- /dev/null +++ b/plugins/Clist_nicer/src/viewmodes.cpp @@ -0,0 +1,1249 @@ +/* +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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. + +contact list view modes (CLVM) + +$Id: viewmodes.cpp 13824 2011-09-03 06:32:11Z borkra $ + +*/ + +#include +#include +#include "../cluiframes/cluiframes.h" + +#define TIMERID_VIEWMODEEXPIRE 100 + +extern HIMAGELIST hCListImages; +extern HPEN g_hPenCLUIFrames; +extern wndFrame *wndFrameViewMode; + +typedef int (__cdecl *pfnEnumCallback)(char *szName); +static HWND clvmHwnd = 0; +static int clvm_curItem = 0; +HMENU hViewModeMenu = 0; + +static HWND hwndSelector = 0; +static HIMAGELIST himlViewModes = 0; +static HANDLE hInfoItem = 0; +static int nullImage; +static DWORD stickyStatusMask = 0; +static char g_szModename[2048]; + +static int g_ViewModeOptDlg = FALSE; + +static UINT _page1Controls[] = {IDC_STATIC1, IDC_STATIC2, IDC_STATIC3, IDC_STATIC5, IDC_STATIC4, + IDC_STATIC8, IDC_ADDVIEWMODE, IDC_DELETEVIEWMODE, IDC_NEWVIEMODE, IDC_GROUPS, IDC_PROTOCOLS, + IDC_VIEWMODES, IDC_STATUSMODES, IDC_STATIC12, IDC_STATIC13, IDC_STATIC14, IDC_PROTOGROUPOP, IDC_GROUPSTATUSOP, + IDC_AUTOCLEAR, IDC_AUTOCLEARVAL, IDC_AUTOCLEARSPIN, IDC_STATIC15, IDC_STATIC16, + IDC_LASTMESSAGEOP, IDC_LASTMESSAGEUNIT, IDC_LASTMSG, IDC_LASTMSGVALUE, 0}; + +static UINT _page2Controls[] = {IDC_CLIST, IDC_STATIC9, IDC_STATIC8, IDC_CLEARALL, IDC_CURVIEWMODE2, 0}; + + +/* + * enumerate all view modes, call the callback function with the mode name + * useful for filling lists, menus and so on.. + */ + +int CLVM_EnumProc(const char *szSetting, LPARAM lParam) +{ + pfnEnumCallback EnumCallback = (pfnEnumCallback)lParam; + if (szSetting != NULL) + EnumCallback((char *)szSetting); + return(0); +} + +void CLVM_EnumModes(pfnEnumCallback EnumCallback) +{ + DBCONTACTENUMSETTINGS dbces; + + dbces.pfnEnumProc = CLVM_EnumProc; + dbces.szModule = CLVM_MODULE; + dbces.ofsSettings=0; + dbces.lParam = (LPARAM)EnumCallback; + CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces); +} + +int FillModes(char *szsetting) +{ + if(szsetting[0] == 'ö') + return 1; + SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)szsetting); + return 1; +} + +static void ShowPage(HWND hwnd, int page) +{ + int i = 0; + int pageChange = 0; + + if(page == 0 && IsWindowVisible(GetDlgItem(hwnd, _page2Controls[0]))) + pageChange = 1; + + if(page == 1 && IsWindowVisible(GetDlgItem(hwnd, _page1Controls[0]))) + pageChange = 1; + + if(pageChange) + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + + switch(page) { + case 0: + while(_page1Controls[i] != 0) + ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_SHOW); + i = 0; + while(_page2Controls[i] != 0) + ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_HIDE); + break; + case 1: + while(_page1Controls[i] != 0) + ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_HIDE); + i = 0; + while(_page2Controls[i] != 0) + ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_SHOW); + break; + } + if(pageChange) { + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE); + } +} + +static int UpdateClistItem(HANDLE hContact, DWORD mask) +{ + int i; + + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hContact, MAKELONG(i - ID_STATUS_OFFLINE, + (1 << (i - ID_STATUS_OFFLINE)) & mask ? i - ID_STATUS_OFFLINE : nullImage)); + + return 0; +} + +static DWORD GetMaskForItem(HANDLE hItem) +{ + int i; + DWORD dwMask = 0; + + for (i = 0; i <= ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE; i++) + dwMask |= (SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i) == nullImage ? 0 : 1 << i); + + return dwMask; +} + +static void UpdateStickies() +{ + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + HANDLE hItem; + DWORD localMask; + int i; + + while(hContact) { + hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0); + if(hItem) + SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, cfg::getByte(hContact, "CLVM", g_szModename, 0) ? 1 : 0); + localMask = HIWORD(cfg::getDword(hContact, "CLVM", g_szModename, 0)); + UpdateClistItem(hItem, (localMask == 0 || localMask == stickyStatusMask) ? stickyStatusMask : localMask); + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + + { + HANDLE hItem; + + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hInfoItem, MAKELONG(i - ID_STATUS_OFFLINE, (1 << (i - ID_STATUS_OFFLINE)) & stickyStatusMask ? i - ID_STATUS_OFFLINE : ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1)); + + hItem=(HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETNEXTITEM,CLGN_ROOT,0); + hItem=(HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP, (LPARAM)hItem); + while(hItem) { + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELONG(i - ID_STATUS_OFFLINE, nullImage)); + hItem=(HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem); + } + ShowPage(clvmHwnd, 0); + } +} + +static int FillDialog(HWND hwnd) +{ + LVCOLUMN lvc = {0}; + HWND hwndList = GetDlgItem(hwnd, IDC_PROTOCOLS); + LVITEMA item = {0}; + int protoCount = 0, i, newItem; + PROTOACCOUNT **accs = 0; + + CLVM_EnumModes(FillModes); + ListView_SetExtendedListViewStyle(GetDlgItem(hwnd, IDC_PROTOCOLS), LVS_EX_CHECKBOXES); + lvc.mask = LVCF_FMT; + lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT; + ListView_InsertColumn(GetDlgItem(hwnd, IDC_PROTOCOLS), 0, &lvc); + + // fill protocols... + + ProtoEnumAccounts( &protoCount, &accs ); + item.mask = LVIF_TEXT; + item.iItem = 1000; + for (i = 0; i < protoCount; i++) { + item.pszText = accs[i]->szModuleName; + newItem = SendMessageA(hwndList, LVM_INSERTITEMA, 0, (LPARAM)&item); + } + + ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); + ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP); + + // fill groups + { + LVITEM item = {0}; + char buf[20]; + DBVARIANT dbv = {0}; + + hwndList = GetDlgItem(hwnd, IDC_GROUPS); + + ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES); + lvc.mask = LVCF_FMT; + lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT; + ListView_InsertColumn(hwndList, 0, &lvc); + + item.mask = LVIF_TEXT; + item.iItem = 1000; + + item.pszText = TranslateT("Ungrouped contacts"); + newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item); + + for (i = 0;;i++) { + mir_snprintf(buf, 20, "%d", i); + if(cfg::getTString(NULL, "CListGroups", buf, &dbv)) + break; + + item.pszText = &dbv.ptszVal[1]; + newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item); + DBFreeVariant(&dbv); + } + ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); + ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP); + } + hwndList = GetDlgItem(hwnd, IDC_STATUSMODES); + ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES); + lvc.mask = LVCF_FMT; + lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT; + ListView_InsertColumn(hwndList, 0, &lvc); + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) { + item.pszText = Translate((char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, 0)); + item.iItem = i - ID_STATUS_OFFLINE; + newItem = SendMessageA(hwndList, LVM_INSERTITEMA, 0, (LPARAM)&item); + } + ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); + ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP); + + SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And")); + SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or")); + SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And")); + SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or")); + + SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Older than")); + SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Newer than")); + + SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Minutes")); + SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Hours")); + SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Days")); + SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, 0, 0); + SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, 0, 0); + SetDlgItemInt(hwnd, IDC_LASTMSGVALUE, 0, 0); + return 0; +} + +static void SetAllChildIcons(HWND hwndList,HANDLE hFirstItem,int iColumn,int iImage) +{ + int typeOfFirst,iOldIcon; + HANDLE hItem,hChildItem; + + typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0); + //check groups + if(typeOfFirst==CLCIT_GROUP) hItem=hFirstItem; + else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem); + while(hItem) { + hChildItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem); + if(hChildItem) + SetAllChildIcons(hwndList,hChildItem,iColumn,iImage); + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem); + } + //check contacts + if(typeOfFirst==CLCIT_CONTACT) hItem=hFirstItem; + else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem); + while(hItem) { + iOldIcon=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn); + if(iOldIcon!=0xFF && iOldIcon!=iImage) SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem); + } +} + +static void SetIconsForColumn(HWND hwndList,HANDLE hItem,HANDLE hItemAll,int iColumn,int iImage) +{ + int itemType; + + itemType=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hItem,0); + if(itemType==CLCIT_CONTACT) { + int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn); + if (oldiImage!=0xFF&&oldiImage!=iImage) + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); + } + else if(itemType==CLCIT_INFO) { + int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn); + if (oldiImage!=0xFF&&oldiImage!=iImage) + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); + if(hItem == hItemAll) + SetAllChildIcons(hwndList,hItem,iColumn,iImage); + else + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); //hItemUnknown + } + else if(itemType==CLCIT_GROUP) { + int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn); + if (oldiImage!=0xFF&&oldiImage!=iImage) + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem); + if(hItem) + SetAllChildIcons(hwndList,hItem,iColumn,iImage); + } +} + +void SaveViewMode(const char *name, const TCHAR *szGroupFilter, const char *szProtoFilter, DWORD statusMask, DWORD stickyStatusMask, unsigned int options, + unsigned int stickies, unsigned int operators, unsigned int lmdat) +{ + char szSetting[512]; + + mir_snprintf(szSetting, 512, "%c%s_PF", 246, name); + cfg::writeString(NULL, CLVM_MODULE, szSetting, szProtoFilter); + mir_snprintf(szSetting, 512, "%c%s_GF", 246, name); + cfg::writeTString(NULL, CLVM_MODULE, szSetting, szGroupFilter); + mir_snprintf(szSetting, 512, "%c%s_SM", 246, name); + cfg::writeDword(CLVM_MODULE, szSetting, statusMask); + mir_snprintf(szSetting, 512, "%c%s_SSM", 246, name); + cfg::writeDword(CLVM_MODULE, szSetting, stickyStatusMask); + mir_snprintf(szSetting, 512, "%c%s_OPT", 246, name); + cfg::writeDword(CLVM_MODULE, szSetting, options); + mir_snprintf(szSetting, 512, "%c%s_LM", 246, name); + cfg::writeDword(CLVM_MODULE, szSetting, lmdat); + + cfg::writeDword(CLVM_MODULE, name, MAKELONG((unsigned short)operators, (unsigned short)stickies)); +} + +/* + * saves the state of the filter definitions for the current item + */ + +void SaveState() +{ + TCHAR newGroupFilter[2048] = _T("|"); + char newProtoFilter[2048] = "|"; + int i, iLen; + HWND hwndList; + char *szModeName = NULL; + DWORD statusMask = 0; + HANDLE hContact, hItem; + DWORD operators = 0; + + if(clvm_curItem == -1) + return; + + { + LVITEMA item = {0}; + char szTemp[256]; + + hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS); + for (i = 0; i < ListView_GetItemCount(hwndList); i++) { + if(ListView_GetCheckState(hwndList, i)) { + item.mask = LVIF_TEXT; + item.pszText = szTemp; + item.cchTextMax = 255; + item.iItem = i; + SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item); + strncat(newProtoFilter, szTemp, 2048); + strncat(newProtoFilter, "|", 2048); + newProtoFilter[2047] = 0; + } + } + } + + { + LVITEM item = {0}; + TCHAR szTemp[256]; + + hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS); + + operators |= ListView_GetCheckState(hwndList, 0) ? CLVM_INCLUDED_UNGROUPED : 0; + + for (i = 0; i < ListView_GetItemCount(hwndList); i++) { + if(ListView_GetCheckState(hwndList, i)) { + item.mask = LVIF_TEXT; + item.pszText = szTemp; + item.cchTextMax = 255; + item.iItem = i; + SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item); + _tcsncat(newGroupFilter, szTemp, 2048); + _tcsncat(newGroupFilter, _T("|"), 2048); + newGroupFilter[2047] = 0; + } + } + } + hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES); + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) { + if(ListView_GetCheckState(hwndList, i - ID_STATUS_OFFLINE)) + statusMask |= (1 << (i - ID_STATUS_OFFLINE)); + } + iLen = SendMessageA(GetDlgItem(clvmHwnd, IDC_VIEWMODES), LB_GETTEXTLEN, clvm_curItem, 0); + if(iLen) { + unsigned int stickies = 0; + DWORD dwGlobalMask, dwLocalMask; + BOOL translated; + + szModeName = ( char* )malloc(iLen + 1); + if(szModeName) { + DWORD options, lmdat; + //char *vastring = NULL; + //int len = GetWindowTextLengthA(GetDlgItem(clvmHwnd, IDC_VARIABLES)) + 1; + + //vastring = (char *)malloc(len); + //if(vastring) + // GetDlgItemTextA(clvmHwnd, IDC_VARIABLES, vastring, len); + SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szModeName); + dwGlobalMask = GetMaskForItem(hInfoItem); + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) { + hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0); + if(hItem) { + if(SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM)hItem, 0)) { + dwLocalMask = GetMaskForItem(hItem); + cfg::writeDword(hContact, "CLVM", szModeName, MAKELONG(1, (unsigned short)dwLocalMask)); + stickies++; + } + else { + if(cfg::getDword(hContact, "CLVM", szModeName, 0)) + cfg::writeDword(hContact, "CLVM", szModeName, 0); + } + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + operators |= ((SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_PROTOGROUP_OP : 0) | + (SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_GROUPSTATUS_OP : 0) | + (IsDlgButtonChecked(clvmHwnd, IDC_AUTOCLEAR) ? CLVM_AUTOCLEAR : 0) | + (IsDlgButtonChecked(clvmHwnd, IDC_LASTMSG) ? CLVM_USELASTMSG : 0)); + + options = SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_GETPOS, 0, 0); + + lmdat = MAKELONG(GetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, &translated, FALSE), + MAKEWORD(SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_GETCURSEL, 0, 0), + SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_GETCURSEL, 0, 0))); + + SaveViewMode(szModeName, newGroupFilter, newProtoFilter, statusMask, dwGlobalMask, options, + stickies, operators, lmdat); + //free(vastring); + free(szModeName); + } + } + Utils::enableDlgControl(clvmHwnd, IDC_APPLY, FALSE); +} + + +/* + * updates the filter list boxes with the data taken from the filtering string + */ + +void UpdateFilters() +{ + DBVARIANT dbv_pf = {0}; + DBVARIANT dbv_gf = {0}; + char szSetting[128]; + char *szBuf = NULL; + int iLen; + DWORD statusMask = 0, localMask = 0; + DWORD dwFlags; + DWORD opt; + char szTemp[100]; + + if(clvm_curItem == LB_ERR) + return; + + iLen = SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXTLEN, clvm_curItem, 0); + + if(iLen == 0) + return; + + szBuf = (char *)malloc(iLen + 1); + SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szBuf); + strncpy(g_szModename, szBuf, sizeof(g_szModename)); + g_szModename[sizeof(g_szModename) - 1] = 0; + mir_snprintf(szTemp, 100, Translate("Current view mode: %s"), g_szModename); + SetDlgItemTextA(clvmHwnd, IDC_CURVIEWMODE2, szTemp); + mir_snprintf(szSetting, 128, "%c%s_PF", 246, szBuf); + if(DBGetContactSetting(NULL, CLVM_MODULE, szSetting, &dbv_pf)) + goto cleanup; + mir_snprintf(szSetting, 128, "%c%s_GF", 246, szBuf); + if(cfg::getTString(NULL, CLVM_MODULE, szSetting, &dbv_gf)) + goto cleanup; + mir_snprintf(szSetting, 128, "%c%s_OPT", 246, szBuf); + if ((opt = cfg::getDword(NULL, CLVM_MODULE, szSetting, -1)) != -1) { + SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_SETPOS, 0, MAKELONG(LOWORD(opt), 0)); + } + mir_snprintf(szSetting, 128, "%c%s_SM", 246, szBuf); + statusMask = cfg::getDword(CLVM_MODULE, szSetting, -1); + mir_snprintf(szSetting, 128, "%c%s_SSM", 246, szBuf); + stickyStatusMask = cfg::getDword(CLVM_MODULE, szSetting, -1); + dwFlags = cfg::getDword(CLVM_MODULE, szBuf, 0); + { + LVITEMA item = {0}; + char szTemp[256]; + char szMask[256]; + int i; + HWND hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS); + + item.mask = LVIF_TEXT; + item.pszText = szTemp; + item.cchTextMax = 255; + + for (i = 0; i < ListView_GetItemCount(hwndList); i++) { + item.iItem = i; + SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item); + mir_snprintf(szMask, 256, "%s|", szTemp); + if(dbv_pf.pszVal && strstr(dbv_pf.pszVal, szMask)) + ListView_SetCheckState(hwndList, i, TRUE) + else + ListView_SetCheckState(hwndList, i, FALSE); + } + } + { + LVITEM item = {0}; + TCHAR szTemp[256]; + TCHAR szMask[256]; + int i; + HWND hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS); + + item.mask = LVIF_TEXT; + item.pszText = szTemp; + item.cchTextMax = 255; + + ListView_SetCheckState(hwndList, 0, dwFlags & CLVM_INCLUDED_UNGROUPED ? TRUE : FALSE); + + for (i = 1; i < ListView_GetItemCount(hwndList); i++) { + item.iItem = i; + SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item); + _sntprintf(szMask, 256, _T("%s|"), szTemp); + if(dbv_gf.ptszVal && _tcsstr(dbv_gf.ptszVal, szMask)) + ListView_SetCheckState(hwndList, i, TRUE) + else + ListView_SetCheckState(hwndList, i, FALSE); + } + } + { + HWND hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES); + int i; + + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) { + if ((1 << (i - ID_STATUS_OFFLINE)) & statusMask) + ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, TRUE) + else + ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, FALSE); + } + } + SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_SETCURSEL, dwFlags & CLVM_PROTOGROUP_OP ? 1 : 0, 0); + SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_SETCURSEL, dwFlags & CLVM_GROUPSTATUS_OP ? 1 : 0, 0); + CheckDlgButton(clvmHwnd, IDC_AUTOCLEAR, dwFlags & CLVM_AUTOCLEAR ? 1 : 0); + UpdateStickies(); + + { + int useLastMsg = dwFlags & CLVM_USELASTMSG; + DWORD lmdat; + BYTE bTmp; + + CheckDlgButton(clvmHwnd, IDC_LASTMSG, useLastMsg); + Utils::enableDlgControl(clvmHwnd, IDC_LASTMESSAGEOP, useLastMsg); + Utils::enableDlgControl(clvmHwnd, IDC_LASTMSGVALUE, useLastMsg); + Utils::enableDlgControl(clvmHwnd, IDC_LASTMESSAGEUNIT, useLastMsg); + + mir_snprintf(szSetting, 128, "%c%s_LM", 246, szBuf); + lmdat = cfg::getDword(CLVM_MODULE, szSetting, 0); + + SetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, LOWORD(lmdat), FALSE); + bTmp = LOBYTE(HIWORD(lmdat)); + SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, bTmp, 0); + bTmp = HIBYTE(HIWORD(lmdat)); + SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, bTmp, 0); + } + + ShowPage(clvmHwnd, 0); +cleanup: + DBFreeVariant(&dbv_pf); + DBFreeVariant(&dbv_gf); + free(szBuf); +} + +INT_PTR CALLBACK DlgProcViewModesSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + clvmHwnd = hwndDlg; + + switch(msg) { + case WM_INITDIALOG: + { + int i = 0; + TCITEMA tci; + RECT rcClient; + CLCINFOITEM cii = {0}; + HICON hIcon; + + if(IS_THEMED) + API::pfnEnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + + himlViewModes = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 12, 0); + for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + ImageList_AddIcon(himlViewModes, LoadSkinnedProtoIcon(NULL, i)); + + hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_MINIMIZE), IMAGE_ICON, 16, 16, 0); + nullImage = ImageList_AddIcon(himlViewModes, hIcon); + DestroyIcon(hIcon); + GetClientRect(hwndDlg, &rcClient); + + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = 0; + tci.pszText = Translate("Sticky contacts"); + SendMessageA(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEMA, (WPARAM)0, (LPARAM)&tci); + + tci.pszText = Translate("Filtering"); + SendMessageA(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEMA, (WPARAM)0, (LPARAM)&tci); + + TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), 0); + + TranslateDialogDefault(hwndDlg); + FillDialog(hwndDlg); + Utils::enableDlgControl(hwndDlg, IDC_ADDVIEWMODE, FALSE); + + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)himlViewModes); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRACOLUMNS, ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE, 0); + cii.cbSize = sizeof(cii); + cii.hParentGroup = 0; + cii.pszText = _T("*** All contacts ***"); + hInfoItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0); + if(SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, 0, 0) != LB_ERR) { + clvm_curItem = 0; + UpdateFilters(); + } + else + clvm_curItem = -1; + g_ViewModeOptDlg = TRUE; + i = 0; + while(_page2Controls[i] != 0) + ShowWindow(GetDlgItem(hwndDlg, _page2Controls[i++]), SW_HIDE); + ShowWindow(hwndDlg, SW_SHOWNORMAL); + Utils::enableDlgControl(hwndDlg, IDC_APPLY, FALSE); + SendDlgItemMessage(hwndDlg, IDC_AUTOCLEARSPIN, UDM_SETRANGE, 0, MAKELONG(1000, 0)); + SetWindowText(hwndDlg, TranslateT("Configure view modes")); + return TRUE; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_PROTOGROUPOP: + case IDC_GROUPSTATUSOP: + case IDC_LASTMESSAGEUNIT: + case IDC_LASTMESSAGEOP: + if (HIWORD(wParam) == CBN_SELCHANGE) + Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE); + break; + case IDC_AUTOCLEAR: + Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE); + break; + case IDC_LASTMSG: + { + int bUseLastMsg = IsDlgButtonChecked(hwndDlg, IDC_LASTMSG); + Utils::enableDlgControl(hwndDlg, IDC_LASTMESSAGEOP, bUseLastMsg); + Utils::enableDlgControl(hwndDlg, IDC_LASTMESSAGEUNIT, bUseLastMsg); + Utils::enableDlgControl(hwndDlg, IDC_LASTMSGVALUE, bUseLastMsg); + Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE); + break; + } + case IDC_AUTOCLEARVAL: + case IDC_LASTMSGVALUE: + if(HIWORD(wParam) == EN_CHANGE && GetFocus() == (HWND)lParam) + Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE); + break; + case IDC_DELETEVIEWMODE: + { + if(MessageBoxA(0, Translate("Really delete this view mode? This cannot be undone"), Translate("Delete a view mode"), MB_YESNO | MB_ICONQUESTION) == IDYES) { + char szSetting[256]; + int iLen = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETTEXTLEN, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0); + if(iLen) { + char *szBuf = ( char* )malloc(iLen + 1); + if(szBuf) { + HANDLE hContact; + + SendDlgItemMessageA(hwndDlg, IDC_VIEWMODES, LB_GETTEXT, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), (LPARAM)szBuf); + mir_snprintf(szSetting, 256, "%c%s_PF", 246, szBuf); + DBDeleteContactSetting(NULL, CLVM_MODULE, szSetting); + mir_snprintf(szSetting, 256, "%c%s_GF", 246, szBuf); + DBDeleteContactSetting(NULL, CLVM_MODULE, szSetting); + mir_snprintf(szSetting, 256, "%c%s_SM", 246, szBuf); + DBDeleteContactSetting(NULL, CLVM_MODULE, szSetting); + mir_snprintf(szSetting, 256, "%c%s_VA", 246, szBuf); + DBDeleteContactSetting(NULL, CLVM_MODULE, szSetting); + mir_snprintf(szSetting, 256, "%c%s_SSM", 246, szBuf); + DBDeleteContactSetting(NULL, CLVM_MODULE, szSetting); + DBDeleteContactSetting(NULL, CLVM_MODULE, szBuf); + if (!strcmp(cfg::dat.current_viewmode, szBuf) && lstrlenA(szBuf) == lstrlenA(cfg::dat.current_viewmode)) { + cfg::dat.bFilterEffective = 0; + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + SetWindowTextA(hwndSelector, Translate("No view mode")); + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) { + if(cfg::getDword(hContact, "CLVM", szBuf, -1) != -1) + cfg::writeDword(hContact, "CLVM", szBuf, 0); + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_DELETESTRING, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0); + if(SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, 0, 0) != LB_ERR) { + clvm_curItem = 0; + UpdateFilters(); + } + else + clvm_curItem = -1; + free(szBuf); + } + } + } + break; + } + case IDC_ADDVIEWMODE: + { + char szBuf[256]; + + szBuf[0] = 0; + GetDlgItemTextA(hwndDlg, IDC_NEWVIEMODE, szBuf, 256); + szBuf[255] = 0; + + if(lstrlenA(szBuf) > 2) { + if(cfg::getDword(CLVM_MODULE, szBuf, -1) != -1) + MessageBox(0, TranslateT("A view mode with this name does alredy exist"), TranslateT("Duplicate name"), MB_OK); + else { + int iNewItem = SendDlgItemMessageA(hwndDlg, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)szBuf); + if(iNewItem != LB_ERR) { + SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, (WPARAM)iNewItem, 0); + SaveViewMode(szBuf, _T(""), "", -1, -1, 0, 0, 0, 0); + clvm_curItem = iNewItem; + UpdateStickies(); + SendDlgItemMessage(hwndDlg, IDC_PROTOGROUPOP, CB_SETCURSEL, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_GROUPSTATUSOP, CB_SETCURSEL, 0, 0); + } + } + SetDlgItemTextA(hwndDlg, IDC_NEWVIEMODE, ""); + } + Utils::enableDlgControl(hwndDlg, IDC_ADDVIEWMODE, FALSE); + break; + } + case IDC_CLEARALL: + { + HANDLE hItem; + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + + while(hContact) { + hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0); + if(hItem) + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, 0); + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + } + case IDOK: + case IDC_APPLY: + SaveState(); + if(cfg::dat.bFilterEffective) + ApplyViewMode(cfg::dat.current_viewmode); + if(LOWORD(wParam) == IDOK) + DestroyWindow(hwndDlg); + break; + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + if(LOWORD(wParam) == IDC_NEWVIEMODE && HIWORD(wParam) == EN_CHANGE) + Utils::enableDlgControl(hwndDlg, IDC_ADDVIEWMODE, TRUE); + if(LOWORD(wParam) == IDC_VIEWMODES && HIWORD(wParam) == LBN_SELCHANGE) { + SaveState(); + clvm_curItem = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0); + UpdateFilters(); + } + break; + case WM_NOTIFY: + { + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_GROUPS: + case IDC_STATUSMODES: + case IDC_PROTOCOLS: + case IDC_CLIST: + if (((LPNMHDR) lParam)->code == NM_CLICK || ((LPNMHDR) lParam)->code == CLN_CHECKCHANGED) + Utils::enableDlgControl(hwndDlg, IDC_APPLY, TRUE); + switch (((LPNMHDR)lParam)->code) + { + case CLN_NEWCONTACT: + case CLN_LISTREBUILT: + //SetAllContactIcons(GetDlgItem(hwndDlg,IDC_CLIST)); + //fall through + /* + case CLN_CONTACTMOVED: + SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL); + break; + case CLN_OPTIONSCHANGED: + ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST)); + break; + case CLN_CHECKCHANGED: + { + HANDLE hItem; + NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam; + int typeOfItem = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETITEMTYPE,(WPARAM)nm->hItem, 0); + break; + }*/ + case NM_CLICK: + { + HANDLE hItem; + NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam; + DWORD hitFlags; + int iImage; + + if(nm->iColumn==-1) + break; + hItem = (HANDLE)SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(nm->pt.x,nm->pt.y)); + if(hItem==NULL) break; + if (!(hitFlags&CLCHT_ONITEMEXTRA)) + break; + iImage = SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn,0)); + if(iImage == nullImage) + iImage = nm->iColumn; + else if(iImage!=0xFF) + iImage = nullImage; + SetIconsForColumn(GetDlgItem(hwndDlg,IDC_CLIST),hItem,hInfoItem,nm->iColumn,iImage); + //SetListGroupIcons(GetDlgItem(hwndDlg,IDC_CLIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hInfoItem,NULL); + break; + } + } + break; + case IDC_TAB: + if (((LPNMHDR) lParam)->code == TCN_SELCHANGE) { + int id = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB)); + if(id == 0) + ShowPage(hwndDlg, 0); + else + ShowPage(hwndDlg, 1); + break; + } + + } + break; + } + case WM_DESTROY: + ImageList_RemoveAll(himlViewModes); + ImageList_Destroy(himlViewModes); + g_ViewModeOptDlg = FALSE; + break; + } + return FALSE; +} + +static int menuCounter = 0; + +static int FillMenuCallback(char *szSetting) +{ + if(szSetting[0] == (char)246) + return 1; + + AppendMenuA(hViewModeMenu, MF_STRING, menuCounter++, szSetting); + return 1; +} + +void BuildViewModeMenu() +{ + if(hViewModeMenu) + DestroyMenu(hViewModeMenu); + + menuCounter = 100; + hViewModeMenu = CreatePopupMenu(); + CLVM_EnumModes(FillMenuCallback); + + if(GetMenuItemCount(hViewModeMenu) > 0) + AppendMenu(hViewModeMenu, MF_SEPARATOR, 0, NULL); + + AppendMenu(hViewModeMenu, MF_STRING, 10001, TranslateT("Setup View Modes...")); + AppendMenu(hViewModeMenu, MF_STRING, 10002, TranslateT("Clear current View Mode")); + +} + +static UINT _buttons[] = {IDC_RESETMODES, IDC_SELECTMODE, IDC_CONFIGUREMODES, 0}; + +LRESULT CALLBACK ViewModeFrameWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_CREATE: + { + hwndSelector = CreateWindowEx(0, MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, + hwnd, (HMENU) IDC_SELECTMODE, g_hInst, NULL); + CustomizeButton(hwndSelector, false, false, false); + SendMessage(hwndSelector, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Select a view mode"), BATF_UNICODE); + SendMessage(hwndSelector, BUTTONSETASMENUACTION, 1, 0); + + HWND hwndButton = CreateWindowEx(0, MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, + hwnd, (HMENU) IDC_CONFIGUREMODES, g_hInst, NULL); + CustomizeButton(hwndButton, false, false, false); + SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Setup view modes"), BATF_UNICODE); + + hwndButton = CreateWindowEx(0, MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20, + hwnd, (HMENU) IDC_RESETMODES, g_hInst, NULL); + CustomizeButton(hwndButton, false, false, false); + SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Clear view mode and return to default display"), BATF_UNICODE); + + SendMessage(hwnd, WM_USER + 100, 0, 0); + return FALSE; + } + case WM_NCCALCSIZE: + { + BOOL hasTitleBar = wndFrameViewMode ? wndFrameViewMode->TitleBar.ShowTitleBar : 0; + return FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam, hasTitleBar); + } + case WM_NCPAINT: + { + BOOL hasTitleBar = wndFrameViewMode ? wndFrameViewMode->TitleBar.ShowTitleBar : 0; + return FrameNCPaint(hwnd, DefWindowProc, wParam, lParam, hasTitleBar); + } + case WM_SIZE: + { + RECT rcCLVMFrame; + HDWP PosBatch = BeginDeferWindowPos(3); + GetClientRect(hwnd, &rcCLVMFrame); + PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_RESETMODES), 0, + rcCLVMFrame.right - 23, 1, 22, 20, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS); + PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_CONFIGUREMODES), 0, + rcCLVMFrame.right - 45, 1, 22, 20, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS); + PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_SELECTMODE), 0, + 1, 1, rcCLVMFrame.right - 46, 20, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS); + EndDeferWindowPos(PosBatch); + break; + } + case WM_USER + 100: + SendMessage(GetDlgItem(hwnd, IDC_RESETMODES), BM_SETIMAGE, IMAGE_ICON, (LPARAM)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"CLN_CLVM_reset")); + SendMessage(GetDlgItem(hwnd, IDC_CONFIGUREMODES), BM_SETIMAGE, IMAGE_ICON, (LPARAM)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"CLN_CLVM_options")); + SendMessage(GetDlgItem(hwnd, IDC_SELECTMODE), BM_SETIMAGE, IMAGE_ICON, (LPARAM)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"CLN_CLVM_select")); + { + bool bSkinned = cfg::getByte("CLCExt", "bskinned", 0) != 0; + for (int i = 0; _buttons[i] != 0; i++ ) + CustomizeButton(hwnd, bSkinned, !bSkinned, bSkinned); + } + + if(cfg::dat.bFilterEffective) + SetWindowTextA(GetDlgItem(hwnd, IDC_SELECTMODE), cfg::dat.current_viewmode); + else + SetWindowText(GetDlgItem(hwnd, IDC_SELECTMODE), TranslateT("No view mode")); + break; + + case WM_ERASEBKGND: + break; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + RECT rc; + //HDC hdc = (HDC)wParam; + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hbm, hbmold; + + GetClientRect(hwnd, &rc); + hbm = CreateCompatibleBitmap(hdc, rc.right, rc.bottom); + hbmold = (HBITMAP)SelectObject(hdcMem, hbm); + + if(cfg::dat.bWallpaperMode) + SkinDrawBg(hwnd, hdcMem); + else + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_3DFACE)); + + BitBlt(hdc, 0, 0, rc.right, rc.bottom, hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hbmold); + DeleteObject(hbm); + DeleteDC(hdcMem); + //InvalidateRect(GetDlgItem(hwnd, IDC_RESETMODES), NULL, FALSE); + //InvalidateRect(GetDlgItem(hwnd, IDC_CONFIGUREMODES), NULL, FALSE); + //InvalidateRect(GetDlgItem(hwnd, IDC_SELECTMODE), NULL, FALSE); + EndPaint(hwnd, &ps); + return 0; + } + case WM_TIMER: + { + switch(wParam) { + case TIMERID_VIEWMODEEXPIRE: + { + POINT pt; + RECT rcCLUI; + + GetWindowRect(pcli->hwndContactList, &rcCLUI); + GetCursorPos(&pt); + if(PtInRect(&rcCLUI, pt)) + break; + + KillTimer(hwnd, wParam); + if (!cfg::dat.old_viewmode[0]) + SendMessage(hwnd, WM_COMMAND, IDC_RESETMODES, 0); + else + ApplyViewMode((const char *)cfg::dat.old_viewmode); + break; + } } + break; + } + case WM_COMMAND: + { + switch(LOWORD(wParam)) { + case IDC_SELECTMODE: + { + RECT rc; + POINT pt; + int selection; + MENUITEMINFOA mii = {0}; + char szTemp[256]; + + BuildViewModeMenu(); + //GetWindowRect(GetDlgItem(hwnd, IDC_SELECTMODE), &rc); + GetWindowRect((HWND)lParam, &rc); + pt.x = rc.left; + pt.y = rc.bottom; + selection = TrackPopupMenu(hViewModeMenu,TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL); + if(selection) { + + if(selection == 10001) + goto clvm_config_command; + else if(selection == 10002) + goto clvm_reset_command; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + mii.dwTypeData = szTemp; + mii.cch = 256; + GetMenuItemInfoA(hViewModeMenu, selection, FALSE, &mii); + ApplyViewMode(szTemp); + } + break; + } + case IDC_RESETMODES: +clvm_reset_command: + cfg::dat.bFilterEffective = 0; + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + SetWindowTextA(GetDlgItem(hwnd, IDC_SELECTMODE), Translate("No view mode")); + CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)cfg::dat.boldHideOffline, 0); + cfg::dat.boldHideOffline = (BYTE)-1; + cfg::dat.current_viewmode[0] = 0; + cfg::dat.old_viewmode[0] = 0; + cfg::writeString(NULL, "CList", "LastViewMode", ""); + break; + case IDC_CONFIGUREMODES: +clvm_config_command: + if (!g_ViewModeOptDlg) + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_OPT_VIEWMODES), 0, DlgProcViewModesSetup, 0); + break; + } + break; + } + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return TRUE; +} + +static HWND hCLVMFrame; +HWND g_hwndViewModeFrame; + +void CreateViewModeFrame() +{ + CLISTFrame frame = {0}; + WNDCLASS wndclass = {0}; + + wndclass.style = 0; + wndclass.lpfnWndProc = ViewModeFrameWndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = g_hInst; + wndclass.hIcon = 0; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH) (COLOR_3DFACE); + wndclass.lpszMenuName = 0; + wndclass.lpszClassName = _T("CLVMFrameWindow"); + + RegisterClass(&wndclass); + + ZeroMemory(&frame, sizeof(frame)); + frame.cbSize = sizeof(frame); + frame.tname = _T("View modes"); + frame.TBtname = TranslateT("View Modes"); + frame.hIcon = 0; + frame.height = 22; + frame.Flags=F_VISIBLE|F_SHOWTBTIP|F_NOBORDER|F_TCHAR; + frame.align = alBottom; + frame.hWnd = CreateWindowEx(0, _T("CLVMFrameWindow"), _T("CLVM"), WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_CLIPCHILDREN, 0, 0, 20, 20, pcli->hwndContactList, (HMENU) 0, g_hInst, NULL); + g_hwndViewModeFrame = frame.hWnd; + hCLVMFrame = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&frame,(LPARAM)0); + CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)hCLVMFrame, FU_FMPOS); +} + +const char *MakeVariablesString(const char *src, const char *UIN); + +void ApplyViewMode(const char *name) +{ + char szSetting[256]; + DBVARIANT dbv = {0}; + + cfg::dat.bFilterEffective = 0; + + mir_snprintf(szSetting, 256, "%c%s_PF", 246, name); + if (!cfg::getString(NULL, CLVM_MODULE, szSetting, &dbv)) { + if(lstrlenA(dbv.pszVal) >= 2) { + strncpy(cfg::dat.protoFilter, dbv.pszVal, sizeof(cfg::dat.protoFilter)); + cfg::dat.protoFilter[sizeof(cfg::dat.protoFilter) - 1] = 0; + cfg::dat.bFilterEffective |= CLVM_FILTER_PROTOS; + } + mir_free(dbv.pszVal); + } + mir_snprintf(szSetting, 256, "%c%s_GF", 246, name); + if (!cfg::getTString(NULL, CLVM_MODULE, szSetting, &dbv)) { + if(lstrlen(dbv.ptszVal) >= 2) { + _tcsncpy(cfg::dat.groupFilter, dbv.ptszVal, safe_sizeof(cfg::dat.groupFilter)); + cfg::dat.groupFilter[safe_sizeof(cfg::dat.groupFilter) - 1] = 0; + cfg::dat.bFilterEffective |= CLVM_FILTER_GROUPS; + } + mir_free(dbv.ptszVal); + } + mir_snprintf(szSetting, 256, "%c%s_SM", 246, name); + cfg::dat.statusMaskFilter = cfg::getDword(CLVM_MODULE, szSetting, -1); + if(cfg::dat.statusMaskFilter >= 1) + cfg::dat.bFilterEffective |= CLVM_FILTER_STATUS; + + mir_snprintf(szSetting, 256, "%c%s_SSM", 246, name); + cfg::dat.stickyMaskFilter = cfg::getDword(CLVM_MODULE, szSetting, -1); + if(cfg::dat.stickyMaskFilter != -1) + cfg::dat.bFilterEffective |= CLVM_FILTER_STICKYSTATUS; + + /* + mir_snprintf(szSetting, 256, "%c%s_VA", 246, name); + if (!DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv)) { + strncpy(g_CluiData.varFilter, dbv.pszVal, sizeof(g_CluiData.varFilter)); + g_CluiData.varFilter[sizeof(g_CluiData.varFilter) - 1] = 0; + if(lstrlenA(g_CluiData.varFilter) > 10 && ServiceExists(MS_VARS_FORMATSTRING)) + g_CluiData.bFilterEffective |= CLVM_FILTER_VARIABLES; + mir_free(dbv.ptszVal); + if(g_CluiData.bFilterEffective & CLVM_FILTER_VARIABLES) { + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + char UIN[256]; + char *id, *szProto; + const char *varstring; + char *temp; + FORMATINFO fi; + + while(hContact) { + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if(szProto) { + id = (char*) CallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); + if(id) { + if (!DBGetContactSetting(hContact, szProto, id, &dbv)) { + if(dbv.type == DBVT_ASCIIZ) { + mir_snprintf(UIN, 256, "<%s:%s>", szProto, dbv.pszVal); + } + else { + mir_snprintf(UIN, 256, "<%s:%d>", szProto, dbv.dVal); + } + varstring = MakeVariablesString(g_CluiData.varFilter, UIN); + ZeroMemory(&fi, sizeof(fi)); + fi.cbSize = sizeof(fi); + fi.szFormat = varstring; + fi.szSource = ""; + fi.hContact = 0; + temp = (char *)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0); + if(temp && atol(temp) > 0) + _DebugPopup(hContact, "%s, %d, %d, %d", temp, temp, fi.pCount, fi.eCount); + variables_free(temp); + DBFreeVariant(&dbv); + } + } + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + } + }*/ + + cfg::dat.filterFlags = cfg::getDword(CLVM_MODULE, name, 0); + + KillTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE); + + if(cfg::dat.filterFlags & CLVM_AUTOCLEAR) { + DWORD timerexpire; + mir_snprintf(szSetting, 256, "%c%s_OPT", 246, name); + timerexpire = LOWORD(cfg::getDword(CLVM_MODULE, szSetting, 0)); + strncpy(cfg::dat.old_viewmode, cfg::dat.current_viewmode, 256); + cfg::dat.old_viewmode[255] = 0; + SetTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE, timerexpire * 1000, NULL); + } + strncpy(cfg::dat.current_viewmode, name, 256); + cfg::dat.current_viewmode[255] = 0; + + if(cfg::dat.filterFlags & CLVM_USELASTMSG) { + DWORD unit; + int i; + BYTE bSaved = cfg::dat.sortOrder[0]; + + cfg::dat.sortOrder[0] = SORTBY_LASTMSG; + for (i = 0; i < cfg::nextCacheEntry; i++) + cfg::eCache[i].dwLastMsgTime = INTSORT_GetLastMsgTime(cfg::eCache[i].hContact); + + cfg::dat.sortOrder[0] = bSaved; + + cfg::dat.bFilterEffective |= CLVM_FILTER_LASTMSG; + mir_snprintf(szSetting, 256, "%c%s_LM", 246, name); + cfg::dat.lastMsgFilter = cfg::getDword(CLVM_MODULE, szSetting, 0); + if(LOBYTE(HIWORD(cfg::dat.lastMsgFilter))) + cfg::dat.bFilterEffective |= CLVM_FILTER_LASTMSG_NEWERTHAN; + else + cfg::dat.bFilterEffective |= CLVM_FILTER_LASTMSG_OLDERTHAN; + unit = LOWORD(cfg::dat.lastMsgFilter); + switch(HIBYTE(HIWORD(cfg::dat.lastMsgFilter))) { + case 0: + unit *= 60; + break; + case 1: + unit *= 3600; + break; + case 2: + unit *= 86400; + break; + } + cfg::dat.lastMsgFilter = unit; + } + + if(HIWORD(cfg::dat.filterFlags) > 0) + cfg::dat.bFilterEffective |= CLVM_STICKY_CONTACTS; + + if(cfg::dat.boldHideOffline == (BYTE)-1) + cfg::dat.boldHideOffline = cfg::getByte("CList", "HideOffline", 0); + + CallService(MS_CLIST_SETHIDEOFFLINE, 0, 0); + SetWindowTextA(hwndSelector, name); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + + cfg::writeString(NULL, "CList", "LastViewMode", cfg::dat.current_viewmode); +} + + diff --git a/plugins/Clist_nicer/src/wallpaper.cpp b/plugins/Clist_nicer/src/wallpaper.cpp new file mode 100644 index 0000000000..1e16afe50a --- /dev/null +++ b/plugins/Clist_nicer/src/wallpaper.cpp @@ -0,0 +1,56 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2003 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 + +typedef enum { + WPS_TILED=0, + WPS_CENTERED, + WPS_STRETCHED +} wallpaperstyle_t; + +HBITMAP hPattern; +HBITMAP hAsSeenOnDesk; + +/* +void GetWallpaperPattern() +{ + // \Control Panel\Desktop + char wpbuf[MAX_PATH]; + if(hPattern) {DeleteObject(hPattern); hPattern=NULL;} + SystemParametersInfo(SPI_GETDESKWALLPAPER,MAX_PATH,wpbuf,NULL); + + if (strlen(wpbuf)>0) + { + hPattern = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)wpbuf); + } +} + +void GetWallpaperStyle() +{ + HKEY regk; + char buff[256]; + RegOpenKeyEx(HKEY_CURRENT_USER,"\\Control Panel\\Desktop",0,KEY_READ,®k); + RegQueryValueEx(regk,"OriginalWallpaper",0,NULL,&buff,256); + MessageBox(0,buff,"",0); +}*/ \ No newline at end of file -- cgit v1.2.3