/*

Miranda NG: the free IM client for Microsoft* Windows*

Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
Copyright (c) 2000-08 Miranda ICQ/IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or ( at your option ) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "hdr/modern_commonheaders.h"

#include "hdr/modern_clc.h"
#include "hdr/modern_skinengine.h"
#include "hdr/modern_commonprototypes.h"
#include "hdr/modern_row.h"
#include "hdr/modern_clcpaint.h"

CLCPaint g_clcPainter;

DWORD CLCPaint::HASH[hi_LastItem] = {0};
const char* CLCPaint::HASHTEXT[hi_LastItem] = {
	"Module",
	"ID",
	"Type",
	"Open",
	"IsEmpty",
	"SubPos",
	"Protocol",
	"RootGroup",
	"Status",
	"HasAvatar",
	"GroupPos",
	"Selected",
	"Hot",
	"Odd",
	"Indent",
	"Index",
	"Name",
	"Group",
	"True",
	"False",
	"ONLINE",
	"AWAY",
	"DND",
	"NA",
	"OCCUPIED",
	"FREECHAT",
	"INVISIBLE",
	"OUTTOLUNCH",
	"ONTHEPHONE",
	"IDLE",
	"OFFLINE",
	"Row",
	"CL",
	"SubContact",
	"MetaContact",
	"Contact",
	"Divider",
	"Info",
	"First-Single",
	"First",
	"Middle",
	"Mid",
	"Single",
	"Last",
	"Rate",
	"None",
	"Low",
	"Medium",
	"High",
	"State",
	"Active",
	"Inactive"
	//ADD item here
};
const int CLCPaint::HORIZONTAL_SPACE     = 2;
const int CLCPaint::EXTRA_CHECKBOX_SPACE = 2;
const int CLCPaint::EXTRA_SPACE          = 2;
const int CLCPaint::SELECTION_BORDER     = 6;
const int CLCPaint::MIN_TEXT_WIDTH       = 20;
const int CLCPaint::BUF2SIZE             = 7;

const BYTE CLCPaint::GIM_SELECTED_AFFECT = 1;
const BYTE CLCPaint::GIM_HOT_AFFECT  = 2;
const BYTE CLCPaint::GIM_TEMP_AFFECT = 4;
const BYTE CLCPaint::GIM_IDLE_AFFECT = 8;
const BYTE CLCPaint::GIM_EXTRAICON_AFFECT = CLCPaint::GIM_SELECTED_AFFECT | CLCPaint::GIM_HOT_AFFECT | CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
const BYTE CLCPaint::GIM_STATUSICON_AFFECT = CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
const BYTE CLCPaint::GIM_AVATAR_AFFECT = CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;

CLCPaint::CLCPaint()
{
	_FillQuickHash();
};

void  CLCPaint::cliPaintClc( HWND hwnd, ClcData *dat, HDC hdc, RECT *rcPaint )
{
	if ( MirandaExiting()) return;
	g_CluiData.mutexPaintLock++;
	g_clcPainter._PaintClc( hwnd, dat, hdc, rcPaint );
	g_CluiData.mutexPaintLock--;
}

BOOL  CLCPaint::IsForegroundWindow( HWND hWnd )
{
	HWND hWindow;
	hWindow = hWnd;
	while ( hWindow ) {
		if ( GetForegroundWindow() == hWindow ) return TRUE;
		hWindow = GetParent( hWindow );
	}
	return FALSE;
}

HFONT CLCPaint::ChangeToFont( HDC hdc, ClcData *dat, int id, int *fontHeight )
{
	if (!dat)
		dat = (ClcData*)GetWindowLongPtr( pcli->hwndContactTree, 0 );

	if (!dat)
		return NULL;

	HFONT res = ( HFONT )SelectObject( hdc, dat->fontModernInfo[id].hFont );
	SetTextColor( hdc, dat->fontModernInfo[id].colour );

	if ( fontHeight )
		*fontHeight = dat->fontModernInfo[id].fontHeight;
	ske_ResetTextEffect( hdc );

	if ( dat->hWnd == pcli->hwndContactTree && dat->fontModernInfo[id].effect != 0 )
		ske_SelectTextEffect( hdc, dat->fontModernInfo[id].effect-1, dat->fontModernInfo[id].effectColour1, dat->fontModernInfo[id].effectColour2 );
	else
		ske_ResetTextEffect( hdc );

	return res;
}

int CLCPaint::GetBasicFontID(ClcContact *contact)
{
	ClcCacheEntry *pdnce = NULL;
	if (contact->type == CLCIT_CONTACT)
		pdnce = pcli->pfnGetCacheEntry(contact->hContact);

	switch (contact->type) {
	case CLCIT_GROUP:
		return ( contact->group->expanded ) ? FONTID_OPENGROUPS : FONTID_CLOSEDGROUPS;

	case CLCIT_INFO:
		return ( contact->flags & CLCIIF_GROUPFONT ) ? FONTID_OPENGROUPS : FONTID_CONTACTS;

	case CLCIT_DIVIDER:
		return FONTID_DIVIDERS;

	case CLCIT_CONTACT:
		if (contact->flags & CONTACTF_NOTONLIST)
			return FONTID_NOTONLIST;
		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)))
		{
			// 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
			return (contact->flags & CONTACTF_ONLINE) ? FONTID_INVIS : FONTID_OFFINVIS;
		}

		switch( pdnce___GetStatus( pdnce )) {
			case ID_STATUS_OFFLINE: return FONTID_OFFLINE;
			case ID_STATUS_AWAY: return FONTID_AWAY;
			case ID_STATUS_DND: return FONTID_DND;
			case ID_STATUS_NA: return FONTID_NA;
			case ID_STATUS_OCCUPIED: return FONTID_OCCUPIED;
			case ID_STATUS_FREECHAT: return FONTID_CHAT;
			case ID_STATUS_INVISIBLE: return FONTID_INVISIBLE;
			case ID_STATUS_ONTHEPHONE: return FONTID_PHONE;
			case ID_STATUS_OUTTOLUNCH: return FONTID_LUNCH;
		}

	default:
		return FONTID_CONTACTS;
	}
}

void  CLCPaint::GetTextSize( SIZE *text_size, HDC hdcMem, RECT free_row_rc, TCHAR *szText, SortedList *plText, UINT uTextFormat, int smiley_height )
{
	if ( szText == NULL || !szText[0] ) {
		text_size->cy = 0;
		text_size->cx = 0;
	}
	else {
		RECT text_rc = free_row_rc;
		int free_width;
		int free_height;

		free_width = text_rc.right - text_rc.left;
		free_height = text_rc.bottom - text_rc.top;

		// Always need cy...
		text_size->cy = ske_DrawText(hdcMem, szText, lstrlen( szText ), &text_rc, DT_CALCRECT | uTextFormat );
		text_size->cy = min( text_size->cy, free_height );
		if ( plText == NULL )
			text_size->cx = min( text_rc.right - text_rc.left + 2, free_width );
		else {
			// See each item of list
			int i;

			text_size->cy = min( max( text_size->cy, smiley_height ), free_height );

			text_size->cx = 0;

			for ( i=0; i < plText->realCount && text_size->cx < free_width; i++ ) {
				ClcContactTextPiece *piece = ( ClcContactTextPiece * ) plText->items[i];

				if ( piece->type == TEXT_PIECE_TYPE_TEXT ) {
					text_rc = free_row_rc;

					ske_DrawText(hdcMem, &szText[piece->start_pos], piece->len, &text_rc, DT_CALCRECT | uTextFormat );
					text_size->cx = min( text_size->cx + text_rc.right - text_rc.left + 2, free_width );
				}
				else {
					double factor;

					if ( piece->smiley_height > text_size->cy )
						factor = text_size->cy / ( double ) piece->smiley_height;
					else
						factor = 1;

					text_size->cx = min( text_size->cx + ( long )( factor * piece->smiley_width ), free_width );
				}
			}
		}
	}
}

void  CLCPaint::AddParam( MODERNMASK *mpModernMask, DWORD dwParamHash, const char* const szValue, DWORD dwValueHash )
{
	static MASKPARAM param = {0}; //AddParameter will clear it so it can be static to avoid initializations
	_FillParam( &param, dwParamHash, szValue, dwValueHash );
	_AddParameter( mpModernMask, &param );
}

BOOL  CLCPaint::CheckMiniMode( ClcData *dat, BOOL selected, BOOL hot )
{
	if ((!dat->bCompactMode /* not mini*/ )
		|| (( dat->bCompactMode&0x01 ) && selected /*mini on selected*/ )
		/* || ( TRUE && hot )*/ ) return FALSE;
	return TRUE;
}

tPaintCallbackProc CLCPaint::PaintCallbackProc( HWND hWnd, HDC hDC, RECT *rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData )
{
	ClcData* dat = ( ClcData* )GetWindowLongPtr( hWnd, 0 );
	if (!dat ) return 0;
	cliPaintClc( hWnd, dat, hDC, rcPaint );
	return NULL;
}

void  CLCPaint::_FillQuickHash()
{
	int i;
	for ( i=0; i < hi_LastItem; i++ )
		HASH[i] = mod_CalcHash( HASHTEXT[i] );
}

void  CLCPaint::_SetHotTrackColour( HDC hdc, 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   CLCPaint::_GetStatusOnlineness( int status )
{
	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;
}

int   CLCPaint::_GetGeneralisedStatus()
{
	int status = ID_STATUS_OFFLINE;
	int statusOnlineness = 0;

	for ( int i=0; i < pcli->hClcProtoCount; i++ )
	{
		int thisStatus = pcli->clcProto[i].dwStatus;
		if ( thisStatus == ID_STATUS_INVISIBLE )
			return ID_STATUS_INVISIBLE;

		int thisOnlineness = _GetStatusOnlineness( thisStatus );
		if ( thisOnlineness > statusOnlineness )
		{
			status = thisStatus;
			statusOnlineness = thisOnlineness;
		}
	}
	return status;
}

int   CLCPaint::_GetRealStatus( ClcContact *pContact, int nStatus )
{
	if (!pContact->proto )
		return nStatus;

	for ( int i=0; i < pcli->hClcProtoCount; i++ )
	{
		if (!lstrcmpA( pcli->clcProto[i].szProto, pContact->proto ))
			return pcli->clcProto[i].dwStatus;
	}
	return nStatus;
}


RECT  CLCPaint::_GetRectangle( ClcData *dat, RECT *row_rc, RECT *free_row_rc, int *left_pos, int *right_pos, BOOL left, int real_width, int width, int height, int horizontal_space )
{
	RECT rc = *free_row_rc;
	int width_tmp = width;
	if ( left )
	{
		if ( dat->row_align_left_items_to_left )
			width_tmp = real_width;

		rc.left += ( width_tmp - real_width ) >> 1;
		rc.right = rc.left + real_width;
		rc.top += ( rc.bottom - rc.top - height ) >> 1;
		rc.bottom = rc.top + height;
		*left_pos += width_tmp + horizontal_space;
		free_row_rc->left = row_rc->left + *left_pos;
	}
	else // if (!left )
	{
		if ( dat->row_align_right_items_to_right )
			width_tmp = real_width;

		if ( width_tmp > rc.right - rc.left )
		{
			rc.left = rc.right + 1;
		}
		else
		{
			rc.left = max( rc.left + horizontal_space, rc.right - width_tmp )  + (( width_tmp - real_width ) >> 1 );
			rc.right = min( rc.left + real_width, rc.right );
			rc.top += max( 0, ( rc.bottom - rc.top - height ) >> 1 );
			rc.bottom = min( rc.top + height, rc.bottom );

			*right_pos += min( width_tmp + horizontal_space, free_row_rc->right - free_row_rc->left );
			free_row_rc->right = row_rc->right - *right_pos;
		}
	}

	return rc;
}



void  CLCPaint::_DrawTextSmiley( HDC hdcMem, RECT *free_rc, SIZE * text_size, TCHAR *szText, int start, int len, SortedList *plText, UINT uTextFormat, BOOL ResizeSizeSmiley )
{
	if ( szText == NULL )return;
	uTextFormat  &= ~DT_RIGHT;
	if ( plText == NULL ) {
		if (start) {
			SIZE size;
			GetTextExtentPoint32(hdcMem, szText, start, &size);
			free_rc->left += size.cx;
		}

		ske_DrawText(hdcMem, szText + start, len, free_rc, uTextFormat );
	}
	else
	{
		// Draw list
		int i;
		int pos_x = 0;
		int row_height;
		RECT tmp_rc = *free_rc;
		if ( len == -1 ) len = (int)_tcslen( szText );
		if ( uTextFormat & DT_RTLREADING )
			i = plText->realCount - 1;
		else
			i=0;

		// Get real height of the line
		row_height = ske_DrawText(hdcMem, _T("A"), 1, &tmp_rc, DT_CALCRECT | uTextFormat );

		// Just draw ellipsis
		if ( free_rc->right <= free_rc->left )
		{
			if ( gl_TrimText ) ske_DrawText(hdcMem, _T("..."), 3, free_rc, uTextFormat & ~DT_END_ELLIPSIS );
		}
		else
		{
			// Draw text and smileys
			for ( ; i < plText->realCount && i >= 0 && pos_x < text_size->cx && len > 0; i += ( uTextFormat & DT_RTLREADING ? -1 : 1 ))
			{
				ClcContactTextPiece *piece = ( ClcContactTextPiece * ) plText->items[i];
				RECT text_rc = *free_rc;

				if ( uTextFormat & DT_RTLREADING )
					text_rc.right -= pos_x;
				else
					text_rc.left += pos_x;

				if ( piece->type == TEXT_PIECE_TYPE_TEXT )
				{
					tmp_rc = text_rc;
					tmp_rc.right += 50;
					ske_DrawText(hdcMem, &szText[piece->start_pos + start], min( len, piece->len ), &tmp_rc, DT_CALCRECT | ( uTextFormat & ~DT_END_ELLIPSIS ));
					pos_x += tmp_rc.right - tmp_rc.left + 2;

					if ( uTextFormat & DT_RTLREADING )
						text_rc.left = max( text_rc.left, text_rc.right - ( tmp_rc.right - tmp_rc.left ));

					ske_DrawText(hdcMem, &szText[piece->start_pos + start], min( len, piece->len ), &text_rc, uTextFormat );
					len -= piece->len;
				}
				else
				{
					float factor = 0;

					if ( len < piece->len )
					{
						len = 0;
					}
					else
					{
						LONG fac_width, fac_height;
						len -= piece->len;

						if ( piece->smiley_height > row_height && ResizeSizeSmiley )
						{
							factor = row_height / ( float ) piece->smiley_height;
						}
						else
						{
							factor = 1;
						}

						fac_width = ( LONG )( piece->smiley_width * factor );
						fac_height = ( LONG )( piece->smiley_height * factor );

						if ( uTextFormat & DT_RTLREADING )
							text_rc.left = max( text_rc.right - fac_width, text_rc.left );

						if ( fac_width <= text_rc.right - text_rc.left )
						{
							text_rc.top += ( row_height - fac_height ) >> 1;

							ske_DrawIconEx(hdcMem, text_rc.left, text_rc.top, piece->smiley,
								fac_width, fac_height, 0, NULL, DI_NORMAL|(( factor < 1 )?128:0 )); //TO DO enchance drawing quality
						}
						else
						{
							ske_DrawText(hdcMem, _T("..."), 3, &text_rc, uTextFormat );
						}

						pos_x += fac_width;
					}
				}
			}
		}
	}
}


void  CLCPaint::_AddParameter( MODERNMASK *mpModernMask, MASKPARAM * lpParam )
{
	mpModernMask->pl_Params = ( MASKPARAM * )realloc( mpModernMask->pl_Params, ( mpModernMask->dwParamCnt+1 )*sizeof( MASKPARAM ));
	memmove( &( mpModernMask->pl_Params[mpModernMask->dwParamCnt] ), lpParam, sizeof( MASKPARAM ));
	mpModernMask->dwParamCnt++;
	memset( lpParam, 0, sizeof( MASKPARAM ));
}

void  CLCPaint::_FillParam( MASKPARAM * lpParam, DWORD dwParamHash, const char* const szValue, DWORD dwValueHash )
{
	lpParam->bMaskParamFlag = MPF_EQUAL|MPF_HASHED;
	lpParam->dwId = dwParamHash;
	if (!dwValueHash && szValue && szValue[0] ) lpParam->dwValueHash = mod_CalcHash( szValue );
	else lpParam->dwValueHash = dwValueHash;
	if ( szValue ) lpParam->szValue = strdupn( szValue, strlen( szValue ));
	else lpParam->szValue = NULL;
}

void  CLCPaint::_AddParamShort( MODERNMASK *mpModernMask, DWORD dwParamIndex, DWORD dwValueIndex )
{
	AddParam( mpModernMask, HASH[dwParamIndex], HASHTEXT[dwValueIndex], HASH[dwValueIndex] );
}


MODERNMASK* CLCPaint::_GetCLCContactRowBackModernMask( ClcGroup *group, ClcContact *Drawing, int indent, int index, BOOL selected, BOOL hottrack, ClcData *dat )
{
	MODERNMASK *mpModernMask = NULL;
	char buf[BUF2SIZE] = {0};
	mpModernMask = ( MODERNMASK* )mir_calloc( sizeof( MODERNMASK ));

	_AddParamShort( mpModernMask, hi_Module, hi_CL );
	_AddParamShort( mpModernMask, hi_ID, hi_Row );
	switch ( Drawing->type )
	{
	case CLCIT_GROUP:
		{
			_AddParamShort( mpModernMask, hi_Type, hi_Group );
			_AddParamShort( mpModernMask, hi_Open, ( Drawing && Drawing->group && Drawing->group->expanded )?hi_True:hi_False );
			_AddParamShort( mpModernMask, hi_IsEmpty, ( Drawing->group->cl.count == 0 )?hi_True:hi_False );
		}
		break;
	case CLCIT_CONTACT:
		{
			ClcContact *mCont = Drawing;
			if ( Drawing->isSubcontact )
			{
				_AddParamShort( mpModernMask, hi_Type, hi_SubContact );
				if ( Drawing->isSubcontact == 1 && Drawing->subcontacts->SubAllocated == 1 )
					_AddParamShort( mpModernMask, hi_SubPos, hi_First_Single );
				else if ( Drawing->isSubcontact == 1 )
					_AddParamShort( mpModernMask, hi_SubPos, hi_First );
				else if ( Drawing->isSubcontact == Drawing->subcontacts->SubAllocated )
					_AddParamShort( mpModernMask, hi_SubPos, hi_Last );
				else
					_AddParamShort( mpModernMask, hi_SubPos, hi_Middle );
				mCont = Drawing->subcontacts;
			}
			else if ( Drawing->SubAllocated )
			{
				_AddParamShort( mpModernMask, hi_Type, hi_MetaContact );
				_AddParamShort( mpModernMask, hi_Open, ( Drawing->SubExpanded )?hi_True:hi_False );
			}
			else
				_AddParamShort( mpModernMask, hi_Type, hi_Contact );
			AddParam( mpModernMask, HASH[hi_Protocol], Drawing->proto, 0 );
			_AddParamShort( mpModernMask, hi_RootGroup, ( group && group->parent == NULL )?hi_True:hi_False );
			switch( GetContactCachedStatus( Drawing->hContact ))
			{
				// case ID_STATUS_CONNECTING: AppendChar( buf, BUFSIZE, "CONNECTING"); break;
			case ID_STATUS_ONLINE:      _AddParamShort( mpModernMask, hi_Status, hi_ONLINE );    break;
			case ID_STATUS_AWAY:        _AddParamShort( mpModernMask, hi_Status, hi_AWAY );      break;
			case ID_STATUS_DND:         _AddParamShort( mpModernMask, hi_Status, hi_DND );       break;
			case ID_STATUS_NA:          _AddParamShort( mpModernMask, hi_Status, hi_NA );        break;
			case ID_STATUS_OCCUPIED:    _AddParamShort( mpModernMask, hi_Status, hi_OCCUPIED );  break;
			case ID_STATUS_FREECHAT:    _AddParamShort( mpModernMask, hi_Status, hi_FREECHAT );  break;
			case ID_STATUS_INVISIBLE:   _AddParamShort( mpModernMask, hi_Status, hi_INVISIBLE ); break;
			case ID_STATUS_OUTTOLUNCH:  _AddParamShort( mpModernMask, hi_Status, hi_OUTTOLUNCH );break;
			case ID_STATUS_ONTHEPHONE:  _AddParamShort( mpModernMask, hi_Status, hi_ONTHEPHONE );break;
			case ID_STATUS_IDLE:        _AddParamShort( mpModernMask, hi_Status, hi_IDLE );      break;
			default:                    _AddParamShort( mpModernMask, hi_Status, hi_OFFLINE );
			}
			_AddParamShort( mpModernMask, hi_HasAvatar, ( dat->avatars_show  && Drawing->avatar_data != NULL )?hi_True:hi_False );
			_AddParamShort( mpModernMask, hi_Rate, hi_None + Drawing->bContactRate );
			break;
		}
	case CLCIT_DIVIDER:
		{
			_AddParamShort( mpModernMask, hi_Type, hi_Divider );
		}
		break;
	case CLCIT_INFO:
		{
			_AddParamShort( mpModernMask, hi_Type, hi_Info );
		}
		break;
	}
	if ( group->scanIndex == 0 && group->cl.count == 1 )
		_AddParamShort( mpModernMask, hi_GroupPos, hi_First_Single );
	else if ( group->scanIndex == 0 )
		_AddParamShort( mpModernMask, hi_GroupPos, hi_First );
	else if ( group->scanIndex+1 == group->cl.count )
		_AddParamShort( mpModernMask, hi_GroupPos, hi_Last );
	else
		_AddParamShort( mpModernMask, hi_GroupPos, hi_Mid );

	_AddParamShort( mpModernMask, hi_Selected, ( selected )?hi_True:hi_False );
	_AddParamShort( mpModernMask, hi_Hot, ( hottrack )?hi_True:hi_False );
	_AddParamShort( mpModernMask, hi_Odd, ( index&1 )?hi_True:hi_False );

	_itoa( indent, buf, BUF2SIZE );
	AddParam( mpModernMask, HASH[hi_Indent], buf, 0 );
	_itoa( index, buf, BUF2SIZE );
	AddParam( mpModernMask, HASH[hi_Index], buf, 0 );
	{
		TCHAR * b2 = mir_tstrdup( Drawing->szText );
		int i, m;
		m = lstrlen( b2 );
		for ( i=0; i < m; i++ )
			if ( b2[i] == _T( ',' )) b2[i] = _T( '.' );
		{
			char* b3 = mir_utf8encodeT( b2 );
			AddParam( mpModernMask, HASH[hi_Name], b3, 0 );
			mir_free( b3 );
		}

		mir_free( b2 );
	}
	if ( group->parent )
	{
		TCHAR * b2 = mir_tstrdup( group->parent->cl.items[0]->szText );
		int i, m;
		m = lstrlen( b2 );
		for ( i=0; i < m; i++ )
			if ( b2[i] == _T( ',' )) b2[i] = _T( '.' );
		{
			char * b3 = mir_utf8encodeT( b2 );
			AddParam( mpModernMask, HASH[hi_Group], b3, 0 );
			mir_free( b3 );
		}

		mir_free( b2 );
	}
	return mpModernMask;
}


void CLCPaint::_RTLRect( RECT *rect, int width, int offset )
{
	int left, right;
	if (!rect ) return;
	left = ( width )-rect->right;
	right = ( width )-rect->left;
	rect->left = left;//-offset;
	rect->right = right;//-offset;
	return;
}

void CLCPaint::_PaintRowItemsEx( HWND hwnd, HDC hdcMem, ClcData *dat, ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
{
	int i=0;
	int dx = free_row_rc.left;
	int dy = row_rc.top+dat->row_border;
	int dg = 0;


	// Let calc placeholder
	int minheight = dat->row_min_heigh;
	int mode2 = -1;
	COLORREF colourFg = RGB( 0, 0, 0 );
	BOOL InClistWindow = ( dat->hWnd == pcli->hwndContactTree );
	ClcCacheEntry *pdnce = NULL;
	int height = RowHeight_CalcRowHeight( dat, hwnd, Drawing, -1 );

	// TO DO DEPRECATE OLD ROW LAYOUT

	if ( Drawing->type == CLCIT_CONTACT )
		pdnce = pcli->pfnGetCacheEntry( Drawing->hContact );

	if ( Drawing->type == CLCIT_GROUP  &&
		Drawing->group->parent->groupId == 0  &&
		Drawing->group->parent->cl.items[0] != Drawing )
	{
		dg = dat->row_before_group_space;
		free_row_rc.top += dg;
		height -= dg;
	}
	if (!InClistWindow || !gl_RowRoot || Drawing->type == CLCIT_GROUP )
	{
		// to do paint simple
		RECT fr_rc = free_row_rc;

		//1 draw icon
		if (!( Drawing->type == CLCIT_GROUP && InClistWindow && dat->row_hide_group_icon ))
		{
			int iImage = -1;
			// Get image
			if ( Drawing->type == CLCIT_GROUP )
			{
				iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
			}
			else if ( Drawing->type == CLCIT_CONTACT )
				iImage = Drawing->iImage;
			if ( iImage != -1 )
			{
				COLORREF colourFg;
				int mode;
				RECT p_rect = {0};
				p_rect.top = fr_rc.top+(( fr_rc.bottom-fr_rc.top-ICON_HEIGHT )>>1 );
				p_rect.left = fr_rc.left;
				p_rect.right = p_rect.left+ICON_HEIGHT;
				p_rect.bottom = p_rect.top+ICON_HEIGHT;
				// Store pos
				if ( dat->text_rtl != 0 ) _RTLRect( &p_rect, free_row_rc.right, dx );
				Drawing->pos_icon = p_rect;
				if ( hottrack )
				{
					colourFg = dat->hotTextColour;
					mode = ILD_NORMAL;
				}
				else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
				{
					colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
					mode = ILD_BLEND50;
				}
				else
				{
					colourFg = dat->selBkColour;
					mode = ILD_NORMAL;
				}

				if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE )  &&
					_GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
				{
					mode = ILD_SELECTED;
				}
				_DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top,   0, 0, CLR_NONE, colourFg, mode );

			}
			fr_rc.left += ICON_HEIGHT+2;
		}
		//2 draw extra
		{
			RECT p_rect = {0};
			p_rect.top = fr_rc.top+(( fr_rc.bottom-fr_rc.top-ICON_HEIGHT )>>1 );
			//p_rect.left = fr_rc.left;
			//p_rect.right = p_rect.left+ICON_HEIGHT;
			p_rect.bottom = p_rect.top+ICON_HEIGHT;

			if (( Drawing->type == CLCIT_GROUP || Drawing->type == CLCIT_CONTACT || Drawing->type == CLCIT_INFO )
				&& dat->extraColumnsCount > 0 && (!InClistWindow || Drawing->type == CLCIT_CONTACT ))
			{
				int BlendedInActiveState = dat->dbbBlendInActiveState;
				int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
				int iImage;
				int count = 0;
				RECT rc;
				int x = 0;
				for ( iImage = dat->extraColumnsCount-1; iImage >= 0 ; iImage-- )
				{
					COLORREF colourFg = dat->selBkColour;
					int mode = BlendedInActiveState?BlendValue:ILD_NORMAL;
					if (Drawing->iExtraImage[iImage] == EMPTY_EXTRA_ICON) {
						x += ( x>0 )?dat->extraColumnSpacing : ICON_HEIGHT;
						SetRect( &rc, fr_rc.right-x, p_rect.top, fr_rc.right-x+ICON_HEIGHT, p_rect.bottom );
						if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
						Drawing->pos_extra[iImage] = rc;
						count++;
						continue;
					}

					if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
					else if ( hottrack )
					{
						mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
						colourFg = dat->hotTextColour;
					}
					else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
					{
						colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
						mode = BlendValue;
					}

					x += ( x>0 )?dat->extraColumnSpacing:ICON_HEIGHT;
					SetRect( &rc, fr_rc.right-x, p_rect.top, fr_rc.right-x+ICON_HEIGHT, p_rect.bottom );
					if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
					Drawing->pos_extra[iImage] = rc;
					Drawing->pos_extra[iImage] = rc;
					if (Drawing->iExtraImage[iImage] != EMPTY_EXTRA_ICON)
						ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
							rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
				}
				fr_rc.right -= x;
			}
		}
		//3 draw text
		{
			SIZE text_size = {0};
			char * szCounts = NULL;
			RECT text_rect = fr_rc;
			RECT counts_rc = {0};
			UINT uTextFormat = DT_LEFT|DT_VCENTER|( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
			uTextFormat |= dat->text_rtl?DT_RTLREADING:0;
			// Select font
			ChangeToFont(hdcMem, dat, GetBasicFontID( Drawing ), NULL );

			// Get text size
			GetTextSize( &text_size, hdcMem, fr_rc, Drawing->szText, Drawing->ssText.plText, uTextFormat,
				dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
			// counters
			if ( Drawing->type == CLCIT_GROUP && InClistWindow )
			{
				RECT nameRect = fr_rc;
				RECT countRect = {0};
				RECT count_rc = {0};
				SIZE count_size = {0};
				int space_width = 0;
				char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
				// Has to draw the count?
				if ( szCounts && strlen( szCounts )>0 )
				{
					// calc width and height
					ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
					ske_DrawText(hdcMem, _T(" "), 1, &count_rc, DT_CALCRECT | DT_NOPREFIX );
					count_size.cx = count_rc.right-count_rc.left;
					space_width = count_size.cx;
					count_rc.right = 0;
					count_rc.left = 0;
					ske_DrawTextA(hdcMem, szCounts, lstrlenA( szCounts ), &count_rc, DT_CALCRECT );
					count_size.cx += count_rc.right-count_rc.left;
					count_size.cy = count_rc.bottom-count_rc.top;
				}
				// modify text rect
				//if (!RTL )
				{
					SIZE text_size = {0};
					int wid = fr_rc.right-fr_rc.left;
					ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
					GetTextSize( &text_size, hdcMem, fr_rc, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );

					if ( wid-count_size.cx > text_size.cx )
					{

						if ( dat->row_align_group_mode != 2 ) //center or left
						{
							int x = ( dat->row_align_group_mode == 1 )?( wid-( text_size.cx+count_size.cx ))>>1:0;
							nameRect.left += x;
							nameRect.right = nameRect.left+text_size.cx;
							countRect.left = nameRect.right+space_width;
							countRect.right = countRect.left+count_size.cx-space_width;
						}
						else
						{
							countRect.right = nameRect.right;
							countRect.left = countRect.right-(( count_size.cx>0 )?( count_size.cx-space_width ):0 );
							nameRect.right = countRect.left-(( count_size.cx>0 )?space_width:0 );
							nameRect.left = nameRect.right-text_size.cx;
						}

					}

					else
					{
						countRect.right = nameRect.right;
						nameRect.right -= count_size.cx;
						countRect.left = nameRect.right+space_width;
					}
					countRect.bottom = nameRect.bottom;
					countRect.top = nameRect.top;
				}



				//if (!( szCounts && strlen( szCounts )>0 ))
				//uTextFormat |= ( dat->row_align_group_mode == 2 )?DT_RIGHT:( dat->row_align_group_mode == 1 )?DT_CENTER:DT_LEFT;

				uTextFormat |= DT_VCENTER;
				ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
				if ( selected )
					SetTextColor(hdcMem, dat->selTextColour );
				else if ( hottrack )
					_SetHotTrackColour(hdcMem, dat );
				if ( dat->text_rtl != 0 ) _RTLRect( &nameRect, free_row_rc.right, dx );
				_DrawTextSmiley(hdcMem, &nameRect, &text_size, Drawing->szText, 0, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );

				if (selected && !dat->filterSearch) {
					SetTextColor(hdcMem, dat->quickSearchColour );
					_DrawTextSmiley(hdcMem, &nameRect, &text_size, Drawing->szText, 0, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
				}
				if ( szCounts && strlen( szCounts )>0 )
				{
					ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
					if ( selected )
						SetTextColor(hdcMem, dat->selTextColour );
					else if ( hottrack )
						_SetHotTrackColour(hdcMem, dat );
					if ( dat->text_rtl != 0 ) _RTLRect( &countRect, free_row_rc.right, dx );
					ske_DrawTextA(hdcMem, szCounts, lstrlenA( szCounts ), &countRect, uTextFormat );
				}
				{
					RECT rc = fr_rc;
					if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
					Drawing->pos_rename_rect = rc;
				}
				Drawing->pos_label = nameRect;
				return;
			}
			else if ( Drawing->type == CLCIT_GROUP )
			{

				szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
				// Has to draw the count?
				if ( szCounts && szCounts[0] )
				{
					RECT space_rc = fr_rc;

					int text_width = 0;
					SIZE space_size = {0};
					SIZE counts_size = {0};
					// Get widths
					counts_rc = fr_rc;
					DrawText(hdcMem, _T(" "), 1, &space_rc, DT_CALCRECT | DT_NOPREFIX );

					space_size.cx = space_rc.right - space_rc.left;
					space_size.cy = min( space_rc.bottom - space_rc.top, fr_rc.bottom-fr_rc.top );

					ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
					DrawTextA(hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, DT_CALCRECT );

					counts_size.cx = counts_rc.right - counts_rc.left;
					counts_size.cy = min( counts_rc.bottom - counts_rc.top, fr_rc.bottom-fr_rc.top );

					text_width = fr_rc.right - fr_rc.left - space_size.cx - counts_size.cx;

					if ( text_width > 4 )
					{
						text_size.cx = min( text_width, text_size.cx );
						text_width = text_size.cx + space_size.cx + counts_size.cx;
					}
					else
					{
						text_width = text_size.cx;
						space_size.cx = 0;
						counts_size.cx = 0;
					}
					text_rect.right = text_rect.left+text_size.cx;
					counts_rc = text_rect;
					counts_rc.left = text_rect.right+space_size.cx;
					counts_rc.right = counts_rc.left+counts_size.cx;
				}
			}
			ChangeToFont(hdcMem, dat, GetBasicFontID( Drawing ), NULL );

			// Set color
			if ( selected )
				SetTextColor(hdcMem, dat->selTextColour );
			else if ( hottrack )
				_SetHotTrackColour(hdcMem, dat );
			if ( dat->text_rtl != 0 ) _RTLRect( &text_rect, free_row_rc.right, dx );
			_DrawTextSmiley(hdcMem, &text_rect, &text_size, Drawing->szText, 0, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
			if ( ((dat->filterSearch && Drawing->type != CLCIT_GROUP) || selected) && dat->szQuickSearch[0] != '\0' )
			{
				int idx = 0;
				if ( dat->filterSearch )
				{
					TCHAR *lowered = CharLowerW(NEWTSTR_ALLOCA(Drawing->szText));
					TCHAR *lowered_search = CharLowerW(NEWTSTR_ALLOCA(dat->szQuickSearch));
					TCHAR *p1 = _tcsstr(lowered, lowered_search);
					if (p1)
						idx = int(p1 - lowered);
				}
				SetTextColor(hdcMem, dat->quickSearchColour );
				_DrawTextSmiley(hdcMem, &text_rect, &text_size, Drawing->szText, idx, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
			}
			if ( Drawing->type == CLCIT_GROUP && szCounts && szCounts[0] && counts_rc.right-counts_rc.left>0 )
			{
				ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
				if ( dat->text_rtl != 0 ) _RTLRect( &counts_rc, free_row_rc.right, dx );
				ske_DrawTextA(hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, uTextFormat );
				if ( dat->text_rtl == 0 )
					text_rect.right = counts_rc.right;
				else
					text_rect.left = counts_rc.left;
			}
			Drawing->pos_label = text_rect;
			{
				RECT rc = fr_rc;
				if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
				Drawing->pos_rename_rect = rc;
			}

			if ((!InClistWindow || !g_CluiData.fLayered ) &&  (( Drawing->type == CLCIT_DIVIDER ) || ( Drawing->type == CLCIT_GROUP && dat->exStyle&CLS_EX_LINEWITHGROUPS )))
			{
				//???
				RECT rc = fr_rc;
				if ( dat->text_rtl != 0 )
				{
					rc.left = Drawing->pos_rename_rect.left;
					rc.right = text_rect.left-3;
				}
				else
					rc.left = text_rect.right+3;
				if ( rc.right-rc.left>4 )
				{
					rc.top += (( rc.bottom-rc.top )>>1 )-1;
					rc.bottom = rc.top+2;
					DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT );
					ske_SetRectOpaque(hdcMem, &rc );
				}
			}

		}
		return;
	}
	minheight = max( minheight, height );
	dy += ( minheight>height )?(( minheight-height )>>1 ):0;
	// Call Placement
	cppCalculateRowItemsPos( gl_RowRoot, free_row_rc.right-free_row_rc.left );
	// Now paint
	while (( gl_RowTabAccess[i] != NULL || ( i < 2 && Drawing->type == CLCIT_GROUP )) && !( i >= 2 && Drawing->type == CLCIT_GROUP ))
	{

		if ( gl_RowTabAccess[i]->r.right-gl_RowTabAccess[i]->r.left>0
			&& gl_RowTabAccess[i]->r.bottom-gl_RowTabAccess[i]->r.top>0 )
		{
			RECT p_rect = gl_RowTabAccess[i]->r;
			OffsetRect( &p_rect, dx, dy );
			if ( dat->text_rtl != 0 && gl_RowTabAccess[i]->type != TC_EXTRA /*each extra icon modified separately*/ ) _RTLRect( &p_rect, free_row_rc.right, 0 );
			switch ( gl_RowTabAccess[i]->type )
			{
			case TC_TEXT1:
				{
					//paint text 1
					SIZE text_size;
					UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
					text_size.cx = p_rect.right-p_rect.left;
					text_size.cy = p_rect.bottom-p_rect.top;
					ChangeToFont(hdcMem, dat, GetBasicFontID( Drawing ), NULL );

					uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
					uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;

					uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
					if ( Drawing->type == CLCIT_CONTACT )
					{
						if ( selected )
							SetTextColor(hdcMem, dat->selTextColour );
						else if ( hottrack )
							_SetHotTrackColour(hdcMem, dat );
						_DrawTextSmiley(hdcMem, &p_rect, &text_size, Drawing->szText, 0, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
						if ( (dat->filterSearch || selected) && dat->szQuickSearch[0] != '\0' )
						{
							int idx = 0;
							if ( dat->filterSearch )
							{
								TCHAR *lowered = CharLowerW(NEWTSTR_ALLOCA(Drawing->szText));
								TCHAR *lowered_search = CharLowerW(NEWTSTR_ALLOCA(dat->szQuickSearch));
								TCHAR *p1 = _tcsstr(lowered, lowered_search);
								if (p1)
									idx = int(p1 - lowered);
							}
							SetTextColor(hdcMem, dat->quickSearchColour );
							_DrawTextSmiley(hdcMem, &p_rect, &text_size, Drawing->szText, idx, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
						}
						Drawing->pos_rename_rect = p_rect;
						{
							SIZE size;
							GetTextSize( &size, hdcMem, p_rect, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
							Drawing->pos_label = p_rect;
							Drawing->pos_label.right = min( Drawing->pos_label.right, Drawing->pos_label.left+size.cx );
						}

					}
					else if ( Drawing->type == CLCIT_GROUP )
					{
						RECT nameRect = p_rect;
						RECT countRect = {0};
						RECT count_rc = {0};
						SIZE count_size = {0};
						int space_width = 0;
						char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
						// Has to draw the count?
						if ( szCounts && strlen( szCounts )>0 )
						{


							// calc width and height
							ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
							ske_DrawText(hdcMem, _T(" "), 1, &count_rc, DT_CALCRECT | DT_NOPREFIX );
							count_size.cx = count_rc.right-count_rc.left;
							space_width = count_size.cx;
							count_rc.right = 0;
							count_rc.left = 0;
							ske_DrawTextA(hdcMem, szCounts, lstrlenA( szCounts ), &count_rc, DT_CALCRECT );
							count_size.cx += count_rc.right-count_rc.left;
							count_size.cy = count_rc.bottom-count_rc.top;
						}
						// modify text rect
						//if (!RTL )
						{
							SIZE text_size = {0};
							int wid = p_rect.right-p_rect.left;
							ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
							GetTextSize( &text_size, hdcMem, p_rect, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );

							if ( wid-count_size.cx > text_size.cx )
							{

								if ( dat->row_align_group_mode != 2 ) //center or left
								{
									int x = ( dat->row_align_group_mode == 1 )?( wid-( text_size.cx+count_size.cx ))>>1:0;
									nameRect.left += x;
									nameRect.right = nameRect.left+text_size.cx;
									countRect.left = nameRect.right+space_width;
									countRect.right = countRect.left+count_size.cx-space_width;
								}
								else
								{
									countRect.right = nameRect.right;
									countRect.left = countRect.right-(( count_size.cx>0 )?( count_size.cx-space_width ):0 );
									nameRect.right = countRect.left-(( count_size.cx>0 )?space_width:0 );
									nameRect.left = nameRect.right-text_size.cx;
								}

							}

							else
							{
								countRect.right = nameRect.right;
								nameRect.right -= count_size.cx;
								countRect.left = nameRect.right+space_width;
							}
							countRect.bottom = nameRect.bottom;
							countRect.top = nameRect.top;
						}



						//if (!( szCounts && strlen( szCounts )>0 ))
						//uTextFormat |= ( dat->row_align_group_mode == 2 )?DT_RIGHT:( dat->row_align_group_mode == 1 )?DT_CENTER:DT_LEFT;

						uTextFormat |= DT_VCENTER;
						ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
						if ( selected )
							SetTextColor(hdcMem, dat->selTextColour );
						else if ( hottrack )
							_SetHotTrackColour(hdcMem, dat );
						_DrawTextSmiley(hdcMem, &nameRect, &text_size, Drawing->szText, 0, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
						if (selected && !dat->filterSearch) {
							SetTextColor(hdcMem, dat->quickSearchColour );
							_DrawTextSmiley(hdcMem, &nameRect, &text_size, Drawing->szText, 0, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
						}
						if ( szCounts && strlen( szCounts )>0 )
						{
							ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
							if ( selected )
								SetTextColor(hdcMem, dat->selTextColour );
							else if ( hottrack )
								_SetHotTrackColour(hdcMem, dat );
							ske_DrawTextA(hdcMem, szCounts, lstrlenA( szCounts ), &countRect, uTextFormat );
						}
						Drawing->pos_rename_rect = p_rect;
						Drawing->pos_label = nameRect;
					}
					break;
				}
			case TC_TEXT2:
				{
					// paint text 2
					//
					// Select font
					SIZE text_size;
					UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
					{
						if ( dat->second_line_show && dat->second_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
						{
							// Get contact time
							TCHAR buf[70] = _T("");
							mir_free_and_nil( pdnce->szSecondLineText );

							tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
							pdnce->szSecondLineText = mir_tstrdup( buf );
						}
					}
					uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
					uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;

					text_size.cx = p_rect.right-p_rect.left;
					text_size.cy = p_rect.bottom-p_rect.top;

					ChangeToFont(hdcMem, dat, FONTID_SECONDLINE, NULL );
					uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
					if ( Drawing->type == CLCIT_CONTACT )
						_DrawTextSmiley(hdcMem, &p_rect, &text_size, pdnce->szSecondLineText, 0, lstrlen( pdnce->szSecondLineText ), pdnce->ssSecondLine.plText, uTextFormat, dat->text_resize_smileys );
					break;
				}
			case TC_TEXT3:
				{
					//paint text 3
					// Select font
					SIZE text_size;
					UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
					{
						if ( dat->third_line_show && dat->third_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
						{
							// Get contact time
							TCHAR buf[70] = _T("");
							mir_free( pdnce->szThirdLineText );

							tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
							pdnce->szThirdLineText = mir_tstrdup( buf );
						}
					}
					uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
					uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;

					text_size.cx = p_rect.right-p_rect.left;
					text_size.cy = p_rect.bottom-p_rect.top;

					ChangeToFont(hdcMem, dat, FONTID_THIRDLINE, NULL );
					uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
					if ( Drawing->type == CLCIT_CONTACT )
						_DrawTextSmiley(hdcMem, &p_rect, &text_size, pdnce->szThirdLineText, 0, lstrlen( pdnce->szThirdLineText ), pdnce->ssThirdLine.plText, uTextFormat, dat->text_resize_smileys );
					break;
				}
			case TC_STATUS:
				{

					if (( Drawing->type == CLCIT_GROUP && !dat->row_hide_group_icon )
						|| ( Drawing->type == CLCIT_CONTACT && Drawing->iImage != -1
						&& !( dat->icon_hide_on_avatar && dat->avatars_show
						&& (( dat->use_avatar_service && Drawing->avatar_data != NULL )  ||
						(!dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE )
						)
						&& !Drawing->image_is_special )))
					{
						int iImage = -1;
						// Get image
						if ( Drawing->type == CLCIT_GROUP )
						{
							if (!dat->row_hide_group_icon ) iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
							else iImage = -1;
						}
						else if ( Drawing->type == CLCIT_CONTACT )
							iImage = Drawing->iImage;
						if ( iImage != -1 )
						{
							COLORREF colourFg;
							int mode;
							// Store pos
							Drawing->pos_icon = p_rect;
							if ( hottrack )
							{
								colourFg = dat->hotTextColour;
								mode = ILD_NORMAL;
							}
							else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
							{
								colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
								mode = ILD_BLEND50;
							}
							else
							{
								colourFg = dat->selBkColour;
								mode = ILD_NORMAL;
							}

							if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE )  &&
								_GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
							{
								mode = ILD_SELECTED;
							}

							_DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top,   0, 0, CLR_NONE, colourFg, mode );

						}
					}

					break;
				}
			case TC_AVATAR:
				{
					BOOL hasAvatar = ( dat->use_avatar_service && Drawing->avatar_data != NULL )  || (!dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE );
					BYTE     blendmode = 255;
					if ( hottrack )
						blendmode = 255;
					else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
						blendmode = 128;
					if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE )  &&
						_GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
						blendmode = 128;
					if (!hasAvatar )  //if no avatar then paint icon image
					{
						int iImage = Drawing->iImage;
						if ( iImage != -1 )
						{
							COLORREF colourFg;
							int mode;
							// Store pos
							Drawing->pos_icon = p_rect;
							if ( hottrack )
							{
								colourFg = dat->hotTextColour;
								mode = ILD_NORMAL;
							}
							else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
							{
								colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
								mode = ILD_BLEND50;
							}
							else
							{
								colourFg = dat->selBkColour;
								mode = ILD_NORMAL;
							}

							if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE )  &&
								_GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
							{
								mode = ILD_SELECTED;
							}

							_DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top,   0, 0, CLR_NONE, colourFg, mode );

						}
					}
					else
					{
						HRGN rgn = NULL;
						HRGN oldrgn;
						int round_radius = 0;
						int width = p_rect.right-p_rect.left;
						int height = p_rect.bottom-p_rect.top;
						// Store pos
						Drawing->pos_avatar = p_rect;
						oldrgn = CreateRectRgn( 0, 0, 0, 0 );
						GetClipRgn(hdcMem, oldrgn );

						// Round corners
						if ( dat->avatars_round_corners )
						{
							if ( dat->avatars_use_custom_corner_size )
								round_radius = dat->avatars_custom_corner_size;
							else
								round_radius = min( width, height ) / 5;
						}
						else
						{
							round_radius = 0;
						}
						if ( dat->avatars_draw_border )
						{
							HBRUSH hBrush = CreateSolidBrush( dat->avatars_border_color );
							HBRUSH hOldBrush = ( HBRUSH )SelectObject(hdcMem, hBrush );
							HRGN rgn2;
							rgn = CreateRoundRectRgn( p_rect.left, p_rect.top, p_rect.right+1, p_rect.bottom+1, round_radius << 1, round_radius << 1 );
							rgn2 = CreateRoundRectRgn( p_rect.left+1, p_rect.top+1, p_rect.right, p_rect.bottom, round_radius << 1, round_radius << 1 );
							CombineRgn( rgn2, rgn, rgn2, RGN_DIFF );
							// FrameRgn(hdcMem, rgn, hBrush, 1, 1 );
							FillRgn(hdcMem, rgn2, hBrush );
							ske_SetRgnOpaque(hdcMem, rgn2 );
							SelectObject(hdcMem, hOldBrush );
							DeleteObject( hBrush );
							DeleteObject( rgn );
							DeleteObject( rgn2 );
						}
						if ( dat->avatars_round_corners || dat->avatars_draw_border )
						{
							int k = dat->avatars_draw_border?1:0;
							rgn = CreateRoundRectRgn( p_rect.left+k, p_rect.top+k, p_rect.right+1-k, p_rect.bottom+1-k, round_radius * 2, round_radius * 2 );
							ExtSelectClipRgn(hdcMem, rgn, RGN_AND );
						}

						// Draw avatar
						if ( dat->use_avatar_service )
						{
							int w = width;
							int h = height;
							_DrawContactAvatar(hdcMem, dat, Drawing, &row_rc, selected, hottrack, p_rect, &p_rect );
						}
						else
						{
							ImageArray_DrawImage( &dat->avatar_cache, Drawing->avatar_pos, hdcMem, p_rect.left, p_rect.top, 255 );
						}
						// Restore region
						if ( dat->avatars_round_corners || dat->avatars_draw_border )
						{
							DeleteObject( rgn );
						}
						SelectClipRgn(hdcMem, oldrgn );
						DeleteObject( oldrgn );


						// Draw borders

						//TODO fix overlays
						// Draw overlay
						if (dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + (dat->avatars_draw_border ? 2 : 0)
							&& GetContactCachedStatus(Drawing->hContact) - ID_STATUS_OFFLINE < SIZEOF(g_pAvatarOverlayIcons))
						{
							p_rect.top = p_rect.bottom - ICON_HEIGHT;
							p_rect.left = p_rect.right - ICON_HEIGHT;

							if ( dat->avatars_draw_border )
							{
								p_rect.top--;
								p_rect.left--;
							}

							switch( dat->avatars_overlay_type )
							{
							case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
								{
									UINT a = blendmode;
									a = ( a << 24 );
									ske_ImageList_DrawEx( hAvatarOverlays, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID,
										hdcMem,
										p_rect.left, p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
										CLR_NONE, CLR_NONE,
										( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );

									//ske_DrawIconEx(hdcMem, p_rect.left, p_rect.top, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].icon,
									//  ICON_HEIGHT, ICON_HEIGHT, 0, NULL, DI_NORMAL|a );
									break;
								}
							case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
								{
									int item = pcli->pfnIconFromStatusMode(Drawing->proto, Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus(Drawing->hContact), Drawing->hContact);
									if (item != -1)
										_DrawStatusIcon(Drawing, dat, item, hdcMem,
											p_rect.left,  p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
											CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
								}
								break;
							case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
								if ( Drawing->iImage != -1 )
									_DrawStatusIcon( Drawing, dat, Drawing->iImage, hdcMem,
										p_rect.left,  p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
										CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
								break;
							}
						}
					}

					break;
				}
			case TC_EXTRA:
				{

					if ( Drawing->type == CLCIT_CONTACT  &&
						(!Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 ))
					{
						int BlendedInActiveState = dat->dbbBlendInActiveState;
						int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
						int iImage;
						int count = 0;
						RECT rc;
						int x = 0;
						for ( iImage = 0; iImage < dat->extraColumnsCount ; iImage++ ) {
							COLORREF colourFg = dat->selBkColour;
							int mode = BlendedInActiveState?BlendValue:ILD_NORMAL;
							if (Drawing->iExtraImage[iImage] == EMPTY_EXTRA_ICON) {
								if (!dat->MetaIgnoreEmptyExtra) {
									SetRect( &rc, p_rect.left+x, p_rect.top, p_rect.left+x+ICON_HEIGHT, p_rect.bottom );
									x += dat->extraColumnSpacing;
									if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
									Drawing->pos_extra[iImage] = rc;
									count++;
								}
								continue;
							}

							if ( selected )
								mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
							else if (hottrack) {
								mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
								colourFg = dat->hotTextColour;
							}
							else if (Drawing->type == CLCIT_CONTACT && (Drawing->flags & CONTACTF_NOTONLIST)) {
								colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
								mode = BlendValue;
							}

							SetRect( &rc, p_rect.left+x, p_rect.top, p_rect.left+x+ICON_HEIGHT, p_rect.bottom );
							x += dat->extraColumnSpacing;
							count++;
							if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
							Drawing->pos_extra[iImage] = rc;
							if (Drawing->iExtraImage[iImage] != EMPTY_EXTRA_ICON)
								ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
									rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
						}
					}
					break;
				}
			case TC_EXTRA1:
			case TC_EXTRA2:
			case TC_EXTRA3:
			case TC_EXTRA4:
			case TC_EXTRA5:
			case TC_EXTRA6:
			case TC_EXTRA7:
			case TC_EXTRA8:
			case TC_EXTRA9:
				{
					if ( Drawing->type == CLCIT_CONTACT  &&
						(!Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 ))
					{
						int eNum = gl_RowTabAccess[i]->type-TC_EXTRA1;
						if ( eNum < dat->extraColumnsCount )
							if (Drawing->iExtraImage[eNum] != EMPTY_EXTRA_ICON) {
								int mode = 0;
								int BlendedInActiveState = dat->dbbBlendInActiveState;
								int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
								if ( mode2 != -1 ) mode = mode2;
								else
								{
									if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
									else if ( hottrack )
									{
										mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
										colourFg = dat->hotTextColour;
									}
									else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
									{
										colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
										mode = BlendValue;
									}
									mode2 = mode;
								}
								if ( dat->text_rtl != 0 ) _RTLRect( &p_rect, free_row_rc.right, 0 );
								Drawing->pos_extra[eNum] = p_rect;
								if (Drawing->iExtraImage[eNum] != EMPTY_EXTRA_ICON)
									ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[eNum], hdcMem,
										p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
							}
					}
				}
			case TC_TIME:
				{
					TCHAR szResult[80];

					if (!tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
					{
						// Select font
						ChangeToFont(hdcMem, dat, FONTID_CONTACT_TIME, NULL );
						ske_DrawText(hdcMem, szResult, lstrlen( szResult ), &p_rect, DT_NOPREFIX | DT_SINGLELINE|( dat->text_rtl ? DT_RTLREADING : 0 ));
					}
					break;
				}
			}
		}
		i++;
	}
	return;
}




void CLCPaint::_DrawStatusIcon( ClcContact *Drawing, ClcData *dat, int iImage, HDC hdcMem, int x, int y, int cx, int cy, DWORD colorbg, DWORD colorfg, int mode )
{
	if ( Drawing->type != CLCIT_CONTACT )
	{
		ske_ImageList_DrawEx( g_himlCListClc, LOWORD(iImage), hdcMem,
			x, y, cx, cy, colorbg, colorfg, mode );
	}
	else if ( Drawing->image_is_special )
	{
		ske_ImageList_DrawEx( g_himlCListClc, LOWORD(iImage), hdcMem,
			x, y, cx, cy, colorbg, colorfg, mode );
	}
	else if ( iImage != -1 && HIWORD(iImage) && dat->drawOverlayedStatus )
	{
		int status = GetContactCachedStatus( Drawing->hContact );
		if (status < ID_STATUS_OFFLINE) status = ID_STATUS_OFFLINE;
		else if (status > ID_STATUS_OUTTOLUNCH) status = ID_STATUS_ONLINE;
		ske_ImageList_DrawEx(g_himlCListClc, HIWORD(iImage), hdcMem, x, y, cx, cy, colorbg, colorfg, mode);
		if (dat->drawOverlayedStatus & 2) //draw overlay
			ske_ImageList_DrawEx( hAvatarOverlays, g_pStatusOverlayIcons[status-ID_STATUS_OFFLINE].listID, hdcMem,
				x, y, cx, cy, colorbg, colorfg, mode );
	}
	else
	{
		ske_ImageList_DrawEx( g_himlCListClc, LOWORD(iImage), hdcMem,
			x, y, cx, cy, colorbg, colorfg, mode );
	}
}

BOOL CLCPaint::_DrawNonEnginedBackground( HWND hwnd, HDC hdcMem, RECT *rcPaint, RECT clRect, ClcData *dat )
{
	if (!dat->hBmpBackground)
		return FALSE;

	// XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98.
	SetStretchBltMode(hdcMem, HALFTONE );

	BITMAP bmp;
	GetObject(dat->hBmpBackground, sizeof(bmp), &bmp);
	HDC hdcBmp = CreateCompatibleDC(hdcMem );
	HBITMAP oldbm = ( HBITMAP )SelectObject( hdcBmp, dat->hBmpBackground );
	int x, y = dat->backgroundBmpUse&CLBF_SCROLL?-dat->yScroll:0;
	int maxx = dat->backgroundBmpUse&CLBF_TILEH?clRect.right:1;
	int maxy = dat->backgroundBmpUse&CLBF_TILEV?maxy = rcPaint->bottom:y+1;
	int destw, desth;

	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;
			if ( dat->backgroundBmpUse&CLBF_TILEVTOROWHEIGHT )
			{
				desth = dat->row_min_heigh;
			}

		}
		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;
		if ( dat->backgroundBmpUse&CLBF_TILEVTOROWHEIGHT )
		{
			desth = dat->row_min_heigh;
		}
		break;
	}

	for ( ;y < maxy;y += desth ) {
		if ( y < rcPaint->top-desth ) continue;
		for ( x = 0;x < maxx;x += destw )
			StretchBlt(hdcMem, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY );
	}
	SelectObject( hdcBmp, oldbm );
	DeleteDC( hdcBmp );
	return TRUE;
}

int CLCPaint::_DetermineDrawMode( HWND hWnd, ClcData *dat )
{
	int paintMode = DM_LAYERED; // by default

	if ( dat->force_in_dialog  )
		paintMode = DM_CONTROL;
	else if ( g_CluiData.fDisableSkinEngine )
		paintMode = DM_CLASSIC;
	else if (!g_CluiData.fLayered )
		paintMode = DM_NON_LAYERED;

	if (!(paintMode&DM_CONTROL) && !CLUI_IsInMainWindow( hWnd ))
		paintMode |= DM_FLOAT;

	LONG lStyle = GetWindowLongPtr( hWnd, GWL_STYLE );
	int  nStatus = _GetGeneralisedStatus();
	if (( lStyle & WS_DISABLED )
		|| ( dat->greyoutFlags & pcli->pfnClcStatusToPf2( nStatus ))
		|| (( dat->greyoutFlags & GREYF_UNFOCUS) && ( GetFocus() != hWnd )))
		paintMode |= DM_GRAY;

	if ( lStyle&CLS_GREYALTERNATE )
		paintMode |= DM_GREYALTERNATE;

	return paintMode;
}

void CLCPaint::_PreparePaintContext( HWND hWnd, ClcData *dat, HDC hdc, int paintMode, RECT& clRect, _PaintContext& pc )
{
	if ((paintMode & DM_GRAY) && !(paintMode & DM_LAYERED)) {
		pc.hdcMem2 = CreateCompatibleDC(hdc);
		if (paintMode & DM_CLASSIC)
			pc.hBmpOsb2 = CreateBitmap( clRect.right, clRect.bottom, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
		else
			pc.hBmpOsb2 = ske_CreateDIB32( clRect.right, clRect.bottom );
		pc.oldbmp2 = (HBITMAP)SelectObject( pc.hdcMem2, pc.hBmpOsb2 );
		pc.fRelease |= _PaintContext::release_hdcmem2;
	}

	if (paintMode & (DM_DRAW_OFFSCREEN | DM_GRAY)) {
		pc.hdcMem = CreateCompatibleDC(hdc);
		pc.fRelease |= _PaintContext::release_hdcmem;
		pc.hBmpOsb = ske_CreateDIB32( clRect.right, clRect.bottom );
		pc.oldbmp = (HBITMAP)SelectObject( pc.hdcMem, pc.hBmpOsb );
	}

	if ((paintMode & DM_CONTROL) && !dat->bkChanged) {
		pc.tmpbkcolour = GetSysColor( COLOR_3DFACE );
		pc.tmpforecolour = GetSysColor( COLOR_BTNTEXT );
	}
	else {
		pc.tmpbkcolour = (!(paintMode & DM_CONTROL) && dat->bkChanged ) ? dat->bkColour : (!dat->useWindowsColours ?  dat->bkColour : GetSysColor( COLOR_3DFACE ));
		pc.tmpforecolour = dat->fontModernInfo[FONTID_CONTACTS].colour;
	}

	if ( paintMode & DM_GREYALTERNATE ) {
		int rDelta = ( GetRValue( pc.tmpbkcolour )  > GetRValue( pc.tmpforecolour )) ? -10 : 10;
		int gDelta = ( GetGValue( pc.tmpbkcolour )  > GetGValue( pc.tmpforecolour )) ? -10 : 10;
		int bDelta = ( GetBValue( pc.tmpbkcolour )  > GetBValue( pc.tmpforecolour )) ? -10 : 10;
		int rValue = GetRValue( pc.tmpbkcolour ) + rDelta;
		int gValue = GetRValue( pc.tmpbkcolour ) + gDelta;
		int bValue = GetRValue( pc.tmpbkcolour ) + bDelta;

		BYTE brValue = ( rValue >255) ? 255 : rValue < 0 ? 0 : (BYTE)rValue;
		BYTE bgValue = ( gValue >255) ? 255 : gValue < 0 ? 0 : (BYTE)gValue;
		BYTE bbValue = ( bValue >255) ? 255 : bValue < 0 ? 0 : (BYTE)bValue;

		pc.hBrushAlternateGrey = CreateSolidBrush( GetNearestColor( pc.hdcMem, RGB( brValue, bgValue, bbValue )));
	}

	// Set some draw states
	SetBkMode(pc.hdcMem, TRANSPARENT);
	SetStretchBltMode(pc.hdcMem, HALFTONE);

	POINT org;
	GetBrushOrgEx( pc.hdcMem, &org );
	SetBrushOrgEx( pc.hdcMem, org.x, org.y, NULL );
}

void CLCPaint::_DrawBackground( HWND hWnd, ClcData *dat, HDC hdc, int paintMode, RECT *rcPaint, RECT& clRect, _PaintContext& pc )
{
	if (paintMode & (DM_FLOAT | DM_CONTROL)) {
		HBRUSH hBrush = CreateSolidBrush( pc.tmpbkcolour );
		FillRect( pc.hdcMem, rcPaint, hBrush );
		DeleteObject( hBrush );
		ske_SetRectOpaque( pc.hdcMem, rcPaint );
		if (!( paintMode & DM_GREYALTERNATE))
			SkinDrawGlyph( pc.hdcMem, &clRect, rcPaint, "CL,ID=Background,Type=Control");
	}
	else if ( paintMode&DM_CLASSIC) {
		if (!_DrawNonEnginedBackground( hWnd, pc.hdcMem, rcPaint, clRect, dat )) {
			HBRUSH hBrush = CreateSolidBrush( pc.tmpbkcolour );
			FillRect( pc.hdcMem, rcPaint, hBrush );
			DeleteObject( hBrush );
		}
	}
	else {
		if ( paintMode&DM_NON_LAYERED )
			ske_BltBackImage( hWnd,  (paintMode&DM_GRAY) ? pc.hdcMem2 : pc.hdcMem, rcPaint );

		SkinDrawGlyph(pc.hdcMem, &clRect, rcPaint, "CL,ID=Background");
	}
}

void CLCPaint::_DrawLines( HWND hWnd, ClcData *dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc )
{
	ClcContact *Drawing;
	ClcGroup *group = &dat->list;
	group->scanIndex = 0;
	int indent = 0;
	int subident = 0;
	int subindex = -1;
	int line_num = -1;
	int y = -dat->yScroll;
	BOOL is_foreground = IsForegroundWindow( hWnd );
	LONG lStyle = GetWindowLongPtr( hWnd, GWL_STYLE );

	while( y < rcPaint->bottom )
	{
		if ( subindex == -1 )
		{
			if ( group->scanIndex >= group->cl.count )
			{
				group = group->parent;
				indent--;
				if ( group == NULL ) break;  // Finished list
				group->scanIndex++;
				continue;
			}
		}

		line_num++;

		// Draw line, if needed
		if ( y > rcPaint->top - dat->row_heights[line_num] )
		{
			int selected;
			int hottrack;
			int left_pos;
			int right_pos;
			int free_row_height;
			RECT row_rc;
			RECT free_row_rc;
			MODERNMASK *mpRequest = NULL;
			RECT rc;

			// Get item to draw
			if ( group->scanIndex < group->cl.count )
			{
				if ( subindex == -1 ) {
					Drawing = group->cl.items[group->scanIndex];
					subident = 0;
				}
				else {
					Drawing = &( group->cl.items[group->scanIndex]->subcontacts[subindex] );
					subident = dat->subIndent;
				}
			}
			else Drawing = NULL;

			// Something to draw?
			if ( Drawing ) {

				// Calc row height
				if (!gl_RowRoot )
					RowHeights_GetRowHeight( dat, hWnd, Drawing, line_num );
				else
					RowHeight_CalcRowHeight( dat, hWnd, Drawing, line_num );

				// Init settings
				selected = (( line_num == dat->selection ) && ( dat->hwndRenameEdit != NULL || dat->showSelAlways || dat->exStyle&CLS_EX_SHOWSELALWAYS || is_foreground ) && Drawing->type != CLCIT_DIVIDER );
				hottrack = dat->exStyle&CLS_EX_TRACKSELECT && Drawing->type != CLCIT_DIVIDER && dat->iHotTrack == line_num;
				left_pos = clRect.left + dat->leftMargin + indent * dat->groupIndent + subident;
				right_pos = dat->rightMargin;   // Border

				SetRect( &row_rc, clRect.left, y, clRect.right, y + dat->row_heights[line_num] );
				free_row_rc = row_rc;
				free_row_rc.left += left_pos;
				free_row_rc.right -= right_pos;
				free_row_rc.top += dat->row_border;
				free_row_rc.bottom -= dat->row_border;
				free_row_height = free_row_rc.bottom - free_row_rc.top;

				{
					HRGN rgn = CreateRectRgn( row_rc.left, row_rc.top, row_rc.right, row_rc.bottom );
					SelectClipRgn( pc.hdcMem, rgn );
					DeleteObject( rgn );
				}

				// Store pos
				Drawing->pos_indent = free_row_rc.left;
				ZeroMemory( &Drawing->pos_check, sizeof( Drawing->pos_check ));
				ZeroMemory( &Drawing->pos_avatar, sizeof( Drawing->pos_avatar ));
				ZeroMemory( &Drawing->pos_icon, sizeof( Drawing->pos_icon ));
				ZeroMemory( &Drawing->pos_label, sizeof( Drawing->pos_label ));
				ZeroMemory( &Drawing->pos_rename_rect, sizeof( Drawing->pos_rename_rect ));
				ZeroMemory( &Drawing->pos_extra, sizeof( Drawing->pos_extra ));


				//**** Draw Background

				// Alternating grey
				if ( paintMode&DM_GREYALTERNATE && line_num&1 )
				{
					if ( paintMode&DM_CONTROL || dat->bkChanged )
					{
						FillRect( pc.hdcMem, &row_rc, pc.hBrushAlternateGrey );
					}
					else
						SkinDrawGlyph( pc.hdcMem, &row_rc, rcPaint, "CL,ID=GreyAlternate");
				}
				if (! (paintMode&(DM_CLASSIC|DM_CONTROL)))
				{
					// Row background
					if (!(paintMode&DM_CONTROL))
					{   //Build mpRequest string
						mpRequest = _GetCLCContactRowBackModernMask( group, Drawing, indent, line_num, selected, hottrack, dat );
						{
							RECT mrc = row_rc;
							if ( group->parent == 0
								&& group->scanIndex != 0
								&& group->scanIndex < group->cl.count
								&& group->cl.items[group->scanIndex]->type == CLCIT_GROUP )
							{
								mrc.top += dat->row_before_group_space;
							}
							SkinDrawGlyphMask( pc.hdcMem, &mrc, rcPaint, mpRequest );
						}
					}
					if ( selected || hottrack )
					{
						RECT mrc = row_rc;
						if ( Drawing->type == CLCIT_GROUP  &&
							Drawing->group->parent->groupId == 0  &&
							Drawing->group->parent->cl.items[0] != Drawing )
						{
							mrc.top += dat->row_before_group_space;
						}
						// Selection background ( only if hole line - full/less )
						if ( dat->HiLightMode == 1 ) // Full  or default
						{
							if ( selected )
								SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=Selection");
							if ( hottrack )
								SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=HotTracking");
						}
						else if ( dat->HiLightMode == 2 ) // Less
						{
							if ( selected )
								SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=Selection");      //instead of free_row_rc
							if ( hottrack )
								SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=HotTracking");
						}
					}

				}
				else
				{
					int checkboxWidth;
					if (( lStyle&CLS_CHECKBOXES && Drawing->type == CLCIT_CONTACT )  ||
						( lStyle&CLS_GROUPCHECKBOXES && Drawing->type == CLCIT_GROUP )  ||
						( Drawing->type == CLCIT_INFO && Drawing->flags&CLCIIF_CHECKBOX ))
						checkboxWidth = dat->checkboxSize+2;
					else checkboxWidth = 0;
					//background
					if ( selected ) {
						switch ( dat->HiLightMode )
						{
						case 0:
						case 1:
							{
								int i = y;
								int row_height = row_rc.bottom-row_rc.top;
								for ( i = y; i < y+row_height; i += max( dat->row_min_heigh, 1 ))
								{
									ImageList_DrawEx( dat->himlHighlight, 0, pc.hdcMem, 0, i, clRect.right,
										min( y+row_height-i, max( dat->row_min_heigh, 1 )), CLR_NONE, CLR_NONE,
										dat->exStyle&CLS_EX_NOTRANSLUCENTSEL?ILD_NORMAL:ILD_BLEND25 );
								}
								SetTextColor( pc.hdcMem, paintMode&DM_CONTROL ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
								break;
							}

						case 2:
							{
								int i;
								int row_height = row_rc.bottom-row_rc.top-1;
								for ( i = y+1; i < y+row_height; i += max( dat->row_min_heigh, 1 ))
								{
									ImageList_DrawEx( dat->himlHighlight, 0, pc.hdcMem, 1, i, clRect.right-2,
										min( y+row_height-i, max( dat->row_min_heigh, 1 )), CLR_NONE, CLR_NONE,
										dat->exStyle&CLS_EX_NOTRANSLUCENTSEL?ILD_NORMAL:ILD_BLEND25 );
								}
								SetTextColor( pc.hdcMem, paintMode&DM_CONTROL ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
								break;
							}
						}
					}

				}
				//**** Checkboxes
				if (( lStyle&CLS_CHECKBOXES && Drawing->type == CLCIT_CONTACT )  ||
					( lStyle&CLS_GROUPCHECKBOXES && Drawing->type == CLCIT_GROUP )  ||
					( Drawing->type == CLCIT_INFO && Drawing->flags&CLCIIF_CHECKBOX ))
				{
					//RECT rc;
					rc = free_row_rc;
					rc.right = rc.left + dat->checkboxSize;
					rc.top += ( rc.bottom - rc.top - dat->checkboxSize ) >> 1;
					rc.bottom = rc.top + dat->checkboxSize;

					if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );

					if ( xpt_IsThemed( dat->hCheckBoxTheme )) {
						xpt_DrawThemeBackground( dat->hCheckBoxTheme, pc.hdcMem, BP_CHECKBOX, Drawing->flags&CONTACTF_CHECKED?( hottrack?CBS_CHECKEDHOT:CBS_CHECKEDNORMAL ):( hottrack?CBS_UNCHECKEDHOT:CBS_UNCHECKEDNORMAL ), &rc, &rc );
					}
					else DrawFrameControl( pc.hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK|DFCS_FLAT|( Drawing->flags&CONTACTF_CHECKED?DFCS_CHECKED:0 )|( hottrack?DFCS_HOT:0 ));

					left_pos += dat->checkboxSize + EXTRA_CHECKBOX_SPACE + HORIZONTAL_SPACE;
					free_row_rc.left = row_rc.left + left_pos;

					// Store pos
					Drawing->pos_check = rc;
				}
				_PaintRowItems( hWnd, pc.hdcMem, dat, Drawing, row_rc, free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
				if ( mpRequest && !dat->force_in_dialog )
				{
					free(mpRequest->pl_Params[1].szValue);
					mpRequest->pl_Params[1].szValue = strdupn("Ovl", 3 );
					mpRequest->pl_Params[1].dwValueHash = mod_CalcHash("Ovl");
					{
						RECT mrc = row_rc;
						if ( Drawing->type == CLCIT_GROUP  &&
							Drawing->group->parent->groupId == 0  &&
							Drawing->group->parent->cl.items[0] != Drawing )
						{
							mrc.top += dat->row_before_group_space;
						}
						SkinDrawGlyphMask( pc.hdcMem, &mrc, rcPaint, mpRequest );
					}
					SkinSelector_DeleteMask( mpRequest );
					mir_free( mpRequest );
				}
			}
		}
		y += dat->row_heights[line_num];
		//increment by subcontacts
		if  (( group->cl.items && group->scanIndex < group->cl.count && group->cl.items[group->scanIndex]->subcontacts != NULL && group->cl.items[group->scanIndex]->type != CLCIT_GROUP )
			&& ( group->cl.items[group->scanIndex]->SubExpanded && dat->expandMeta ))
		{
			if ( subindex < group->cl.items[group->scanIndex]->SubAllocated-1 )
				subindex++;
			else
				subindex = -1;
		}

		if ( subindex == -1 && group->scanIndex < group->cl.count )
		{
			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;
				subindex = -1;
				continue;
			}
			group->scanIndex++;
		}
		else if ( group->scanIndex >= group->cl.count )
		{
			subindex = -1;
		}
	}
	SelectClipRgn( pc.hdcMem, NULL );
}


void CLCPaint::_DrawInsertionMark( ClcData *dat, RECT& clRect, _PaintContext& pc )
{
	HBRUSH hBrush, hoBrush;
	POINT pts[8];
	HRGN hRgn;
	int identation = dat->nInsertionLevel*dat->groupIndent;
	int yt = cliGetRowTopY( dat, dat->iInsertionMark );

	pts[0].y = yt - dat->yScroll - 4;
	if ( pts[0].y < -3 ) pts[0].y = -3;
	pts[0].x = 1+identation*( dat->text_rtl?0:1 );

	pts[1].x = pts[0].x+2;
	pts[1].y = pts[0].y+3;

	pts[2].x = clRect.right-identation*( dat->text_rtl?1:0 )-4;
	pts[2].y = pts[1].y;

	pts[3].x = clRect.right-1-identation*( dat->text_rtl?1:0 );
	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->fontModernInfo[FONTID_CONTACTS].colour );
	hoBrush = ( HBRUSH )SelectObject( pc.hdcMem, hBrush );
	FillRgn( pc.hdcMem, hRgn, hBrush );
	ske_SetRgnOpaque( pc.hdcMem, hRgn );
	SelectObject( pc.hdcMem, hoBrush );
	DeleteObject( hBrush );
}

void CLCPaint::_CopyPaintToDest( HWND hWnd, ClcData *dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc )
{
	if (!( paintMode&DM_GRAY ) && ( paintMode & DM_DRAW_OFFSCREEN ))
	{
		BitBlt( hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem, rcPaint->left, rcPaint->top, SRCCOPY );
	}

	if (( paintMode&DM_GRAY ) && hdc && hdc != pc.hdcMem )
	{
		BLENDFUNCTION bf = {AC_SRC_OVER, 0, 80, AC_SRC_ALPHA };
		BOOL a = (( paintMode&DM_GRAY ) && (( paintMode&DM_NON_LAYERED)));
		ske_AlphaBlend( a ? pc.hdcMem2 : hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, bf );
		if ( a )
			BitBlt( hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem2, rcPaint->left, rcPaint->top, SRCCOPY );
	}
}
void CLCPaint::_FreePaintContext( _PaintContext& pc )
{
	if ( pc.hBrushAlternateGrey ) DeleteObject( pc.hBrushAlternateGrey );
	SelectObject( pc.hdcMem, (HFONT) GetStockObject( DEFAULT_GUI_FONT ));
	if ( pc.fRelease&_PaintContext::release_hdcmem )
	{
		SelectObject( pc.hdcMem, pc.oldbmp );
		DeleteObject( pc.hBmpOsb );
		DeleteDC( pc.hdcMem );
	}
	if ( pc.fRelease&_PaintContext::release_hdcmem2)
	{
		SelectObject( pc.hdcMem2, pc.oldbmp2 );
		DeleteObject( pc.hBmpOsb2 );
		DeleteDC( pc.hdcMem2 );
	}
}
void CLCPaint::_PaintClc( HWND hwnd, ClcData *dat, HDC hdc, RECT *_rcPaint )
{
	g_CluiData.t_now = time( NULL );

	if ( _rcPaint && IsRectEmpty( _rcPaint )) return;       // check if draw area is not empty
	if (!IsWindowVisible( hwnd )) return;                  // and window is visible

	RECT clRect;
	GetClientRect( hwnd, &clRect );

	RECT *rcPaint = _rcPaint ? _rcPaint : &clRect;       // if null is transmitted - use whole client area

	// Invalidate ani avatars, avatars have to be validated in row paint routine below
	if ( rcPaint->top == 0 && rcPaint->bottom == clRect.bottom && dat->avatars_show )
		AniAva_InvalidateAvatarPositions( NULL );

	// Now determine paint mode
	int paintMode = _DetermineDrawMode( hwnd, dat );

	// Preparing drawing contexts
	_PaintContext pc( hdc );
	_PreparePaintContext( hwnd, dat, hdc, paintMode, clRect, pc );

	// Draw background
	_DrawBackground( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );
	// Draw lines
	if ( dat->row_heights )
		_DrawLines( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );

	//insertion mark
	if ( dat->iInsertionMark != -1 )
		_DrawInsertionMark( dat, clRect, pc );

	// BitBlt from memory to destination
	_CopyPaintToDest( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );

	// Free
	_FreePaintContext( pc );

	// all still non-validated animated avatars have to be removed
	AniAva_RemoveInvalidatedAvatars();

}

void CLCPaint::_StoreItemPos( ClcContact *contact, int ItemType, RECT *rc )
{
	contact->ext_mpItemsDesc[contact->ext_nItemsNum].itemType = ItemType;
	contact->ext_mpItemsDesc[contact->ext_nItemsNum].itemRect = *rc;
	contact->ext_nItemsNum++;
	switch ( ItemType )
	{
	case CIT_AVATAR:
		contact->pos_avatar = *rc;
		break;
	case CIT_ICON:
		contact->pos_icon = *rc;
		break;
	case CIT_TIME:
		contact->pos_contact_time = *rc;
		break;
	case CIT_TEXT:
		//	RECT pos_label;//TODO label ( CIT_TEXT??? )
		//	RECT pos_rename; //TODO		( CIT_TEXT??? )
		break;
	case CIT_CHECKBOX:
		break;
	default:
		if (( ItemType&CIT_EXTRA ) == CIT_EXTRA )
		{
			int iImage = ItemType&0x3F;
			contact->pos_extra[iImage] = *rc;
		}
		break;
	}
}


void CLCPaint::_CalcItemsPos( HWND hwnd, HDC hdcMem, ClcData *dat, ClcContact *Drawing, RECT *in_row_rc, RECT *in_free_row_rc, int left_pos, int right_pos, int selected, int hottrack )
{
	int item_iterator, item, item_text, text_left_pos;
	BOOL left = TRUE;               //TODO remove
	RECT free_row_rc = *in_free_row_rc;
	RECT row_rc = *in_row_rc;
	Drawing->ext_nItemsNum = 0;
	text_left_pos = row_rc.right;
	// Now let's check what we have to draw
	for ( item_iterator = 0 ; item_iterator < NUM_ITEM_TYPE && free_row_rc.left < free_row_rc.right ; item_iterator++ )
	{
		if ( Drawing->ext_nItemsNum >= SIZEOF( Drawing->ext_mpItemsDesc )) break;
		if ( left )
			item = item_iterator;
		else
			item = NUM_ITEM_TYPE - ( item_iterator - item_text );

		switch( dat->row_items[item] )
		{
		case ITEM_AVATAR: ///////////////////////////////////////////////////////////////////////////////////////////////////
			{
				RECT rc;
				int max_width;
				int width;
				int height;
				BOOL miniMode;
				if (!dat->avatars_show || Drawing->type != CLCIT_CONTACT )
					break;
				miniMode = CheckMiniMode( dat, selected, hottrack );
				AniAva_InvalidateAvatarPositions( Drawing->hContact );
				if ( dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space )
					max_width = max( dat->iconXSpace, dat->avatars_maxheight_size );
				else
					max_width = dat->avatars_maxheight_size;

				// Has to draw?
				if (( dat->use_avatar_service && Drawing->avatar_data == NULL )
					|| (!dat->use_avatar_service && Drawing->avatar_pos == AVATAR_POS_DONT_HAVE )
					|| miniMode )
				{
					// Don't have to draw avatar

					// Has to draw icon instead?
					if ( dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && Drawing->iImage != -1 )
					{
						RECT rc;

						// Make rectangle
						rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
							left, dat->iconXSpace, max_width, ICON_HEIGHT, HORIZONTAL_SPACE );

						if ( rc.left < rc.right )
						{
							/* center icon in avatar place */
							if ( rc.right-rc.left>16 ) rc.left += (( ( rc.right-rc.left )-16 )>>1 );
							if ( rc.bottom-rc.top>16 ) rc.top += (( ( rc.bottom-rc.top )-16 )>>1 );

							// Store position
							_StoreItemPos( Drawing, CIT_ICON, &rc );
						}
					}
					else
					{
						// Has to keep the empty space??
						if (( left && !dat->row_align_left_items_to_left ) || (!left && !dat->row_align_right_items_to_right ))
						{
							// Make rectangle
							rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
								left, max_width, max_width, dat->avatars_maxheight_size, HORIZONTAL_SPACE );

							// Store position
							//StoreItemPos( Drawing, CIT_AVATAR, &rc );
							//Drawing->pos_avatar = rc;
						}
					}
					break;
				}

				// Has to draw avatar
				if ( dat->avatar_cache.nodes && Drawing->avatar_pos > AVATAR_POS_DONT_HAVE ) {
					width = dat->avatar_cache.nodes[Drawing->avatar_pos].width;
					height = dat->avatar_cache.nodes[Drawing->avatar_pos].height;
				}else if ( Drawing->avatar_pos == AVATAR_POS_ANIMATED ) {
					width = Drawing->avatar_size.cx;
					height = Drawing->avatar_size.cy;
				}else {
					width = 0;
					height = 0;
				}

				// Make rectangle
				rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
					left, width, max_width, height, HORIZONTAL_SPACE );

				rc.top = max( free_row_rc.top, rc.top );
				rc.bottom = min( free_row_rc.bottom, rc.bottom );

				if ( rc.left < rc.right ) {
					// Store position
					_StoreItemPos( Drawing, CIT_AVATAR, &rc );
				}
				//TO DO: CALC avatar overlays
				break;
			}
		case ITEM_ICON: /////////////////////////////////////////////////////////////////////////////////////////////////////
			{
				RECT rc;
				int iImage = -1;
				BOOL has_avatar = (( dat->use_avatar_service && Drawing->avatar_data != NULL )  ||
					(!dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE ))
					&& !( CheckMiniMode( dat, selected, hottrack ));

				if ( Drawing->type == CLCIT_CONTACT
					&& dat->icon_hide_on_avatar
					&& !dat->icon_draw_on_avatar_space
					&& has_avatar
					&& !Drawing->image_is_special )
				{
					// Don't have to draw, but has to keep the empty space?
					if (( left && !dat->row_align_left_items_to_left ) || (!left && !dat->row_align_right_items_to_right ))
					{
						rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
							left, dat->iconXSpace, dat->iconXSpace, ICON_HEIGHT, HORIZONTAL_SPACE );

						if ( rc.left < rc.right ) {
							// Store position
							_StoreItemPos( Drawing, CIT_ICON, &rc );
						}
					}
					break;
				}
				if ( Drawing->type == CLCIT_CONTACT
					&& dat->icon_hide_on_avatar
					&& dat->icon_draw_on_avatar_space
					&& (!Drawing->image_is_special || !has_avatar  ||
					(
					dat->avatars_draw_overlay
					&& dat->avatars_maxheight_size >= ICON_HEIGHT + (dat->avatars_draw_border ? 2 : 0)
					&& GetContactCachedStatus(Drawing->hContact) - ID_STATUS_OFFLINE < SIZEOF(g_pAvatarOverlayIcons)
					&& dat->avatars_overlay_type == SETTING_AVATAR_OVERLAY_TYPE_CONTACT
					)))
				{
					// Don't have to draw and don't have to keep the empty space
					break;
				}

				// Get image
				iImage = -1;
				if ( Drawing->type == CLCIT_GROUP && !dat->row_hide_group_icon )
					iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
				else if ( Drawing->type == CLCIT_CONTACT )
					iImage = Drawing->iImage;

				// Has image to draw?
				if ( iImage != -1 )
				{
					// Make rectangle
					rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
						left, dat->iconXSpace, dat->iconXSpace, ICON_HEIGHT, HORIZONTAL_SPACE );

					if ( rc.left < rc.right )
					{
						// Store position
						_StoreItemPos( Drawing, CIT_ICON, &rc );
					}
				}
				break;
			}
		case ITEM_CONTACT_TIME: /////////////////////////////////////////////////////////////////////////////////////////////////////
			{
				ClcCacheEntry *pdnce = (Drawing->type == CLCIT_CONTACT) ? pcli->pfnGetCacheEntry(Drawing->hContact) : NULL;
				if ( Drawing->type == CLCIT_CONTACT && dat->contact_time_show && pdnce->hTimeZone )
				{
					TCHAR szResult[80];

					if (!tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
					{
						SIZE text_size;
						RECT rc;

						// Select font
						ChangeToFont(hdcMem, dat, FONTID_CONTACT_TIME, NULL );

						// Get text size
						text_size.cy = ske_DrawText(hdcMem, szResult, lstrlen( szResult ), &rc, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE );
						text_size.cy = min( text_size.cy, free_row_rc.bottom - free_row_rc.top );
						text_size.cx = rc.right - rc.left;

						// Get rc
						rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos, left,
							text_size.cx, text_size.cx, text_size.cy, HORIZONTAL_SPACE );

						if ( rc.left < rc.right )
						{
							// Store pos
							Drawing->pos_contact_time = rc;
							_StoreItemPos( Drawing, CIT_TIME, &rc );
						}
					}
				}
				break;
			}
		case ITEM_TEXT: /////////////////////////////////////////////////////////////////////////////////////////////////////
			{
				// Store init text position:
				text_left_pos = left_pos;

				left_pos += MIN_TEXT_WIDTH;
				free_row_rc.left = row_rc.left + left_pos;

				item_text = item;
				left = FALSE;
				break;
			}
		case ITEM_EXTRA_ICONS: //////////////////////////////////////////////////////////////////////////////////////////////
			{
				// Draw extra icons
				if (!Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 )
				{
					int iImage;
					int count = 0;
					RECT rc;

					for ( iImage = dat->extraColumnsCount-1 ; iImage >= 0 ; iImage-- ) {
						if ( Drawing->iExtraImage[iImage] != EMPTY_EXTRA_ICON || !dat->MetaIgnoreEmptyExtra ) {
							rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
								left, dat->extraColumnSpacing, dat->extraColumnSpacing, ICON_HEIGHT, 0 );
							if (rc.left < rc.right) {
								// Store position
								_StoreItemPos( Drawing, CIT_EXTRA|( iImage&0x3F ), &rc );
								//Drawing->pos_extra[iImage] = rc;
								count++;
							}
						}
					}
					// Add extra space
					if ( count )
					{
						_GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
							left, HORIZONTAL_SPACE, HORIZONTAL_SPACE, ICON_HEIGHT, 0 );
					}
				}
				break;
			}
		}
	}
	if ( text_left_pos < free_row_rc.right )
	{
		// Draw text
		RECT text_rc;
		RECT selection_text_rc;
		SIZE text_size = {0};
		SIZE second_line_text_size = {0};
		SIZE third_line_text_size = {0};
		SIZE space_size = {0};
		SIZE counts_size = {0};
		char *szCounts = NULL;//mir_tstrdup( _T(""));
		int free_width;
		int free_height;
		int max_bottom_selection_border = SELECTION_BORDER;
		UINT uTextFormat = DT_NOPREFIX| /*DT_VCENTER |*/ DT_SINGLELINE | ( dat->text_rtl ? DT_RTLREADING : 0 ) | ( dat->text_align_right ? DT_RIGHT : 0 );

		free_row_rc.left = text_left_pos;
		free_width = free_row_rc.right - free_row_rc.left;
		free_height = free_row_rc.bottom - free_row_rc.top;

		// Select font
		ChangeToFont(hdcMem, dat, GetBasicFontID( Drawing ), NULL );

		// Get text size
		GetTextSize( &text_size, hdcMem, free_row_rc, Drawing->szText, Drawing->ssText.plText, uTextFormat,
			dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );

		// Get rect
		text_rc = free_row_rc;

		free_height -= text_size.cy;
		text_rc.top += free_height >> 1;
		text_rc.bottom = text_rc.top + text_size.cy;

		if ( dat->text_align_right )
			text_rc.left = max( free_row_rc.left, free_row_rc.right - text_size.cx );
		else
			text_rc.right = min( free_row_rc.right, free_row_rc.left + text_size.cx );

		selection_text_rc = text_rc;

		// If group, can have the size of count
		if ( Drawing->type == CLCIT_GROUP )
		{
			int full_text_width = text_size.cx;
			// Group conts?
			szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );

			// Has to draw the count?
			if ( szCounts && szCounts[0] )
			{
				RECT space_rc = free_row_rc;
				RECT counts_rc = free_row_rc;
				int text_width;

				free_height = free_row_rc.bottom - free_row_rc.top;

				// Get widths
				ske_DrawText(hdcMem, _T(" "), 1, &space_rc, DT_CALCRECT | DT_NOPREFIX );
				space_size.cx = space_rc.right - space_rc.left;
				space_size.cy = min( space_rc.bottom - space_rc.top, free_height );

				ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
				DrawTextA(hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, DT_CALCRECT );

				//Store position
				//StoreItemPos( Drawing, CIT_SUBTEXT1, &counts_rc ); //  Or not to comment?

				counts_size.cx = counts_rc.right - counts_rc.left;
				counts_size.cy = min( counts_rc.bottom - counts_rc.top, free_height );

				text_width = free_row_rc.right - free_row_rc.left - space_size.cx - counts_size.cx;

				if ( text_width > 4 )
				{
					text_size.cx = min( text_width, text_size.cx );
					text_width = text_size.cx + space_size.cx + counts_size.cx;
				}
				else
				{
					text_width = text_size.cx;
					space_size.cx = 0;
					space_size.cy = 0;
					counts_size.cx = 0;
					counts_size.cy = 0;
				}

				// Get rect
				free_height -= max( text_size.cy, counts_size.cy );
				text_rc.top = free_row_rc.top + ( free_height >> 1 );
				text_rc.bottom = text_rc.top + max( text_size.cy, counts_size.cy );

				if ( dat->text_align_right )
					text_rc.left = free_row_rc.right - text_width;
				else
					text_rc.right = free_row_rc.left + text_width;

				selection_text_rc = text_rc;
				full_text_width = text_width;
				ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
			}

			if ( dat->row_align_group_mode == 1 ) //center
			{
				int x;
				x = free_row_rc.left+(( free_row_rc.right-free_row_rc.left-full_text_width )>>1 );
				//int l = dat->leftMargin;
				//int r = dat->rightMargin;
				//x = l+row_rc.left+(( row_rc.right-row_rc.left-full_text_width-l-r )>>1 );
				text_rc.left = x;
				text_rc.right = x+full_text_width;
			}
			else if ( dat->row_align_group_mode == 2 ) //right
			{
				text_rc.left = free_row_rc.right-full_text_width;
				text_rc.right = free_row_rc.right;
			}
			else //left
			{
				text_rc.left = free_row_rc.left;
				text_rc.right = free_row_rc.left+full_text_width;
			}

		}
		else if ( Drawing->type == CLCIT_CONTACT && !CheckMiniMode( dat, selected, hottrack ))
		{
			int tmp;
			ClcCacheEntry *pdnce = (Drawing->type == CLCIT_CONTACT) ? pcli->pfnGetCacheEntry(Drawing->hContact) : NULL;
			if ( dat->second_line_show && dat->second_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone)
			{
				// Get contact time
				TCHAR buf[70] = _T("");
				tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
				mir_free( pdnce->szThirdLineText );
				pdnce->szSecondLineText = mir_tstrdup( buf );
			}

			if ( dat->second_line_show && pdnce->szSecondLineText && pdnce->szSecondLineText[0]
			&& free_height > dat->second_line_top_space )
			{
				//RECT rc_tmp = free_row_rc;

				ChangeToFont(hdcMem, dat, FONTID_SECONDLINE, NULL );

				// Get sizes
				GetTextSize( &second_line_text_size, hdcMem, free_row_rc, pdnce->szSecondLineText, pdnce->ssSecondLine.plText,
					uTextFormat, dat->text_resize_smileys ? 0 : pdnce->ssSecondLine.iMaxSmileyHeight );

				// Get rect
				tmp = min( free_height, dat->second_line_top_space + second_line_text_size.cy );

				free_height -= tmp;
				text_rc.top = free_row_rc.top + ( free_height >> 1 );
				text_rc.bottom = text_rc.top + free_row_rc.bottom - free_row_rc.top - free_height;

				if ( dat->text_align_right )
					text_rc.left = max( free_row_rc.left, min( text_rc.left, free_row_rc.right - second_line_text_size.cx ));
				else
					text_rc.right = min( free_row_rc.right, max( text_rc.right, free_row_rc.left + second_line_text_size.cx ));

				selection_text_rc.top = text_rc.top;
				selection_text_rc.bottom = min( selection_text_rc.bottom, selection_text_rc.top + text_size.cy );

				max_bottom_selection_border = min( max_bottom_selection_border, dat->second_line_top_space / 2 );
			}
			if ( dat->third_line_show && dat->third_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
			{
				// Get contact time
				TCHAR buf[70] = _T("");
				tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
				mir_free( pdnce->szThirdLineText );
				pdnce->szThirdLineText = mir_tstrdup( buf );
			}
			if ( dat->third_line_show && pdnce->szThirdLineText != NULL && pdnce->szThirdLineText[0]
			&& free_height > dat->third_line_top_space )
			{
				//RECT rc_tmp = free_row_rc;

				ChangeToFont(hdcMem, dat, FONTID_THIRDLINE, NULL );

				// Get sizes
				GetTextSize( &third_line_text_size, hdcMem, free_row_rc, pdnce->szThirdLineText, pdnce->ssThirdLine.plText,
					uTextFormat, dat->text_resize_smileys ? 0 : pdnce->ssThirdLine.iMaxSmileyHeight );

				// Get rect
				tmp = min( free_height, dat->third_line_top_space + third_line_text_size.cy );

				free_height -= tmp;
				text_rc.top = free_row_rc.top + ( free_height >> 1 );
				text_rc.bottom = text_rc.top + free_row_rc.bottom - free_row_rc.top - free_height;

				if ( dat->text_align_right )
					text_rc.left = max( free_row_rc.left, min( text_rc.left, free_row_rc.right - third_line_text_size.cx ));
				else
					text_rc.right = min( free_row_rc.right, max( text_rc.right, free_row_rc.left + third_line_text_size.cx ));

				selection_text_rc.top = text_rc.top;
				selection_text_rc.bottom = min( selection_text_rc.bottom, selection_text_rc.top + text_size.cy );

				max_bottom_selection_border = min( max_bottom_selection_border, dat->third_line_top_space / 2 );
			}

			ChangeToFont(hdcMem, dat, GetBasicFontID( Drawing ), NULL );
		}


		selection_text_rc.left = text_rc.left;
		selection_text_rc.right = text_rc.right;

		Drawing->pos_label = text_rc;

		selection_text_rc.top = max( selection_text_rc.top - SELECTION_BORDER, row_rc.top );
		selection_text_rc.bottom = min( selection_text_rc.bottom + max_bottom_selection_border, row_rc.bottom );

		if ( dat->text_align_right )
			selection_text_rc.left = max( selection_text_rc.left - SELECTION_BORDER, free_row_rc.left );
		else
			selection_text_rc.right = min( selection_text_rc.right + SELECTION_BORDER, free_row_rc.right );
		_StoreItemPos( Drawing, CIT_SELECTION, &selection_text_rc );

		Drawing->pos_rename_rect = free_row_rc;

		{
			// Draw text
			uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 );

			switch ( Drawing->type )
			{
			case CLCIT_DIVIDER:
				{
					//devider
					RECT trc = free_row_rc;
					RECT rc = free_row_rc;
					rc.top += ( rc.bottom - rc.top ) >> 1;
					rc.bottom = rc.top + 2;
					rc.right = rc.left + (( rc.right - rc.left - text_size.cx )>>1 ) - 3;
					trc.left = rc.right + 3;
					trc.right = trc.left + text_size.cx + 6;
					if ( text_size.cy < trc.bottom - trc.top )
					{
						trc.top += ( trc.bottom - trc.top - text_size.cy ) >> 1;
						trc.bottom = trc.top + text_size.cy;
					}
					_StoreItemPos( Drawing, CIT_TEXT, &trc );
					rc.left = rc.right + 6 + text_size.cx;
					rc.right = free_row_rc.right;
					break;
				}
			case CLCIT_GROUP:
				{
					RECT rc = text_rc;

					// Get text rectangle
					if ( dat->text_align_right )
						rc.left = rc.right - text_size.cx;
					else
						rc.right = rc.left + text_size.cx;


					if ( text_size.cy < rc.bottom - rc.top )
					{
						rc.top += ( rc.bottom - rc.top - text_size.cy ) >> 1;
						rc.bottom = rc.top + text_size.cy;
					}

					// Draw text
					_StoreItemPos( Drawing, CIT_TEXT, &rc );

					// Has to draw the count?
					if ( counts_size.cx > 0 )
					{
						RECT counts_rc = text_rc;
						//counts_size.cx;
						if ( dat->text_align_right )
							counts_rc.right = text_rc.left + counts_size.cx;
						else
							counts_rc.left = text_rc.right - counts_size.cx;

						if ( counts_size.cy < counts_rc.bottom - counts_rc.top )
						{
							counts_rc.top += ( counts_rc.bottom - counts_rc.top - counts_size.cy + 1 ) >> 1;
							counts_rc.bottom = counts_rc.top + counts_size.cy;
						}
						// Draw counts
						_StoreItemPos( Drawing, CIT_SUBTEXT1, &counts_rc );
					}
					break;
				}
			case CLCIT_CONTACT:
				{

					RECT free_rc = text_rc;
					ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry( Drawing->hContact );
					if ( text_size.cx > 0 && free_rc.bottom > free_rc.top )
					{
						RECT rc = free_rc;
						rc.bottom = min( rc.bottom, rc.top + text_size.cy );

						if ( text_size.cx < rc.right - rc.left )
						{
							if ( dat->text_align_right )
								rc.left = rc.right - text_size.cx;
							else
								rc.right = rc.left + text_size.cx;
						}
						uTextFormat |= DT_VCENTER;
						_StoreItemPos( Drawing, CIT_TEXT, &rc );
						free_rc.top = rc.bottom;
					}
					uTextFormat &= ~DT_VCENTER;
					if ( second_line_text_size.cx > 0 && free_rc.bottom > free_rc.top )
					{
						free_rc.top += dat->second_line_top_space;

						if ( free_rc.bottom > free_rc.top )
						{
							RECT rc = free_rc;
							rc.bottom = min( rc.bottom, rc.top + second_line_text_size.cy );

							if ( second_line_text_size.cx < rc.right - rc.left )
							{
								if ( dat->text_align_right )
									rc.left = rc.right - second_line_text_size.cx;
								else
									rc.right = rc.left + second_line_text_size.cx;
							}
							_StoreItemPos( Drawing, CIT_SUBTEXT1, &rc );
							free_rc.top = rc.bottom;
						}
					}

					if ( third_line_text_size.cx > 0 && free_rc.bottom > free_rc.top )
					{
						free_rc.top += dat->third_line_top_space;

						if ( free_rc.bottom > free_rc.top )
						{
							RECT rc = free_rc;
							rc.bottom = min( rc.bottom, rc.top + third_line_text_size.cy );

							if ( third_line_text_size.cx < rc.right - rc.left )
							{
								if ( dat->text_align_right )
									rc.left = rc.right - third_line_text_size.cx;
								else
									rc.right = rc.left + third_line_text_size.cx;
							}
							_StoreItemPos( Drawing, CIT_SUBTEXT2, &rc );
							free_rc.top = rc.bottom;
						}
					}
					break;
				}
			default: // CLCIT_INFO
				{
					_StoreItemPos( Drawing, CIT_TEXT, &text_rc );
				}
			}
		}
	}

	*in_free_row_rc = free_row_rc;
	*in_row_rc = row_rc;
	Drawing->ext_fItemsValid = FALSE; /*TO DO: correctly implement placement recalculation*/
}
BOOL CLCPaint::__IsVisible( RECT *firtRect, RECT *secondRect )
{
	RECT res;
	IntersectRect( &res, firtRect, secondRect );
	return !IsRectEmpty( &res );
}


void CLCPaint::_GetBlendMode( IN ClcData *dat, IN ClcContact *Drawing, IN BOOL selected, IN BOOL hottrack, IN BOOL bFlag, OUT COLORREF * OutColourFg, OUT int * OutMode )
{
	COLORREF colourFg;
	int mode;
	int BlendedInActiveState = ( dat->dbbBlendInActiveState );
	int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
	if ( selected && ( bFlag&GIM_SELECTED_AFFECT ))
	{
		colourFg = dat->selBkColour;
		mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
	}
	else if ( hottrack && ( bFlag&GIM_HOT_AFFECT ))
	{
		mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
		colourFg = dat->hotTextColour;
	}
	else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST && ( bFlag&GIM_TEMP_AFFECT ))
	{
		colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
		mode = BlendValue;
	}
	else
	{
		colourFg = dat->selBkColour;
		mode = ILD_NORMAL;
	}
	if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE )  &&
		_GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE   &&
		( bFlag&GIM_IDLE_AFFECT )
		)
		mode = ILD_SELECTED;
	if ( OutColourFg ) *OutColourFg = colourFg;
	if ( OutMode )
	{
		if ( OutColourFg )    *OutMode = mode;  //return ILD_MODE if color requested
		else *OutMode =
			( mode == ILD_BLEND50 )?128 :
			( mode == ILD_BLEND25 )?64 :
			255;    //return alpha otherwise
	}
}

void CLCPaint::_DrawContactAvatar( HDC hdcMem, ClcData *dat, ClcContact *Drawing, RECT *row_rc, int& selected, int& hottrack, RECT& text_rc, RECT *prcItem )
{
	if ( Drawing->avatar_pos == AVATAR_POS_ANIMATED )
	{
		int overlayIdx = -1;
		int blendmode = 255;
		if (dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + (dat->avatars_draw_border ? 2 : 0)
			&&  GetContactCachedStatus(Drawing->hContact) - ID_STATUS_OFFLINE < SIZEOF(g_pAvatarOverlayIcons))
		{
			switch(dat->avatars_overlay_type) {
			case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
				overlayIdx = g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID;
				break;
			case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
				overlayIdx = pcli->pfnIconFromStatusMode(Drawing->proto, Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus(Drawing->hContact), Drawing->hContact);
				break;
			case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
				overlayIdx = Drawing->iImage;
				break;
			}
		}
		_GetBlendMode( dat, Drawing, selected, hottrack, GIM_AVATAR_AFFECT, NULL, &blendmode );
		AniAva_SetAvatarPos( Drawing->hContact, prcItem, overlayIdx, blendmode );
		AniAva_RenderAvatar( Drawing->hContact, hdcMem, prcItem );
	}
	else if ( Drawing->avatar_pos>AVATAR_POS_DONT_HAVE )
	{
		int round_radius = 0;
		HRGN rgn;
		int blendmode = 255;

		_GetBlendMode( dat, Drawing, selected, hottrack, GIM_AVATAR_AFFECT, NULL, &blendmode );

		//get round corner radius
		if ( dat->avatars_round_corners )
		{
			if ( dat->avatars_use_custom_corner_size )
				round_radius = dat->avatars_custom_corner_size;
			else
				round_radius = min( _rcWidth( prcItem ), _rcHeight( prcItem )) / 5;
		}
		// draw borders
		if ( dat->avatars_draw_border )
		{
			HBRUSH hBrush = CreateSolidBrush( dat->avatars_border_color );
			HBRUSH hOldBrush = ( HBRUSH )SelectObject(hdcMem, hBrush );
			HRGN rgnOutside = CreateRoundRectRgn( prcItem->left, prcItem->top, prcItem->right+1, prcItem->bottom+1, round_radius << 1, round_radius << 1 );
			HRGN rgnInside = CreateRoundRectRgn( prcItem->left+1, prcItem->top+1, prcItem->right, prcItem->bottom, round_radius << 1, round_radius << 1 );
			CombineRgn( rgnOutside, rgnOutside, rgnInside, RGN_DIFF );
			FillRgn(hdcMem, rgnOutside, hBrush );
			ske_SetRgnOpaque(hdcMem, rgnOutside );
			SelectObject(hdcMem, hOldBrush );
			DeleteObject( hBrush );
			DeleteObject( rgnInside );
			DeleteObject( rgnOutside );
		}

		//set clip area to clip avatars within borders
		if ( dat->avatars_round_corners || dat->avatars_draw_border )
		{
			int k = dat->avatars_draw_border?1:0;
			rgn = CreateRoundRectRgn( prcItem->left+k, prcItem->top+k, prcItem->right+1-k, prcItem->bottom+1-k, round_radius * 2, round_radius * 2 );

		}
		else
			rgn = CreateRectRgn( prcItem->left, prcItem->top, prcItem->right, prcItem->bottom );
		ExtSelectClipRgn(hdcMem, rgn, RGN_AND );
		// Draw avatar
		ImageArray_DrawImage( &dat->avatar_cache, Drawing->avatar_pos, hdcMem, prcItem->left, prcItem->top, blendmode );

		// Restore region
		DeleteObject( rgn );
		rgn = CreateRectRgn( row_rc->left, row_rc->top, row_rc->right, row_rc->bottom );
		SelectClipRgn(hdcMem, rgn );
		DeleteObject( rgn );
		// Draw overlays
		if (dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + (dat->avatars_draw_border ? 2 : 0)
			&&  GetContactCachedStatus(Drawing->hContact) - ID_STATUS_OFFLINE < SIZEOF(g_pAvatarOverlayIcons))
		{
			POINT ptOverlay = { prcItem->right-ICON_HEIGHT, prcItem->bottom-ICON_HEIGHT };
			if ( dat->avatars_draw_border ) {
				ptOverlay.x--;
				ptOverlay.y--;
			}
			switch( dat->avatars_overlay_type ) {
			case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
				ske_ImageList_DrawEx( hAvatarOverlays, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID,
					hdcMem,
					ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
					CLR_NONE, CLR_NONE,
					( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
				break;
			case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
				{
					int item = pcli->pfnIconFromStatusMode(Drawing->proto, Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus(Drawing->hContact), Drawing->hContact);
					if ( item != -1 )
						_DrawStatusIcon( Drawing, dat, item, hdcMem,
							ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
							CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
				}
				break;
			case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
				if ( Drawing->iImage != -1 )
					_DrawStatusIcon( Drawing, dat, Drawing->iImage, hdcMem,
						ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
						CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
				break;
			}
		}
	}
}

void CLCPaint::_DrawContactIcon( HDC hdcMem, ClcData *dat, ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT *prcItem )
{
	//Draw   Icon
	int iImage = -1;
	// Get image
	if ( Drawing->type == CLCIT_GROUP )
	{
		if (!dat->row_hide_group_icon ) iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
		else iImage = -1;
	}
	else if ( Drawing->type == CLCIT_CONTACT )
		iImage = Drawing->iImage;

	// Has image to draw?
	if ( iImage != -1 )
	{
		COLORREF colourFg;
		int mode;
		_GetBlendMode( dat, Drawing, selected, hottrack, GIM_STATUSICON_AFFECT, &colourFg, &mode );
		_DrawStatusIcon( Drawing, dat, iImage, hdcMem,
			prcItem->left, prcItem->top,
			0, 0, CLR_NONE, colourFg, mode );
	}
}

void CLCPaint::_DrawContactText( HDC hdcMem, ClcData *dat, ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT *prcItem, UINT uTextFormat )
{
	ChangeToFont(hdcMem, dat, GetBasicFontID( Drawing ), NULL );
	if ( selected )
		SetTextColor(hdcMem,  dat->force_in_dialog ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
	else if ( hottrack || (dat->filterSearch && dat->szQuickSearch[0] != '\0' && Drawing->type != CLCIT_GROUP) )
		_SetHotTrackColour(hdcMem, dat );

	if ( Drawing->type == CLCIT_GROUP )
	{
		ske_DrawText(hdcMem, Drawing->szText, -1, prcItem, uTextFormat );
		if (selected && !dat->filterSearch) {
			SetTextColor(hdcMem, dat->quickSearchColour );
			ske_DrawText(hdcMem, Drawing->szText, lstrlen( dat->szQuickSearch ), prcItem, uTextFormat );
		}
	}
	else if ( Drawing->type == CLCIT_CONTACT )
	{
		SIZE text_size;
		text_size.cx = _rcWidth( prcItem );
		text_size.cy = _rcHeight( prcItem );
		uTextFormat |= DT_VCENTER;
		//get font
		_DrawTextSmiley(hdcMem, prcItem, &text_size, Drawing->szText, 0, -1, Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
		if ( (dat->filterSearch || selected) && dat->szQuickSearch[0] != '\0' )
		{
			int idx = 0;
			if ( dat->filterSearch )
			{
				TCHAR *lowered = CharLowerW(NEWTSTR_ALLOCA(Drawing->szText));
				TCHAR *lowered_search = CharLowerW(NEWTSTR_ALLOCA(dat->szQuickSearch));
				TCHAR *p1 = _tcsstr(lowered, lowered_search);
				if (p1)
					idx = int(p1 - lowered);
			}
			SetTextColor(hdcMem, dat->quickSearchColour );
			_DrawTextSmiley(hdcMem, prcItem, &text_size, Drawing->szText, idx, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
		}
	}
	else
	{
		ske_DrawText(hdcMem, Drawing->szText, -1, prcItem, uTextFormat );
	}
	text_rc.right = max( text_rc.right, prcItem->right );
	text_rc.left = min( text_rc.left, prcItem->left );
}
void CLCPaint::_DrawContactSubText( HDC hdcMem, ClcData *dat, ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT *prcItem, UINT uTextFormat, BYTE itemType )
{
	if ( Drawing->type == CLCIT_GROUP )
	{
		char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );

		// Has to draw the count?
		if ( szCounts && szCounts[0] )
		{
			ChangeToFont(hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
			if ( selected )
				SetTextColor(hdcMem, dat->selTextColour );
			else if ( hottrack )
				_SetHotTrackColour(hdcMem, dat );
			ske_DrawTextA(hdcMem, szCounts, -1, prcItem, uTextFormat );
			ske_ResetTextEffect(hdcMem );
		}
	}
	else if ( Drawing->type == CLCIT_CONTACT )
	{
		SIZE text_size = { _rcWidth( prcItem ), _rcHeight( prcItem ) };
		ClcCacheEntry *pdnce = (Drawing->type == CLCIT_CONTACT) ? pcli->pfnGetCacheEntry(Drawing->hContact) : NULL;
		if ( pdnce ) {
			ChangeToFont(hdcMem, dat, itemType == CIT_SUBTEXT1 ? FONTID_SECONDLINE : FONTID_THIRDLINE, NULL );
			//draw second and third line
			if ( selected )
				SetTextColor(hdcMem, dat->selTextColour );
			else if ( hottrack )
				_SetHotTrackColour(hdcMem, dat );
			uTextFormat |= DT_VCENTER;
			if ( itemType == CIT_SUBTEXT1 )
				_DrawTextSmiley(hdcMem, prcItem,  &text_size, pdnce->szSecondLineText, 0, -1, pdnce->ssSecondLine.plText, uTextFormat, dat->text_resize_smileys );
			else
				_DrawTextSmiley(hdcMem, prcItem,  &text_size, pdnce->szThirdLineText, 0, -1, pdnce->ssThirdLine.plText, uTextFormat, dat->text_resize_smileys );
		}
	}
	text_rc.right = max( text_rc.right, prcItem->right );
	text_rc.left = min( text_rc.left, prcItem->left );
}

void CLCPaint::_DrawContactTime( HDC hdcMem, ClcData *dat, ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT *prcItem )
{
	TCHAR szResult[80];
	ClcCacheEntry *pdnce = (Drawing->type == CLCIT_CONTACT) ? pcli->pfnGetCacheEntry(Drawing->hContact) : NULL;
	if (!pdnce )
		return;

	if (!tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0)) {
		// Select font
		ChangeToFont(hdcMem, dat, FONTID_CONTACT_TIME, NULL );
		ske_DrawText(hdcMem, szResult, lstrlen( szResult ), prcItem,  DT_NOPREFIX | DT_SINGLELINE );
	}
}

void CLCPaint::_DrawContactSelection( HDC hdcMem, ClcData *dat, ClcContact *Drawing, int& selected, int& hottrack, RECT *rcPaint, RECT *prcItem )
{
	// Selection background
	if (( selected || hottrack ) && dat->HiLightMode == 0) {
		if ( selected )
			SkinDrawGlyph(hdcMem, prcItem, rcPaint, "Contact List/Selection");
		else if ( hottrack )
			SkinDrawGlyph(hdcMem, prcItem, rcPaint, "Contact List/HotTracking");
	}
}

void CLCPaint::_DrawContactExtraIcon( HDC hdcMem, ClcData *dat, ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT *rc, int iImage )
{
	//Draw extra icon
	if ( iImage != -1 ) {
		int mode;
		COLORREF colourFg;
		_GetBlendMode( dat, Drawing, selected, hottrack, GIM_EXTRAICON_AFFECT, &colourFg, &mode );
		if (Drawing->iExtraImage[iImage] != EMPTY_EXTRA_ICON)
			ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
				rc->left, rc->top, 0, 0, CLR_NONE, colourFg, mode );
	}
}

void CLCPaint::_DrawContactLine( HDC hdcMem, ClcData *dat, ClcContact *Drawing, RECT *free_row_rc, RECT *rcPaint, RECT& text_rc )
{   //draw line
	RECT rc1 = *free_row_rc;
	RECT rc2 = *free_row_rc;
	rc1.right = text_rc.left-3;
	rc2.left = text_rc.right+3;
	rc1.top += ( rc1.bottom - rc1.top ) >> 1;
	rc1.bottom = rc1.top + 2;
	rc2.top += ( rc2.bottom - rc2.top ) >> 1;
	rc2.bottom = rc2.top + 2;
	{
		RECT rcTemp = rc1;
		IntersectRect( &rc1, &rcTemp, rcPaint );
	}

	{	//Subtract icon rect from left and right.
		RECT rcTemp;
		IntersectRect( &rcTemp, &Drawing->pos_icon, &rc1 );
		if (!IsRectEmpty( &rcTemp )) rc1.right = rcTemp.left;
		IntersectRect( &rcTemp, &Drawing->pos_icon, &rc2 );
		if (!IsRectEmpty( &rcTemp )) rc2.left = rcTemp.right;
	}

	if ( rc1.right-rc1.left >= 6 && !IsRectEmpty( &rc1 ))
	{
		DrawEdge(hdcMem, &rc1, BDR_SUNKENOUTER, BF_RECT );
		ske_SetRectOpaque(hdcMem, &rc1 );
	}
	{
		RECT rcTemp = rc2;
		IntersectRect( &rc2, &rcTemp, rcPaint );
	}
	if ( rc2.right-rc2.left >= 6 && !IsRectEmpty( &rc2 ))
	{
		DrawEdge(hdcMem, &rc2, BDR_SUNKENOUTER, BF_RECT );
		ske_SetRectOpaque(hdcMem, &rc2 );
	}
}

void CLCPaint::_DrawContactItems( HWND hwnd, HDC hdcMem, ClcData *dat, ClcContact *Drawing, RECT *row_rc, RECT *free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
{
	UINT uTextFormat = DT_NOPREFIX |
		/*DT_VCENTER |*/
		DT_SINGLELINE |
		( dat->text_rtl ? DT_RTLREADING : 0 ) |
		( dat->text_align_right ? DT_RIGHT : 0 )|
		( gl_TrimText?DT_END_ELLIPSIS:0 )|
		(( dat->force_in_dialog || dat->bkChanged ) ? DT_FORCENATIVERENDER:0 );

	RECT text_rc = *row_rc;

	text_rc.right = row_rc->left;
	text_rc.left = row_rc->right;

	for (int i=0; i < Drawing->ext_nItemsNum; i++ )
	{
		RECT *prcItem = &( Drawing->ext_mpItemsDesc[i].itemRect );
		if ( __IsVisible( rcPaint, prcItem ) || ( Drawing->ext_mpItemsDesc[i].itemType == CIT_AVATAR && Drawing->avatar_pos == AVATAR_POS_ANIMATED ))
		{
			switch( Drawing->ext_mpItemsDesc[i].itemType )
			{
			case CIT_AVATAR:
				_DrawContactAvatar(hdcMem, dat, Drawing, row_rc, selected, hottrack, text_rc, prcItem );
				break;
			case CIT_ICON:
				_DrawContactIcon(hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem );
				break;
			case CIT_TEXT:
				_DrawContactText(hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, uTextFormat );
				break;
			case CIT_SUBTEXT1:
			case CIT_SUBTEXT2:
				_DrawContactSubText(hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, uTextFormat, Drawing->ext_mpItemsDesc[i].itemType );
				break;
			case CIT_TIME:
				_DrawContactTime(hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem );
				break;
			case CIT_CHECKBOX:
				//_DrawNothing no check boxes in skinned mode
				break;
				//other here
			case CIT_SELECTION:
				_DrawContactSelection(hdcMem, dat, Drawing, selected, hottrack, rcPaint, prcItem );
				break;
			default:
				if ( Drawing->ext_mpItemsDesc[i].itemType&CIT_EXTRA )
					_DrawContactExtraIcon(hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, Drawing->ext_mpItemsDesc[i].itemType&0x3F );
				break;
			}
		}
	}
	if (( Drawing->type == CLCIT_GROUP && dat->exStyle&CLS_EX_LINEWITHGROUPS )
		|| ( Drawing->type == CLCIT_DIVIDER ))
		_DrawContactLine(hdcMem, dat, Drawing, free_row_rc, rcPaint, text_rc );
}
void CLCPaint::_PaintRowItems ( HWND hwnd, HDC hdcMem, ClcData *dat, ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
{
	//Extended LAYOUT
	if ( gl_RowRoot && ( dat->hWnd == pcli->hwndContactTree ))
	{
		_PaintRowItemsEx( hwnd, hdcMem, dat, Drawing, row_rc, free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
		ske_ResetTextEffect(hdcMem );
		return;
	}
	//END OFF Extended LAYOUT
	if (!Drawing->ext_fItemsValid ) _CalcItemsPos( hwnd, hdcMem, dat, Drawing, &row_rc, &free_row_rc, left_pos, right_pos, selected, hottrack );
	_DrawContactItems( hwnd, hdcMem, dat, Drawing, &row_rc, &free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
	ske_ResetTextEffect(hdcMem );
}

/* TODO Render items

V avatar
V avatars overlays
V avatar clipping if ignore avatar height for row height calculation is set
V icon
V text
V time
V extra icons
V selection/hot
V groups and divider lines

Milestones to implement Extended row layout

-   1. Implement separate Row item position calculation and drawing
V       a. Separation of painting and positions calculation
V       b. Use Items rect array for hit test
.       c. Calculate row height via appropriate function
.       d. Invalidate row items only when needed

.   2. Implement extended row item layout
.       a. layout template parsing
.       b. calculate positions according to template
.       c. GUI to modify template
.       d. skin defined template
*/