summaryrefslogtreecommitdiff
path: root/plugins/Clist_nicer/src/clcpaint.cpp
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/clcpaint.cpp
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/clcpaint.cpp')
-rw-r--r--plugins/Clist_nicer/src/clcpaint.cpp1674
1 files changed, 1674 insertions, 0 deletions
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();
+}