/*

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

Copyright 2000-2003 Miranda ICQ/IM project, 
all portions of this codebase are copyrighted to the people 
listed in contributors.txt.

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

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

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#include "hdr/modern_commonheaders.h"
#include "m_clui.h"
#include "hdr/modern_clist.h"
#include "./hdr/modern_cluiframes.h"
#include "hdr/modern_commonprototypes.h"
#include "hdr/modern_clcpaint.h"

/**************************************************/
/*   Notify Event Area Frame implementation       */
/**************************************************/

/* Declarations */
static HANDLE hNotifyFrame=NULL;
static int EventArea_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData);
static int EventArea_Draw(HWND hwnd, HDC hDC);
static int EventArea_DrawWorker(HWND hwnd, HDC hDC);
static void EventArea_HideShowNotifyFrame();
static LRESULT CALLBACK EventArea_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int EventArea_Create(HWND hCluiWnd);
int EventArea_UnloadModule();
void EventArea_ConfigureEventArea();

/**************************************************/

HWND g_hwndEventArea = 0;

struct CListEvent {
	int imlIconIndex;
	int flashesDone;
	CLISTEVENT cle;

	int menuId;
	int imlIconOverlayIndex;
};

static struct CListEvent *event;
static int eventCount;
static int disableTrayFlash;
static int disableIconFlash;


struct CListImlIcon {
	int index;
	HICON hIcon;
};

static struct CListImlIcon *imlIcon;
static int imlIconCount;
static UINT flashTimerId;
static int iconsOn;


struct NotifyMenuItemExData {
	HANDLE hContact;
	int iIcon;              // icon index in the image list
	HICON hIcon;            // corresponding icon handle
	HANDLE hDbEvent;
};

static CLISTEVENT* MyGetEvent(int iSelection)
{
	int i;

	for (i = 0; i < pcli->events.count; i++) {
		struct CListEvent* p = pcli->events.items[i];
		if (p->menuId == iSelection)
			return &p->cle;
	}
	return NULL;
}


CListEvent* cliCreateEvent( void )
{
	CListEvent *p = (CListEvent *)mir_alloc(sizeof(CListEvent));
	if(p)
		ZeroMemory(p, sizeof(struct CListEvent));

	return p;
}

struct CListEvent* cli_AddEvent(CLISTEVENT *cle)
{
	struct CListEvent* p = corecli.pfnAddEvent(cle);
		if ( p == NULL )
		return NULL;

	if (1) {
		if (p->cle.hContact != 0 && p->cle.hDbEvent != (HANDLE) 1 && !(p->cle.flags & CLEF_ONLYAFEW)) {
			int j;
			struct NotifyMenuItemExData *nmi = 0;
			char *szProto;
			TCHAR *szName;
			MENUITEMINFO mii = {0};
			mii.cbSize = sizeof(mii);
			mii.fMask = MIIM_DATA | MIIM_BITMAP | MIIM_ID;
			if (p->cle.pszService && (    !strncmp("SRMsg/ReadMessage", p->cle.pszService, SIZEOF("SRMsg/ReadMessage"))
								   	   || !strncmp("GChat/DblClickEvent", p->cle.pszService, SIZEOF("GChat/DblClickEvent")) ))
										
			{
				// dup check only for msg events
				for (j = 0; j < GetMenuItemCount(g_CluiData.hMenuNotify); j++) {
					if (GetMenuItemInfo(g_CluiData.hMenuNotify, j, TRUE, &mii) != 0) {
						nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
						if (nmi != 0 && (HANDLE) nmi->hContact == (HANDLE) p->cle.hContact && nmi->iIcon == p->imlIconIndex)
							return p;
			}	}	}

			szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) p->cle.hContact, 0);
			szName = pcli->pfnGetContactDisplayName(p->cle.hContact, 0);
			if (szProto && szName) {
				nmi = (struct NotifyMenuItemExData *) malloc(sizeof(struct NotifyMenuItemExData));
				if (nmi) {
					TCHAR szBuffer[128];
					TCHAR* szStatus = pcli->pfnGetStatusModeDescription(ModernGetSettingWord(p->cle.hContact, szProto, "Status", ID_STATUS_OFFLINE), 0);
#if defined(_UNICODE)
					TCHAR szwProto[64];
					MultiByteToWideChar(CP_ACP, 0, szProto, -1, szwProto, 64);
					szwProto[63] = 0;
					mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s: %s (%s)"), szwProto, szName, szStatus);
#else
					mir_snprintf(szBuffer, SIZEOF(szBuffer), "%s: %s (%s)", szProto, szName, szStatus);
#endif
					szBuffer[127] = 0;
					AppendMenu(g_CluiData.hMenuNotify, MF_BYCOMMAND | MF_STRING, g_CluiData.wNextMenuID, szBuffer);
					mii.hbmpItem = HBMMENU_CALLBACK;
					nmi->hContact = p->cle.hContact;
					nmi->iIcon = p->imlIconIndex;
					nmi->hIcon = p->cle.hIcon;
					nmi->hDbEvent = p->cle.hDbEvent;
					mii.dwItemData = (ULONG_PTR) nmi;
					mii.wID = g_CluiData.wNextMenuID;
					SetMenuItemInfo(g_CluiData.hMenuNotify, g_CluiData.wNextMenuID, FALSE, &mii);
					p-> menuId = g_CluiData.wNextMenuID;
					g_CluiData.wNextMenuID++;
					if (g_CluiData.wNextMenuID > 0x7fff)
						g_CluiData.wNextMenuID = 1;
					g_CluiData.iIconNotify = p->imlIconIndex;
				}
			}
		} 

		else if (p->cle.hContact != 0 && (p->cle.flags & CLEF_ONLYAFEW)) 
		{
			g_CluiData.iIconNotify = p->imlIconIndex;
			g_CluiData.hUpdateContact = p->cle.hContact;
		}
		if (pcli->events.count > 0) {
			g_CluiData.bEventAreaEnabled = TRUE;
			if (g_CluiData.bNotifyActive == FALSE) {
				g_CluiData.bNotifyActive = TRUE;
				EventArea_HideShowNotifyFrame();
			}
		}
		CLUI__cliInvalidateRect(g_CluiData.hwndEventFrame, NULL, FALSE);
	}
	
	return p;
}


int cli_RemoveEvent(HANDLE hContact, HANDLE hDbEvent)
{
	int i;
    int res=0;

	// Find the event that should be removed
	for (i = 0; i < pcli->events.count; i++) 
    {
		if ((pcli->events.items[i]->cle.hContact == hContact) && (pcli->events.items[i]->cle.hDbEvent == hDbEvent)) 
        {
			break;
		}
	}

	// Event was not found
	if (i == pcli->events.count)
		return 1;

	// remove event from the notify menu
	if (1) 
    {
		if (pcli->events.items[i]->menuId > 0) 
        {
			MENUITEMINFO mii = {0};
			mii.cbSize = sizeof(mii);
			mii.fMask = MIIM_DATA;
			if (GetMenuItemInfo(g_CluiData.hMenuNotify, pcli->events.items[i]->menuId, FALSE, &mii) != 0) 
            {
				struct NotifyMenuItemExData *nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
				if (nmi && nmi->hContact == hContact && nmi->hDbEvent == hDbEvent) 
                {
					free(nmi);
					DeleteMenu(g_CluiData.hMenuNotify, pcli->events.items[i]->menuId, MF_BYCOMMAND);
                }	
            }	
        }	
    }

	res=corecli.pfnRemoveEvent(hContact, hDbEvent);

	if (pcli->events.count == 0) 
    {
		g_CluiData.bNotifyActive = FALSE;
		EventArea_HideShowNotifyFrame();
    }

	if (hContact == g_CluiData.hUpdateContact || (INT_PTR)hDbEvent == 1)
		g_CluiData.hUpdateContact = 0;
    CLUI__cliInvalidateRect(g_CluiData.hwndEventFrame, NULL, FALSE);
	return res;
}


/* Implementations */

struct event_area_t
{
	HBITMAP  hBmpBackground;
	COLORREF bkColour;
	int      useWinColors;
	int      backgroundBmpUse;

	event_area_t():
		hBmpBackground( NULL),
		bkColour( CLCDEFAULT_BKCOLOUR ),
		useWinColors( CLCDEFAULT_USEWINDOWSCOLOURS ),
		backgroundBmpUse( CLCDEFAULT_USEBITMAP )
	{}
};

static event_area_t event_area;

static BOOL sttDrawEventAreaBackground(HWND hwnd, HDC hdc, RECT * rect)
{
	BOOL bFloat = (GetParent(hwnd)!=pcli->hwndContactList);
	if (g_CluiData.fDisableSkinEngine || !g_CluiData.fLayered || bFloat)
	{	
		RECT rc;

		if (rect) rc=*rect;
		else	  GetClientRect(hwnd,&rc);

		if (!event_area.hBmpBackground && !event_area.useWinColors)
		{			
			HBRUSH hbr=CreateSolidBrush(event_area.bkColour);
			FillRect(hdc, &rc, hbr);
			DeleteObject(hbr);
		}
		else 
		{
			DrawBackGround(hwnd,hdc,event_area.hBmpBackground,event_area.bkColour,event_area.backgroundBmpUse);
		}
	}
	return TRUE;
}

COLORREF sttGetColor(char * module, char * color, COLORREF defColor); //clcutils

static int  ehhEventAreaBackgroundSettingsChanged(WPARAM wParam, LPARAM lParam)
{
	if(event_area.hBmpBackground) 
	{
		DeleteObject(event_area.hBmpBackground); 
		event_area.hBmpBackground=NULL;
	}
	if (g_CluiData.fDisableSkinEngine)
	{
		DBVARIANT dbv;
		event_area.bkColour=sttGetColor("EventArea","BkColour",CLCDEFAULT_BKCOLOUR);
		if(ModernGetSettingByte(NULL,"EventArea","UseBitmap",CLCDEFAULT_USEBITMAP)) {
			if(!ModernGetSettingString(NULL,"EventArea","BkBitmap",&dbv)) {
				event_area.hBmpBackground=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
				ModernDBFreeVariant(&dbv);
			}
		}
		event_area.useWinColors = ModernGetSettingByte(NULL, "EventArea", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
		event_area.backgroundBmpUse = ModernGetSettingWord(NULL, "EventArea", "BkBmpUse", CLCDEFAULT_BKBMPUSE);
	}	
	PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
	return 0;
}

void EventArea_ConfigureEventArea()
{
	int iCount = pcli->events.count;
  
    g_CluiData.dwFlags&=~(CLUI_FRAME_AUTOHIDENOTIFY|CLUI_FRAME_SHOWALWAYS);
    if (ModernGetSettingByte(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT)==1) g_CluiData.dwFlags|=CLUI_FRAME_AUTOHIDENOTIFY;
    if (ModernGetSettingByte(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT)==2) g_CluiData.dwFlags|=CLUI_FRAME_SHOWALWAYS;

	if (g_CluiData.dwFlags & CLUI_FRAME_SHOWALWAYS)
		g_CluiData.bNotifyActive = 1;
    else if (g_CluiData.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
        g_CluiData.bNotifyActive = iCount > 0 ? 1 : 0;
	else
		g_CluiData.bNotifyActive = 0;

	EventArea_HideShowNotifyFrame();
}


static int EventArea_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
{
    return EventArea_Draw(hWnd,hDC);   
}

static int EventArea_Draw(HWND hwnd, HDC hDC)
{
  if (hwnd==(HWND)-1) return 0;
  if (GetParent(hwnd)==pcli->hwndContactList)
    return EventArea_DrawWorker(hwnd,hDC);
  else
    CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
  return 0;
}

static int EventArea_DrawWorker(HWND hWnd, HDC hDC)
{
    RECT rc;
    HFONT hOldFont;
    GetClientRect(hWnd,&rc);   
	if ( g_CluiData.fDisableSkinEngine )
	{
		sttDrawEventAreaBackground( hWnd, hDC, &rc );
	}
	else
	{
		SkinDrawGlyph(hDC,&rc,&rc,"Main,ID=EventArea");
	}
    hOldFont=g_clcPainter.ChangeToFont(hDC,NULL,FONTID_EVENTAREA,NULL);
	SetBkMode(hDC,TRANSPARENT);
    //ske_DrawText(hDC,_T("DEBUG"),lstrlen(_T("DEBUG")),&rc,0);
    {
	    int iCount = GetMenuItemCount(g_CluiData.hMenuNotify);
        rc.left += 26; 
        if (g_CluiData.hUpdateContact != 0) 
        {
		    TCHAR *szName = pcli->pfnGetContactDisplayName(g_CluiData.hUpdateContact, 0);
		    int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) g_CluiData.hUpdateContact, 0);

		    ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
		    rc.left += 18;
		    ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE);
		    ske_ImageList_DrawEx(g_himlCListClc, (int)g_CluiData.iIconNotify, hDC, 4, (rc.bottom + rc.top - 16) / 2, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
	    }
        else if (iCount > 0) 
        {
		    MENUITEMINFO mii = {0};
		    struct NotifyMenuItemExData *nmi;
		    TCHAR *szName;
		    int iIcon;

		    mii.cbSize = sizeof(mii);
		    mii.fMask = MIIM_DATA;
		    GetMenuItemInfo(g_CluiData.hMenuNotify, iCount - 1, TRUE, &mii);
		    nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
		    szName = pcli->pfnGetContactDisplayName(nmi->hContact, 0);
		    iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);
		    ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
		    rc.left += 18;
		    ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, hDC, 4, (rc.bottom + rc.top) / 2 - 8, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
		    ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE);
	    } 
        else 
        {
		    HICON hIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 16, 16, 0);
		    ske_DrawText(hDC, g_CluiData.szNoEvents, lstrlen(g_CluiData.szNoEvents), &rc, DT_VCENTER | DT_SINGLELINE);
		    ske_DrawIconEx(hDC, 4, (rc.bottom + rc.top - 16) / 2, hIcon, 16, 16, 0, 0, DI_NORMAL | DI_COMPAT);
		    DestroyIcon(hIcon);
	    }
    }
	ske_ResetTextEffect(hDC);
    SelectObject(hDC,hOldFont);
    return 0;
}

static void EventArea_HideShowNotifyFrame()
{
 	int dwVisible = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hNotifyFrame), 0) & F_VISIBLE;
    int desired;
    
    if (g_CluiData.dwFlags & CLUI_FRAME_SHOWALWAYS)
        desired = TRUE;
    else if(g_CluiData.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
        desired = g_CluiData.bNotifyActive ? TRUE : FALSE;
    else
        desired = FALSE;

    if(desired) 
    {
		if(!dwVisible)
			CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
	}
	else 
    {
		if(dwVisible)
			CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
	}
}


int EventArea_Create(HWND hCluiWnd)
{

  CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Event Area Background/EventArea",0);
  ModernHookEvent(ME_BACKGROUNDCONFIG_CHANGED,ehhEventAreaBackgroundSettingsChanged); 
  ehhEventAreaBackgroundSettingsChanged(0,0);

  WNDCLASS wndclass={0};
  TCHAR pluginname[]=TEXT("EventArea");
  int h=GetSystemMetrics(SM_CYSMICON)+2;
  if (GetClassInfo(g_hInst,pluginname,&wndclass) ==0)
  {
    wndclass.style         = 0;
    wndclass.lpfnWndProc   = EventArea_WndProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance     = g_hInst;
    wndclass.hIcon         = NULL;
    wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = pluginname;
    RegisterClass(&wndclass);
  }
  g_CluiData.hwndEventFrame=CreateWindow(pluginname,pluginname,WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,
    0,0,0,h,hCluiWnd,NULL,g_hInst,NULL);
  // register frame

  {
    CLISTFrame Frame;
    memset(&Frame,0,sizeof(Frame));
    Frame.cbSize=sizeof(CLISTFrame);
    Frame.hWnd=g_CluiData.hwndEventFrame;
    Frame.align=alBottom;
    Frame.hIcon=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
    Frame.Flags=(ModernGetSettingByte(NULL,"CLUI","ShowEventArea",SETTING_SHOWEVENTAREAFRAME_DEFAULT)?F_VISIBLE:0)|F_LOCKED|F_NOBORDER|F_NO_SUBCONTAINER|F_TCHAR;
    Frame.height=h;
    Frame.tname=_T("EventArea"); //do not translate
    Frame.TBtname=TranslateT("Event Area");
    hNotifyFrame=(HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);
    CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)Frame.hWnd,(LPARAM)EventArea_PaintCallbackProc); //$$$$$ register sub for frame
    CallService(MS_CLIST_FRAMES_UPDATEFRAME,-1,0);
    EventArea_HideShowNotifyFrame();
  }
  g_CluiData.szNoEvents=TranslateT("No Events");
  g_CluiData.hMenuNotify = CreatePopupMenu();
  g_CluiData.wNextMenuID = 1;
  EventArea_ConfigureEventArea();
  return 0;
}

int EventArea_UnloadModule()
{
	// remove frame window
	// remove all events data from menu
	DestroyMenu( g_CluiData.hMenuNotify );
	return 0;
}

#define IDC_NOTIFYBUTTON 1900
static LRESULT CALLBACK EventArea_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg) 
    {
	case WM_MEASUREITEM:
		{
			MEASUREITEMSTRUCT *lpi = (LPMEASUREITEMSTRUCT) lParam;
			MENUITEMINFOA mii = {0};

			mii.cbSize = sizeof(mii);
			mii.fMask = MIIM_DATA | MIIM_ID;
			if (GetMenuItemInfoA(g_CluiData.hMenuNotify, lpi->itemID, FALSE, &mii) != 0) {
				if (mii.dwItemData == lpi->itemData) 
                {
					lpi->itemWidth = 8 + 16;
					lpi->itemHeight = 0;
					return TRUE;
				}
			}
			break;
		}  
    case WM_DRAWITEM:
		{
			LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
			if (dis->hwndItem == (HWND) g_CluiData.hMenuNotify) 
            {
				MENUITEMINFOA mii = {0};

				struct NotifyMenuItemExData *nmi = 0;
				int iIcon;

				mii.cbSize = sizeof(mii);
				mii.fMask = MIIM_DATA;
				if (GetMenuItemInfoA(g_CluiData.hMenuNotify, (UINT) dis->itemID, FALSE, &mii) != 0) 
                {
					nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
					if (nmi) 
                    {
						iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);                        
                        ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, dis->hDC, 2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
                        ske_ImageList_DrawEx(g_himlCListClc, iIcon, dis->hDC, 2+GetSystemMetrics(SM_CXSMICON)+2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
						return TRUE;
					}
				}
			}
			break;
		}
    case WM_LBUTTONUP:
		if(g_CluiData.bEventAreaEnabled)
			SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0);
		break;
	case WM_COMMAND:
		if(LOWORD(wParam) == IDC_NOTIFYBUTTON) {
			int iSelection;
			MENUITEMINFO mii = {0};
			POINT pt;
			struct NotifyMenuItemExData *nmi = 0;
			int iCount = GetMenuItemCount(g_CluiData.hMenuNotify);
			BOOL result;

			GetCursorPos(&pt);
			mii.cbSize = sizeof(mii);
			mii.fMask = MIIM_DATA;
			if (iCount > 1)
				iSelection = TrackPopupMenu(g_CluiData.hMenuNotify, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
			else
				iSelection = GetMenuItemID(g_CluiData.hMenuNotify, 0);
			result = GetMenuItemInfo(g_CluiData.hMenuNotify, (UINT) iSelection, FALSE, &mii);
			if (result != 0) {
				nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
				if (nmi) {
					CLISTEVENT *cle = MyGetEvent(iSelection);
					if (cle) {
						CLISTEVENT *cle1 = NULL;
						CallService(cle->pszService, (WPARAM) NULL, (LPARAM) cle);
						// re-obtain the pointer, it may already be invalid/point to another event if the
						// event we're interested in was removed by the service (nasty one...)
						cle1 = MyGetEvent(iSelection);
						if (cle1 != NULL)
							CallService(MS_CLIST_REMOVEEVENT, (WPARAM) cle->hContact, (LPARAM) cle->hDbEvent);
					}
				}
			}
			break;
		}
		break;
    case WM_SIZE:
	  if (!g_CluiData.fLayered)InvalidateRect(hwnd,NULL,FALSE);
	  return DefWindowProc(hwnd, msg, wParam, lParam);
    case WM_ERASEBKGND:
	  return 1;
    case WM_PAINT:
        {
            if (GetParent(hwnd)==pcli->hwndContactList && g_CluiData.fLayered)
                CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
            else if (GetParent(hwnd)==pcli->hwndContactList && !g_CluiData.fLayered)
	        {
		        HDC hdc, hdc2;
		        HBITMAP hbmp,hbmpo;
		        RECT rc={0};
		        GetClientRect(hwnd,&rc);
		        rc.right++;
		        rc.bottom++;
		        hdc = GetDC(hwnd);
		        hdc2=CreateCompatibleDC(hdc);
		        hbmp=ske_CreateDIB32(rc.right,rc.bottom);
		        hbmpo=(HBITMAP)SelectObject(hdc2,hbmp);		
		        ske_BltBackImage(hwnd,hdc2,&rc);
		        EventArea_DrawWorker(hwnd,hdc2);
		        BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
			        hdc2,rc.left,rc.top,SRCCOPY);
		        SelectObject(hdc2,hbmpo);
		        DeleteObject(hbmp);
		        mod_DeleteDC(hdc2);
		        SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
		        ReleaseDC(hwnd,hdc);
		        ValidateRect(hwnd,NULL);
            }
            else
            {
                HDC hdc, hdc2;
                HBITMAP hbmp, hbmpo;
                RECT rc;
                PAINTSTRUCT ps;
                HBRUSH br=GetSysColorBrush(COLOR_3DFACE);
                GetClientRect(hwnd,&rc);
                hdc=BeginPaint(hwnd,&ps);
                hdc2=CreateCompatibleDC(hdc);
                hbmp=ske_CreateDIB32(rc.right,rc.bottom);
				hbmpo=(HBITMAP)SelectObject(hdc2,hbmp);
                FillRect(hdc2,&ps.rcPaint,br);
                EventArea_DrawWorker(hwnd,hdc2);
                BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
                hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
                SelectObject(hdc2,hbmpo);
                DeleteObject(hbmp);
                mod_DeleteDC(hdc2);
                ps.fErase=FALSE;
                EndPaint(hwnd,&ps);
            }
        }
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return TRUE;
}
