summaryrefslogtreecommitdiff
path: root/plugins/Clist_nicer/src
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-08-01 05:54:33 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-08-01 05:54:33 +0000
commit8d284bebe3c2392680949c06bbd17253960ce0f8 (patch)
treeedc69c2a8a0e3d15a8d31b38b88b2843585bda0e /plugins/Clist_nicer/src
parentee71ed09de7ce60a6a3d60c778f60db4f3e0a9b8 (diff)
git-svn-id: http://svn.miranda-ng.org/main/trunk@1295 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Clist_nicer/src')
-rw-r--r--plugins/Clist_nicer/src/CLCButton.cpp552
-rw-r--r--plugins/Clist_nicer/src/CLUIFrames/cluiframes.cpp3584
-rw-r--r--plugins/Clist_nicer/src/CLUIFrames/cluiframes.h105
-rw-r--r--plugins/Clist_nicer/src/CLUIFrames/framesmenu.cpp228
-rw-r--r--plugins/Clist_nicer/src/CLUIFrames/groupmenu.cpp704
-rw-r--r--plugins/Clist_nicer/src/CLUIFrames/movetogroup.cpp60
-rw-r--r--plugins/Clist_nicer/src/Coolsb/coolsb_internal.h95
-rw-r--r--plugins/Clist_nicer/src/Coolsb/coolsblib.cpp1003
-rw-r--r--plugins/Clist_nicer/src/Coolsb/coolsblib.h41
-rw-r--r--plugins/Clist_nicer/src/Coolsb/coolscroll.cpp3206
-rw-r--r--plugins/Clist_nicer/src/Coolsb/coolscroll.h232
-rw-r--r--plugins/Clist_nicer/src/Coolsb/userdefs.h79
-rw-r--r--plugins/Clist_nicer/src/Docking.cpp286
-rw-r--r--plugins/Clist_nicer/src/Include/alphablend.h30
-rw-r--r--plugins/Clist_nicer/src/Include/clc.h632
-rw-r--r--plugins/Clist_nicer/src/Include/clist.h48
-rw-r--r--plugins/Clist_nicer/src/Include/commonheaders.h223
-rw-r--r--plugins/Clist_nicer/src/Include/config.h209
-rw-r--r--plugins/Clist_nicer/src/Include/extBackg.h97
-rw-r--r--plugins/Clist_nicer/src/Include/m_cln_skinedit.h174
-rw-r--r--plugins/Clist_nicer/src/Include/resource.h416
-rw-r--r--plugins/Clist_nicer/src/Include/rowheight_funcs.h85
-rw-r--r--plugins/Clist_nicer/src/Include/vsstyle.h1606
-rw-r--r--plugins/Clist_nicer/src/Include/vssym32.h712
-rw-r--r--plugins/Clist_nicer/src/alphablend.cpp545
-rw-r--r--plugins/Clist_nicer/src/clc.cpp806
-rw-r--r--plugins/Clist_nicer/src/clcidents.cpp102
-rw-r--r--plugins/Clist_nicer/src/clcitems.cpp659
-rw-r--r--plugins/Clist_nicer/src/clcmsgs.cpp221
-rw-r--r--plugins/Clist_nicer/src/clcopts.cpp1620
-rw-r--r--plugins/Clist_nicer/src/clcpaint.cpp1674
-rw-r--r--plugins/Clist_nicer/src/clcutils.cpp624
-rw-r--r--plugins/Clist_nicer/src/clistevents.cpp397
-rw-r--r--plugins/Clist_nicer/src/clistmenus.cpp493
-rw-r--r--plugins/Clist_nicer/src/clistmod.cpp258
-rw-r--r--plugins/Clist_nicer/src/clistopts.cpp220
-rw-r--r--plugins/Clist_nicer/src/clistsettings.cpp33
-rw-r--r--plugins/Clist_nicer/src/clisttray.cpp171
-rw-r--r--plugins/Clist_nicer/src/clnplus.cpp40
-rw-r--r--plugins/Clist_nicer/src/clui.cpp2191
-rw-r--r--plugins/Clist_nicer/src/cluiopts.cpp476
-rw-r--r--plugins/Clist_nicer/src/cluiservices.cpp261
-rw-r--r--plugins/Clist_nicer/src/commonheaders.cpp1
-rw-r--r--plugins/Clist_nicer/src/config.cpp482
-rw-r--r--plugins/Clist_nicer/src/contact.cpp333
-rw-r--r--plugins/Clist_nicer/src/extBackg.cpp1859
-rw-r--r--plugins/Clist_nicer/src/init.cpp386
-rw-r--r--plugins/Clist_nicer/src/rowheight_funcs.cpp287
-rw-r--r--plugins/Clist_nicer/src/statusbar.cpp197
-rw-r--r--plugins/Clist_nicer/src/statusfloater.cpp1240
-rw-r--r--plugins/Clist_nicer/src/viewmodes.cpp1249
-rw-r--r--plugins/Clist_nicer/src/wallpaper.cpp56
52 files changed, 31288 insertions, 0 deletions
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 <m_button_int.h>
+#include <m_toptoolbar.h>
+
+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<HBITMAP>(SelectObject(hdcMem, hbmMem));
+
+ hOldFont = reinterpret_cast<HFONT>(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 <commonheaders.h>
+#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<alclient frame height
+ int alfrm = CLUIFramesGetalClientFrame();
+
+ if (alfrm != -1) {
+ Frames[FrameId].collapsed = FALSE;
+ if (Frames[alfrm].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<HBITMAP>(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<HPEN>(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<HBRUSH>(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<HBITMAP>(SelectObject(hdcMem, hBmpOsb));
+
+ SetBkMode(hdcMem, TRANSPARENT);
+
+ hBack = GetSysColorBrush(COLOR_3DFACE);
+ hoBrush = reinterpret_cast<HBRUSH>(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<HFONT>(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<HPEN>(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<HBRUSH>(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<pThreadFuncEx>(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 <commonheaders.h>
+#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<lpFrameMenuExecParam>(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)&param);
+ 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 <commonheaders.h>
+
+//////////////////////////////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)&param);
+ //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)&param);
+ 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 <commonheaders.h>
+
+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 <windows.h>
+
+//
+// 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 <commonheaders.h>
+#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 <windows.h>
+
+
+#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 <commonheaders.h>
+#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<HBITMAP>(SelectObject(hdcmem1, hbm1));
+
+
+ //NORMAL bitmap to draw the arrow into
+ hdcmem2 = CreateCompatibleDC(hdc);
+ hbm2 = CreateCompatibleBitmap(hdc, width, height);
+ UnrealizeObject(hbm2);
+ oldbm2 = reinterpret_cast<HBITMAP>(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<HBRUSH>(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 <windows.h>
+#include <win2k.h>
+
+// 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 <m_stdhdr.h>
+#include <windows.h>
+#include <commctrl.h>
+#include <uxtheme.h>
+#include <vssym32.h>
+#include <stdio.h>
+#include <time.h>
+#include <stddef.h>
+#include <process.h>
+#include <io.h>
+#include <string.h>
+#include <direct.h>
+#include <math.h>
+#include <shlwapi.h>
+#include "resource.h"
+#include <newpluginapi.h>
+#include <win2k.h>
+#include <m_clist.h>
+#include <m_clistint.h>
+#include <m_clui.h>
+#include <m_system.h>
+#include <m_utils.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_avatars.h>
+#include <m_button.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_file.h>
+#include <m_addcontact.h>
+#include <m_message.h>
+#include <m_timezones.h>
+#include <m_genmenu.h>
+#include <m_cluiframes.h>
+#include <m_clui.h>
+#include <m_icolib.h>
+#include <m_popup.h>
+#include <m_fontservice.h>
+#include <m_metacontacts.h>
+#include <m_cln_skinedit.h>
+
+#include "extbackg.h"
+#include "clc.h"
+#include <config.h>
+
+
+#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 <stdexcept>
+
+#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<HPEN>(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<HPEN>(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<HBITMAP>(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<HBITMAP>(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<HBRUSH>(SelectObject(hdc, BrMask));
+ holdbitmap = reinterpret_cast<HBITMAP>(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<HBITMAP>(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 <commonheaders.h>
+#include <resource.h>
+#include <m_userinfo.h>
+#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 <commonheaders.h>
+
+/* 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(posy<dat->yScroll)
+ *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 <commonheaders.h>
+#include <m_icq.h>
+
+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<StatusItems_t *>(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 <commonheaders.h>
+
+//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 <commonheaders.h>
+#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<HICON>(LoadImage(g_hInst, MAKEINTRESOURCE(IDI_NOTICK), IMAGE_ICON, 16, 16, 0));
+ HICON hIconTick = reinterpret_cast<HICON>(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("<current>"));
+
+ 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<HFONT>(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<HICON>(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<HBITMAP>(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<HBITMAP>(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<HBITMAP>(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<HBITMAP>(SelectObject(hdcMem, hBmpOsb));
+ {
+ TEXTMETRIC tm;
+ hOldFont = reinterpret_cast<HFONT>(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 <commonheaders.h>
+#include <richedit.h>
+#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<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont));
+ else
+ hFont = reinterpret_cast<HFONT>(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<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont));
+ else
+ hFont = reinterpret_cast<HFONT>(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->selection<groupy+contentCount) dat->selection=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 (h<dat->fontInfo[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<HBITMAP>(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<HBITMAP>(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<HBITMAP>(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 <commonheaders.h>
+#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<CListEvent *>(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<HBITMAP>(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 <commonheaders.h>
+#include <m_genmenu.h>
+#include <m_ignore.h>
+#include "../CLUIFrames/cluiframes.h"
+
+#pragma hdrstop
+
+static HMENU hMainMenu, hMainStatusMenu;
+
+void DestroyTrayMenu(HMENU hMenu)
+{
+ int i, cnt;
+
+ cnt = GetMenuItemCount(hMenu);
+ for (i=0; i<cnt; ++i)
+ {
+ HMENU hSubMenu = GetSubMenu(hMenu, i);
+ if (hSubMenu == hMainStatusMenu || hSubMenu == hMainMenu)
+ RemoveMenu(hMenu, i--, MF_BYPOSITION);
+ }
+ DestroyMenu(hMenu);
+}
+
+INT_PTR CloseAction(WPARAM wParam,LPARAM lParam)
+{
+ int k;
+ cfg::shutDown = 1;
+ k=CallService(MS_SYSTEM_OKTOEXIT,(WPARAM)0,(LPARAM)0);
+ if (k) {
+ DestroyWindow(pcli->hwndContactList);
+ 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 <commonheaders.h>
+
+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 <commonheaders.h>
+#include <shobjidl.h>
+
+#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 <commonheaders.h>
+#include <m_findadd.h>
+#include <m_icq.h>
+#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<TCHAR *>(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<HBITMAP>(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<HBITMAP>(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 <commonheaders.h>
+#include "../cluiframes/cluiframes.h"
+#include <m_icq.h>
+
+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;nPanel<nParts;nPanel++)
+ {
+ ProtocolData *PD;
+ PD=(ProtocolData *)SendMessage(pcli->hwndStatus,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<HFONT>(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 <commonheaders.h> \ 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 <commonheaders.h>
+
+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<char *>(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 <commonheaders.h>
+
+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 <commonheaders.h>
+#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<HBITMAP>(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<ImageItem *>(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<ImageItem *>(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<ImageItem *>(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<ImageItem *>(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<char *>(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<char *>(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<StatusItems_t *>(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;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:
+ {
+ 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 <commonheaders.h>
+#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<TExtraCache *>(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 <commonheaders.h>
+#include <rowheight_funcs.h>
+
+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 <commonheaders.h>
+#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<HBITMAP>(SelectObject(hdcMem, hbmMem));
+ SetBkMode(hdcMem, TRANSPARENT);
+ hOldFont = reinterpret_cast<HFONT>(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, "<b>%s</b>: %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 <commonheaders.h>
+
+#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<HFONT>(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<HFONT>(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<HBITMAP>(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<HFONT>(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<HBITMAP>(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<HBITMAP>(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 <commonheaders.h>
+#include <m_variables.h>
+#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 <commonheaders.h>
+
+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,&regk);
+ RegQueryValueEx(regk,"OriginalWallpaper",0,NULL,&buff,256);
+ MessageBox(0,buff,"",0);
+}*/ \ No newline at end of file