From 8d284bebe3c2392680949c06bbd17253960ce0f8 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Wed, 1 Aug 2012 05:54:33 +0000 Subject: git-svn-id: http://svn.miranda-ng.org/main/trunk@1295 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Clist_nicer/src/clcpaint.cpp | 1674 ++++++++++++++++++++++++++++++++++ 1 file changed, 1674 insertions(+) create mode 100644 plugins/Clist_nicer/src/clcpaint.cpp (limited to 'plugins/Clist_nicer/src/clcpaint.cpp') diff --git a/plugins/Clist_nicer/src/clcpaint.cpp b/plugins/Clist_nicer/src/clcpaint.cpp new file mode 100644 index 0000000000..c9b11d07b3 --- /dev/null +++ b/plugins/Clist_nicer/src/clcpaint.cpp @@ -0,0 +1,1674 @@ +/* + * astyle --force-indent=tab=4 --brackets=linux --indent-switches + * --pad=oper --one-line=keep-blocks --unpad=paren + * + * Miranda IM: the free IM client for Microsoft* Windows* + * + * Copyright 2000-2010 Miranda ICQ/IM project, + * all portions of this codebase are copyrighted to the people + * listed in contributors.txt. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * you should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * part of clist_nicer plugin for Miranda. + * + * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + * + * $Id: clcpaint.cpp 12909 2010-10-06 14:53:00Z silvercircle $ + * + */ + +#include "commonheaders.h" + +extern struct avatarCache *g_avatarCache; +extern int g_curAvatar; + +extern ImageItem *g_glyphItem; + +extern int hClcProtoCount; +extern ORDERTREEDATA OrderTreeData[]; + +extern HIMAGELIST hCListImages; +static BYTE divide3[765] = {255}; +extern char *im_clients[]; +extern HICON im_clienthIcons[]; +extern HICON overlayicons[]; + +extern TCHAR *statusNames[]; + +extern LONG g_cxsmIcon, g_cysmIcon; +extern StatusItems_t *StatusItems; + +int g_hottrack, g_center, g_ignoreselforgroups, g_selectiveIcon, g_exIconSpacing, g_hottrack_done; +HWND g_focusWnd; +BYTE selBlend; +BYTE saved_alpha; +int my_status; + +BOOL g_inCLCpaint = FALSE; +int g_list_avatars = 0; + +HFONT __fastcall ChangeToFont(HDC hdc, struct ClcData *dat, int id, int *fontHeight) +{ + HFONT hOldFont = 0; + /* + hOldFont = SelectObject(hdc, dat->fontInfo[id].hFont); + SetTextColor(hdc, dat->fontInfo[id].colour); + if (fontHeight) + *fontHeight = dat->fontInfo[id].fontHeight; + */ + hOldFont = reinterpret_cast(SelectObject(hdc, cfg::clcdat->fontInfo[id].hFont)); + SetTextColor(hdc, cfg::clcdat->fontInfo[id].colour); + if (fontHeight) + *fontHeight = cfg::clcdat->fontInfo[id].fontHeight; + + dat->currentFontID = id; + return hOldFont; +} + +static void __inline SetHotTrackColour(HDC hdc, struct ClcData *dat) +{ + if (dat->gammaCorrection) { + COLORREF oldCol, newCol; + int oldLum, newLum; + + oldCol = GetTextColor(hdc); + oldLum = (GetRValue(oldCol) * 30 + GetGValue(oldCol) * 59 + GetBValue(oldCol) * 11) / 100; + newLum = (GetRValue(dat->hotTextColour) * 30 + GetGValue(dat->hotTextColour) * 59 + GetBValue(dat->hotTextColour) * 11) / 100; + if (newLum == 0) { + SetTextColor(hdc, dat->hotTextColour); + return; + } + if (newLum >= oldLum + 20) { + oldLum += 20; + newCol = RGB(GetRValue(dat->hotTextColour) * oldLum / newLum, GetGValue(dat->hotTextColour) * oldLum / newLum, GetBValue(dat->hotTextColour) * oldLum / newLum); + } else if (newLum <= oldLum) { + int r, g, b; + r = GetRValue(dat->hotTextColour) * oldLum / newLum; + g = GetGValue(dat->hotTextColour) * oldLum / newLum; + b = GetBValue(dat->hotTextColour) * oldLum / newLum; + if (r > 255) { + g +=(r-255)*3 / 7; + b +=(r-255)*3 / 7; + r = 255; + } + if (g > 255) { + r +=(g-255)*59 / 41; + if (r > 255) + r = 255; + b +=(g-255)*59 / 41; + g = 255; + } + if (b > 255) { + r +=(b-255)*11 / 89; + if (r > 255) + r = 255; + g +=(b-255)*11 / 89; + if (g > 255) + g = 255; + b = 255; + } + newCol = RGB(r, g, b); + } else + newCol = dat->hotTextColour; + SetTextColor(hdc, newCol); + } else + SetTextColor(hdc, dat->hotTextColour); +} + +int __fastcall GetStatusOnlineness(int status) +{ + if(status >= ID_STATUS_CONNECTING && status < ID_STATUS_OFFLINE) + return 120; + + switch (status) { + case ID_STATUS_FREECHAT: + return 110; + case ID_STATUS_ONLINE: + return 100; + case ID_STATUS_OCCUPIED: + return 60; + case ID_STATUS_ONTHEPHONE: + return 50; + case ID_STATUS_DND: + return 40; + case ID_STATUS_AWAY: + return 30; + case ID_STATUS_OUTTOLUNCH: + return 20; + case ID_STATUS_NA: + return 10; + case ID_STATUS_INVISIBLE: + return 5; + } + return 0; +} + +static int __fastcall GetGeneralisedStatus(void) +{ + int i, status, thisStatus, statusOnlineness, thisOnlineness; + + status = ID_STATUS_OFFLINE; + statusOnlineness = 0; + + for (i = 0; i < pcli->hClcProtoCount; i++) { + thisStatus = pcli->clcProto[i].dwStatus; + if (thisStatus == ID_STATUS_INVISIBLE) + return ID_STATUS_INVISIBLE; + thisOnlineness = GetStatusOnlineness(thisStatus); + if (thisOnlineness > statusOnlineness) { + status = thisStatus; + statusOnlineness = thisOnlineness; + } + } + return status; +} + +static int __fastcall GetRealStatus(struct ClcContact *contact, int status) +{ + int i; + char *szProto = contact->proto; + if (!szProto) + return status; + for (i = 0; i < pcli->hClcProtoCount; i++) { + if (!lstrcmpA(pcli->clcProto[i].szProto, szProto)) { + return pcli->clcProto[i].dwStatus; + } + } + return status; +} + +int GetBasicFontID(struct ClcContact * contact) +{ + switch (contact->type) + { + case CLCIT_GROUP: + return FONTID_GROUPS; + break; + case CLCIT_INFO: + if(contact->flags & CLCIIF_GROUPFONT) + return FONTID_GROUPS; + else + return FONTID_CONTACTS; + break; + case CLCIT_DIVIDER: + return FONTID_DIVIDERS; + break; + case CLCIT_CONTACT: + if (contact->flags & CONTACTF_NOTONLIST) + return FONTID_NOTONLIST; + else if ((contact->flags&CONTACTF_INVISTO && GetRealStatus(contact, ID_STATUS_OFFLINE) != ID_STATUS_INVISIBLE) + || (contact->flags&CONTACTF_VISTO && GetRealStatus(contact, ID_STATUS_OFFLINE) == ID_STATUS_INVISIBLE)) + return contact->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS; + else + return contact->flags & CONTACTF_ONLINE ? FONTID_CONTACTS : FONTID_OFFLINE; + break; + default: + return FONTID_CONTACTS; + } +} + +void PaintNotifyArea(HDC hDC, RECT *rc) +{ + struct ClcData *dat = (struct ClcData *) GetWindowLongPtr(pcli->hwndContactTree, 0); + int iCount; + static int ev_lastIcon = 0; + + rc->left += 26; // button + iCount = GetMenuItemCount(cfg::dat.hMenuNotify); + if (cfg::dat.hUpdateContact != 0) { + TCHAR *szName = pcli->pfnGetContactDisplayName(cfg::dat.hUpdateContact, 0); + int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) cfg::dat.hUpdateContact, 0); + + ImageList_DrawEx(hCListImages, iIcon, hDC, rc->left, (rc->bottom + rc->top - g_cysmIcon) / 2, g_cxsmIcon, g_cysmIcon, CLR_NONE, CLR_NONE, ILD_NORMAL); + rc->left += 18; + DrawText(hDC, szName, -1, rc, DT_VCENTER | DT_SINGLELINE); + ImageList_DrawEx(hCListImages, (int)cfg::dat.hIconNotify, hDC, 4, (rc->bottom + rc->top - 16) / 2, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL); + ev_lastIcon = cfg::dat.hIconNotify; + } else if (iCount > 0) { + MENUITEMINFO mii = {0}; + struct NotifyMenuItemExData *nmi; + TCHAR *szName; + int iIcon; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA; + GetMenuItemInfo(cfg::dat.hMenuNotify, iCount - 1, TRUE, &mii); + nmi = (struct NotifyMenuItemExData *) mii.dwItemData; + szName = pcli->pfnGetContactDisplayName(nmi->hContact, 0); + iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0); + ImageList_DrawEx(hCListImages, iIcon, hDC, rc->left, (rc->bottom + rc->top - g_cysmIcon) / 2, g_cxsmIcon, g_cysmIcon, CLR_NONE, CLR_NONE, ILD_NORMAL); + rc->left += 18; + ImageList_DrawEx(hCListImages, nmi->iIcon, hDC, 4, (rc->bottom + rc->top) / 2 - 8, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL); + DrawText(hDC, szName, -1, rc, DT_VCENTER | DT_SINGLELINE); + ev_lastIcon = (int)nmi->hIcon; + } else { + HICON hIcon = reinterpret_cast(LoadImage(g_hInst, MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 16, 16, 0)); + DrawText(hDC, cfg::dat.szNoEvents, lstrlen(cfg::dat.szNoEvents), rc, DT_VCENTER | DT_SINGLELINE); + DrawIconEx(hDC, 4, (rc->bottom + rc->top - 16) / 2, hIcon, 16, 16, 0, 0, DI_NORMAL | DI_COMPAT); + DestroyIcon(hIcon); + } +} + +static BLENDFUNCTION bf = {0, 0, AC_SRC_OVER, 0}; +static BOOL avatar_done = FALSE; +HDC g_HDC; +static BOOL g_RTL; +HDC hdcTempAV; +HBITMAP hbmTempAV, hbmTempOldAV; + +HDC hdcAV; + +LONG g_maxAV_X = 200, g_maxAV_Y = 200; + +static int __fastcall DrawAvatar(HDC hdcMem, RECT *rc, struct ClcContact *contact, int y, struct ClcData *dat, WORD cstatus, int rowHeight, DWORD dwFlags) +{ + float dScale = 0.; + float newHeight, newWidth; + HDC hdcAvatar = hdcAV; + //HBITMAP hbmMem; + DWORD topoffset = 0, leftoffset = 0; + LONG bmWidth, bmHeight; + float dAspect; + HBITMAP hbm, hbmOldAV; + HRGN rgn = 0; + int avatar_size = cfg::dat.avatarSize; + DWORD av_saved_left; + StatusItems_t *item = contact->wStatus == ID_STATUS_OFFLINE ? &StatusItems[ID_EXTBKAVATARFRAMEOFFLINE - ID_STATUS_OFFLINE] : &StatusItems[ID_EXTBKAVATARFRAME - ID_STATUS_OFFLINE]; + int skinMarginX, skinMarginY; + BOOL fOverlay = (cfg::dat.dwFlags & CLUI_FRAME_OVERLAYICONS); + + contact->avatarLeft = -1; + if (!cfg::dat.bAvatarServiceAvail || dat->bisEmbedded) + return 0; + + if(contact->ace != NULL && contact->ace->cbSize == sizeof(struct avatarCacheEntry)) { + if(contact->ace->dwFlags & AVS_HIDEONCLIST) { + if (cfg::dat.dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) + return avatar_size + 2; + else + return 0; + } + bmHeight = contact->ace->bmHeight; + bmWidth = contact->ace->bmWidth; + if(bmWidth != 0) + dAspect = (float)bmHeight / (float)bmWidth; + else + dAspect = 1.0; + hbm = contact->ace->hbmPic; + contact->ace->t_lastAccess = cfg::dat.t_now; + } + else if (cfg::dat.dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) + return avatar_size + 2; + else + return 0; + + if(bmHeight == 0 || bmWidth == 0 || hbm == 0) + return 0; + + g_maxAV_X = max(bmWidth, g_maxAV_X); + g_maxAV_Y = max(bmHeight, g_maxAV_Y); + + if(dAspect >= 1.0) { // height > width + skinMarginY = item->IGNORED ? 0 : (item->MARGIN_TOP + item->MARGIN_BOTTOM); + skinMarginX = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + + dScale = (float)(avatar_size - 2) / (float)bmHeight; + newHeight = (float)(avatar_size - skinMarginY - 2); + newWidth = (float)(bmWidth * dScale) - skinMarginX; + } + else { + skinMarginY = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + skinMarginX = item->IGNORED ? 0 : (item->MARGIN_LEFT + item->MARGIN_RIGHT); + + newWidth = (float)(avatar_size - 2) - skinMarginX; + dScale = (float)(avatar_size - 2) / (float)bmWidth; + newHeight = (float)(bmHeight * dScale) - skinMarginY; + } + topoffset = rowHeight > (int)newHeight ? (rowHeight - (int)newHeight) / 2 : 0; + if (!item->IGNORED) { + //topoffset += item->MARGIN_TOP; + leftoffset = item->MARGIN_LEFT; + } + // create the region for the avatar border - use the same region for clipping, if needed. + + av_saved_left = rc->left; + if(cfg::dat.bCenterStatusIcons && newWidth < newHeight) + rc->left += (((avatar_size - 2) - ((int)newWidth + skinMarginX)) / 2); + + if(cfg::dat.dwFlags & CLUI_FRAME_ROUNDAVATAR) + rgn = CreateRoundRectRgn(leftoffset + rc->left, y + topoffset, leftoffset + rc->left + (int)newWidth + 1, y + topoffset + (int)newHeight + 1, 2 * cfg::dat.avatarRadius, 2 * cfg::dat.avatarRadius); + else + rgn = CreateRectRgn(leftoffset + rc->left, y + topoffset, leftoffset + rc->left + (int)newWidth, y + topoffset + (int)newHeight); + + hbmOldAV = reinterpret_cast(SelectObject(hdcAV, hbm)); + bf.SourceConstantAlpha = 255; //(g_CluiData.dwFlags & CLUI_FRAME_TRANSPARENTAVATAR && (UCHAR)saved_alpha > 20) ? (UCHAR)saved_alpha : 255; + bf.AlphaFormat = contact->ace->dwFlags & AVS_PREMULTIPLIED ? AC_SRC_ALPHA : 0; + + /* + if(dat->showIdle && contact->flags & CONTACTF_IDLE) + bf.SourceConstantAlpha -= (bf.SourceConstantAlpha > 100 ? 50 : 0); + */ + + SelectClipRgn(hdcMem, rgn); + SetStretchBltMode(hdcMem, HALFTONE); + if(bf.SourceConstantAlpha == 255 && bf.AlphaFormat == 0) { + StretchBlt(hdcMem, leftoffset + rc->left - (g_RTL ? 1 : 0), y + topoffset, (int)newWidth, (int)newHeight, hdcAvatar, 0, 0, bmWidth, bmHeight, SRCCOPY); + } + else { + /* + * get around SUCKY AlphaBlend() rescaling quality... + */ + SetStretchBltMode(hdcTempAV, HALFTONE); + StretchBlt(hdcTempAV, 0, 0, bmWidth, bmHeight, hdcMem, leftoffset + rc->left, y + topoffset, (int)newWidth, (int)newHeight, SRCCOPY); + API::pfnAlphaBlend(hdcTempAV, 0, 0, bmWidth, bmHeight, hdcAvatar, 0, 0, bmWidth, bmHeight, bf); + StretchBlt(hdcMem, leftoffset + rc->left - (g_RTL ? 1 : 0), y + topoffset, (int)newWidth, (int)newHeight, hdcTempAV, 0, 0, bmWidth, bmHeight, SRCCOPY); + } + SelectObject(hdcAV, hbmOldAV); + + if(cfg::dat.dwFlags & CLUI_FRAME_AVATARBORDER) { + if(g_RTL) + OffsetRgn(rgn, -1 , 0); + FrameRgn(hdcMem, rgn, cfg::dat.hBrushAvatarBorder, 1, 1); + } + + if(fOverlay) + fOverlay = (dwFlags & ECF_HIDEOVERLAY) ? 0 : 1; + else + fOverlay = (dwFlags & ECF_FORCEOVERLAY) ? 1 : 0; + + if(fOverlay && cstatus && (int)newHeight >= g_cysmIcon) + DrawIconEx(hdcMem, rc->left + (int)newWidth - 15, y + topoffset + (int)newHeight - 15, overlayicons[cstatus - ID_STATUS_OFFLINE], g_cxsmIcon, g_cysmIcon, 0, 0, DI_NORMAL | DI_COMPAT); + + SelectClipRgn(hdcMem, NULL); + DeleteObject(rgn); + + if (!item->IGNORED) { + RECT rcFrame; + BOOL inClCPaint_save = g_inCLCpaint; + HDC hdcTemp = 0, hdcSaved = 0; + HBITMAP hbmOld, hbmTemp; + + g_inCLCpaint = FALSE; + rcFrame.left = rc->left; + rcFrame.top = y + topoffset - item->MARGIN_TOP; + rcFrame.right = rcFrame.left + (int)newWidth + item->MARGIN_RIGHT + item->MARGIN_LEFT; + rcFrame.bottom = rcFrame.top + (int)newHeight + item->MARGIN_BOTTOM + item->MARGIN_TOP; + if(g_RTL) { + RECT rcTemp; + + OffsetRect(&rcFrame, 1, 0); + rcTemp.left = rcTemp.top = 0; + rcTemp.right = rcFrame.right - rcFrame.left; + rcTemp.bottom = rcFrame.bottom - rcFrame.top; + hdcTemp = CreateCompatibleDC(g_HDC); + hbmTemp = CreateCompatibleBitmap(g_HDC, rcTemp.right, rcTemp.bottom); + hbmOld = reinterpret_cast(SelectObject(hdcTemp, hbmTemp)); + API::pfnSetLayout(hdcTemp, LAYOUT_RTL); + BitBlt(hdcTemp, 0, 0, rcTemp.right, rcTemp.bottom, + hdcMem, rcFrame.left, rcFrame.top, SRCCOPY); + API::pfnSetLayout(hdcTemp, 0); + DrawAlpha(hdcTemp, &rcTemp, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, item->GRADIENT, + item->CORNER, item->BORDERSTYLE, item->imageItem); + BitBlt(hdcMem, rcFrame.left, rcFrame.top, rcFrame.right - rcFrame.left, rcFrame.bottom - rcFrame.top, + hdcTemp, 0, 0, SRCCOPY); + SelectObject(hdcTemp, hbmOld); + DeleteObject(hbmTemp); + DeleteDC(hdcTemp); + } else + DrawAlpha(hdcMem, &rcFrame, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT, item->GRADIENT, + item->CORNER, item->BORDERSTYLE, item->imageItem); + g_inCLCpaint = inClCPaint_save; + } + contact->avatarLeft = rc->left; + avatar_done = TRUE; + rc->left = av_saved_left; + return avatar_size + 2; + +} + +static BOOL pi_avatar = FALSE; +static RECT rcContent; +static BOOL pi_selectiveIcon; + +static BOOL av_left, av_right, av_rightwithnick; +static BOOL mirror_rtl, mirror_always, mirror_rtltext; + +BYTE savedCORNER = -1; +int g_padding_y = 0; + +void __inline PaintItem(HDC hdcMem, struct ClcGroup *group, struct ClcContact *contact, int indent, int y, struct ClcData *dat, int index, HWND hwnd, DWORD style, RECT *clRect, BOOL *bFirstNGdrawn, int groupCountsFontTopShift, int rowHeight) +{ + RECT rc; + int iImage = -1; + int selected; + SIZE textSize, countsSize, spaceSize; + int width, checkboxWidth; + char *szCounts; + int fontHeight; + BOOL twoRows = FALSE; + WORD cstatus; + DWORD leftOffset = 0, rightOffset = 0; + int iconXSpace = dat->iconXSpace; + //BOOL xStatusValid = 0; + HFONT hPreviousFont = 0; + BYTE type; + BYTE flags; + COLORREF oldGroupColor = -1; + DWORD qLeft = 0; + int leftX = dat->leftMargin + indent * dat->groupIndent; + int bg_indent_r = 0; + int bg_indent_l = 0; + int rightIcons = 0; + DWORD dt_nickflags = 0, dt_2ndrowflags = 0; + struct TExtraCache *cEntry = NULL; + DWORD dwFlags = cfg::dat.dwFlags; + int scanIndex; + BOOL check_selected, av_local_wanted, fLocalTime; + + rowHeight -= cfg::dat.bRowSpacing; + savedCORNER = -1; + + if(group == NULL || contact == NULL) + return; + + g_RTL = FALSE; + scanIndex = group->scanIndex; + av_local_wanted = (g_list_avatars > 0); + + type = contact->type; + flags = contact->flags; + selected = index == dat->selection && (dat->showSelAlways || dat->exStyle &CLS_EX_SHOWSELALWAYS || g_focusWnd == hwnd) && type != CLCIT_DIVIDER; + avatar_done = FALSE; + if(contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry) + cEntry = &cfg::eCache[contact->extraCacheEntry]; + else + cEntry = cfg::eCache; + + + if(dat->bisEmbedded) + goto set_bg_l; + + if(type == CLCIT_CONTACT && (cEntry->dwCFlags & ECF_RTLNICK || mirror_always)) { + if(API::pfnSetLayout != NULL && (mirror_rtl || mirror_always)) { + g_RTL = TRUE; + bg_indent_r = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else if(mirror_rtltext) { + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + dt_nickflags = DT_RTLREADING | DT_RIGHT; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else if(type == CLCIT_GROUP && API::pfnSetLayout != NULL) { + if ((contact->isRtl && cfg::dat.bGroupAlign == CLC_GROUPALIGN_AUTO) || cfg::dat.bGroupAlign == CLC_GROUPALIGN_RIGHT) { + g_RTL = TRUE; + bg_indent_r = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + } + else + bg_indent_l = cfg::dat.bApplyIndentToBg ? indent * dat->groupIndent : 0; + +set_bg_l: + + + g_hottrack = dat->exStyle & CLS_EX_TRACKSELECT && type == CLCIT_CONTACT && dat->iHotTrack == index; + if (g_hottrack == selected) + g_hottrack = 0; + + saved_alpha = 0; + + //setup + if (type == CLCIT_GROUP) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else if (type == CLCIT_INFO) { + if (flags & CLCIIF_GROUPFONT) + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + } else if (type == CLCIT_DIVIDER) { + ChangeToFont(hdcMem, dat, FONTID_DIVIDERS, &fontHeight); + GetTextExtentPoint32(hdcMem, contact->szText, lstrlen(contact->szText), &textSize); + } + else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) + ChangeToFont(hdcMem, dat, FONTID_NOTONLIST, &fontHeight); + else if (type == CLCIT_CONTACT && ((flags & CONTACTF_INVISTO && GetRealStatus(contact, my_status) != ID_STATUS_INVISIBLE) || (flags & CONTACTF_VISTO && GetRealStatus(contact, my_status) == ID_STATUS_INVISIBLE))) { + // the contact is in the always visible list and the proto is invisible + // the contact is in the always invisible and the proto is in any other mode + ChangeToFont(hdcMem, dat, flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS, &fontHeight); + } else if (type == CLCIT_CONTACT && !(flags & CONTACTF_ONLINE)) + ChangeToFont(hdcMem, dat, FONTID_OFFLINE, &fontHeight); + else + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + + if (type == CLCIT_GROUP) { + GetTextExtentPoint32(hdcMem, contact->szText, lstrlen(contact->szText), &textSize); + width = textSize.cx; + szCounts = pcli->pfnGetGroupCountsText(dat, contact); + if (szCounts[0]) { + GetTextExtentPoint32(hdcMem, _T(" "), 1, &spaceSize); + ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &fontHeight); + GetTextExtentPoint32A(hdcMem, szCounts, lstrlenA(szCounts), &countsSize); + width += spaceSize.cx + countsSize.cx; + } + } + if ((style & CLS_CHECKBOXES && type == CLCIT_CONTACT) || (style & CLS_GROUPCHECKBOXES && type == CLCIT_GROUP) || (type == CLCIT_INFO && flags & CLCIIF_CHECKBOX)) + checkboxWidth = dat->checkboxSize + 2; + else + checkboxWidth = 0; + + rc.left = 0; + cstatus = contact->wStatus; + + /***** BACKGROUND DRAWING *****/ + // contacts + + g_hottrack_done = 0; + check_selected = (!selected || selBlend); + + if(dat->bisEmbedded) { + rc.left = bg_indent_l; + rc.top = y; + rc.right = clRect->right - bg_indent_r; + rc.bottom = y + rowHeight; + if (selected) { + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); + SetTextColor(hdcMem, dat->selTextColour); + } + else { + FillRect(hdcMem, &rc, cfg::dat.hBrushCLCBk); + if(g_hottrack) + SetHotTrackColour(hdcMem,dat); + } + goto bgskipped; + } + + if (type == CLCIT_CONTACT || type == CLCIT_DIVIDER) { + StatusItems_t *sitem, *sfirstitem, *ssingleitem, *slastitem, *slastitem_NG, + *sfirstitem_NG, *ssingleitem_NG, *sevencontact_pos, *soddcontact_pos, *pp_item; + + if (cstatus >= ID_STATUS_OFFLINE && cstatus <= ID_STATUS_OUTTOLUNCH) { + BYTE perstatus_ignored; + + if ((flags & CONTACTF_IDLE) && !StatusItems[ID_EXTBKIDLE - ID_STATUS_OFFLINE].IGNORED) + sitem = &StatusItems[ID_EXTBKIDLE - ID_STATUS_OFFLINE]; + else + sitem = &StatusItems[cstatus - ID_STATUS_OFFLINE]; + + if (!dat->bisEmbedded) { + pp_item = cEntry->status_item ? cEntry->status_item : cEntry->proto_status_item; + + if (!(perstatus_ignored = sitem->IGNORED) && !(flags & CONTACTF_NOTONLIST)) + SetTextColor(hdcMem, sitem->TEXTCOLOR); + + if(cfg::dat.bUsePerProto && pp_item && !pp_item->IGNORED) { + sitem = pp_item; + if ((perstatus_ignored || cfg::dat.bOverridePerStatusColors) && sitem->TEXTCOLOR != -1) + SetTextColor(hdcMem, sitem->TEXTCOLOR); + } + } + else if (!sitem->IGNORED) + SetTextColor(hdcMem, sitem->TEXTCOLOR); + + sevencontact_pos = &StatusItems[ID_EXTBKEVEN_CNTCTPOS - ID_STATUS_OFFLINE]; + soddcontact_pos = &StatusItems[ID_EXTBKODD_CNTCTPOS - ID_STATUS_OFFLINE]; + sfirstitem = &StatusItems[ID_EXTBKFIRSTITEM - ID_STATUS_OFFLINE]; + ssingleitem = &StatusItems[ID_EXTBKSINGLEITEM - ID_STATUS_OFFLINE]; + slastitem = &StatusItems[ID_EXTBKLASTITEM - ID_STATUS_OFFLINE]; + + sfirstitem_NG = &StatusItems[ID_EXTBKFIRSTITEM_NG - ID_STATUS_OFFLINE]; + ssingleitem_NG = &StatusItems[ID_EXTBKSINGLEITEM_NG - ID_STATUS_OFFLINE]; + slastitem_NG = &StatusItems[ID_EXTBKLASTITEM_NG - ID_STATUS_OFFLINE]; + + rc.left = sitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + sitem->MARGIN_TOP; + rc.right = clRect->right - sitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sitem->MARGIN_BOTTOM; + + // check for special cases (first item, single item, last item) + // this will only change the shape for this status. Color will be blended over with ALPHA value + if (!ssingleitem->IGNORED && scanIndex == 0 && group->cl.count == 1 && group->parent != NULL) { + rc.left = ssingleitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + ssingleitem->MARGIN_TOP; + rc.right = clRect->right - ssingleitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - ssingleitem->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, ssingleitem->CORNER, ssingleitem->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, ssingleitem->CORNER, ssingleitem->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, ssingleitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = ssingleitem->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, ssingleitem->COLOR, ssingleitem->ALPHA, ssingleitem->COLOR2, ssingleitem->COLOR2_TRANSPARENT, ssingleitem->GRADIENT, ssingleitem->CORNER, ssingleitem->BORDERSTYLE, ssingleitem->imageItem); + } else if (scanIndex == 0 && group->cl.count > 1 && !sfirstitem->IGNORED && group->parent != NULL) { + rc.left = sfirstitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + sfirstitem->MARGIN_TOP; + rc.right = clRect->right - sfirstitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sfirstitem->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, sfirstitem->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, sfirstitem->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, sfirstitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = sfirstitem->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, sfirstitem->COLOR, sfirstitem->ALPHA, sfirstitem->COLOR2, sfirstitem->COLOR2_TRANSPARENT, sfirstitem->GRADIENT, sfirstitem->CORNER, sfirstitem->BORDERSTYLE, sfirstitem->imageItem); + } else if (scanIndex == group->cl.count - 1 && !slastitem->IGNORED && group->parent != NULL) { + // last item of group + rc.left = slastitem->MARGIN_LEFT + bg_indent_l; + rc.top = y + slastitem->MARGIN_TOP; + rc.right = clRect->right - slastitem->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - slastitem->MARGIN_BOTTOM; + rc.bottom = y + rowHeight - slastitem->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, slastitem->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, slastitem->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, slastitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = slastitem->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, slastitem->COLOR, slastitem->ALPHA, slastitem->COLOR2, slastitem->COLOR2_TRANSPARENT, slastitem->GRADIENT, slastitem->CORNER, slastitem->BORDERSTYLE, slastitem->imageItem); + } else + // - - - Non-grouped items - - - + if (type != CLCIT_GROUP // not a group + && group->parent == NULL // not grouped + && !sfirstitem_NG->IGNORED && scanIndex != group->cl.count - 1 && !(*bFirstNGdrawn)) { + // first NON-grouped + *bFirstNGdrawn = TRUE; + rc.left = sfirstitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + sfirstitem_NG->MARGIN_TOP; + rc.right = clRect->right - sfirstitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sfirstitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, sfirstitem_NG->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, sfirstitem_NG->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, sfirstitem_NG->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = sfirstitem_NG->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, sfirstitem_NG->COLOR, sfirstitem_NG->ALPHA, sfirstitem_NG->COLOR2, sfirstitem_NG->COLOR2_TRANSPARENT, sfirstitem_NG->GRADIENT, sfirstitem_NG->CORNER, sfirstitem->BORDERSTYLE, sfirstitem->imageItem); + } else if (type != CLCIT_GROUP // not a group + && group->parent == NULL && !slastitem_NG->IGNORED && scanIndex == group->cl.count - 1 && (*bFirstNGdrawn)) { + // last item of list (NON-group) + // last NON-grouped + rc.left = slastitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + slastitem_NG->MARGIN_TOP; + rc.right = clRect->right - slastitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - slastitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, slastitem_NG->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, slastitem_NG->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, slastitem_NG->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = slastitem_NG->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, slastitem_NG->COLOR, slastitem_NG->ALPHA, slastitem_NG->COLOR2, slastitem_NG->COLOR2_TRANSPARENT, slastitem_NG->GRADIENT, slastitem_NG->CORNER, slastitem->BORDERSTYLE, slastitem->imageItem); + } else if (type != CLCIT_GROUP // not a group + && group->parent == NULL && !slastitem_NG->IGNORED && !(*bFirstNGdrawn)) { + // single item of NON-group + // single NON-grouped + rc.left = ssingleitem_NG->MARGIN_LEFT + bg_indent_l; + rc.top = y + ssingleitem_NG->MARGIN_TOP; + rc.right = clRect->right - ssingleitem_NG->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - ssingleitem_NG->MARGIN_BOTTOM; + + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, ssingleitem_NG->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, ssingleitem_NG->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (!sitem->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, ssingleitem_NG->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = ssingleitem_NG->CORNER; + } + if (check_selected) + DrawAlpha(hdcMem, &rc, ssingleitem_NG->COLOR, ssingleitem_NG->ALPHA, ssingleitem_NG->COLOR2, ssingleitem_NG->COLOR2_TRANSPARENT, ssingleitem_NG->GRADIENT, ssingleitem_NG->CORNER, ssingleitem->BORDERSTYLE, ssingleitem->imageItem); + } else if (!sitem->IGNORED) { + // draw default grouped + // draw odd/even contact underlay + if ((scanIndex == 0 || scanIndex % 2 == 0) && !sevencontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, sevencontact_pos->COLOR, sevencontact_pos->ALPHA, sevencontact_pos->COLOR2, sevencontact_pos->COLOR2_TRANSPARENT, sevencontact_pos->GRADIENT, sitem->CORNER, sevencontact_pos->BORDERSTYLE, sevencontact_pos->imageItem); + } else if (scanIndex % 2 != 0 && !soddcontact_pos->IGNORED) { + if (check_selected) + DrawAlpha(hdcMem, &rc, soddcontact_pos->COLOR, soddcontact_pos->ALPHA, soddcontact_pos->COLOR2, soddcontact_pos->COLOR2_TRANSPARENT, soddcontact_pos->GRADIENT, sitem->CORNER, soddcontact_pos->BORDERSTYLE, soddcontact_pos->imageItem); + } + + if (check_selected) + DrawAlpha(hdcMem, &rc, sitem->COLOR, sitem->ALPHA, sitem->COLOR2, sitem->COLOR2_TRANSPARENT, sitem->GRADIENT, sitem->CORNER, sitem->BORDERSTYLE, sitem->imageItem); + savedCORNER = sitem->CORNER; + } + } + } + if (type == CLCIT_GROUP) { + StatusItems_t *sempty = &StatusItems[ID_EXTBKEMPTYGROUPS - ID_STATUS_OFFLINE]; + StatusItems_t *sexpanded = &StatusItems[ID_EXTBKEXPANDEDGROUP - ID_STATUS_OFFLINE]; + StatusItems_t *scollapsed = &StatusItems[ID_EXTBKCOLLAPSEDDGROUP - ID_STATUS_OFFLINE]; + + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); + if (contact->group->cl.count == 0) { + if (!sempty->IGNORED) { + rc.left = sempty->MARGIN_LEFT + bg_indent_l; + rc.top = y + sempty->MARGIN_TOP; + rc.right = clRect->right - sempty->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sempty->MARGIN_BOTTOM; + DrawAlpha(hdcMem, &rc, sempty->COLOR, sempty->ALPHA, sempty->COLOR2, sempty->COLOR2_TRANSPARENT, sempty->GRADIENT, sempty->CORNER, sempty->BORDERSTYLE, sempty->imageItem); + savedCORNER = sempty->CORNER; + oldGroupColor = SetTextColor(hdcMem, sempty->TEXTCOLOR); + } + } else if (contact->group->expanded) { + if (!sexpanded->IGNORED) { + rc.left = sexpanded->MARGIN_LEFT + bg_indent_l; + rc.top = y + sexpanded->MARGIN_TOP; + rc.right = clRect->right - sexpanded->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - (char) sexpanded->MARGIN_BOTTOM; + DrawAlpha(hdcMem, &rc, sexpanded->COLOR, sexpanded->ALPHA, sexpanded->COLOR2, sexpanded->COLOR2_TRANSPARENT, sexpanded->GRADIENT, sexpanded->CORNER, sexpanded->BORDERSTYLE, sexpanded->imageItem); + savedCORNER = sexpanded->CORNER; + oldGroupColor = SetTextColor(hdcMem, sexpanded->TEXTCOLOR); + } + } else { + if (!scollapsed->IGNORED) { + // collapsed but not empty + rc.left = scollapsed->MARGIN_LEFT + bg_indent_l; + rc.top = y + scollapsed->MARGIN_TOP; + rc.right = clRect->right - scollapsed->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - scollapsed->MARGIN_BOTTOM; + DrawAlpha(hdcMem, &rc, scollapsed->COLOR, scollapsed->ALPHA, scollapsed->COLOR2, scollapsed->COLOR2_TRANSPARENT, scollapsed->GRADIENT, scollapsed->CORNER, scollapsed->BORDERSTYLE, scollapsed->imageItem); + savedCORNER = scollapsed->CORNER; + oldGroupColor = SetTextColor(hdcMem, scollapsed->TEXTCOLOR); + } + } + } + if (selected) { + StatusItems_t *sselected = &StatusItems[ID_EXTBKSELECTION - ID_STATUS_OFFLINE]; + + if (!g_ignoreselforgroups || type != CLCIT_GROUP) { + if (!sselected->IGNORED) { + rc.left = sselected->MARGIN_LEFT + bg_indent_l; + rc.top = y + sselected->MARGIN_TOP; + rc.right = clRect->right - sselected->MARGIN_RIGHT - bg_indent_r; + rc.bottom = y + rowHeight - sselected->MARGIN_BOTTOM; + if (cfg::getByte("CLCExt", "EXBK_EqualSelection", 0) == 1 && savedCORNER != -1) { + DrawAlpha(hdcMem, &rc, sselected->COLOR, sselected->ALPHA, sselected->COLOR2, sselected->COLOR2_TRANSPARENT, sselected->GRADIENT, savedCORNER, sselected->BORDERSTYLE, sselected->imageItem); + } else { + DrawAlpha(hdcMem, &rc, sselected->COLOR, sselected->ALPHA, sselected->COLOR2, sselected->COLOR2_TRANSPARENT, sselected->GRADIENT, sselected->CORNER, sselected->BORDERSTYLE, sselected->imageItem); + } + SetTextColor(hdcMem, sselected->TEXTCOLOR); + } + else { + rc.left = bg_indent_l; + rc.top = y; + rc.right = clRect->right - bg_indent_r; + rc.bottom = y + rowHeight; + FillRect(hdcMem, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); + SetTextColor(hdcMem, dat->selTextColour); + } + } + } + else if (g_hottrack) { + StatusItems_t *ht = &StatusItems[ID_EXTBKHOTTRACK - ID_STATUS_OFFLINE]; + + SetHotTrackColour(hdcMem,dat); + if(ht->IGNORED == 0) + SetTextColor(hdcMem, ht->TEXTCOLOR); + if (!g_hottrack_done) { + if (ht->IGNORED == 0) { + DrawAlpha(hdcMem, &rc, ht->COLOR, ht->ALPHA, ht->COLOR2, ht->COLOR2_TRANSPARENT, ht->GRADIENT, + ht->CORNER, ht->BORDERSTYLE, ht->imageItem); + } + } + } + + if(g_RTL) + API::pfnSetLayout(hdcMem, LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED); +bgskipped: + + rcContent.top = y + g_padding_y; + rcContent.bottom = y + rowHeight - (2 * g_padding_y); + rcContent.left = leftX; + rcContent.right = clRect->right - dat->rightMargin; + twoRows = ((dat->fontInfo[FONTID_STATUS].fontHeight + fontHeight <= rowHeight + 1) && (contact->bSecondLine != MULTIROW_NEVER)) && !dat->bisEmbedded; + + pi_avatar = !dat->bisEmbedded && type == CLCIT_CONTACT && (contact->cFlags & ECF_AVATAR) && contact->ace != 0 && !(contact->ace->dwFlags & AVS_HIDEONCLIST); + + //checkboxes + if (checkboxWidth) { + RECT rc; + HANDLE hTheme = 0; + + if (IS_THEMED) + hTheme = API::pfnOpenThemeData(hwnd, L"BUTTON"); + + rc.left = leftX; + rc.right = rc.left + dat->checkboxSize; + rc.top = y + ((rowHeight - dat->checkboxSize) >> 1); + rc.bottom = rc.top + dat->checkboxSize; + if (hTheme) { + API::pfnDrawThemeBackground(hTheme, hdcMem, BP_CHECKBOX, flags & CONTACTF_CHECKED ? (g_hottrack ? CBS_CHECKEDHOT : CBS_CHECKEDNORMAL) : (g_hottrack ? CBS_UNCHECKEDHOT : CBS_UNCHECKEDNORMAL), &rc, &rc); + API::pfnCloseThemeData(hTheme); + hTheme = 0; + } + else + DrawFrameControl(hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT | (flags & CONTACTF_CHECKED ? DFCS_CHECKED : 0) | (g_hottrack ? DFCS_HOT : 0)); + rcContent.left += checkboxWidth; + leftX += checkboxWidth; + } + + if (type == CLCIT_GROUP) + iImage = (contact->group->expanded) ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; + else if (type == CLCIT_CONTACT) + iImage = contact->iImage; + + + if(pi_avatar && (av_left || av_right)) { + RECT rc; + + rc.left = rcContent.left; + rc.right = clRect->right; + rc.top = y; + rc.bottom = rc.top + rowHeight; + + if(av_left) { + leftOffset += DrawAvatar(hdcMem, &rc, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + rcContent.left += leftOffset; + leftX += leftOffset; + } + else { + rc.left = (rcContent.right - cfg::dat.avatarSize) + 1; + rightOffset += DrawAvatar(hdcMem, &rc, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + rcContent.right -= (rightOffset); + } + } + else if(type == CLCIT_CONTACT && !dat->bisEmbedded && !g_selectiveIcon && (dwFlags & CLUI_FRAME_ALWAYSALIGNNICK) && av_local_wanted && (av_left || av_right)) { + if(av_right) + rcContent.right -= (cfg::dat.avatarSize + 2); + if(av_left) + rcContent.left += (cfg::dat.avatarSize + 2); + } + //icon + + // skip icon for groups if the option is enabled... + + if(type == CLCIT_GROUP && dwFlags & CLUI_FRAME_NOGROUPICON) { + iconXSpace = 0; + goto text; + } + if (iImage != -1) { + // this doesnt use CLS_CONTACTLIST since the colour prolly wont match anyway + COLORREF colourFg = dat->selBkColour; + //int clientId = contact->clientId; + int mode = ILD_NORMAL; + pi_selectiveIcon = g_selectiveIcon && (type == CLCIT_CONTACT); + + if ((dwFlags & CLUI_FRAME_STATUSICONS && !pi_selectiveIcon) || type != CLCIT_CONTACT || (pi_selectiveIcon && !avatar_done)) { + HIMAGELIST hImgList = 0; + if (!dat->bisEmbedded && type == CLCIT_CONTACT && cEntry && (dwFlags & CLUI_FRAME_USEXSTATUSASSTATUS) && cEntry->iExtraImage[EXTRA_ICON_ADV1] != 0xff) { + if(pcli->pfnIconFromStatusMode(contact->proto, contact->wStatus, contact->hContact) == iImage) { + hImgList = dat->himlExtraColumns; + iImage = cEntry->iExtraImage[EXTRA_ICON_ADV1]; + } + else hImgList = hCListImages; + } + else + hImgList = hCListImages; + + if (g_hottrack) { + colourFg = dat->hotTextColour; + } else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; + mode = ILD_BLEND50; + } + if (type == CLCIT_CONTACT && dat->showIdle && (flags & CONTACTF_IDLE) && contact->wStatus != ID_STATUS_OFFLINE) + mode = ILD_SELECTED; + + if(pi_selectiveIcon && av_right) { + ImageList_DrawEx(hImgList, iImage, hdcMem, rcContent.right - 18, (twoRows && type == CLCIT_CONTACT && !cfg::dat.bCenterStatusIcons) ? y + 2 : y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + rcContent.right -= 18; + } + else { + LONG offset = 0; + BOOL centered = FALSE; + offset += (type != CLCIT_CONTACT || avatar_done || !(av_local_wanted) ? 20 : dwFlags & CLUI_FRAME_ALWAYSALIGNNICK && av_left && g_selectiveIcon ? cfg::dat.avatarSize + 2 : 20); + centered = (cfg::dat.bCenterStatusIcons && offset == cfg::dat.avatarSize + 2); + ImageList_DrawEx(hImgList, iImage, hdcMem, centered ? rcContent.left + offset / 2 - 10 : rcContent.left, (twoRows && type == CLCIT_CONTACT && !cfg::dat.bCenterStatusIcons) ? y + 2 : y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + rcContent.left += offset; + } + } + else + iconXSpace = 0; + if (type == CLCIT_CONTACT && !dat->bisEmbedded) { + BYTE bApparentModeDontCare = !((flags & CONTACTF_VISTO) ^ (flags & CONTACTF_INVISTO)); + contact->extraIconRightBegin = 0; + if(cEntry && (contact->extraCacheEntry >= 0 && contact->extraCacheEntry < cfg::nextCacheEntry && cEntry->iExtraValid)) { + int i, iIndex, id; + DWORD dwOldMask = cEntry->dwXMask; + if(dwFlags & CLUI_FRAME_USEXSTATUSASSTATUS) + cEntry->dwXMask &= ~EIMG_SHOW_ADV1; + + for (i = EXICON_COUNT - 1; i >= 0; i--) { + iIndex = cfg::dat.exIconOrder[i] - 1; + if(iIndex >= 0 && iIndex < EXICON_COUNT) { + id = OrderTreeData[iIndex].ID; + if(cEntry->iExtraImage[id] != 0xff && ((1 << id) & cEntry->dwXMask)) { + if(contact->extraIconRightBegin == 0 && i != (EXICON_COUNT - 1)) + contact->extraIconRightBegin = rcContent.right; + ImageList_DrawEx(dat->himlExtraColumns, cEntry->iExtraImage[id], hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL); + rcContent.right -= g_exIconSpacing; + rightIcons++; + } + } + } + cEntry->dwXMask = dwOldMask; + } + if (!bApparentModeDontCare && (dwFlags & CLUI_SHOWVISI) && contact->proto) { + BOOL fVisi; + + if(dwFlags & CLUI_SHOWVISI) + fVisi = cEntry->dwDFlags & ECF_HIDEVISIBILITY ? 0 : 1; + else + fVisi = cEntry->dwDFlags & ECF_FORCEVISIBILITY ? 1 : 0; + + if(fVisi) { + if(cEntry->isChatRoom) + DrawIconEx(hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + cfg::dat.hIconChatactive, cfg::dat.exIconScale, cfg::dat.exIconScale, 0, 0, DI_NORMAL | DI_COMPAT); + else + DrawIconEx(hdcMem, rcContent.right - cfg::dat.exIconScale, twoRows ? rcContent.bottom - g_exIconSpacing : y + ((rowHeight - cfg::dat.exIconScale) >> 1), + flags & CONTACTF_VISTO ? cfg::dat.hIconVisible : cfg::dat.hIconInvisible, cfg::dat.exIconScale, cfg::dat.exIconScale, 0, 0, DI_NORMAL | DI_COMPAT); + rcContent.right -= g_exIconSpacing; + rightIcons++; + } + } + } + } + //text +text: + if (type == CLCIT_DIVIDER) { + RECT rc; + rc.top = y + ((rowHeight) >> 1); rc.bottom = rc.top + 2; + rc.left = rcContent.left; + rc.right = rc.left - dat->rightMargin + ((clRect->right - rc.left - textSize.cx) >> 1) - 3; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + TextOut(hdcMem, rc.right + 3, y + ((rowHeight - fontHeight) >> 1), contact->szText, lstrlen(contact->szText)); + rc.left = rc.right + 6 + textSize.cx; + rc.right = clRect->right - dat->rightMargin; + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } else if (type == CLCIT_GROUP) { + RECT rc; + int leftMargin = 0, countStart = 0, leftLineEnd, rightLineStart; + fontHeight = dat->fontInfo[FONTID_GROUPS].fontHeight; + rc.top = y + ((rowHeight - fontHeight) >> 1) + cfg::dat.group_padding; + rc.bottom = rc.top + textSize.cy; + if (szCounts[0]) { + int required, labelWidth, offset = 0; + int height = 0; + COLORREF clr = GetTextColor(hdcMem); + + ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &height); + if(oldGroupColor != -1) + SetTextColor(hdcMem, clr); + + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + iconXSpace; + rc.right = clRect->right - dat->rightMargin; + + if(indent == 0 && iconXSpace == 0) + rc.left += 2; + + required = textSize.cx + countsSize.cx + spaceSize.cx; + + if(required > rc.right - rc.left) + textSize.cx = (rc.right - rc.left) - countsSize.cx - spaceSize.cx; + + labelWidth = textSize.cx + countsSize.cx + spaceSize.cx; + if(g_center) + offset = ((rc.right - rc.left) - labelWidth) / 2; + + + TextOutA(hdcMem, rc.left + offset + textSize.cx + spaceSize.cx, rc.top + groupCountsFontTopShift, szCounts, lstrlenA(szCounts)); + rightLineStart = rc.left + offset + textSize.cx + spaceSize.cx + countsSize.cx + 2; + + if (selected && !g_ignoreselforgroups) + SetTextColor(hdcMem, dat->selTextColour); + else + SetTextColor(hdcMem, clr); + ChangeToFont(hdcMem, dat, FONTID_GROUPS, &height); + SetTextColor(hdcMem, clr); + rc.left += offset; + rc.right = rc.left + textSize.cx; + leftLineEnd = rc.left - 2; + qLeft = rc.left; + DrawText(hdcMem, contact->szText, -1, &rc, DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS); + } else if (g_center && !szCounts[0]) { + int offset; + + rc.left = rcContent.left; + rc.right = clRect->right - dat->rightMargin; + if(textSize.cx >= rc.right - rc.left) + textSize.cx = rc.right - rc.left; + + offset = ((rc.right - rc.left) - textSize.cx) / 2; + rc.left += offset; + rc.right = rc.left + textSize.cx; + leftLineEnd = rc.left - 2; + rightLineStart = rc.right + 2; + DrawText(hdcMem, contact->szText, -1, &rc, DT_CENTER | DT_NOPREFIX | DT_SINGLELINE); + qLeft = rc.left; + } else { + qLeft = rcContent.left + (indent == 0 && iconXSpace == 0 ? 2 : 0);; + rc.left = qLeft; + rc.right = min(rc.left + textSize.cx, clRect->right - dat->rightMargin);; + DrawText(hdcMem, contact->szText, -1, &rc, DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE | DT_WORD_ELLIPSIS); + rightLineStart = qLeft + textSize.cx + 2; + } + + if (dat->exStyle & CLS_EX_LINEWITHGROUPS) { + if (!g_center) { + rc.top = y + ((rowHeight) >> 1); rc.bottom = rc.top + 2; + rc.left = rightLineStart; + rc.right = clRect->right - 1 - dat->extraColumnSpacing * dat->extraColumnsCount - dat->rightMargin; + if (rc.right - rc.left > 1) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + else { + rc.top = y + ((rowHeight) >> 1); rc.bottom = rc.top + 2; + rc.left = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + iconXSpace; + rc.right = leftLineEnd; + if (rc.right > rc.left) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + rc.right = clRect->right - dat->rightMargin; + rc.left = rightLineStart; + if (rc.right > rc.left) + DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); + } + } + } else { + TCHAR *szText = contact->szText; + + rcContent.top = y + ((rowHeight - fontHeight) >> 1); + + // avatar + + if (!dat->bisEmbedded) { + if(av_local_wanted && !avatar_done && pi_avatar) { + if(av_rightwithnick) { + RECT rcAvatar = rcContent; + + rcAvatar.left = rcContent.right - (cfg::dat.avatarSize - 1); + DrawAvatar(hdcMem, &rcAvatar, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + rcContent.right -= (cfg::dat.avatarSize + 2); + } + else + rcContent.left += DrawAvatar(hdcMem, &rcContent, contact, y, dat, (WORD)(iImage ? cstatus : 0), rowHeight, cEntry->dwDFlags); + } + else if(dwFlags & CLUI_FRAME_ALWAYSALIGNNICK && !avatar_done && av_local_wanted) + rcContent.left += (dwFlags & (CLUI_FRAME_AVATARSLEFT | CLUI_FRAME_AVATARSRIGHT | CLUI_FRAME_AVATARSRIGHTWITHNICK) ? 0 : cfg::dat.avatarSize + 2); + } + + // nickname + if (!twoRows) { + if(dt_nickflags) + DrawText(hdcMem, szText, -1, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE | dt_nickflags); + else + DrawText(hdcMem, szText, -1, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + else { + int statusFontHeight; + DWORD dtFlags = DT_WORD_ELLIPSIS | DT_NOPREFIX | DT_NOCLIP | DT_SINGLELINE; + DWORD saved_right = rcContent.right; + BOOL verticalfit = FALSE; + + rcContent.top = y + cfg::dat.avatarPadding / 2; + + if(cfg::dat.bShowLocalTime) + fLocalTime = cEntry->dwDFlags & ECF_HIDELOCALTIME ? 0 : 1; + else + fLocalTime = cEntry->dwDFlags & ECF_FORCELOCALTIME ? 1 : 0; + + if (cEntry->hTimeZone && fLocalTime) { + int idOldFont; + DWORD now = cfg::dat.t_now; + SIZE szTime; + RECT rc = rcContent; + COLORREF oldColor; + int fHeight = 0; + + + TCHAR szResult[80]; + if (tmi.printDateTime(cEntry->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0)) + goto nodisplay; + + oldColor = GetTextColor(hdcMem); + idOldFont = dat->currentFontID; + ChangeToFont(hdcMem, dat, FONTID_TIMESTAMP, &fHeight); + GetTextExtentPoint32(hdcMem, szResult, lstrlen(szResult), &szTime); + verticalfit = (rowHeight - fHeight >= cfg::dat.exIconScale + 1); + + if(av_right) { + if(verticalfit) + rc.left = rcContent.right + (rightIcons * g_exIconSpacing) - szTime.cx - 2; + else + rc.left = rcContent.right - szTime.cx - 2; + } + else if(av_rightwithnick) { + if(verticalfit && rightIcons * g_exIconSpacing >= szTime.cx) + rc.left = clRect->right - dat->rightMargin - szTime.cx; + else if(verticalfit && !avatar_done) + rc.left = clRect->right - dat->rightMargin - szTime.cx; + else { + rc.left = rcContent.right - szTime.cx - 2; + rcContent.right = rc.left - 2; + } + } + else { + if(verticalfit) + rc.left = clRect->right - dat->rightMargin - szTime.cx; + else + rc.left = rcContent.right - szTime.cx - 2; + } + DrawText(hdcMem, szResult, -1, &rc, DT_NOPREFIX | DT_NOCLIP | DT_SINGLELINE); + ChangeToFont(hdcMem, dat, idOldFont, 0); + SetTextColor(hdcMem, oldColor); + + verticalfit = (rowHeight - fontHeight >= cfg::dat.exIconScale + 1); + if(verticalfit && av_right) + rcContent.right = min(clRect->right - cfg::dat.avatarSize - 2, rc.left - 2); + else if(verticalfit && !av_rightwithnick) + rcContent.right = min(clRect->right - dat->rightMargin, rc.left - 3); + } + else { +nodisplay: + verticalfit = (rowHeight - fontHeight >= cfg::dat.exIconScale + 1); + if(avatar_done) { + if(verticalfit && av_right) + rcContent.right = clRect->right - cfg::dat.avatarSize - 2; + else if(verticalfit && !av_rightwithnick) + rcContent.right = clRect->right - dat->rightMargin; + } + } + DrawText(hdcMem, szText, -1, &rcContent, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE | dt_nickflags); + + rcContent.right = saved_right; + rcContent.top += (fontHeight - 1); + hPreviousFont = ChangeToFont(hdcMem, dat, FONTID_STATUS, &statusFontHeight); + //if(selected) + // SetTextColor(hdcMem, dat->selTextColour); + rcContent.bottom = y + rowHeight; + + if(cstatus >= ID_STATUS_OFFLINE && cstatus <= ID_STATUS_OUTTOLUNCH) { + TCHAR *szText = NULL; + BYTE smsgValid = cEntry->bStatusMsgValid; + + if ((dwFlags & CLUI_FRAME_SHOWSTATUSMSG && smsgValid > STATUSMSG_XSTATUSID) || smsgValid == STATUSMSG_XSTATUSNAME) + szText = cEntry->statusMsg; + else + + szText = &statusNames[cstatus - ID_STATUS_OFFLINE][0]; + + if(cEntry->dwCFlags & ECF_RTLSTATUSMSG && cfg::dat.bUseDCMirroring == 3) + dt_2ndrowflags |= (DT_RTLREADING | DT_RIGHT); + + if(rightIcons == 0) { + if ((rcContent.bottom - rcContent.top) >= (2 * statusFontHeight)) { + dtFlags &= ~(DT_SINGLELINE | DT_BOTTOM | DT_NOCLIP); + dtFlags |= DT_WORDBREAK; + rcContent.bottom -= ((rcContent.bottom - rcContent.top) % statusFontHeight); + } + DrawText(hdcMem, szText, -1, &rcContent, dtFlags | dt_2ndrowflags); + } + else { + if ((rcContent.bottom - rcContent.top) < (2 * statusFontHeight) - 2) + DrawText(hdcMem, szText, -1, &rcContent, dtFlags | dt_2ndrowflags); + else { + DRAWTEXTPARAMS dtp = {0}; + LONG rightIconsTop = rcContent.bottom - g_exIconSpacing; + LONG old_right = rcContent.right; + ULONG textCounter = 0; + ULONG ulLen = lstrlen(szText); + LONG old_bottom = rcContent.bottom; + DWORD i_dtFlags = DT_WORDBREAK | DT_NOPREFIX | dt_2ndrowflags; + dtp.cbSize = sizeof(dtp); + rcContent.right = clRect->right - dat->rightMargin - rightOffset; + do { + if(rcContent.top + (statusFontHeight - 1) > rightIconsTop + 1) + rcContent.right = old_right; + dtp.uiLengthDrawn = 0; + rcContent.bottom = rcContent.top + statusFontHeight - 1; + if(rcContent.bottom + statusFontHeight >= old_bottom) + i_dtFlags |= DT_END_ELLIPSIS; + DrawTextEx(hdcMem, &szText[textCounter], -1, &rcContent, i_dtFlags, &dtp); + rcContent.top += statusFontHeight; + textCounter += dtp.uiLengthDrawn; + } while (textCounter <= ulLen && dtp.uiLengthDrawn && rcContent.top + statusFontHeight <= old_bottom); + } + } + } + } + } + if (selected) { + if (type != CLCIT_DIVIDER) { + TCHAR *szText = contact->szText; + RECT rc; + int qlen = lstrlen(dat->szQuickSearch); + if(hPreviousFont) + SelectObject(hdcMem, hPreviousFont); + SetTextColor(hdcMem, dat->quickSearchColour); + if(type == CLCIT_CONTACT) { + rc.left = rcContent.left; + rc.top = y + ((rowHeight - fontHeight) >> 1); + rc.right = clRect->right - rightOffset; + rc.right = rcContent.right; + rc.bottom = rc.top; + if(twoRows) + rc.top = y; + } + else { + rc.left = qLeft; + rc.top = y + ((rowHeight - fontHeight) >> 1); + rc.right = clRect->right - rightOffset; + rc.bottom = rc.top; + } + if (qlen) + DrawText(hdcMem, szText, qlen, &rc, DT_EDITCONTROL | DT_NOPREFIX | DT_NOCLIP | DT_WORD_ELLIPSIS | DT_SINGLELINE); + } + } + //extra icons + for (iImage = 0; iImage< dat->extraColumnsCount; iImage++) { + COLORREF colourFg = dat->selBkColour; + int mode = ILD_NORMAL; + if (contact->iExtraImage[iImage] == 0xFF) + continue; + if (selected) + mode = ILD_SELECTED; + else if (g_hottrack) { + mode = ILD_FOCUS; colourFg = dat->hotTextColour; + } else if (type == CLCIT_CONTACT && flags & CONTACTF_NOTONLIST) { + colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; mode = ILD_BLEND50; + } + ImageList_DrawEx(dat->himlExtraColumns, contact->iExtraImage[iImage], hdcMem, clRect->right - rightOffset - dat->extraColumnSpacing * (dat->extraColumnsCount - iImage), y + ((rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); + } + if(g_RTL) + API::pfnSetLayout(hdcMem, 0); +} + +void SkinDrawBg(HWND hwnd, HDC hdc) +{ + RECT rcCl; + POINT ptTest = {0}; + + ClientToScreen(hwnd, &ptTest); + GetClientRect(hwnd, &rcCl); + + BitBlt(hdc, 0, 0, rcCl.right - rcCl.left, rcCl.bottom - rcCl.top, cfg::dat.hdcBg, ptTest.x - cfg::dat.ptW.x, ptTest.y - cfg::dat.ptW.y, SRCCOPY); +} + +void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint) +{ + HDC hdcMem; + RECT clRect; + int y,indent,index,fontHeight; + struct ClcGroup *group; + HBITMAP hBmpOsb, hOldBitmap; + HFONT hOldFont; + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + int grey = 0,groupCountsFontTopShift; + BOOL bFirstNGdrawn = FALSE; + int line_num = -1; + COLORREF tmpbkcolour = style & CLS_CONTACTLIST ? (dat->useWindowsColours ? GetSysColor(COLOR_3DFACE) : dat->bkColour) : dat->bkColour; + DWORD done, now = GetTickCount(); + selBlend = cfg::getByte("CLCExt", "EXBK_SelBlend", 1); + g_inCLCpaint = TRUE; + g_focusWnd = GetFocus(); + my_status = GetGeneralisedStatus(); + g_HDC = hdc; + + /* + * temporary DC for avatar drawing + */ + + g_padding_y = 0; + + hdcTempAV = CreateCompatibleDC(g_HDC); + hdcAV = CreateCompatibleDC(g_HDC); + hbmTempAV = CreateCompatibleBitmap(g_HDC, g_maxAV_X, g_maxAV_Y); + hbmTempOldAV = reinterpret_cast(SelectObject(hdcTempAV, hbmTempAV)); + + cfg::dat.t_now = time(NULL); + GetSystemTime(&cfg::dat.st); + SystemTimeToFileTime(&cfg::dat.st, &cfg::dat.ft); + + cfg::dat.bUseFastGradients = cfg::dat.bWantFastGradients && (API::pfnGradientFill != 0); + + av_left = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSLEFT); + av_right = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSRIGHT); + av_rightwithnick = (cfg::dat.dwFlags & CLUI_FRAME_AVATARSRIGHTWITHNICK); + + mirror_rtl = (cfg::dat.bUseDCMirroring == 2); + mirror_always = (cfg::dat.bUseDCMirroring == 1); + mirror_rtltext = (cfg::dat.bUseDCMirroring == 3); + + g_center = cfg::getByte("CLCExt", "EXBK_CenterGroupnames", 0) && !dat->bisEmbedded; + g_ignoreselforgroups = cfg::getByte("CLC", "IgnoreSelforGroups", 0); + g_exIconSpacing = cfg::dat.exIconScale + 2; + + if (dat->greyoutFlags & pcli->pfnClcStatusToPf2(my_status) || style & WS_DISABLED) + grey = 1; + else if (GetFocus() != hwnd && dat->greyoutFlags & GREYF_UNFOCUS) + grey = 1; + GetClientRect(hwnd, &clRect); + if (rcPaint == NULL) + rcPaint = &clRect; + if (IsRectEmpty(rcPaint)) { + SelectObject(hdcTempAV, hbmTempOldAV); + DeleteObject(hbmTempAV); + DeleteDC(hdcTempAV); + + DeleteDC(hdcAV); + return; + } + y = -dat->yScroll; + hdcMem = CreateCompatibleDC(hdc); + hBmpOsb = CreateBitmap(clRect.right, clRect.bottom, 1, GetDeviceCaps(hdc, BITSPIXEL), NULL); + + hOldBitmap = reinterpret_cast(SelectObject(hdcMem, hBmpOsb)); + { + TEXTMETRIC tm; + hOldFont = reinterpret_cast(SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPS].hFont)); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift = tm.tmAscent; + SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); + GetTextMetrics(hdcMem, &tm); + groupCountsFontTopShift -= tm.tmAscent; + } + ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); + + SetBkMode(hdcMem, TRANSPARENT); { + HBRUSH hBrush, hoBrush; + + hBrush = CreateSolidBrush(tmpbkcolour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRect(hdcMem, rcPaint, hBrush); + + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + + if(1) { + if(cfg::dat.bWallpaperMode && !dat->bisEmbedded) { + SkinDrawBg(hwnd, hdcMem); + goto bgdone; + } + if (dat->hBmpBackground) { + BITMAP bmp; + HDC hdcBmp; + int x, y; + int bitx, bity; + int maxx, maxy; + int destw, desth; + // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98. + SetStretchBltMode(hdcMem, HALFTONE); + + GetObject(dat->hBmpBackground, sizeof(bmp), &bmp); + hdcBmp = CreateCompatibleDC(hdcMem); + SelectObject(hdcBmp, dat->hBmpBackground); + y = dat->backgroundBmpUse & CLBF_SCROLL ? -dat->yScroll : 0; + maxx = dat->backgroundBmpUse & CLBF_TILEH ? clRect.right : 1; + maxy = dat->backgroundBmpUse & CLBF_TILEV ? maxy = rcPaint->bottom : y + 1; + switch (dat->backgroundBmpUse & CLBM_TYPE) { + case CLB_STRETCH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + if (clRect.right * bmp.bmHeight < clRect.bottom * bmp.bmWidth) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } else { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } + } else { + destw = clRect.right; + desth = clRect.bottom; + } + break; + case CLB_STRETCHH: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + destw = clRect.right; + desth = destw * bmp.bmHeight / bmp.bmWidth; + } else { + destw = clRect.right; + desth = bmp.bmHeight; + } + break; + case CLB_STRETCHV: + if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { + desth = clRect.bottom; + destw = desth * bmp.bmWidth / bmp.bmHeight; + } else { + destw = bmp.bmWidth; + desth = clRect.bottom; + } + break; + default: + //clb_topleft + destw = bmp.bmWidth; + desth = bmp.bmHeight; + break; + } + + bitx = 0; + bity = 0; + + for (; y < maxy; y += desth) { + if (y< rcPaint->top - desth) + continue; + for (x = 0; x < maxx; x += destw) { + StretchBlt(hdcMem, x, y, destw, desth, cfg::dat.hdcPic, bitx, bity, bmp.bmWidth, bmp.bmHeight, SRCCOPY); + } + } + DeleteDC(hdcBmp); + } + } + } +bgdone: + group = &dat->list; + group->scanIndex = 0; + + if ( dat->row_heights == NULL ) + RowHeight::calcRowHeights(dat, hwnd); + + group = &dat->list; + group->scanIndex = 0; + + g_list_avatars = 0; + while(TRUE) + { + if (group->scanIndex==group->cl.count) + { + group=group->parent; + if(group==NULL) break; // Finished list + group->scanIndex++; + continue; + } + + if(group->cl.items[group->scanIndex]->cFlags & ECF_AVATAR) + g_list_avatars++; + + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) { + group=group->cl.items[group->scanIndex]->group; + group->scanIndex=0; + continue; + } + group->scanIndex++; + } + g_selectiveIcon = (g_list_avatars > 0) && (cfg::dat.dwFlags & CLUI_FRAME_SELECTIVEICONS) && !dat->bisEmbedded; + + group = &dat->list; + group->scanIndex = 0; + indent = 0; + + for (index = 0; y< rcPaint->bottom;) { + if (group->scanIndex == group->cl.count) { + group = group->parent; + indent--; + if (group == NULL) { + break; + } + group->scanIndex++; + continue; + } + + line_num++; + if(cfg::dat.bForceRefetchOnPaint) + group->cl.items[group->scanIndex]->ace = (struct avatarCacheEntry*)-1; + + if (y > rcPaint->top - dat->row_heights[line_num] && y <= rcPaint->bottom) { + if (group->cl.items[group->scanIndex]->ace == (struct avatarCacheEntry*)-1 ) + group->cl.items[group->scanIndex]->ace = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)group->cl.items[group->scanIndex]->hContact, 0); + RowHeight::getRowHeight(dat, hwnd, group->cl.items[group->scanIndex], line_num, style); + PaintItem(hdcMem, group, group->cl.items[group->scanIndex], indent, y, dat, index, hwnd, style, &clRect, &bFirstNGdrawn, groupCountsFontTopShift, dat->row_heights[line_num]); + } + index++; + y += dat->row_heights[line_num]; + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) { + group = group->cl.items[group->scanIndex]->group; + indent++; + group->scanIndex = 0; + continue; + } + group->scanIndex++; + } + + SelectObject(hdcTempAV, hbmTempOldAV); + DeleteObject(hbmTempAV); + DeleteDC(hdcTempAV); + + DeleteDC(hdcAV); + + if (dat->iInsertionMark != -1) { + //insertion mark + HBRUSH hBrush, hoBrush; + POINT pts[8]; + HRGN hRgn; + + pts[0].x=dat->leftMargin; pts[0].y = RowHeight::getItemTopY(dat, dat->iInsertionMark) - dat->yScroll - 4; + //pts[0]. x = dat->leftMargin; pts[0]. y = dat->iInsertionMark * rowHeight - dat->yScroll - 4; + pts[1]. x = pts[0].x + 2; pts[1]. y = pts[0].y + 3; + pts[2]. x = clRect.right - 4; pts[2]. y = pts[1].y; + pts[3]. x = clRect.right - 1; pts[3]. y = pts[0].y - 1; + pts[4]. x = pts[3].x; pts[4]. y = pts[0].y + 7; + pts[5]. x = pts[2].x + 1; pts[5]. y = pts[1].y + 2; + pts[6]. x = pts[1].x; pts[6]. y = pts[5].y; + pts[7]. x = pts[0].x; pts[7]. y = pts[4].y; + hRgn = CreatePolygonRgn(pts, sizeof(pts) / sizeof(pts[0]), ALTERNATE); + hBrush = CreateSolidBrush(dat->fontInfo[FONTID_CONTACTS].colour); + hoBrush = (HBRUSH) SelectObject(hdcMem, hBrush); + FillRgn(hdcMem, hRgn, hBrush); + SelectObject(hdcMem, hoBrush); + DeleteObject(hBrush); + } + if (!grey) + BitBlt(hdc, rcPaint->left, rcPaint->top, rcPaint->right - rcPaint->left, rcPaint->bottom - rcPaint->top, hdcMem, rcPaint->left, rcPaint->top, SRCCOPY); + + SelectObject(hdcMem, hOldBitmap); + SelectObject(hdcMem, hOldFont); + + DeleteDC(hdcMem); + if (grey) { + PBYTE bits; + BITMAPINFOHEADER bmih = {0}; + + int i; + int greyRed, greyGreen, greyBlue; + COLORREF greyColour; + bmih.biBitCount = 32; + bmih.biSize = sizeof(bmih); + bmih.biCompression = BI_RGB; + bmih.biHeight = -clRect.bottom; + bmih.biPlanes = 1; + bmih.biWidth = clRect.right; + bits = (PBYTE) mir_alloc(4 * bmih.biWidth * -bmih.biHeight); + GetDIBits(hdc, hBmpOsb, 0, clRect.bottom, bits, (BITMAPINFO *) &bmih, DIB_RGB_COLORS); + greyColour = GetSysColor(COLOR_3DFACE); + greyRed = GetRValue(greyColour) * 2; + greyGreen = GetGValue(greyColour) * 2; + greyBlue = GetBValue(greyColour) * 2; + if (divide3[0] == 255) { + for (i = 0; i < sizeof(divide3) / sizeof(divide3[0]); i++) { + divide3[i] = (i + 1) / 3; + } + } + for (i = 4 * clRect.right *clRect.bottom - 4; i >= 0; i -= 4) { + bits[i] = divide3[bits[i] + greyBlue]; + bits[i + 1] = divide3[bits[i + 1] + greyGreen]; + bits[i + 2] = divide3[bits[i + 2] + greyRed]; + } + SetDIBitsToDevice(hdc, 0, 0, clRect.right, clRect.bottom, 0, 0, 0, clRect.bottom, bits, (BITMAPINFO *) &bmih, DIB_RGB_COLORS); + mir_free(bits); + } + DeleteObject(hBmpOsb); + g_inCLCpaint = FALSE; + done = GetTickCount(); +} -- cgit v1.2.3