/* astyle --force-indent=tab=4 --brackets=linux --indent-switches
 *		  --pad=oper --one-line=keep-blocks  --unpad=paren
 *
 * Miranda IM: the free IM client for Microsoft* Windows*
 *
 * Copyright 2000-2009 Miranda ICQ/IM project,
 * all portions of this codebase are copyrighted to the people
 * listed in contributors.txt.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * you should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * part of tabSRMM messaging plugin for Miranda.
 *
 * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
 *
 * $Id: tabctrl.cpp 12644 2010-09-09 04:00:25Z silvercircle $
 *
 * a custom tab control, skinable, aero support, single/multi row, button
 * tabs support, proper rendering for bottom row tabs and more.
 *
 */

#include "commonheaders.h"
#pragma hdrstop

static WNDPROC		OldTabControlClassProc;
extern ButtonSet	g_ButtonSet;

static LRESULT CALLBACK TabControlSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

#define FIXED_TAB_SIZE 100

/*
 * register the new tab control as a window class (TSTabCtrlClass)
 */

int TSAPI RegisterTabCtrlClass(void)
{
	WNDCLASSEXA wc;
	WNDCLASSEX wce;

	ZeroMemory(&wc, sizeof(wc));
	wc.cbSize         = sizeof(wc);
	wc.lpszClassName  = "TSTabCtrlClass";
	wc.lpfnWndProc    = TabControlSubclassProc;
	wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
	wc.cbWndExtra     = sizeof(struct TabControlData *);
	wc.hbrBackground  = 0;
	wc.style          = CS_GLOBALCLASS | CS_DBLCLKS | CS_PARENTDC;
	RegisterClassExA(&wc);

	ZeroMemory(&wce, sizeof(wce));
	wce.cbSize         = sizeof(wce);
	wce.lpszClassName  = _T("TSStatusBarClass");
	wce.lpfnWndProc    = StatusBarSubclassProc;
	wce.hCursor        = LoadCursor(NULL, IDC_ARROW);
	wce.cbWndExtra     = sizeof(void*);
	wce.hbrBackground  = 0;
	wce.style          = CS_GLOBALCLASS | CS_DBLCLKS | CS_PARENTDC;
	RegisterClassEx(&wce);

	ZeroMemory(&wce, sizeof(wce));
	wce.cbSize         = sizeof(wce);
	wce.lpszClassName  = _T("TS_SideBarClass");
	wce.lpfnWndProc    = CSideBar::wndProcStub;;
	wce.hCursor        = LoadCursor(NULL, IDC_ARROW);
	wce.cbWndExtra     = sizeof(void*);
	wce.hbrBackground  = 0;
	wce.style          = CS_GLOBALCLASS;// | CS_DBLCLKS; // | CS_PARENTDC;
	RegisterClassEx(&wce);

	ZeroMemory(&wce, sizeof(wce));
	wce.cbSize         = sizeof(wce);
	wce.lpszClassName  = _T("TSHK");
	wce.lpfnWndProc    = HotkeyHandlerDlgProc;
	wce.hCursor        = LoadCursor(NULL, IDC_ARROW);
	wce.cbWndExtra     = sizeof(void*);
	wce.hbrBackground  = 0;
	wce.style          = CS_GLOBALCLASS;// | CS_DBLCLKS; // | CS_PARENTDC;
	RegisterClassEx(&wce);

	return 0;
}

static int TabCtrl_TestForCloseButton(const TabControlData *tabdat, HWND hwnd, POINT& pt)
{
	TCHITTESTINFO tci = {0};
	tci.pt.x = pt.x;
	tci.pt.y = pt.y;
	int iTab;

	ScreenToClient(hwnd, &tci.pt);
	iTab = TabCtrl_HitTest(hwnd, &tci);
	if(iTab != -1) {
		RECT  rcTab;

		if(tci.flags & TCHT_NOWHERE)
			return(-1);

		TabCtrl_GetItemRect(hwnd, iTab, &rcTab);
		if(tabdat->dwStyle & TCS_BUTTONS) {
			rcTab.right -= 1;
			rcTab.left = rcTab.right - 18;
		}
		else {
			rcTab.left = rcTab.right - 18;
			rcTab.right -= 5;
		}
		rcTab.bottom -= 4;
		rcTab.top += 4;
		if(PtInRect(&rcTab, tci.pt))
			return(iTab);
	}
	return(-1);
}

/*
 * tabctrl helper function
 * Finds leftmost down item.
 */

static UINT FindLeftDownItem(HWND hwnd)
{
	RECT rctLeft = {100000, 0, 0, 0}, rctCur;
	int nCount = TabCtrl_GetItemCount(hwnd) - 1;
	UINT nItem = 0;
	int i;

	for (i = 0;i < nCount;i++) {
		TabCtrl_GetItemRect(hwnd, i, &rctCur);
		if (rctCur.left > 0 && rctCur.left <= rctLeft.left) {
			if (rctCur.bottom > rctLeft.bottom) {
				rctLeft = rctCur;
				nItem = i;
			}
		}
	}
	return nItem;
}

/*
 * tab control color definitions, including the database setting key names
 */

static struct colOptions {
	UINT defclr;
	char *szKey;
	char *szSkinnedKey;
} tabcolors[] = {
	COLOR_BTNTEXT, "tab_txt_normal", "S_tab_txt_normal",
	COLOR_BTNTEXT, "tab_txt_active", "S_tab_txt_active",
	COLOR_HOTLIGHT, "tab_txt_hottrack", "S_tab_txt_hottrack",
	COLOR_HOTLIGHT, "tab_txt_unread", "S_tab_txt_unread",
	COLOR_3DFACE, "tab_bg_normal", "tab_bg_normal",
	COLOR_3DFACE, "tab_bg_active", "tab_bg_active",
	COLOR_3DFACE, "tab_bg_hottrack", "tab_bg_hottrack",
	COLOR_3DFACE, "tab_bg_unread", "tab_bg_unread",
	0, 0, NULL, NULL
};

/*
 * hints for drawing functions
 */

#define HINT_ACTIVATE_RIGHT_SIDE 1
#define HINT_ACTIVE_ITEM 2
#define FLOAT_ITEM_HEIGHT_SHIFT 2
#define ACTIVE_ITEM_HEIGHT_SHIFT 2
#define SHIFT_FROM_CUT_TO_SPIN 4
#define HINT_TRANSPARENT 16
#define HINT_HOTTRACK 32

static void TSAPI DrawCustomTabPage(HDC hdc, RECT& rcClient)
{
	HBRUSH brOld = reinterpret_cast<HBRUSH>(::SelectObject(hdc, CSkin::m_BrushFill));
	HPEN   hPen = ::CreatePen(PS_SOLID, 1, PluginConfig.m_cRichBorders);
	HPEN   hPenOld = reinterpret_cast<HPEN>(::SelectObject(hdc, hPen));
	::Rectangle(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
	::SelectObject(hdc, hPenOld);
	::SelectObject(hdc, brOld);
	::DeleteObject(hPen);
}

void TSAPI FillTabBackground(const HDC hdc, int iStateId, const TWindowData* dat, RECT* rc)
{
	unsigned clrIndex;

	if(dat && dat->mayFlashTab)
		clrIndex = 7;
	else
		clrIndex = (iStateId == PBS_PRESSED ? 5 : (iStateId == PBS_HOT ? 6 : 4));

	if(PluginConfig.tabConfig.colors[clrIndex] != PluginConfig.m_fillColor)
		FillRect(hdc, rc, PluginConfig.tabConfig.m_brushes[clrIndex - 4]);
	else
		CSkin::FillBack(hdc, rc);
}

/*
 * draws the item contents (icon and label)
 * it obtains the label and icon handle directly from the message window data
 * no image list is used and necessary, the message window dialog procedure has to provide a valid
 * icon handle in dat->hTabIcon
 */

static void DrawItem(TabControlData *tabdat, HDC dc, RECT *rcItem, int nHint, int nItem, TWindowData* dat)
{
	int				iSize = 16;
	DWORD			dwTextFlags = DT_SINGLELINE | DT_VCENTER/* | DT_NOPREFIX*/;
	BOOL			leftMost = FALSE;

	if (dat) {
		HICON 	 hIcon;
		COLORREF clr = 0;
		HFONT 	 oldFont;
		DWORD 	 dwStyle = tabdat->dwStyle;
		int 	 oldMode = 0;
		unsigned clrIndex = 0;

		InflateRect(rcItem, -2, -2);

		if(dat->mayFlashTab)
			clrIndex = 3;
		else
			clrIndex = (nHint & HINT_ACTIVE_ITEM ? 1 : (nHint & HINT_HOTTRACK ? 2 : 0));

		clr = PluginConfig.tabConfig.colors[clrIndex];

		oldMode = SetBkMode(dc, TRANSPARENT);

		if (!(dwStyle & TCS_BOTTOM))
			OffsetRect(rcItem, 0, 1);

		if (dat->dwFlags & MWF_ERRORSTATE)
			hIcon = PluginConfig.g_iconErr;
		else if (dat->mayFlashTab)
			hIcon = dat->iFlashIcon;
		else {
			if (dat->si && dat->iFlashIcon) {
				int sizeX, sizeY;

				hIcon = dat->iFlashIcon;
				Utils::getIconSize(hIcon, sizeX, sizeY);
				iSize = sizeX;
			} else if (dat->hTabIcon == dat->hTabStatusIcon && dat->hXStatusIcon)
				hIcon = dat->hXStatusIcon;
			else
				hIcon = dat->hTabIcon;
		}


		if (dat->mayFlashTab == FALSE || (dat->mayFlashTab == TRUE && dat->bTabFlash != 0) || !(dat->pContainer->dwFlagsEx & TCF_FLASHICON)) {
			DWORD ix = rcItem->left + tabdat->m_xpad - 1;
			DWORD iy = (rcItem->bottom + rcItem->top - iSize) / 2;
			if (dat->dwFlagsEx & MWF_SHOW_ISIDLE && PluginConfig.m_IdleDetect)
				CSkin::DrawDimmedIcon(dc, ix, iy, iSize, iSize, hIcon, 180);
			else
				DrawIconEx(dc, ix, iy, hIcon, iSize, iSize, 0, NULL, DI_NORMAL | DI_COMPAT);
		}

		rcItem->left += (iSize + 2 + tabdat->m_xpad);

		if(tabdat->fCloseButton) {
			if(tabdat->iHoveredCloseIcon != nItem)
				CSkin::m_default_bf.SourceConstantAlpha = 150;

			CMimAPI::m_MyAlphaBlend(dc, rcItem->right - 16 - tabdat->m_xpad, (rcItem->bottom + rcItem->top - 16) / 2, 16, 16, CSkin::m_tabCloseHDC,
									0, 0, 16, 16, CSkin::m_default_bf);

			rcItem->right -= (18 + tabdat->m_xpad);
			CSkin::m_default_bf.SourceConstantAlpha = 255;
		}

		if (dat->mayFlashTab == FALSE || (dat->mayFlashTab == TRUE && dat->bTabFlash != 0) || !(dat->pContainer->dwFlagsEx & TCF_FLASHLABEL)) {
			oldFont = (HFONT)SelectObject(dc, (HFONT)SendMessage(tabdat->hwnd, WM_GETFONT, 0, 0));
			if (tabdat->dwStyle & TCS_BUTTONS || !(tabdat->dwStyle & TCS_MULTILINE)) { // || (tabdat->m_moderntabs && leftMost)) {
				rcItem->right -= tabdat->m_xpad;
				dwTextFlags |= DT_WORD_ELLIPSIS;
			}
			CSkin::RenderText(dc, dwStyle & TCS_BUTTONS ? tabdat->hThemeButton : tabdat->hTheme, dat->newtitle, rcItem, dwTextFlags, CSkin::m_glowSize, clr);
			SelectObject(dc, oldFont);
		}
		if (oldMode)
			SetBkMode(dc, oldMode);
	}
}

/*
 * draws the item rect (the "tab") in *classic* style (no visual themes
 */

static RECT rcTabPage = {0};

static void DrawItemRect(struct TabControlData *tabdat, HDC dc, RECT *rcItem, int nHint, int iItem, const TWindowData* dat)
{
	POINT pt;
	DWORD dwStyle = tabdat->dwStyle;

	rcItem->bottom -= 1;
	if (rcItem->left >= 0) {

		/*
		 * draw "button style" tabs... raised edge for hottracked, sunken edge for active (pushed)
		 * otherwise, they get a normal border
		 */

		if (dwStyle & TCS_BUTTONS) {
			BOOL bClassicDraw = (tabdat->m_VisualStyles == FALSE);

			// draw frame controls for button or bottom tabs
			if (dwStyle & TCS_BOTTOM)
				rcItem->top++;

			rcItem->right += 6;
			if(tabdat->fAeroTabs) {
				if(M->isAero()) {
					InflateRect(rcItem, 2, 0);
					FillRect(dc, rcItem, CSkin::m_BrushBack);
				}
				else if(dat) {
					int iStateId = (nHint & HINT_ACTIVE_ITEM ? PBS_PRESSED : 0) | (nHint & HINT_HOTTRACK ? PBS_HOT : 0);

					InflateRect(rcItem, 1, 0);
					FillTabBackground(dc, iStateId, dat, rcItem);
				}
				CSkin::m_switchBarItem->setAlphaFormat(AC_SRC_ALPHA, nHint & HINT_ACTIVE_ITEM ? 255 : 200);
				CSkin::m_switchBarItem->Render(dc, rcItem, true);


				if(nHint & HINT_ACTIVE_ITEM || nHint & HINT_HOTTRACK) {
					RECT rcGlow = *rcItem;

					if(dwStyle & TCS_BOTTOM)
						rcGlow.top++;
					else
						rcGlow.bottom--;

					tabdat->helperGlowItem->setAlphaFormat(AC_SRC_ALPHA, nHint & HINT_ACTIVE_ITEM ? 200 : 150);
					tabdat->helperGlowItem->Render(dc, &rcGlow, true);
				}
			}
			else if(bClassicDraw) {
				if (CSkin::m_skinEnabled) {
					CSkinItem *item = nHint & HINT_ACTIVE_ITEM ? &SkinItems[ID_EXTBKBUTTONSPRESSED] : (nHint & HINT_HOTTRACK ? &SkinItems[ID_EXTBKBUTTONSMOUSEOVER] : &SkinItems[ID_EXTBKBUTTONSNPRESSED]);

					if (!item->IGNORED) {
						CSkin::SkinDrawBG(tabdat->hwnd, tabdat->pContainer->hwnd, tabdat->pContainer, rcItem, dc);
						CSkin::DrawItem(dc, rcItem, item);
					} else
						goto b_nonskinned;
				} else {
b_nonskinned:
					if (nHint & HINT_ACTIVE_ITEM)
						DrawEdge(dc, rcItem, EDGE_ETCHED, BF_RECT | BF_SOFT);
					else if (nHint & HINT_HOTTRACK)
						DrawEdge(dc, rcItem, EDGE_BUMP, BF_RECT | BF_MONO | BF_SOFT);
					else
						DrawEdge(dc, rcItem, EDGE_RAISED, BF_RECT | BF_SOFT);
				}
			} else {
				if(M->isAero() && !(dwStyle & TCS_BOTTOM))
					FillRect(dc, rcItem, CSkin::m_BrushBack);
				else
					CSkin::FillBack(dc, rcItem);
				CMimAPI::m_pfnDrawThemeBackground(tabdat->hThemeButton, dc, 1, nHint & HINT_ACTIVE_ITEM ? 3 : (nHint & HINT_HOTTRACK ? 2 : 1), rcItem, rcItem);
			}
			return;
		}
		SelectObject(dc, PluginConfig.tabConfig.m_hPenLight);

		if (nHint & HINT_ACTIVE_ITEM) {
			if (dwStyle & TCS_BOTTOM) {
				if (!CSkin::m_skinEnabled)
					CSkin::FillBack(dc, rcItem);
				rcItem->bottom += 2;
			} else {
				rcItem->bottom += 2;
				if (!CSkin::m_skinEnabled)
					CSkin::FillBack(dc, rcItem);
				rcItem->bottom--;
				rcItem->top -= 2;
			}
			if (CSkin::m_skinEnabled) {
				CSkinItem *item = &SkinItems[dwStyle & TCS_BOTTOM ? ID_EXTBKTABITEMACTIVEBOTTOM : ID_EXTBKTABITEMACTIVE];
				if (!item->IGNORED) {
					rcItem->left += item->MARGIN_LEFT;
					rcItem->right -= item->MARGIN_RIGHT;
					rcItem->top += item->MARGIN_TOP;
					rcItem->bottom -= item->MARGIN_BOTTOM;
					CSkin::DrawItem(dc, rcItem, item);
					return;
				}
			}
		}
		if (CSkin::m_skinEnabled) {
			CSkinItem *item = &SkinItems[dwStyle & TCS_BOTTOM ? (nHint & HINT_HOTTRACK ? ID_EXTBKTABITEMHOTTRACKBOTTOM : ID_EXTBKTABITEMBOTTOM) :
													   (nHint & HINT_HOTTRACK ? ID_EXTBKTABITEMHOTTRACK : ID_EXTBKTABITEM)];
			if (!item->IGNORED) {
				if (dwStyle & TCS_BOTTOM)
					rcItem->top = (rcItem->top > rcTabPage.bottom + 5) ? --rcItem->top : rcItem->top;
				else
					rcItem->bottom++;
				//rcItem->bottom = (rcItem->bottom < rcTabPage.top - 5) ? ++rcItem->bottom : rcItem->bottom;

				rcItem->left += item->MARGIN_LEFT;
				rcItem->right -= item->MARGIN_RIGHT;
				CSkin::DrawItem(dc, rcItem, item);
				return;
			}
		}
		if (dwStyle & TCS_BOTTOM) {
			MoveToEx(dc, rcItem->left, rcItem->top - (nHint & HINT_ACTIVE_ITEM ? 1 : 0), &pt);
			LineTo(dc, rcItem->left, rcItem->bottom - 2);
			LineTo(dc, rcItem->left + 2, rcItem->bottom);
			SelectObject(dc, PluginConfig.tabConfig.m_hPenShadow);
			LineTo(dc, rcItem->right - 3, rcItem->bottom);

			LineTo(dc, rcItem->right - 1, rcItem->bottom - 2);
			LineTo(dc, rcItem->right - 1, rcItem->top - 1);
			MoveToEx(dc, rcItem->right - 2, rcItem->top, &pt);
			SelectObject(dc, PluginConfig.tabConfig.m_hPenItemShadow);
			LineTo(dc, rcItem->right - 2, rcItem->bottom - 1);
			MoveToEx(dc, rcItem->right - 3, rcItem->bottom - 1, &pt);
		LineTo(dc, rcItem->left + 2, rcItem->bottom - 1);
		} else {
			MoveToEx(dc, rcItem->left, rcItem->bottom, &pt);
			LineTo(dc, rcItem->left, rcItem->top + 2);
			LineTo(dc, rcItem->left + 2, rcItem->top);
			LineTo(dc, rcItem->right - 2, rcItem->top);
			SelectObject(dc, PluginConfig.tabConfig.m_hPenItemShadow);

			MoveToEx(dc, rcItem->right - 2, rcItem->top + 1, &pt);
			LineTo(dc, rcItem->right - 2, rcItem->bottom + 1);
			SelectObject(dc, PluginConfig.tabConfig.m_hPenShadow);
			MoveToEx(dc, rcItem->right - 1, rcItem->top + 2, &pt);
			LineTo(dc, rcItem->right - 1, rcItem->bottom + 1);
		}
	}
}

static int DWordAlign(int n)
{
	int rem = n % 4;
	if (rem)
		n += (4 - rem);
	return n;
}

static HRESULT DrawThemesPartWithAero(const TabControlData *tabdat, HDC hDC, int iPartId, int iStateId, LPRECT prcBox, TWindowData* dat)
{
	HRESULT hResult = 0;
	bool	fAero = M->isAero();

	if(tabdat->fAeroTabs) {
		if(tabdat->dwStyle & TCS_BOTTOM)
			prcBox->top += (fAero ? 2 : iStateId == PBS_PRESSED ? (M->isVSThemed() ? 1 : -1) : 0);
		else if (!fAero)
			prcBox->bottom -= (iStateId == PBS_PRESSED ? (M->isVSThemed() ? 1 : -1) : 0);

		if(fAero)
			FillRect(hDC, prcBox, CSkin::m_BrushBack);
		else if(dat)
			FillTabBackground(hDC, iStateId, dat, prcBox);

		tabdat->helperItem->setAlphaFormat(AC_SRC_ALPHA, iStateId == PBS_PRESSED ? 255 : (fAero ? 240 : 255));
		tabdat->helperItem->Render(hDC, prcBox, true);
		tabdat->helperGlowItem->setAlphaFormat(AC_SRC_ALPHA, iStateId == PBS_PRESSED ? 220 : 180);

		if(iStateId != PBS_NORMAL)
			tabdat->helperGlowItem->Render(hDC, prcBox, true);
	}
	else if(CMimAPI::m_pfnDrawThemeBackground) {
		if (tabdat->hTheme != 0)
			hResult = CMimAPI::m_pfnDrawThemeBackground(tabdat->hTheme, hDC, iPartId, iStateId, prcBox, NULL);
	}

	return hResult;
}
/*
 * draws a theme part (identifier in uiPartNameID) using the given clipping rectangle
 */

static HRESULT DrawThemesPart(const TabControlData *tabdat, HDC hDC, int iPartId, int iStateId, LPRECT prcBox)
{
	HRESULT hResult = 0;

	if (CMimAPI::m_pfnDrawThemeBackground == 0)
		return 0;

	if (tabdat->hTheme != 0)
		hResult = CMimAPI::m_pfnDrawThemeBackground(tabdat->hTheme, hDC, iPartId, iStateId, prcBox, NULL);

	return hResult;
}

/*
 * draw a themed tab item. either a tab or the body pane
 * handles image mirroring for tabs at the bottom
 */

static void DrawThemesXpTabItem(HDC pDC, int ixItem, RECT *rcItem, UINT uiFlag, struct TabControlData *tabdat, TWindowData* dat)
{
	BOOL bBody  = (uiFlag & 1) ? TRUE : FALSE;
	BOOL bSel   = (uiFlag & 2) ? TRUE : FALSE;
	BOOL bHot   = (uiFlag & 4) ? TRUE : FALSE;
	BOOL bBottom = (uiFlag & 8) ? TRUE : FALSE;	// mirror
	SIZE szBmp;
	HDC  dcMem;
	HBITMAP bmpMem, pBmpOld;
	RECT rcMem;
	BITMAPINFO biOut;
	BITMAPINFOHEADER *bihOut;
	int nBmpWdtPS;
	int nSzBuffPS;
	LPBYTE pcImg = NULL, pcImg1 = NULL;
	int nStart = 0, nLenSub = 0;
	szBmp.cx = rcItem->right - rcItem->left;
	szBmp.cy = rcItem->bottom - rcItem->top;

	/*
	 * for top row tabs, it's easy. Just draw to the provided dc (it's a mem dc already)
	 */

	if (!bBottom) {
		if (bBody) {
			if(PluginConfig.m_bIsVista) {
				rcItem->right += 2;							// hide right tab sheet shadow (only draw the actual border line)
				rcItem->bottom += 1;
			}
			DrawThemesPart(tabdat, pDC, 9, 0, rcItem);	// TABP_PANE id = 9
		} else {
			int iStateId = bSel ? 3 : (bHot ? 2 : 1);                       // leftmost item has different part id
			DrawThemesPartWithAero(tabdat, pDC, rcItem->left < 20 ? 2 : 1, iStateId, rcItem, dat);
		}
		return;
	}
	else if(tabdat->fAeroTabs && !bBody) {
		int iStateId = bSel ? 3 : (bHot ? 2 : 1);                       // leftmost item has different part id
		DrawThemesPartWithAero(tabdat, pDC, rcItem->left < 20 ? 2 : 1, iStateId, rcItem, dat);
		return;
	}

	/*
	 * remaining code is for bottom tabs only.
	 */

	dcMem = CreateCompatibleDC(pDC);
	bmpMem = CreateCompatibleBitmap(pDC, szBmp.cx, szBmp.cy);

	pBmpOld = (HBITMAP)SelectObject(dcMem, bmpMem);

	rcMem.left = rcMem.top = 0;
	rcMem.right = szBmp.cx;
	rcMem.bottom = szBmp.cy;

	ZeroMemory(&biOut, sizeof(BITMAPINFO));	// Fill local pixel arrays
	bihOut = &biOut.bmiHeader;

	bihOut->biSize = sizeof(BITMAPINFOHEADER);
	bihOut->biCompression = BI_RGB;
	bihOut->biPlanes = 1;
	bihOut->biBitCount = 24;	// force as RGB: 3 bytes, 24 bits
	bihOut->biWidth = szBmp.cx;
	bihOut->biHeight = szBmp.cy;

	nBmpWdtPS = DWordAlign(szBmp.cx * 3);
	nSzBuffPS = ((nBmpWdtPS * szBmp.cy) / 8 + 2) * 8;

	/*
	 * blit the background to the memory dc, so that transparent tabs will draw properly
	 * for bottom tabs, it's more complex, because the background part must not be mirrored
	 * the body part does not need that (filling with the background color is much faster
	 * and sufficient for the tab "page" part.
	 */

	if (!bSel)
		CSkin::FillBack(dcMem, &rcMem);
	else {
		/*
		 * mirror the background horizontally for bottom selected tabs (they can overwrite others)
		 * needed, because after drawing the theme part the images will again be mirrored
		 * to "flip" the tab item.
		 */
		BitBlt(dcMem, 0, 0, szBmp.cx, szBmp.cy, pDC, rcItem->left, rcItem->top, SRCCOPY);

		pcImg1 = (BYTE *)mir_alloc(nSzBuffPS);

		if (pcImg1) {
			GetDIBits(pDC, bmpMem, nStart, szBmp.cy - nLenSub, pcImg1, &biOut, DIB_RGB_COLORS);
			bihOut->biHeight = -szBmp.cy; 				// to mirror bitmap is eough to use negative height between Get/SetDIBits
			SetDIBits(pDC, bmpMem, nStart, szBmp.cy - nLenSub, pcImg1, &biOut, DIB_RGB_COLORS);
			mir_free(pcImg1);
		}
	}

	/*
	 * body may be *large* so rotating the final image can be very slow.
	 * workaround: draw the skin item (tab pane) into a small dc, rotate this (small) image and render
	 * it to the final DC with the IMG_RenderItem() routine.
	 */

	if (bBody) {
		HDC hdcTemp = CreateCompatibleDC(pDC);
		HBITMAP hbmTemp = CreateCompatibleBitmap(pDC, 100, 50);
		HBITMAP hbmTempOld = (HBITMAP)SelectObject(hdcTemp, hbmTemp);
		RECT rcTemp = {0};

		rcTemp.right = 100;
		rcTemp.bottom = 50;

		bihOut->biWidth = 100;
		bihOut->biHeight = 50;

		nBmpWdtPS = DWordAlign(100 * 3);
		nSzBuffPS = ((nBmpWdtPS * 50) / 8 + 2) * 8;

		CSkin::FillBack(hdcTemp, &rcTemp);
		DrawThemesPart(tabdat, hdcTemp, 9, 0, &rcTemp);	// TABP_PANE id = 9
		pcImg = (BYTE *)mir_alloc(nSzBuffPS);
		if (pcImg)	{									// get bits:
			GetDIBits(hdcTemp, hbmTemp, nStart, 50 - nLenSub, pcImg, &biOut, DIB_RGB_COLORS);
			bihOut->biHeight = -50;
			SetDIBits(hdcTemp, hbmTemp, nStart, 50 - nLenSub, pcImg, &biOut, DIB_RGB_COLORS);
			mir_free(pcImg);
		}
		CImageItem tempItem(10, 10, 10, 10, hdcTemp, 0, IMAGE_FLAG_DIVIDED | IMAGE_FILLSOLID,
							GetSysColorBrush(COLOR_3DFACE), 255, 30, 80, 50, 100);

		if(PluginConfig.m_bIsVista)	{								// hide right tab sheet shadow (only draw the actual border line)
			rcItem->right += 2;
		}

		tempItem.Render(pDC, rcItem, true);
		tempItem.Clear();
		SelectObject(hdcTemp, hbmTempOld);
		DeleteObject(hbmTemp);
		DeleteDC(hdcTemp);

		SelectObject(dcMem, pBmpOld);
		DeleteObject(bmpMem);
		DeleteDC(dcMem);
		return;
	} else {
		int iStateId = bSel ? 3 : (bHot ? 2 : 1);
		DrawThemesPart(tabdat, dcMem, rcItem->left < 20 ? 2 : 1, iStateId, &rcMem);
	}

	bihOut->biHeight = szBmp.cy;
	pcImg = (BYTE *)mir_alloc(nSzBuffPS);

	if (pcImg)	{									// get bits:
		GetDIBits(pDC, bmpMem, nStart, szBmp.cy - nLenSub, pcImg, &biOut, DIB_RGB_COLORS);
		bihOut->biHeight = -szBmp.cy;
		SetDIBits(pDC, bmpMem, nStart, szBmp.cy - nLenSub, pcImg, &biOut, DIB_RGB_COLORS);
		mir_free(pcImg);
	}

	/*
	 * finally, blit the result to the destination dc
	 */

	BitBlt(pDC, rcItem->left, rcItem->top, szBmp.cx, szBmp.cy, dcMem, 0, 0, SRCCOPY);
	SelectObject(dcMem, pBmpOld);
	DeleteObject(bmpMem);
	DeleteDC(dcMem);
}

static POINT ptMouseT = {0};

static LRESULT CALLBACK TabControlSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	struct		TabControlData *tabdat = 0;

	tabdat = (struct TabControlData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
	if (tabdat) {
		if (tabdat->pContainer == NULL)
			tabdat->pContainer = (TContainerData *)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
		tabdat->dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
	}

	switch (msg) {
		case WM_NCCREATE: {
			WNDCLASSEXA wcl = {0};

			wcl.cbSize = sizeof(wcl);
			GetClassInfoExA(g_hInst, "SysTabControl32", &wcl);

			tabdat = (struct TabControlData *)mir_alloc(sizeof(struct TabControlData));
			SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)tabdat);
			ZeroMemory((void *)tabdat, sizeof(struct TabControlData));
			tabdat->hwnd = hwnd;
			tabdat->cx = GetSystemMetrics(SM_CXSMICON);
			tabdat->cy = GetSystemMetrics(SM_CYSMICON);
			tabdat->fTipActive = FALSE;
			tabdat->iHoveredCloseIcon = -1;
			SendMessage(hwnd, EM_THEMECHANGED, 0, 0);
			OldTabControlClassProc = wcl.lpfnWndProc;
			return TRUE;
		}
		case EM_THEMECHANGED:
			tabdat->m_xpad = M->GetByte("x-pad", 3);
			tabdat->m_VisualStyles = FALSE;
			if (PluginConfig.m_bIsXP && M->isVSAPIState()) {
				if (CMimAPI::m_pfnIsThemeActive != 0)
					if (CMimAPI::m_pfnIsThemeActive()) {
						tabdat->m_VisualStyles = TRUE;
						if (tabdat->hTheme != 0 && CMimAPI::m_pfnCloseThemeData != 0) {
							CMimAPI::m_pfnCloseThemeData(tabdat->hTheme);
							CMimAPI::m_pfnCloseThemeData(tabdat->hThemeButton);
						}
						if (CMimAPI::m_pfnOpenThemeData != 0) {
							if ((tabdat->hTheme = CMimAPI::m_pfnOpenThemeData(hwnd, L"TAB")) == 0 || (tabdat->hThemeButton = CMimAPI::m_pfnOpenThemeData(hwnd, L"BUTTON")) == 0)
								tabdat->m_VisualStyles = FALSE;
						}
					}
			}
			return 0;
		case EM_SEARCHSCROLLER: {
			HWND hwndChild;
			/*
			 * search the updown control (scroll arrows) to subclass it...
			 * the control is dynamically created and may not exist as long as it is
			 * not needed. So we have to search it everytime we need to paint. However,
			 * it is sufficient to search it once. So this message is called, whenever
			 * a new tab is inserted
			 */

			if ((hwndChild = FindWindowEx(hwnd, 0, _T("msctls_updown32"), NULL)) != 0)
				DestroyWindow(hwndChild);
			return 0;
		}
		case EM_VALIDATEBOTTOM: {
			BOOL bClassicDraw = (tabdat->m_VisualStyles == FALSE);
			if ((tabdat->dwStyle & TCS_BOTTOM) && !bClassicDraw && PluginConfig.tabConfig.m_bottomAdjust != 0)
				InvalidateRect(hwnd, NULL, FALSE);
			break;
		}
		case EM_REFRESHWITHOUTCLIP:
			if (TabCtrl_GetItemCount(hwnd) > 1)
				return 0;
			else {
				tabdat->bRefreshWithoutClip = TRUE;
				RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW | RDW_NOCHILDREN | RDW_INVALIDATE);
				tabdat->bRefreshWithoutClip = FALSE;
				return 0;
			}
		case TCM_INSERTITEM:
		case TCM_DELETEITEM:
			tabdat->iHoveredCloseIcon = -1;
			if (!(tabdat->dwStyle & TCS_MULTILINE) || tabdat->dwStyle & TCS_BUTTONS) {
				LRESULT result;
				RECT rc;
				int iTabs = TabCtrl_GetItemCount(hwnd);
				if (iTabs >= 1 && msg == TCM_INSERTITEM) {
					TabCtrl_GetItemRect(hwnd, 0, &rc);
					TabCtrl_SetItemSize(hwnd, 10, rc.bottom - rc.top);
				}
				result = CallWindowProc(OldTabControlClassProc, hwnd, msg, wParam, lParam);
				TabCtrl_GetItemRect(hwnd, 0, &rc);
				SendMessage(hwnd, WM_SIZE, 0, 0);
				return result;
			}
			break;
		case WM_DESTROY:
			if (tabdat) {
				if (tabdat->hTheme != 0 && CMimAPI::m_pfnCloseThemeData != 0) {
					CMimAPI::m_pfnCloseThemeData(tabdat->hTheme);
					CMimAPI::m_pfnCloseThemeData(tabdat->hThemeButton);
				}
			}
			break;
		case WM_NCDESTROY:
			if(tabdat) {
				mir_free(tabdat);
				SetWindowLongPtr(hwnd, GWLP_USERDATA, 0L);
			}
			break;
		case WM_MBUTTONDOWN: {
			POINT pt;
			GetCursorPos(&pt);
			SendMessage(GetParent(hwnd), DM_CLOSETABATMOUSE, 0, (LPARAM)&pt);
			return 1;
		}
		case WM_SETCURSOR: {
			POINT pt;

			GetCursorPos(&pt);
			SendMessage(GetParent(hwnd), msg, wParam, lParam);
			if (abs(pt.x - ptMouseT.x) < 4  && abs(pt.y - ptMouseT.y) < 4)
				return 1;
			ptMouseT = pt;
			if (tabdat->fTipActive) {
				KillTimer(hwnd, TIMERID_HOVER_T);
				CallService("mToolTip/HideTip", 0, 0);
				tabdat->fTipActive = FALSE;
			}
			KillTimer(hwnd, TIMERID_HOVER_T);
			if(tabdat->pContainer && (!tabdat->pContainer->SideBar->isActive() && (TabCtrl_GetItemCount(hwnd) > 1 || !(tabdat->pContainer->dwFlags & CNT_HIDETABS))))
				SetTimer(hwnd, TIMERID_HOVER_T, 750, 0);
			break;
		}
		case WM_SIZE: {
			int iTabs = TabCtrl_GetItemCount(hwnd);

			if (!tabdat->pContainer)
				break;

			if (!(tabdat->dwStyle & TCS_MULTILINE)) {
				RECT rcClient, rc;
				DWORD newItemSize;
				if (iTabs > (tabdat->pContainer->dwFlags & CNT_HIDETABS ? 1 : 0)) {
					GetClientRect(hwnd, &rcClient);
					TabCtrl_GetItemRect(hwnd, iTabs - 1, &rc);
					newItemSize = (rcClient.right - 6) - (tabdat->dwStyle & TCS_BUTTONS ? (iTabs) * 10 : 0);
					newItemSize = newItemSize / iTabs;
					if (newItemSize < PluginConfig.tabConfig.m_fixedwidth) {
						TabCtrl_SetItemSize(hwnd, newItemSize, rc.bottom - rc.top);
					} else {
						TabCtrl_SetItemSize(hwnd, PluginConfig.tabConfig.m_fixedwidth, rc.bottom - rc.top);
					}
					SendMessage(hwnd, EM_SEARCHSCROLLER, 0, 0);
				}
			} else if (tabdat->dwStyle & TCS_BUTTONS && iTabs > 0) {
				RECT rcClient, rcItem;
				int nrTabsPerLine;
				GetClientRect(hwnd, &rcClient);
				TabCtrl_GetItemRect(hwnd, 0, &rcItem);
				nrTabsPerLine = (rcClient.right) / PluginConfig.tabConfig.m_fixedwidth;
				if (iTabs >= nrTabsPerLine && nrTabsPerLine > 0)
					TabCtrl_SetItemSize(hwnd, ((rcClient.right - 6) / nrTabsPerLine) - (tabdat->dwStyle & TCS_BUTTONS ? 8 : 0), rcItem.bottom - rcItem.top);
				else
					TabCtrl_SetItemSize(hwnd, PluginConfig.tabConfig.m_fixedwidth, rcItem.bottom - rcItem.top);
			}
			break;
		}
		case WM_LBUTTONDBLCLK: {
			POINT pt;
			GetCursorPos(&pt);
			SendMessage(GetParent(hwnd), DM_CLOSETABATMOUSE, 0, (LPARAM)&pt);
			break;
		}
		case WM_RBUTTONDOWN:
			KillTimer(hwnd, TIMERID_HOVER_T);
			CallService("mToolTip/HideTip", 0, 0);
			tabdat->fTipActive = FALSE;
			break;

		case WM_LBUTTONDOWN: {
			TCHITTESTINFO tci = {0};

			KillTimer(hwnd, TIMERID_HOVER_T);
			CallService("mToolTip/HideTip", 0, 0);
			tabdat->fTipActive = FALSE;

			if (GetKeyState(VK_CONTROL) & 0x8000) {
				tci.pt.x = (short)LOWORD(GetMessagePos());
				tci.pt.y = (short)HIWORD(GetMessagePos());
				if (DragDetect(hwnd, tci.pt) && TabCtrl_GetItemCount(hwnd) > 1) {
					int i;
					tci.flags = TCHT_ONITEM;

					ScreenToClient(hwnd, &tci.pt);
					i = TabCtrl_HitTest(hwnd, &tci);
					if (i != -1) {
						TCITEM tc;
						struct TWindowData *dat = NULL;

						tc.mask = TCIF_PARAM;
						TabCtrl_GetItem(hwnd, i, &tc);
						dat = (struct TWindowData *)GetWindowLongPtr((HWND)tc.lParam, GWLP_USERDATA);
						if (dat)	{
							tabdat->bDragging = TRUE;
							tabdat->iBeginIndex = i;
							tabdat->hwndDrag = (HWND)tc.lParam;
							tabdat->dragDat = dat;
							tabdat->fSavePos = TRUE;
							tabdat->himlDrag = ImageList_Create(16, 16, ILC_MASK | (PluginConfig.m_bIsXP ? ILC_COLOR32 : ILC_COLOR16), 1, 0);
							ImageList_AddIcon(tabdat->himlDrag, dat->hTabIcon);
							ImageList_BeginDrag(tabdat->himlDrag, 0, 8, 8);
							ImageList_DragEnter(hwnd, tci.pt.x, tci.pt.y);
							SetCapture(hwnd);
						}
						return TRUE;
					}
				}
			}

			if (GetKeyState(VK_MENU) & 0x8000) {
				tci.pt.x = (short)LOWORD(GetMessagePos());
				tci.pt.y = (short)HIWORD(GetMessagePos());
				if (DragDetect(hwnd, tci.pt) && TabCtrl_GetItemCount(hwnd) > 1) {
					int i;
					tci.flags = TCHT_ONITEM;

					ScreenToClient(hwnd, &tci.pt);
					i = TabCtrl_HitTest(hwnd, &tci);
					if (i != -1) {
						TCITEM tc;
						TWindowData *dat = NULL;

						tc.mask = TCIF_PARAM;
						TabCtrl_GetItem(hwnd, i, &tc);
						dat = (TWindowData *)GetWindowLongPtr((HWND)tc.lParam, GWLP_USERDATA);
						if (dat)	{
							tabdat->bDragging = TRUE;
							tabdat->iBeginIndex = i;
							tabdat->hwndDrag = (HWND)tc.lParam;
							tabdat->dragDat = dat;
							tabdat->himlDrag = ImageList_Create(16, 16, ILC_MASK | (PluginConfig.m_bIsXP ? ILC_COLOR32 : ILC_COLOR16), 1, 0);
							tabdat->fSavePos = FALSE;
							ImageList_AddIcon(tabdat->himlDrag, dat->hTabIcon);
							ImageList_BeginDrag(tabdat->himlDrag, 0, 8, 8);
							ImageList_DragEnter(hwnd, tci.pt.x, tci.pt.y);
							SetCapture(hwnd);
						}
						return TRUE;
					}
				}
			}
			if(tabdat->fCloseButton) {
				POINT	pt;
				GetCursorPos(&pt);

				if(TabCtrl_TestForCloseButton(tabdat, hwnd, pt) != -1)
					return(TRUE);
			}
		}
		break;

		case WM_CAPTURECHANGED: {
			tabdat->bDragging = FALSE;
			ImageList_DragLeave(hwnd);
			ImageList_EndDrag();
			if (tabdat->himlDrag) {
				ImageList_RemoveAll(tabdat->himlDrag);
				ImageList_Destroy(tabdat->himlDrag);
				tabdat->himlDrag = 0;
			}
		}
		break;

		case WM_MOUSEMOVE: {
			if (tabdat->bDragging) {
				TCHITTESTINFO tci = {0};
				tci.pt.x = (short)LOWORD(GetMessagePos());
				tci.pt.y = (short)HIWORD(GetMessagePos());
				ScreenToClient(hwnd, &tci.pt);
				ImageList_DragMove(tci.pt.x, tci.pt.y);
			}
			if(tabdat->fCloseButton) {
				POINT	pt;

				GetCursorPos(&pt);
				int iOldHovered = tabdat->iHoveredCloseIcon;
				tabdat->iHoveredCloseIcon = TabCtrl_TestForCloseButton(tabdat, hwnd, pt);
				if(tabdat->iHoveredCloseIcon != iOldHovered)
					InvalidateRect(hwnd, NULL, FALSE);
			}
		}
		break;

		case WM_LBUTTONUP: {
			CallWindowProc(OldTabControlClassProc, hwnd, msg, wParam, lParam);
			if (tabdat->bDragging && ReleaseCapture()) {
				TCHITTESTINFO tci = {0};
				int i;
				tci.pt.x = (short)LOWORD(GetMessagePos());
				tci.pt.y = (short)HIWORD(GetMessagePos());
				tci.flags = TCHT_ONITEM;
				tabdat->bDragging = FALSE;
				ImageList_DragLeave(hwnd);
				ImageList_EndDrag();

				ScreenToClient(hwnd, &tci.pt);
				i = TabCtrl_HitTest(hwnd, &tci);
				if (i != -1 && i != tabdat->iBeginIndex)
					RearrangeTab(tabdat->hwndDrag, tabdat->dragDat, MAKELONG(i, 0xffff), tabdat->fSavePos);
				tabdat->hwndDrag = (HWND) - 1;
				tabdat->dragDat = NULL;
				if (tabdat->himlDrag) {
					ImageList_RemoveAll(tabdat->himlDrag);
					ImageList_Destroy(tabdat->himlDrag);
					tabdat->himlDrag = 0;
				}
			}
			if(tabdat->fCloseButton) {
				POINT	pt;

				GetCursorPos(&pt);
				int iItem = TabCtrl_TestForCloseButton(tabdat, hwnd, pt);
				if(iItem != -1)
					SendMessage(GetParent(hwnd), DM_CLOSETABATMOUSE, 0, (LPARAM)&pt);
			}
		}
		break;

		case WM_ERASEBKGND:
			if (tabdat->pContainer && (CSkin::m_skinEnabled || M->isAero()))
				return TRUE;
			return(0);
		case WM_PAINT: {
			PAINTSTRUCT ps;
			HDC hdcreal, hdc;
			RECT rectTemp, rctPage, rctActive, rcItem, rctClip, rctOrig;
			RECT rectUpDn = {0, 0, 0, 0};
			int nCount = TabCtrl_GetItemCount(hwnd), i;
			TCITEM item = {0};
			int iActive, hotItem;
			POINT pt;
			DWORD dwStyle = tabdat->dwStyle;
			HPEN hPenOld = 0;
			UINT uiFlags = 1;
			UINT uiBottom = 0;
			TCHITTESTINFO hti;
			HBITMAP bmpMem, bmpOld;
			DWORD cx, cy;
			bool  isAero = M->isAero();
			HANDLE hpb = 0;
			BOOL bClassicDraw = !isAero && (tabdat->m_VisualStyles == FALSE || CSkin::m_skinEnabled);
			if(GetUpdateRect(hwnd, NULL, TRUE) == 0)
				break;

			item.mask = TCIF_PARAM;

			tabdat->fAeroTabs = (CSkin::m_fAeroSkinsValid && (isAero || PluginConfig.m_fillColor)) ? TRUE : FALSE;
			tabdat->fCloseButton = tabdat->pContainer ? (tabdat->pContainer->dwFlagsEx & TCF_CLOSEBUTTON ? TRUE : FALSE) : FALSE;

			tabdat->helperDat = 0;

			if(tabdat->fAeroTabs && tabdat->pContainer) {
				TWindowData *dat = (TWindowData *)GetWindowLongPtr(tabdat->pContainer->hwndActive, GWLP_USERDATA);
				if(dat) {
					tabdat->helperDat = dat;
				}
				else
					tabdat->fAeroTabs = 0;

				tabdat->helperItem =  (dwStyle & TCS_BOTTOM) ? CSkin::m_tabBottom : CSkin::m_tabTop;
				tabdat->helperGlowItem = (dwStyle & TCS_BOTTOM) ? CSkin::m_tabGlowBottom : CSkin::m_tabGlowTop;
			}
			else
				tabdat->fAeroTabs = FALSE;

			hdcreal = BeginPaint(hwnd, &ps);

			/*
			 * switchbar is active, don't paint a single pixel, the tab control won't be visible at all
			 * same when we have only ONE tab and do not want it to be visible because of the container
			 * option "Show tab bar only when needed".
			 */

			if((tabdat->pContainer->dwFlags & CNT_SIDEBAR) || (nCount == 1 && tabdat->pContainer->dwFlags & CNT_HIDETABS)) {
				if(nCount == 0)
					FillRect(hdcreal, &ps.rcPaint, GetSysColorBrush(COLOR_3DFACE)); // avoid flickering/ugly black background during container creation
				EndPaint(hwnd, &ps);
				return(0);
			}

			GetClientRect(hwnd, &rctPage);
			rctOrig = rctPage;
			iActive = TabCtrl_GetCurSel(hwnd);
			TabCtrl_GetItemRect(hwnd, iActive, &rctActive);
			cx = rctPage.right - rctPage.left;
			cy = rctPage.bottom - rctPage.top;

			/*
			 * draw everything to a memory dc to avoid flickering
			 */

			if(CMimAPI::m_haveBufferedPaint)
				hpb = tabdat->hbp = CSkin::InitiateBufferedPaint(hdcreal, rctPage, hdc);
			else {
				hdc = CreateCompatibleDC(hdcreal);
				bmpMem = tabdat->fAeroTabs ? CSkin::CreateAeroCompatibleBitmap(rctPage, hdcreal) : CreateCompatibleBitmap(hdcreal, cx, cy);
				bmpOld = (HBITMAP)SelectObject(hdc, bmpMem);
			}

			if (nCount == 1 && tabdat->pContainer->dwFlags & CNT_HIDETABS)
				rctClip = rctPage;

			if (CSkin::m_skinEnabled)
				CSkin::SkinDrawBG(hwnd, tabdat->pContainer->hwnd, tabdat->pContainer, &rctPage, hdc);
			else
				CSkin::FillBack(hdc, &rctPage);

			if (dwStyle & TCS_BUTTONS) {
				RECT rc1;
				TabCtrl_GetItemRect(hwnd, nCount - 1, &rc1);
				if (dwStyle & TCS_BOTTOM) {
					rctPage.bottom = rc1.top;
					uiBottom = 8;
				} else {
					rctPage.top = rc1.bottom + 2;
					uiBottom = 0;
				}
			} else {
				if (dwStyle & TCS_BOTTOM) {
					rctPage.bottom = rctActive.top;
					uiBottom = 8;
				} else {
					rctPage.top = rctActive.bottom;
					uiBottom = 0;
				}
			}

			if (nCount > 1 || !(tabdat->pContainer->dwFlags & CNT_HIDETABS)) {
				rctClip = rctPage;
				InflateRect(&rctClip, -tabdat->pContainer->tBorder, -tabdat->pContainer->tBorder);
			}
			else
				ZeroMemory(&rctClip, sizeof(RECT));

			hPenOld = (HPEN)SelectObject(hdc, PluginConfig.tabConfig.m_hPenLight);
			/*
			 * visual style support
			 */

			CopyRect(&rcTabPage, &rctPage);
			if (!tabdat->bRefreshWithoutClip)
				ExcludeClipRect(hdc, rctClip.left, rctClip.top, rctClip.right, rctClip.bottom);
			else
				ZeroMemory(&rctClip, sizeof(RECT));
			if ((!bClassicDraw || PluginConfig.m_fillColor) && IntersectRect(&rectTemp, &rctPage, &ps.rcPaint) && !CSkin::m_skinEnabled) {
				RECT rcClient = rctPage;
				if (dwStyle & TCS_BOTTOM) {
					rcClient.bottom = rctPage.bottom;
					uiFlags |= uiBottom;
				} else
					rcClient.top = rctPage.top;
				if(PluginConfig.m_fillColor)
					DrawCustomTabPage(hdc, rcClient);
				else 
					DrawThemesXpTabItem(hdc, -1, &rcClient, uiFlags, tabdat, 0);	// TABP_PANE=9,0,'TAB'
				if (tabdat->bRefreshWithoutClip)
					goto skip_tabs;
			} else {
				if (IntersectRect(&rectTemp, &rctPage, &ps.rcPaint)) {
					if (CSkin::m_skinEnabled) {
						CSkinItem *item = &SkinItems[ID_EXTBKTABPAGE];

						if (!item->IGNORED) {
							DrawAlpha(hdc, &rctPage, item->COLOR, item->ALPHA, item->COLOR2, item->COLOR2_TRANSPARENT,
									  item->GRADIENT, item->CORNER, item->BORDERSTYLE, item->imageItem);
							goto page_done;
						}
					}

					if (tabdat->bRefreshWithoutClip)
						goto skip_tabs;

					if (dwStyle & TCS_BUTTONS) {
						rectTemp = rctPage;
						if (dwStyle & TCS_BOTTOM) {
							rectTemp.top--;
							rectTemp.bottom--;
						} else {
							rectTemp.bottom--;
							rectTemp.top++;
						}
						if(PluginConfig.m_fillColor)
							DrawCustomTabPage(hdc, rectTemp);
						else {
							MoveToEx(hdc, rectTemp.left, rectTemp.bottom, &pt);
							LineTo(hdc, rectTemp.left, rectTemp.top + 1);
							LineTo(hdc, rectTemp.right - 1, rectTemp.top + 1);
							SelectObject(hdc, PluginConfig.tabConfig.m_hPenShadow);
							LineTo(hdc, rectTemp.right - 1, rectTemp.bottom);
							LineTo(hdc, rectTemp.left, rectTemp.bottom);
						}
					} else {
						rectTemp = rctPage;
						if(PluginConfig.m_fillColor)
							DrawCustomTabPage(hdc, rectTemp);
						else {
							MoveToEx(hdc, rectTemp.left, rectTemp.bottom - 1, &pt);
							LineTo(hdc, rectTemp.left, rectTemp.top);

							if (dwStyle & TCS_BOTTOM) {
								LineTo(hdc, rectTemp.right - 1, rectTemp.top);
								SelectObject(hdc, PluginConfig.tabConfig.m_hPenShadow);
								LineTo(hdc, rectTemp.right - 1, rectTemp.bottom - 1);
								LineTo(hdc, rctActive.right, rectTemp.bottom - 1);
								MoveToEx(hdc, rctActive.left - 2, rectTemp.bottom - 1, &pt);
								LineTo(hdc, rectTemp.left - 1, rectTemp.bottom - 1);
								SelectObject(hdc, PluginConfig.tabConfig.m_hPenItemShadow);
								MoveToEx(hdc, rectTemp.right - 2, rectTemp.top + 1, &pt);
								LineTo(hdc, rectTemp.right - 2, rectTemp.bottom - 2);
								LineTo(hdc, rctActive.right, rectTemp.bottom - 2);
								MoveToEx(hdc, rctActive.left - 2, rectTemp.bottom - 2, &pt);
								LineTo(hdc, rectTemp.left, rectTemp.bottom - 2);
							} else {
								if (rctActive.left >= 0) {
									LineTo(hdc, rctActive.left, rctActive.bottom);
									if (IsRectEmpty(&rectUpDn))
										MoveToEx(hdc, rctActive.right, rctActive.bottom, &pt);
									else {
										if (rctActive.right >= rectUpDn.left)
											MoveToEx(hdc, rectUpDn.left - SHIFT_FROM_CUT_TO_SPIN + 2, rctActive.bottom + 1, &pt);
										else
											MoveToEx(hdc, rctActive.right, rctActive.bottom, &pt);
									}
									LineTo(hdc, rectTemp.right - 2, rctActive.bottom);
								} else {
									RECT rectItemLeftmost;
									UINT nItemLeftmost = FindLeftDownItem(hwnd);
									TabCtrl_GetItemRect(hwnd, nItemLeftmost, &rectItemLeftmost);
									LineTo(hdc, rectTemp.right - 2, rctActive.bottom);
								}
								SelectObject(hdc, PluginConfig.tabConfig.m_hPenItemShadow);
								LineTo(hdc, rectTemp.right - 2, rectTemp.bottom - 2);
								LineTo(hdc, rectTemp.left, rectTemp.bottom - 2);

								SelectObject(hdc, PluginConfig.tabConfig.m_hPenShadow);
								MoveToEx(hdc, rectTemp.right - 1, rctActive.bottom, &pt);
								LineTo(hdc, rectTemp.right - 1, rectTemp.bottom - 1);
								LineTo(hdc, rectTemp.left - 2, rectTemp.bottom - 1);
							}
						}
					}
				}
			}
page_done:
			/*
			 * if aero is active _and_ the infopanel is visible in the current window, we "flatten" out the top area
			 * of the tab page by overpainting it black (thus it will appear transparent)
			 */
			if(isAero && tabdat->helperDat) {
				RECT	rcLog, rcPage;
				POINT	pt;

				GetClientRect(hwnd, &rcPage);
				if(dwStyle & TCS_BOTTOM) {
					GetWindowRect(tabdat->helperDat->hwnd, &rcLog);
					pt.y = rcLog.bottom;
					pt.x = rcLog.left;
					ScreenToClient(hwnd, &pt);
					rcPage.top = pt.y + ((nCount > 1 || !(tabdat->helperDat->pContainer->dwFlags & CNT_HIDETABS)) ? tabdat->helperDat->pContainer->tBorder : 0);
					FillRect(hdc, &rcPage, CSkin::m_BrushBack);
					rcPage.top = 0;
				}
				GetWindowRect(GetDlgItem(tabdat->helperDat->hwnd, tabdat->helperDat->bType == SESSIONTYPE_IM ? IDC_LOG : IDC_CHAT_LOG), &rcLog);
				pt.y = rcLog.top;
				pt.x = rcLog.left;
				ScreenToClient(hwnd, &pt);
				rcPage.bottom = pt.y;
				FillRect(hdc, &rcPage, CSkin::m_BrushBack);
			}

			uiFlags = 0;
			/*
			 * figure out hottracked item (if any)
			 */

			if (tabdat->bRefreshWithoutClip)
				goto skip_tabs;

			GetCursorPos(&hti.pt);
			ScreenToClient(hwnd, &hti.pt);
			hti.flags = 0;
			hotItem = TabCtrl_HitTest(hwnd, &hti);
			for (i = 0; i < nCount; i++) {
				TWindowData* dat = 0;

				if (i != iActive) {
					TabCtrl_GetItem(hwnd, i, &item);
					if(item.lParam)
						dat = (TWindowData *)GetWindowLongPtr((HWND)item.lParam, GWLP_USERDATA);
					TabCtrl_GetItemRect(hwnd, i, &rcItem);
					if (!bClassicDraw && uiBottom) {
						rcItem.top -= PluginConfig.tabConfig.m_bottomAdjust;
						rcItem.bottom -= PluginConfig.tabConfig.m_bottomAdjust;
					}
					if (IntersectRect(&rectTemp, &rcItem, &ps.rcPaint) || bClassicDraw) {
						int nHint = 0;
						if (!bClassicDraw && !(dwStyle & TCS_BUTTONS)) {
							DrawThemesXpTabItem(hdc, i, &rcItem, uiFlags | uiBottom | (i == hotItem ? 4 : 0), tabdat, dat);
							DrawItem(tabdat, hdc, &rcItem, nHint | (i == hotItem ? HINT_HOTTRACK : 0), i, dat);
						} else {
							if(tabdat->fAeroTabs && !CSkin::m_skinEnabled && !(dwStyle & TCS_BUTTONS))
								DrawThemesPartWithAero(tabdat, hdc, 0, (i == hotItem ? PBS_HOT : PBS_NORMAL), &rcItem, dat);
							else
								DrawItemRect(tabdat, hdc, &rcItem, nHint | (i == hotItem ? HINT_HOTTRACK : 0), i, dat);
							DrawItem(tabdat, hdc, &rcItem, nHint | (i == hotItem ? HINT_HOTTRACK : 0), i, dat);
						}
					}
				}
			}
			/*
			 * draw the active item
			 */
			if (!bClassicDraw && uiBottom) {
				rctActive.top -= PluginConfig.tabConfig.m_bottomAdjust;
				rctActive.bottom -= PluginConfig.tabConfig.m_bottomAdjust;
			}
			if (rctActive.left >= 0) {
				TWindowData*	dat = 0;
				int 			nHint = 0;

				rcItem = rctActive;
				TabCtrl_GetItem(hwnd, iActive, &item);
				if(item.lParam)
					dat = (TWindowData *)GetWindowLongPtr((HWND)item.lParam, GWLP_USERDATA);

				if (!bClassicDraw && !(dwStyle & TCS_BUTTONS)) {
					InflateRect(&rcItem, 2, 2);
					DrawThemesXpTabItem(hdc, iActive, &rcItem, 2 | uiBottom, tabdat, dat);
					DrawItem(tabdat, hdc, &rcItem, nHint | HINT_ACTIVE_ITEM, iActive, dat);
				} else {
					if (!(dwStyle & TCS_BUTTONS)) {
						if (iActive == 0) {
							rcItem.right += 2;
							rcItem.left--;
						} else
							InflateRect(&rcItem, 2, 0);
					}
					if(tabdat->fAeroTabs && !CSkin::m_skinEnabled && !(dwStyle & TCS_BUTTONS)) {
						if(dwStyle & TCS_BOTTOM)
							rcItem.bottom+= 2;
						else
							rcItem.top-= 2;
						DrawThemesPartWithAero(tabdat, hdc, 0, PBS_PRESSED, &rcItem, dat);
					}
					else
						DrawItemRect(tabdat, hdc, &rcItem, HINT_ACTIVATE_RIGHT_SIDE | HINT_ACTIVE_ITEM | nHint, iActive, dat);
					DrawItem(tabdat, hdc, &rcItem, HINT_ACTIVE_ITEM | nHint, iActive, dat);
				}
			}
skip_tabs:
			if (hPenOld)
				SelectObject(hdc, hPenOld);

			/*
			 * finally, bitblt the contents of the memory dc to the real dc
			 */
			//if(!tabdat->pContainer->bSkinned)
			if (!tabdat->bRefreshWithoutClip)
				ExcludeClipRect(hdcreal, rctClip.left, rctClip.top, rctClip.right, rctClip.bottom);

			if(hpb)
				CSkin::FinalizeBufferedPaint(hpb, &rctOrig);
				//CMimAPI::m_pfnEndBufferedPaint(hpb, TRUE);
			else {
				BitBlt(hdcreal, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY);
				SelectObject(hdc, bmpOld);
				DeleteObject(bmpMem);
				DeleteDC(hdc);
			}
			EndPaint(hwnd, &ps);
			return 0;
		}
		case WM_TIMER: {
			if (wParam == TIMERID_HOVER_T &&  M->GetByte("d_tooltips", 0)) {
				POINT pt;
				CLCINFOTIP ti = {0};
				ti.cbSize = sizeof(ti);

				KillTimer(hwnd, TIMERID_HOVER_T);
				GetCursorPos(&pt);
				if (abs(pt.x - ptMouseT.x) < 5 && abs(pt.y - ptMouseT.y) < 5) {
					TCITEM item = {0};
					int    nItem = 0;
					struct TWindowData *dat = 0;

					ti.ptCursor = pt;
					//ScreenToClient(hwnd, &pt);

					item.mask = TCIF_PARAM;
					nItem = GetTabItemFromMouse(hwnd, &pt);
					if (nItem >= 0 && nItem < TabCtrl_GetItemCount(hwnd)) {
						TabCtrl_GetItem(hwnd, nItem, &item);
						/*
						 * get the message window data for the session to which this tab item belongs
						 */

						if (IsWindow((HWND)item.lParam) && item.lParam != 0)
							dat = (struct TWindowData *)GetWindowLongPtr((HWND)item.lParam, GWLP_USERDATA);
						if (dat) {
							tabdat->fTipActive = TRUE;
							ti.isGroup = 0;
							ti.hItem = dat->hContact;
							ti.isTreeFocused = 0;
							CallService("mToolTip/ShowTip", 0, (LPARAM)&ti);
						}
					}
				}
			}
			break;
		}
		case WM_MOUSEWHEEL: {
			short amount = (short)(HIWORD(wParam));
			if (lParam != -1)
				break;
			if (amount > 0)
				SendMessage(GetParent(hwnd), DM_SELECTTAB, DM_SELECT_PREV, 0);
			else if (amount < 0)
				SendMessage(GetParent(hwnd), DM_SELECTTAB, DM_SELECT_NEXT, 0);
			InvalidateRect(hwnd, NULL, FALSE);
			break;
		}
		case  WM_USER + 100: {
			if (tabdat->fTipActive) {
				tabdat->fTipActive = FALSE;
				CallService("mToolTip/HideTip", 0, 0);
			}
		}
	}
	return CallWindowProc(OldTabControlClassProc, hwnd, msg, wParam, lParam);
}

/*
 * load the tab control configuration data (colors, fonts, flags...
 */

void TSAPI ReloadTabConfig()
{
	NONCLIENTMETRICS nclim;
	int i = 0;

	PluginConfig.tabConfig.m_hPenLight = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
	PluginConfig.tabConfig.m_hPenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
	PluginConfig.tabConfig.m_hPenItemShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));

	nclim.cbSize = sizeof(nclim);
	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nclim, 0);
	PluginConfig.tabConfig.m_hMenuFont = CreateFontIndirect(&nclim.lfMessageFont);

	while (tabcolors[i].szKey != NULL) {
		PluginConfig.tabConfig.colors[i] = M->GetDword(CSkin::m_skinEnabled ? tabcolors[i].szSkinnedKey : tabcolors[i].szKey, GetSysColor(tabcolors[i].defclr));
		i++;
	}
	PluginConfig.tabConfig.m_brushes[0] = CreateSolidBrush(PluginConfig.tabConfig.colors[4]);
	PluginConfig.tabConfig.m_brushes[1] = CreateSolidBrush(PluginConfig.tabConfig.colors[5]);
	PluginConfig.tabConfig.m_brushes[2] = CreateSolidBrush(PluginConfig.tabConfig.colors[6]);
	PluginConfig.tabConfig.m_brushes[3] = CreateSolidBrush(PluginConfig.tabConfig.colors[7]);

	PluginConfig.tabConfig.m_bottomAdjust = (int)M->GetDword("bottomadjust", 0);
	PluginConfig.tabConfig.m_fixedwidth = M->GetDword("fixedwidth", FIXED_TAB_SIZE);

	PluginConfig.tabConfig.m_fixedwidth = (PluginConfig.tabConfig.m_fixedwidth < 60 ? 60 : PluginConfig.tabConfig.m_fixedwidth);
}

void TSAPI FreeTabConfig()
{
	int i;

	if(PluginConfig.tabConfig.m_hPenItemShadow)
		DeleteObject(PluginConfig.tabConfig.m_hPenItemShadow);

	if(PluginConfig.tabConfig.m_hPenLight)
		DeleteObject(PluginConfig.tabConfig.m_hPenLight);

	if(PluginConfig.tabConfig.m_hPenShadow)
		DeleteObject(PluginConfig.tabConfig.m_hPenShadow);

	if(PluginConfig.tabConfig.m_hMenuFont)
		DeleteObject(PluginConfig.tabConfig.m_hMenuFont);

	for(i = 0; i < 4; i++) {
		if(PluginConfig.tabConfig.m_brushes[i]) {
			DeleteObject(PluginConfig.tabConfig.m_brushes[i]);
			PluginConfig.tabConfig.m_brushes[i] = 0;
		}
	}
	ZeroMemory(&PluginConfig.tabConfig, sizeof(myTabCtrl));
}

/*
 * options dialog for setting up tab options
 */

static bool tconfig_init = false;

INT_PTR CALLBACK DlgProcTabConfig(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
		case WM_INITDIALOG: {
			tconfig_init = false;
			TranslateDialogDefault(hwndDlg);
			SendMessage(hwndDlg, WM_USER + 100, 0, 0);
			tconfig_init = true;
			return TRUE;
		}
		case WM_USER + 100: {
			DWORD dwFlags = M->GetDword("tabconfig", TCF_DEFAULT);
			int i = 0;

			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPIN, UDM_SETRANGE, 0, MAKELONG(10, 0));
			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPIN, UDM_SETPOS, 0, (int)M->GetByte(CSkin::m_skinEnabled ? "S_tborder" : "tborder", 2));
			SetDlgItemInt(hwndDlg, IDC_TABBORDER, (int)M->GetByte(CSkin::m_skinEnabled ? "S_tborder" : "tborder", 2), FALSE);;

			SendDlgItemMessage(hwndDlg, IDC_BOTTOMTABADJUSTSPIN, UDM_SETRANGE, 0, MAKELONG(3, -3));
			SendDlgItemMessage(hwndDlg, IDC_BOTTOMTABADJUSTSPIN, UDM_SETPOS, 0, PluginConfig.tabConfig.m_bottomAdjust);
			SetDlgItemInt(hwndDlg, IDC_BOTTOMTABADJUST, PluginConfig.tabConfig.m_bottomAdjust, TRUE);

			SendDlgItemMessage(hwndDlg, IDC_TABWIDTHSPIN, UDM_SETRANGE, 0, MAKELONG(400, 50));
			SendDlgItemMessage(hwndDlg, IDC_TABWIDTHSPIN, UDM_SETPOS, 0, PluginConfig.tabConfig.m_fixedwidth);
			SetDlgItemInt(hwndDlg, IDC_TABWIDTH, PluginConfig.tabConfig.m_fixedwidth, TRUE);

			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTER, UDM_SETRANGE, 0, MAKELONG(50, 0));
			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTERRIGHT, UDM_SETRANGE, 0, MAKELONG(50, 0));
			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTERTOP, UDM_SETRANGE, 0, MAKELONG(40, 0));
			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTERBOTTOM, UDM_SETRANGE, 0, MAKELONG(40, 0));

			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTER, UDM_SETPOS, 0, (int)M->GetByte(CSkin::m_skinEnabled ? "S_tborder_outer_left" : "tborder_outer_left", 2));
			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTERRIGHT, UDM_SETPOS, 0, (int)M->GetByte(CSkin::m_skinEnabled ? "S_tborder_outer_right" : "tborder_outer_right", 2));
			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTERTOP, UDM_SETPOS, 0, (int)M->GetByte(CSkin::m_skinEnabled ? "S_tborder_outer_top" : "tborder_outer_top", 2));
			SendDlgItemMessage(hwndDlg, IDC_TABBORDERSPINOUTERBOTTOM, UDM_SETPOS, 0, (int)M->GetByte(CSkin::m_skinEnabled ? "S_tborder_outer_bottom" : "tborder_outer_bottom", 2));

			SendDlgItemMessage(hwndDlg, IDC_SPIN1, UDM_SETRANGE, 0, MAKELONG(10, 1));
			SendDlgItemMessage(hwndDlg, IDC_SPIN3, UDM_SETRANGE, 0, MAKELONG(10, 1));
			SendDlgItemMessage(hwndDlg, IDC_SPIN1, UDM_SETPOS, 0, (LPARAM)M->GetByte("y-pad", 3));
			SendDlgItemMessage(hwndDlg, IDC_SPIN3, UDM_SETPOS, 0, (LPARAM)M->GetByte("x-pad", 4));
			SetDlgItemInt(hwndDlg, IDC_TABPADDING, (int)M->GetByte("y-pad", 3), FALSE);;
			SetDlgItemInt(hwndDlg, IDC_HTABPADDING, (int)M->GetByte("x-pad", 4), FALSE);;
			return 0;
		}
		case WM_NOTIFY:
			switch (((LPNMHDR) lParam)->idFrom) {
				case 0:
					switch (((LPNMHDR) lParam)->code) {
						case PSN_APPLY: {
							int i = 0;
							BOOL translated;
							int  fixedWidth;

							struct TContainerData *pContainer = pFirstContainer;

							M->WriteByte(SRMSGMOD_T, "y-pad", (BYTE)(GetDlgItemInt(hwndDlg, IDC_TABPADDING, NULL, FALSE)));
							M->WriteByte(SRMSGMOD_T, "x-pad", (BYTE)(GetDlgItemInt(hwndDlg, IDC_HTABPADDING, NULL, FALSE)));
							M->WriteByte(SRMSGMOD_T, "tborder", (BYTE) GetDlgItemInt(hwndDlg, IDC_TABBORDER, &translated, FALSE));
							M->WriteByte(SRMSGMOD_T, CSkin::m_skinEnabled ? "S_tborder_outer_left" : "tborder_outer_left", (BYTE) GetDlgItemInt(hwndDlg, IDC_TABBORDEROUTER, &translated, FALSE));
							M->WriteByte(SRMSGMOD_T, CSkin::m_skinEnabled ? "S_tborder_outer_right" : "tborder_outer_right", (BYTE) GetDlgItemInt(hwndDlg, IDC_TABBORDEROUTERRIGHT, &translated, FALSE));
							M->WriteByte(SRMSGMOD_T, CSkin::m_skinEnabled ? "S_tborder_outer_top" : "tborder_outer_top", (BYTE) GetDlgItemInt(hwndDlg, IDC_TABBORDEROUTERTOP, &translated, FALSE));
							M->WriteByte(SRMSGMOD_T, CSkin::m_skinEnabled ? "S_tborder_outer_bottom" : "tborder_outer_bottom", (BYTE) GetDlgItemInt(hwndDlg, IDC_TABBORDEROUTERBOTTOM, &translated, FALSE));
							M->WriteDword(SRMSGMOD_T, "bottomadjust", GetDlgItemInt(hwndDlg, IDC_BOTTOMTABADJUST, &translated, TRUE));

							fixedWidth = GetDlgItemInt(hwndDlg, IDC_TABWIDTH, &translated, FALSE);
							fixedWidth = (fixedWidth < 60 ? 60 : fixedWidth);
							M->WriteDword(SRMSGMOD_T, "fixedwidth", fixedWidth);
							FreeTabConfig();
							ReloadTabConfig();
							while (pContainer) {
								TabCtrl_SetPadding(GetDlgItem(pContainer->hwnd, IDC_MSGTABS), GetDlgItemInt(hwndDlg, IDC_HTABPADDING, NULL, FALSE), GetDlgItemInt(hwndDlg, IDC_TABPADDING, NULL, FALSE));
								RedrawWindow(GetDlgItem(pContainer->hwnd, IDC_MSGTABS), NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
								pContainer = pContainer->pNextContainer;
							}
							return TRUE;
						}
					}
					break;
			}
			break;
		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDC_TABWIDTH:
				case IDC_TABPADDING:
				case IDC_HTABPADDING:
				case IDC_TABBORDER:
				case IDC_TABBORDEROUTER:
				case IDC_TABBORDEROUTERBOTTOM:
				case IDC_TABBORDEROUTERRIGHT:
				case IDC_TABBORDEROUTERTOP:
					if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())
						return TRUE;
					break;

				default:
					break;

			}
			if(tconfig_init)
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
			break;

		case WM_DESTROY:
			tconfig_init = false;
	}
	return FALSE;
}

