diff options
| author | Robert Pösel <robyer@seznam.cz> | 2013-09-04 09:58:45 +0000 | 
|---|---|---|
| committer | Robert Pösel <robyer@seznam.cz> | 2013-09-04 09:58:45 +0000 | 
| commit | 88efdb32b732e4335de0a3f3c93966a6c4d67031 (patch) | |
| tree | 3fbd0e39b6f6bdfe8a08ec99fa6253e7105402ea /plugins/!NotAdopted/MirandaG15/src/CAppletManager.cpp | |
| parent | ca27f47e6cdaef69d3ab504a1643f692e5ca3c47 (diff) | |
Added MirandaG15 plugin sources (not adopted)
git-svn-id: http://svn.miranda-ng.org/main/trunk@5938 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/!NotAdopted/MirandaG15/src/CAppletManager.cpp')
| -rw-r--r-- | plugins/!NotAdopted/MirandaG15/src/CAppletManager.cpp | 1958 | 
1 files changed, 1958 insertions, 0 deletions
| diff --git a/plugins/!NotAdopted/MirandaG15/src/CAppletManager.cpp b/plugins/!NotAdopted/MirandaG15/src/CAppletManager.cpp new file mode 100644 index 0000000000..13809df875 --- /dev/null +++ b/plugins/!NotAdopted/MirandaG15/src/CAppletManager.cpp @@ -0,0 +1,1958 @@ +#include "stdafx.h"
 +#include "CConfig.h"
 +#include "CAppletManager.h"
 +#include "m_system.h"
 +
 +// specifies how long contact status notifications are ignored after signon
 +#define PROTOCOL_NOTIFY_DELAY 1500
 +
 +//########################################################################
 +// functions
 +//########################################################################
 +
 +//************************************************************************
 +// returns the AppletManager's instance
 +//************************************************************************
 +CAppletManager *CAppletManager::GetInstance()
 +{
 +	return (CAppletManager*)CLCDOutputManager::GetInstance();
 +}
 +
 +//************************************************************************
 +// Constructor
 +//************************************************************************
 +CAppletManager::CAppletManager()
 +{
 +	m_uiTimer = NULL;
 +	m_pLastScreen = NULL;
 +
 +	
 +}
 +
 +//************************************************************************
 +// Destructor
 +//************************************************************************
 +CAppletManager::~CAppletManager()
 +{
 +
 +}
 +
 +//************************************************************************
 +// Initializes the AppletManager
 +//************************************************************************
 +bool CAppletManager::Initialize(tstring strAppletName)
 +{
 +	if(!CLCDOutputManager::Initialize(strAppletName))
 +		return false;
 +	
 +	GetLCDConnection()->Connect(CConfig::GetIntSetting(DEVICE));
 +
 +	// set the volumewheel hook
 +	SetVolumeWheelHook();
 +
 +	// initialize the screens
 +	m_NotificationScreen.Initialize();
 +	m_EventScreen.Initialize();
 +	m_ContactlistScreen.Initialize();
 +	m_ChatScreen.Initialize();
 +	m_CreditsScreen.Initialize();
 +	m_ScreensaverScreen.Initialize();
 +
 +	// add the screens to the list
 +	AddScreen(&m_NotificationScreen);
 +	AddScreen(&m_EventScreen);
 +	AddScreen(&m_ContactlistScreen);
 +	AddScreen(&m_ChatScreen);
 +	AddScreen(&m_CreditsScreen);
 +	AddScreen(&m_ScreensaverScreen);
 +
 +	// activate the event screen
 +	ActivateScreen(&m_EventScreen);
 +
 +	// hook the neccessary events
 +	m_hMIHookMessageWindowEvent = HookEvent(ME_MSG_WINDOWEVENT,CAppletManager::HookMessageWindowEvent);
 +	m_hMIHookEventAdded = HookEvent(ME_DB_EVENT_ADDED, CAppletManager::HookEventAdded);
 +	m_hMIHookStatusChanged  = HookEvent(ME_DB_CONTACT_SETTINGCHANGED,  CAppletManager::HookStatusChanged);
 +	m_hMIHookProtoAck =  HookEvent(ME_PROTO_ACK,  CAppletManager::HookProtoAck);
 +	m_hMIHookContactDeleted = HookEvent(ME_DB_CONTACT_DELETED,  CAppletManager::HookContactDeleted); 
 +	m_hMIHookContactAdded = HookEvent(ME_DB_CONTACT_ADDED,  CAppletManager::HookContactAdded);
 +	m_hMIHookSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED,CAppletManager::HookSettingChanged);
 +	m_hMIHookContactIsTyping = HookEvent(ME_PROTO_CONTACTISTYPING,CAppletManager::HookContactIsTyping);
 +	
 +	// enumerate protocols
 +	int iCount;
 +	int iProtoCount = 0;
 +	PROTOCOLDESCRIPTOR **ppProtocolDescriptor;
 +	CProtocolData *pProtoData = NULL;
 +	CIRCConnection *pIRCConnection = NULL;
 +
 +	CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&iCount,(LPARAM)&ppProtocolDescriptor);
 +	for(int i=0;i<iCount;i++)
 +	{
 +		if(ppProtocolDescriptor[i]->type != PROTOTYPE_PROTOCOL)
 +			continue;
 +
 +		iProtoCount++;
 +		pProtoData = new CProtocolData();
 +		pProtoData->iStatus = ID_STATUS_OFFLINE;
 +		pProtoData->strProtocol = toTstring(ppProtocolDescriptor[i]->szName);
 +		pProtoData->lTimeStamp = 0;
 +		
 +		// try to create an irc connection for that protocol (will fail if it is no irc protocol)
 +		pIRCConnection = CreateIRCConnection(pProtoData->strProtocol);
 +
 +		m_vProtocolData.push_back(pProtoData);
 +	}
 +
 +	// load status bitmaps
 +	m_ahStatusBitmaps[0] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_OFFLINE),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	m_ahStatusBitmaps[1] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_ONLINE),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	m_ahStatusBitmaps[2] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_AWAY),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	m_ahStatusBitmaps[3] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_NA),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	m_ahStatusBitmaps[4] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_OCCUPIED),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	m_ahStatusBitmaps[5] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_DND),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	m_ahStatusBitmaps[6] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_INVISIBLE),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	m_ahStatusBitmaps[7] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_STATUS_FFC),
 +												IMAGE_BITMAP,5, 5, LR_MONOCHROME);
 +	// Load event bitmaps
 +	m_ahEventBitmaps[0] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_MSG),
 +												IMAGE_BITMAP,6, 6, LR_MONOCHROME);
 +	m_ahEventBitmaps[1] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_CON),
 +												IMAGE_BITMAP,6, 6, LR_MONOCHROME);
 +	m_ahEventBitmaps[2] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_USER),
 +												IMAGE_BITMAP,6, 6, LR_MONOCHROME);
 +	m_ahEventBitmaps[3] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_INFO),
 +												IMAGE_BITMAP,6, 6, LR_MONOCHROME);
 +	
 +	m_ahLargeEventBitmaps[0] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_MSG_LARGE),
 +												IMAGE_BITMAP,8, 8, LR_MONOCHROME);
 +	m_ahLargeEventBitmaps[1] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_CON_LARGE),
 +												IMAGE_BITMAP,8, 8, LR_MONOCHROME);
 +	m_ahLargeEventBitmaps[2] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_USER_LARGE),
 +												IMAGE_BITMAP,8, 8, LR_MONOCHROME);
 +	m_ahLargeEventBitmaps[3] = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_EVENT_INFO_LARGE),
 +												IMAGE_BITMAP,8, 8, LR_MONOCHROME);
 +
 +	
 +	// start the update timer
 +	m_uiTimer = SetTimer(0,0,1000/10,CAppletManager::UpdateTimer);
 +
 +		
 +
 +	return true;
 +}
 +
 +//************************************************************************
 +// Deinitializes the AppletManager
 +//************************************************************************
 +bool CAppletManager::Shutdown()
 +{
 +	if(!IsInitialized())
 +		return false;
 +
 +	// stop the update timer
 +	KillTimer(0,m_uiTimer);
 +	
 +	// delete status bitmaps
 +	for(int i=0;i<8;i++)
 +		DeleteObject(m_ahStatusBitmaps[i]);
 +
 +	// delete event bitmaps
 +	for(int i=0;i<8;i++)
 +	{
 +		DeleteObject(m_ahLargeEventBitmaps[i]);	
 +		DeleteObject(m_ahEventBitmaps[i]);
 +	}
 +
 +	// unhook the events	
 +	UnhookEvent(m_hMIHookMessageWindowEvent);
 +	UnhookEvent(m_hMIHookEventAdded);
 +	UnhookEvent(m_hMIHookStatusChanged);
 +	UnhookEvent(m_hMIHookProtoAck);
 +	UnhookEvent(m_hMIHookContactDeleted);
 +	UnhookEvent(m_hMIHookContactAdded);
 +	UnhookEvent(m_hMIHookSettingChanged);
 +
 +	// unhook all irc protocols, and delete the classes
 +	vector<CIRCConnection*>::iterator iter = m_vIRCConnections.begin();
 +	while(iter != m_vIRCConnections.end())
 +	{
 +		UnhookEvent((*iter)->hEventHook);
 +		delete *iter;
 +		iter++;
 +	}
 +	m_vIRCConnections.clear();
 +	
 +	// Deinitialize the screens
 +	m_NotificationScreen.Shutdown();
 +	m_EventScreen.Shutdown();
 +	m_ContactlistScreen.Shutdown();
 +	m_ChatScreen.Shutdown();
 +	m_CreditsScreen.Shutdown();
 +	m_ScreensaverScreen.Shutdown();
 +
 +	// deinitialize the configuration manager
 +	CConfig::Shutdown();
 +	
 +	// delete the protocol information
 +	CProtocolData *pProtoData;
 +	for(int i=0;i<m_vProtocolData.size();i++)
 +	{
 +		pProtoData = m_vProtocolData[i];
 +		delete pProtoData;
 +	}
 +	m_vProtocolData.clear();
 +
 +	// deinitialize the outputmanager
 +	if(!CLCDOutputManager::Shutdown())
 +		return false;
 +	return true;
 +}
 +
 +//************************************************************************
 +// Translates the specified string, and inserts the parameters
 +//************************************************************************
 +tstring CAppletManager::TranslateString(TCHAR *szString,...)
 +{
 +	TCHAR out[1024];
 +	TCHAR *szTranslatedString = TranslateTS((LPARAM)szString);
 +
 +	va_list body;
 +	va_start(body, szString);
 +	_vstprintf(out, szTranslatedString, body);
 +	va_end(body);
 +	return out;
 +}
 +
 +//************************************************************************
 +// checks if the patched IRC protocol is in place
 +//************************************************************************
 +bool CAppletManager::IsIRCHookEnabled()
 +{
 +	if(m_vIRCConnections.size() == NULL)
 +		return false;
 +	return true;
 +}
 +
 +//************************************************************************
 +// returns the informations structure for the specified protocol
 +//************************************************************************
 +CProtocolData* CAppletManager::GetProtocolData(tstring strProtocol)
 +{
 +	for(int i=0;i<m_vProtocolData.size();i++)
 +	{
 +		if(m_vProtocolData[i]->strProtocol == strProtocol)
 +			return m_vProtocolData[i];
 +	}
 +	return NULL;
 +}
 +
 +//************************************************************************
 +// Updates the AppletManager
 +//************************************************************************
 +bool CAppletManager::Update()
 +{
 +	if(!CLCDOutputManager::Update())
 +		return false;
 +	
 +	// Update Messagejobs
 +	UpdateMessageJobs();
 +
 +	// Screensaver detection
 +	BOOL bActive = false;
 +	SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &bActive, 0);
 +	if(bActive != m_bScreensaver)
 +	{
 +		if(CConfig::GetBoolSetting(SCREENSAVER_LOCK)) {
 +			if(!m_bScreensaver) {
 +				ActivateScreensaverScreen();
 +			} else {
 +				ActivateEventScreen();
 +			}
 +		}
 +		if(CConfig::GetBoolSetting(CONTROL_BACKLIGHTS)) {
 +			if(GetLCDConnection() &&
 +				GetLCDConnection()->GetConnectionType() == TYPE_LOGITECH)
 +			{
 +				CLCDConnectionLogitech *pLCDConnection = (CLCDConnectionLogitech*)GetLCDConnection();
 +				
 +				// Screensaver starts
 +				if(!m_bScreensaver)
 +				{
 +					m_G15LightStatus = pLCDConnection->GetLightStatus();
 +					pLCDConnection->SetLCDBacklight(LCD_OFF);
 +					pLCDConnection->SetKBDBacklight(KBD_OFF);
 +					pLCDConnection->SetMKeyLight(0,0,0,0);
 +				}
 +				// Screensaver ends
 +				else
 +				{
 +					SG15LightStatus currentStatus = pLCDConnection->GetLightStatus();
 +					
 +					if(currentStatus.eLCDBrightness == LCD_OFF)
 +						pLCDConnection->SetLCDBacklight(m_G15LightStatus.eLCDBrightness);
 +					if(currentStatus.eKBDBrightness == KBD_OFF)
 +						pLCDConnection->SetKBDBacklight(m_G15LightStatus.eKBDBrightness);
 +					if(!currentStatus.bMRKey && !currentStatus.bMKey[0] && !currentStatus.bMKey[1]
 +						&& !currentStatus.bMKey[2])	
 +						pLCDConnection->SetMKeyLight(m_G15LightStatus.bMKey[0],m_G15LightStatus.bMKey[1],m_G15LightStatus.bMKey[2],m_G15LightStatus.bMRKey);
 +				}
 +			}
 +		}
 +		m_bScreensaver = bActive;
 +	}
 +
 +	return true;	
 +}
 +
 +//************************************************************************
 +// Called when the active screen has expired
 +//************************************************************************
 +void CAppletManager::OnScreenExpired(CLCDScreen *pScreen)
 +{
 +	// If the notification screen has expired, activate the last active screen
 +	if(pScreen == (CLCDScreen*)&m_NotificationScreen)
 +	{
 +		ActivateScreen(m_pLastScreen);
 +		if(CConfig::GetBoolSetting(TRANSITIONS))
 +			m_pGfx->StartTransition();
 +	}
 +}
 +
 +//************************************************************************
 +// the update timer's callback function
 +//************************************************************************
 +VOID CALLBACK CAppletManager::UpdateTimer(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
 +{
 +	CAppletManager::GetInstance()->Update();
 +}
 +
 +//************************************************************************
 +// applies the volumewheel setting
 +//************************************************************************
 +void CAppletManager::SetVolumeWheelHook()
 +{
 +	// Set the volumewheel hook
 +	if(GetLCDConnection() && GetLCDConnection()->GetConnectionType() == TYPE_LOGITECH)
 +	{
 +		CLCDConnectionLogitech *pLCDConnection = (CLCDConnectionLogitech*)GetLCDConnection();
 +		if(pLCDConnection->GetConnectionState() == CONNECTED)
 +			pLCDConnection->SetVolumeWheelHook(CConfig::GetBoolSetting(HOOK_VOLUMEWHEEL));
 +	}
 +}
 +
 +//************************************************************************
 +// Called when the connection state has changed
 +//************************************************************************
 +void CAppletManager::OnConnectionChanged(int iConnectionState)
 +{
 +	if(iConnectionState == CONNECTED)
 +	{
 +		SetVolumeWheelHook();
 +	}
 +	CConfig::OnConnectionChanged();
 +}
 +
 +//************************************************************************
 +// called when the plugin's configuration has changed
 +//************************************************************************
 +void CAppletManager::OnConfigChanged()
 +{
 +	GetLCDConnection()->Connect(CConfig::GetIntSetting(DEVICE));
 +
 +	m_pGfx->StartTransition(TRANSITION_MORPH);
 +
 +	// Set the volumewheel hook
 +	SetVolumeWheelHook();
 +	// send the event to all screens
 +	m_NotificationScreen.OnConfigChanged();
 +	m_ChatScreen.OnConfigChanged();
 +	m_EventScreen.OnConfigChanged();
 +	m_ContactlistScreen.OnConfigChanged();
 +	m_CreditsScreen.OnConfigChanged();
 +}
 +//************************************************************************
 +// activate a screen
 +//************************************************************************
 +void CAppletManager::ActivateScreen(CScreen *pScreen) {
 +	if(GetActiveScreen() && GetActiveScreen() != &m_NotificationScreen) {
 +		m_pLastScreen = (CScreen*)GetActiveScreen();
 +	}
 +
 +	CLCDOutputManager::ActivateScreen(pScreen);
 +}
 +
 +//************************************************************************
 +// activates the previous screen
 +//************************************************************************
 +void CAppletManager::ActivatePreviousScreen() {
 +	if(m_pLastScreen) {
 +		ActivateScreen(m_pLastScreen);
 +	}
 +}
 +	
 +//************************************************************************
 +// activates the credits screen
 +//************************************************************************
 +void CAppletManager::ActivateScreensaverScreen()
 +{
 +	m_ScreensaverScreen.Reset();
 +	ActivateScreen(&m_ScreensaverScreen);
 +}
 +
 +//************************************************************************
 +// activates the credits screen
 +//************************************************************************
 +void CAppletManager::ActivateCreditsScreen()
 +{
 +	m_CreditsScreen.Reset();
 +	ActivateScreen(&m_CreditsScreen);
 +}
 +
 +//************************************************************************
 +// activates the event screen
 +//************************************************************************
 +void CAppletManager::ActivateEventScreen()
 +{
 +	m_ChatScreen.SetContact(NULL);
 +	ActivateScreen(&m_EventScreen);
 +
 +	if(CConfig::GetBoolSetting(TRANSITIONS))
 +		m_pGfx->StartTransition();
 +}
 +
 +//************************************************************************
 +// activates the contactlist screen
 +//************************************************************************
 +void CAppletManager::ActivateCListScreen()
 +{
 +	m_ChatScreen.SetContact(NULL);
 +	m_ContactlistScreen.ResetPosition();
 +	ActivateScreen(&m_ContactlistScreen);
 +
 +	if(CConfig::GetBoolSetting(TRANSITIONS))
 +		m_pGfx->StartTransition();
 +}
 +
 +//************************************************************************
 +// activates the chat screen
 +//************************************************************************
 +bool CAppletManager::ActivateChatScreen(HANDLE hContact)
 +{
 +	if(!m_ChatScreen.SetContact(hContact))
 +		return false;
 +
 +	m_ContactlistScreen.OnSessionOpened(hContact);
 +	ActivateScreen(&m_ChatScreen);
 +	
 +	if(CConfig::GetBoolSetting(TRANSITIONS))
 +		m_pGfx->StartTransition();
 +	return true;
 +}
 +
 +//************************************************************************
 +// returns the contacts displayname
 +//************************************************************************
 +tstring CAppletManager::GetContactDisplayname(HANDLE hContact,bool bShortened)
 +{
 +	if(!bShortened || !CConfig::GetBoolSetting(NOTIFY_NICKCUTOFF))
 +		return (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
 +	
 +	tstring strNick = GetContactDisplayname(hContact,false);
 +	if(strNick.length() > CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET))
 +		return strNick.erase(CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET)) + _T("...");
 +	
 +	return strNick;
 +}
 +
 +//************************************************************************
 +// returns the contacts group
 +//************************************************************************
 +tstring CAppletManager::GetContactGroup(HANDLE hContact)
 +{
 +	DBVARIANT dbv;
 +	int res = DBGetContactSettingTString(hContact, "CList", "Group",	&dbv);
 +
 +	tstring strGroup = _T("");
 +	if(!res)
 +		strGroup = dbv.ptszVal;
 +	
 +	DBFreeVariant(&dbv);
 +	return strGroup;
 +}
 +
 +//************************************************************************
 +// returns the bitmap for the specified event
 +//************************************************************************
 +HBITMAP CAppletManager::GetEventBitmap(EventType eType, bool bLarge)
 +{
 +	switch(eType)
 +	{
 +	case EVENT_MSG_RECEIVED:
 +	case EVENT_MSG_SENT:
 +	case EVENT_IRC_RECEIVED:
 +	case EVENT_IRC_SENT:
 +		if(bLarge)
 +			return m_ahLargeEventBitmaps[0];
 +		else
 +			return m_ahEventBitmaps[0];
 +	case EVENT_PROTO_STATUS:
 +	case EVENT_PROTO_CONNECTED:
 +	case EVENT_PROTO_DISCONNECTED:
 +		if(bLarge)
 +			return m_ahLargeEventBitmaps[1];
 +		else
 +			return m_ahEventBitmaps[1];
 +	case EVENT_STATUS:
 +	case EVENT_SIGNED_ON:
 +	case EVENT_SIGNED_OFF:
 +		if(bLarge)
 +			return m_ahLargeEventBitmaps[2];
 +		else
 +			return m_ahEventBitmaps[2];
 +	default:
 +		if(bLarge)
 +			return m_ahLargeEventBitmaps[3];
 +		else
 +			return m_ahEventBitmaps[3];
 +	}
 +}
 +
 +//************************************************************************
 +// returns the bitmap for the specified status
 +//************************************************************************
 +HBITMAP CAppletManager::GetStatusBitmap(int iStatus)
 +{
 +	switch(iStatus)
 +	{
 +	case ID_STATUS_OFFLINE:
 +		return m_ahStatusBitmaps[0];
 +	case ID_STATUS_ONLINE:
 +		return m_ahStatusBitmaps[1];
 +	case ID_STATUS_NA:
 +		return m_ahStatusBitmaps[3];
 +	case ID_STATUS_OCCUPIED:
 +		return m_ahStatusBitmaps[4];
 +	case ID_STATUS_DND:
 +		return m_ahStatusBitmaps[5];
 +	case ID_STATUS_INVISIBLE:
 +		return m_ahStatusBitmaps[6];
 +	case ID_STATUS_FREECHAT:
 +		return m_ahStatusBitmaps[7];
 +	case ID_STATUS_AWAY:
 +	default:
 +		return m_ahStatusBitmaps[2];
 +	}
 +}
 +//************************************************************************
 +// returns a formatted timestamp string
 +//************************************************************************
 +tstring CAppletManager::GetFormattedTimestamp(tm *tm_time)
 +{
 +	time_t now;
 +	tm tm_now;
 +	time(&now);
 +	localtime_s(&tm_now,&now);
 +
 +	TCHAR buffer[128];
 +	setlocale( LC_ALL, "" );
 +	
 +	if(tm_time->tm_mday != tm_now.tm_mday || tm_time->tm_mon != tm_now.tm_mon)
 +	{
 +		if(CConfig::GetBoolSetting(TIMESTAMP_SECONDS))
 +			_tcsftime(buffer,128,_T("[%x %H:%M:%S]"),tm_time);
 +		else
 +			_tcsftime(buffer,128,_T("[%x %H:%M]"),tm_time);
 +	}
 +	else
 +	{
 +		if(CConfig::GetBoolSetting(TIMESTAMP_SECONDS))
 +			_tcsftime(buffer,128,_T("[%H:%M:%S]"),tm_time);
 +		else
 +			_tcsftime(buffer,128,_T("[%H:%M]"),tm_time);
 +	}
 +
 +	return toTstring(buffer);
 +}
 +
 +//************************************************************************
 +// called to process the specified event
 +//************************************************************************
 +void CAppletManager::HandleEvent(CEvent *pEvent)
 +{
 +	TRACE(_T("<< Event: %i\n"),(int)pEvent->eType);
 +	
 +	// check if the event's timestamp needs to be set
 +	if(!pEvent->bTime)
 +	{
 +		time_t now;
 +		time(&now);
 +		localtime_s(&pEvent->Time,&now);
 +	}
 +	// check wether the event needs notification
 +	
 +	// check for protocol filters
 +	if(pEvent->hContact != NULL && pEvent->eType != EVENT_CONTACT_ADDED)
 +	{
 +		char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)pEvent->hContact, 0);
 +		if(szProto == NULL || !CConfig::GetProtocolNotificationFilter(toTstring(szProto)))
 +			pEvent->bNotification = false;
 +	}
 +	pEvent->bLog = pEvent->bNotification;
 +
 +	if(CAppletManager::IsSubContact(pEvent->hContact))
 +	{
 +		pEvent->bLog = false;
 +		pEvent->bNotification = false;
 +	}
 +
 +	// if the applet is in foreground, skip notifications for the chatsession contact
 +	if(pEvent->hContact && GetLCDConnection()->IsForeground() && pEvent->hContact == m_ChatScreen.GetContact() &&
 +		(!m_ChatScreen.IsInputActive() || !CConfig::GetBoolSetting(NOTIFY_NO_SKIP_REPLY)))
 +	{
 +		if(pEvent->eType == EVENT_STATUS  && CConfig::GetBoolSetting(NOTIFY_SKIP_STATUS))
 +			pEvent->bNotification = false;
 +		if( pEvent->eType == EVENT_SIGNED_ON && CConfig::GetBoolSetting(NOTIFY_SKIP_SIGNON))
 +			pEvent->bNotification = false;
 +		if(pEvent->eType == EVENT_SIGNED_OFF && CConfig::GetBoolSetting(NOTIFY_SKIP_SIGNOFF))
 +			pEvent->bNotification = false;
 +		if((pEvent->eType == EVENT_IRC_RECEIVED || pEvent->eType == EVENT_MSG_RECEIVED) && CConfig::GetBoolSetting(NOTIFY_SKIP_MESSAGES))
 +			pEvent->bNotification = false;
 +	}
 +
 +	// send the event to all screens
 +	m_NotificationScreen.OnEventReceived(pEvent);
 +	m_ChatScreen.OnEventReceived(pEvent);
 +	m_EventScreen.OnEventReceived(pEvent);
 +	m_ContactlistScreen.OnEventReceived(pEvent);
 +
 +	// activate notification screen if neccessary (and screensaverscreen is not active)
 +	if(pEvent->bNotification)
 +	{
 +		if(GetActiveScreen() != (CLCDScreen*)&m_NotificationScreen && GetActiveScreen() != (CLCDScreen*)&m_ScreensaverScreen)
 +		{
 +			m_NotificationScreen.SetAlert(true);
 +			m_NotificationScreen.SetExpiration(CConfig::GetIntSetting(NOTIFY_DURATION)*1000);
 +			ActivateScreen(&m_NotificationScreen);
 +
 +			if(GetLCDConnection()->IsForeground() && CConfig::GetBoolSetting(TRANSITIONS))
 +				m_pGfx->StartTransition();
 +		}
 +	}
 +}
 +
 +bool CAppletManager::IsUtfSendAvailable(HANDLE hContact) {
 +	char* szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
 +	if ( szProto == NULL )
 +		return FALSE;
 +
 +	return ( CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF ) ? TRUE : FALSE;
 +}
 +
 +//************************************************************************
 +// returns the contacts message service name
 +//************************************************************************
 +char *CAppletManager::GetMessageServiceName(HANDLE hContact,bool bIsUnicode)
 +{
 +	if(g_bUnicode) {
 +		char szServiceName[100];
 +		char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
 +		
 +		if(szProto == NULL)
 +			return NULL;
 +
 +		if (!bIsUnicode)
 +			return PSS_MESSAGE;
 +
 +		_snprintf(szServiceName, sizeof(szServiceName), "%s%sW", szProto, PSS_MESSAGE);
 +		if (ServiceExists(szServiceName))
 +			return PSS_MESSAGE "W";
 +	} else {
 +		return PSS_MESSAGE;
 +	}
 +}
 +
 +//************************************************************************
 +// updates all pending message jobs
 +//************************************************************************
 +void CAppletManager::UpdateMessageJobs()
 +{
 +	list<SMessageJob*>::iterator iter = m_MessageJobs.begin();
 +	while(iter != m_MessageJobs.end())
 +	{
 +		// TODO: Fertigstellen
 +		if((*iter)->dwTimestamp + 15*1000 < GetTickCount())
 +		{
 +			CEvent Event;
 +
 +			Event.eType = EVENT_MESSAGE_ACK;
 +			Event.hValue = (*iter)->hEvent;
 +			Event.hContact = (*iter)->hContact;
 +			Event.iValue = ACKRESULT_FAILED;
 +			Event.strValue = TranslateString(_T("Timeout: No response from contact/server"));
 +			
 +			HandleEvent(&Event);
 +
 +			SMessageJob *pJob = *iter;
 +			m_MessageJobs.erase(iter);
 +			free(pJob->pcBuffer);
 +			delete(pJob);
 +			break;
 +		}
 +		iter++;
 +	}
 +}
 +
 +//************************************************************************
 +// adds a message job to the list
 +//************************************************************************
 +void CAppletManager::AddMessageJob(SMessageJob *pJob)
 +{
 +	m_MessageJobs.push_back(pJob);
 +}
 +
 +//************************************************************************
 +// finishes a message job
 +//************************************************************************
 +void CAppletManager::FinishMessageJob(SMessageJob *pJob)
 +{
 +	list<SMessageJob*>::iterator iter = m_MessageJobs.begin();
 +	while(iter != m_MessageJobs.end())
 +	{
 +		if((*iter) == pJob)
 +		{
 +			char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)pJob->hContact, 0);
 +			tstring strProto = toTstring(szProto);
 +			CIRCConnection *pIRCCon = GetIRCConnection(strProto);
 +
 +			// Only add the message to the history if the contact isn't an irc chatroom
 +			if(!(pIRCCon && DBGetContactSettingByte(pJob->hContact, szProto, "ChatRoom", 0) != 0))
 +			{	
 +				// Add the message to the database
 +				DBEVENTINFO dbei = { 0 };
 +				dbei.cbSize = sizeof(dbei);
 +				dbei.eventType = EVENTTYPE_MESSAGE;
 +				dbei.flags = DBEF_SENT;		
 +				dbei.szModule = szProto;
 +				dbei.timestamp = time(NULL);
 +				// Check if protocoll is valid
 +				if(dbei.szModule == NULL)
 +					return;
 +
 +				if(pJob->dwFlags & PREF_UTF) {
 +					dbei.flags |= DBEF_UTF;
 +				}	
 +
 +				dbei.cbBlob = pJob->iBufferSize;
 +				dbei.pBlob = (PBYTE) pJob->pcBuffer;
 +
 +				CallService(MS_DB_EVENT_ADD, (WPARAM) pJob->hContact, (LPARAM) & dbei);
 +			}
 +			SMessageJob *pJob = *iter;
 +			m_MessageJobs.erase(iter);
 +			free(pJob->pcBuffer);
 +			delete(pJob);
 +			return;
 +		}
 +	}
 +}
 +
 +//************************************************************************
 +// cancels a message job
 +//************************************************************************
 +void CAppletManager::CancelMessageJob(SMessageJob *pJob)
 +{
 +	list<SMessageJob*>::iterator iter = m_MessageJobs.begin();
 +	while(iter != m_MessageJobs.end())
 +	{
 +		if((*iter) == pJob)
 +		{
 +			SMessageJob *pJob = *iter;
 +			m_MessageJobs.erase(iter);
 +			free(pJob->pcBuffer);
 +			delete(pJob);
 +			return;
 +		}
 +	}
 +}
 +
 +//************************************************************************
 +// returns wether or not a contact is a subcontact
 +//************************************************************************
 +bool CAppletManager::IsSubContact(HANDLE hContact)
 +{
 +	if(!DBGetContactSettingByte(0, "MetaContacts", "Enabled", 1))
 +		return false;
 +	bool bIsSubcontact = DBGetContactSettingByte(hContact,"MetaContacts","IsSubcontact",0);
 +	return bIsSubcontact;
 +	// HANDLE hMetaContact = (HANDLE)CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, NULL);
 +	// return hMetaContact != NULL;
 +}
 +
 +//************************************************************************
 +// sends typing notifications to the specified contact
 +//************************************************************************
 +void CAppletManager::SendTypingNotification(HANDLE hContact,bool bEnable)
 +{
 +	DWORD protoStatus;
 +    DWORD protoCaps;
 +    DWORD typeCaps;
 +
 +	if (!hContact)
 +        return;
 +
 +    // Don't send to protocols who don't support typing
 +    // Don't send to users who are unchecked in the typing notification options
 +    // Don't send to protocols that are offline
 +    // Don't send to users who are not visible and
 +    // Don't send to users who are not on the visible list when you are in invisible mode.
 +    if (!DBGetContactSettingByte(hContact, "SRMsg", "SupportTyping", DBGetContactSettingByte(NULL, "SRMsg", "DefaultTyping", 1)))
 +        return;
 +
 +	char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
 +    if (!szProto)
 +        return;
 +
 +    protoStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
 +    protoCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0);
 +    typeCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0);
 +
 +    if (!(typeCaps & PF4_SUPPORTTYPING))
 +        return;
 +    if (protoStatus < ID_STATUS_ONLINE)
 +        return;
 +    if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE)
 +        return;
 +    if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0) != ID_STATUS_ONLINE)
 +        return;
 +    if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0)
 +        && !DBGetContactSettingByte(NULL, "SRMsg", "UnknownTyping", 1))
 +        return;
 +    // End user check
 +	CallService(MS_PROTO_SELFISTYPING, (WPARAM) hContact, bEnable?PROTOTYPE_SELFTYPING_ON:PROTOTYPE_SELFTYPING_OFF);
 +}
 +
 +//************************************************************************
 +// sends a message to the specified contact
 +//************************************************************************
 +HANDLE CAppletManager::SendMessageToContact(HANDLE hContact,tstring strMessage)
 +{
 +	string strAscii = toNarrowString(strMessage);
 +	int bufSize = lstrlenA(strAscii.c_str())+1;
 +	SMessageJob *pJob = new SMessageJob();
 +	pJob->dwTimestamp = GetTickCount();
 +	pJob->hContact = hContact;
 +
 +	char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
 +	tstring strProto = toTstring(szProto);
 +
 +	CIRCConnection *pIRCCon = CAppletManager::GetInstance()->GetIRCConnection(strProto);
 +
 +	if(pIRCCon && DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0) != 0)
 +	{
 +		GCDEST gcd = {0};
 +		GCEVENT gce = {0};
 +
 +		DBVARIANT dbv;
 +		if (!DBGetContactSetting((HANDLE)hContact, szProto, "Nick", &dbv) && dbv.type == DBVT_ASCIIZ ) 
 +			gcd.pszID = dbv.pszVal;
 +		else
 +			return NULL;
 +
 +		string strID = string(gcd.pszID) + " - " + toNarrowString(pIRCCon->strNetwork).c_str();
 +		gcd.pszID = (char*)strID.c_str();
 +		gcd.pszModule = szProto;
 +		gcd.iType = GC_EVENT_SENDMESSAGE;
 +
 +		gce.cbSize = sizeof(GCEVENT);
 +		gce.pDest = &gcd;
 +		gce.pszStatus = "";
 +		// gce.bAddToLog = true;
 +		gce.pszUserInfo = NULL;
 +
 +		gce.pszText = (char *)strAscii.c_str();
 +
 +		gce.dwItemData = NULL;
 +		gce.time = time(NULL);
 +		gce.bIsMe = true;
 +
 +		CallService(MS_GC_EVENT, NULL, (LPARAM) &gce);
 +
 +		pJob->hEvent = NULL;
 +	}
 +	else
 +	{
 +		DWORD pref = 0;
 +		bool bIsUnicode = false;
 +		if(CAppletManager::IsUtfSendAvailable(pJob->hContact)) {
 +			pref = PREF_UTF;
 +			char* szMsgUtf = NULL;
 +			#if defined( _UNICODE )
 +				szMsgUtf = mir_utf8encodeW( strMessage.c_str());
 +			#else
 +				int codepage = CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 );
 +				szMsgUtf = mir_utf8encodecp(strMessage.c_str(), codepage);
 +			#endif
 +
 +			pJob->iBufferSize = strlen(szMsgUtf)+1;
 +			pJob->pcBuffer = (char *)malloc(pJob->iBufferSize);
 +			pJob->dwFlags = PREF_UTF;
 +
 +			memcpy(pJob->pcBuffer,szMsgUtf,pJob->iBufferSize);
 +			mir_free(szMsgUtf);
 +		} else {
 +			
 +#ifdef _UNICODE			
 +			bIsUnicode = !IsUnicodeAscii(strMessage.c_str(),lstrlen(strMessage.c_str()));
 +#endif
 +			if(bIsUnicode) {
 +				pref = PREF_UNICODE;
 +				pJob->iBufferSize = bufSize * (sizeof(TCHAR) + 1);
 +			} else {
 +				pJob->iBufferSize = bufSize;
 +			}
 +			pJob->pcBuffer = (char *)malloc(pJob->iBufferSize);
 +			memcpy(pJob->pcBuffer,strAscii.c_str(),bufSize);
 +
 +			if(bIsUnicode) {
 +				memcpy(&pJob->pcBuffer[bufSize],strMessage.c_str(),bufSize*sizeof(TCHAR));
 +			}
 +		}
 +		char *szService = CAppletManager::GetMessageServiceName(pJob->hContact,bIsUnicode);
 +
 +		if(szService == NULL)
 +		{
 +			free(pJob->pcBuffer);
 +			pJob->pcBuffer == NULL;
 +			return NULL;
 +		}
 +		pJob->hEvent = (HANDLE) CallContactService(pJob->hContact, szService , pref, (LPARAM)pJob->pcBuffer );
 +		CAppletManager::GetInstance()->AddMessageJob(pJob);
 +	}
 +
 +	
 +	return pJob->hEvent;
 +}
 +
 +//************************************************************************
 +// check if a contacts message window is opened
 +//************************************************************************
 +bool CAppletManager::IsMessageWindowOpen(HANDLE hContact)
 +{
 +	MessageWindowInputData mwid;
 +	mwid.cbSize = sizeof(MessageWindowInputData);
 +	mwid.hContact = hContact;
 +	mwid.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
 +
 +	MessageWindowData mwd;
 +	mwd.cbSize = sizeof(MessageWindowData);
 +	CallService(MS_MSG_GETWINDOWDATA,(WPARAM)&mwid,(LPARAM)&mwd);
 +	if(mwd.uState & MSG_WINDOW_STATE_EXISTS)
 +		return true;
 +	return false;
 +}
 +
 +//************************************************************************
 +// marks the given message as read
 +//************************************************************************
 +void CAppletManager::MarkMessageAsRead(HANDLE hContact,HANDLE hEvent)
 +{
 +	CallService(MS_DB_EVENT_MARKREAD,(WPARAM)hContact,(LPARAM)hEvent);
 +	CallService(MS_CLIST_REMOVEEVENT,(WPARAM)hContact,(LPARAM)hEvent);
 +}
 +
 +//************************************************************************
 +// translates the given database event
 +//************************************************************************
 +bool CAppletManager::TranslateDBEvent(CEvent *pEvent,WPARAM wParam, LPARAM lParam)
 +{
 +	HANDLE hContact = (HANDLE)wParam;
 +	HANDLE hdbevent = (HANDLE)lParam;
 +
 +
 +	// Create struct for dbevent
 +	DBEVENTINFO dbevent;
 +	ZeroMemory(&dbevent, sizeof(dbevent));
 +	//dbevent.flags |= PREF_UNICODE;
 +	dbevent.cbSize = sizeof(dbevent);
 +	dbevent.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hdbevent, 0);
 +	if(dbevent.cbBlob == -1)		// hdbevent is invalid
 +	{
 +		return false;
 +	}
 +	dbevent.pBlob = (PBYTE)malloc(dbevent.cbBlob);
 +	if(CallService(MS_DB_EVENT_GET, (WPARAM)hdbevent, (LPARAM)&dbevent) != 0)
 +	{
 +		free(dbevent.pBlob);
 +		return false;
 +	}
 +	
 +	pEvent->dwFlags = dbevent.flags;
 +	pEvent->hContact = hContact;
 +	pEvent->hValue = hdbevent;
 +
 +	time_t timestamp = (time_t)dbevent.timestamp;
 +	localtime_s(&pEvent->Time,×tamp);
 +	pEvent->bTime = true;
 +	/*
 +	if(dbevent.eventType == EVENTTYPE_MESSAGE && dbevent.flags & DBEF_READ) {
 +		free(dbevent.pBlob);
 +		return false;
 +	}
 +	*/
 +	// Skip events from the user except for messages
 +	if(dbevent.eventType != EVENTTYPE_MESSAGE && (dbevent.flags & DBEF_SENT))
 +	{
 +		free(dbevent.pBlob);
 +		return false;
 +	}
 +	
 +	int msglen = 0;
 +
 +	tstring strName = CAppletManager::GetContactDisplayname(hContact,true);
 +	
 +	switch(dbevent.eventType)
 +	{
 +	case EVENTTYPE_MESSAGE:
 +		msglen = strlen((char *) dbevent.pBlob) + 1;
 +#ifdef _UNICODE
 +		if (dbevent.flags & DBEF_UTF) {
 +			pEvent->strValue = Utf8_Decode((char*)dbevent.pBlob);
 +		} else if ((int) dbevent.cbBlob == msglen*3){
 +			pEvent->strValue =  (TCHAR *) & dbevent.pBlob[msglen];
 +		} else {
 +			pEvent->strValue = toTstring((char*)dbevent.pBlob);
 +		}
 +#else
 +		pEvent->strValue = toTstring((char*)dbevent.pBlob);
 +#endif
 +		pEvent->eType = (dbevent.flags & DBEF_SENT) ? EVENT_MSG_SENT:EVENT_MSG_RECEIVED;
 +		if(pEvent->eType == EVENT_MSG_RECEIVED)
 +		{	
 +			pEvent->dwFlags = MSG_UNREAD;
 +			if(CConfig::GetBoolSetting(NOTIFY_MESSAGES))
 +				pEvent->bNotification = true;
 +		}
 +
 +		pEvent->strDescription = strName + _T(": ") +pEvent->strValue;
 +		pEvent->strSummary = TranslateString(_T("New message from %s"),strName.c_str());
 +		break;
 +	case EVENTTYPE_URL:
 +		if(CConfig::GetBoolSetting(NOTIFY_URL))
 +			pEvent->bNotification = true;
 +
 +		pEvent->eType = EVENT_URL;
 +		pEvent->strDescription = TranslateString(_T("Incoming URL from %s"),strName.c_str());
 +		break;
 +	case EVENTTYPE_CONTACTS:
 +		if(CConfig::GetBoolSetting(NOTIFY_CONTACTS))
 +			pEvent->bNotification = true;
 +
 +		pEvent->strDescription = TranslateString(_T("Incoming contacts from %s"),strName.c_str());
 +		pEvent->eType = EVENT_CONTACTS;
 +		break;
 +	case EVENTTYPE_ADDED:
 +		if(CConfig::GetBoolSetting(NOTIFY_CONTACTS))
 +			pEvent->bNotification = true;
 +
 +		pEvent->strDescription = TranslateString(_T("You were added by %s"),strName.c_str());
 +		pEvent->eType = EVENT_ADDED;
 +		break;
 +	case EVENTTYPE_AUTHREQUEST:
 +		if(CConfig::GetBoolSetting(NOTIFY_CONTACTS))
 +			pEvent->bNotification = true;
 +
 +		pEvent->strDescription = TranslateString(_T("Incoming Authrequest!"));
 +		pEvent->eType = EVENT_AUTHREQUEST;
 +		break;
 +	case EVENTTYPE_FILE:
 +		if(CConfig::GetBoolSetting(NOTIFY_FILE))
 +			pEvent->bNotification = true;
 +
 +		pEvent->strDescription = TranslateString(_T("Incoming file from %s"),strName.c_str());
 +		pEvent->eType = EVENT_FILE;
 +		break;
 +	default:
 +		return false;
 +		break;
 +	}
 +
 +	if(CConfig::GetBoolSetting(NOTIFY_SHOWPROTO))
 +	{
 +		char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)pEvent->hContact, 0);
 +		pEvent->strDescription = _T("(")+toTstring(szProto)+_T(") ") + pEvent->strDescription;
 +	}
 +
 +	// Clean up
 +	free(dbevent.pBlob);
 +	return true;
 +}
 +
 +//************************************************************************
 +// removes IRC formatting tags from the string
 +//************************************************************************
 +tstring CAppletManager::StripIRCFormatting(tstring strText)
 +{
 +	tstring::size_type End=0,Start=0;
 +	tstring strEntity = _T("");
 +	tstring strReplace = _T("");
 +	tstring::size_type len = strText.length();
 +
 +	int i = 0;
 +	while(i < strText.length())
 +	{
 +		Start = strText.find(_T("%"),i);
 +		if(Start != string::npos && Start < strText.length() - 1)
 +		{
 +			strEntity = strText[Start+1];
 +			if(strEntity == _T("%"))
 +			{
 +				strText.replace(Start,2,_T("%"));
 +				i = Start +1;
 +			}
 +			/*
 +			else if(strEntity == _T("b") || strEntity == _T("B") || 
 +				strEntity == _T("i") || strEntity == _T("I") || 
 +				strEntity ==_T("u") || strEntity == _T("U") ||
 +				strEntity == _T("C") ||strEntity == _T("F"))
 +			{
 +				strText.erase(Start,2);
 +				i = Start;
 +			}
 +			*/
 +			else if(strEntity == _T("c") || strEntity == _T("f"))
 +			{
 +				strText.erase(Start,4);			
 +				i = Start;
 +			}
 +			else
 +			{
 +				strText.erase(Start,2);
 +				i = Start;
 +			}
 +		}
 +		else
 +			break;
 +	}
 +
 +	return strText;
 +}
 +
 +//************************************************************************
 +// returns the IRC connection class for the specified protocol
 +//************************************************************************
 +CIRCConnection *CAppletManager::GetIRCConnection(tstring strProtocol)
 +{
 +	vector<CIRCConnection*>::iterator iter = m_vIRCConnections.begin();
 +	while(iter != m_vIRCConnections.end())
 +	{
 +		if((*iter)->strProtocol == strProtocol)
 +			return *iter;
 +		iter++;
 +	}
 +	return NULL;
 +}
 +
 +//************************************************************************
 +// creates the IRC connection class for the specified protocol
 +//************************************************************************
 +CIRCConnection *CAppletManager::CreateIRCConnection(tstring strProtocol)
 +{
 +	char buffer[128];
 +	sprintf(buffer,"%s/HookableEvents",toNarrowString(strProtocol).c_str());
 +
 +	// try to hook the events
 +	HANDLE hEventHook = HookEvent(buffer,CAppletManager::HookChatInbound);
 +	// if the hook could not be established, the protocol is not an IRC instance
 +	if(!hEventHook)
 +		return NULL;
 +	
 +	TRACE(_T("Patched IRC-Connection found: %s\n"),strProtocol.c_str());
 +	CIRCConnection *pIRCCon = new CIRCConnection();
 +	pIRCCon->strProtocol = strProtocol;
 +	pIRCCon->hEventHook = hEventHook;
 +	pIRCCon->strNetwork = _T("");
 +	
 +	m_vIRCConnections.push_back(pIRCCon);
 +
 +	return pIRCCon;
 +}
 +
 +//************************************************************************
 +// returns the history class for the specified IRC channel
 +//************************************************************************
 +CIRCHistory *CAppletManager::GetIRCHistory(HANDLE hContact)
 +{
 +	list<CIRCHistory*>::iterator iter = m_LIRCHistorys.begin();
 +	while(iter != m_LIRCHistorys.end())
 +	{
 +		if((*iter)->hContact == hContact)
 +			return *iter;
 +		iter++;
 +	}
 +	return NULL;
 +}
 +
 +CIRCHistory *CAppletManager::GetIRCHistoryByName(tstring strProtocol,tstring strChannel)
 +{
 +	list<CIRCHistory*>::iterator iter = m_LIRCHistorys.begin();
 +	while(iter != m_LIRCHistorys.end())
 +	{
 +		if((*iter)->strChannel == strChannel && (*iter)->strProtocol == strProtocol)
 +			return *iter;
 +		iter++;
 +	}
 +	return NULL;
 +}
 +
 +//************************************************************************
 +// deletes the history class for the specified IRC channel
 +//************************************************************************
 +void CAppletManager::DeleteIRCHistory(HANDLE hContact)
 +{
 +	list<CIRCHistory*>::iterator iter = m_LIRCHistorys.begin();
 +	while(iter != m_LIRCHistorys.end())
 +	{
 +		if((*iter)->hContact == hContact)
 +		{
 +			CIRCHistory *pHistory = *iter;
 +			pHistory->LMessages.clear();
 +			pHistory->LUsers.clear();
 +
 +			m_LIRCHistorys.erase(iter);
 +			
 +			delete pHistory;
 +
 +			return;
 +		}
 +		iter++;
 +	}
 +}
 +
 +//************************************************************************
 +// creates a history class for the specified IRC channel
 +//************************************************************************
 +CIRCHistory *CAppletManager::CreateIRCHistory(HANDLE hContact,tstring strChannel)
 +{
 +	char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
 +	if(!szProto)
 +		return NULL;
 +
 +	CIRCHistory *pHistory = GetIRCHistoryByName(toTstring(szProto),strChannel);
 +	if(pHistory)
 +	{
 +		pHistory->hContact = hContact;
 +		return pHistory;
 +	}
 +
 +	pHistory = new CIRCHistory();
 +	pHistory->hContact = hContact;
 +	pHistory->strChannel = strChannel;
 +	pHistory->strProtocol = toTstring(szProto);
 +
 +	m_LIRCHistorys.push_back(pHistory);
 +	
 +	return pHistory;
 +}
 +
 +CIRCHistory *CAppletManager::CreateIRCHistoryByName(tstring strProtocol,tstring strChannel)
 +{
 +	CIRCHistory *pHistory = GetIRCHistoryByName(strProtocol,strChannel);
 +	if(pHistory)
 +		return pHistory;
 +
 +	pHistory = new CIRCHistory();
 +	pHistory->hContact = NULL;
 +	pHistory->strChannel = strChannel;
 +	pHistory->strProtocol = strProtocol;
 +
 +	m_LIRCHistorys.push_back(pHistory);
 +	
 +	return pHistory;
 +}
 +
 +//########################################################################
 +// hook functions
 +//########################################################################
 +
 +//************************************************************************
 +// inbound chat event hook function
 +//************************************************************************
 +int CAppletManager::HookChatInbound(WPARAM wParam,LPARAM lParam)
 +{
 +	GCEVENT *gce = (GCEVENT*)lParam;
 +	GCDEST *gcd = (GCDEST*)gce->pDest;
 +	
 +	if(gce == NULL || gcd == NULL)
 +		TRACE(_T("<< [%s] skipping invalid IRC event\n"));
 +
 +	TRACE(_T("<< [%s:%s] IRC event %04X\n"),toTstring(gcd->pszModule).c_str(),toTstring(gcd->pszID).c_str(),gcd->iType);
 +	
 +	// get the matching irc connection entry
 +	CIRCConnection *pIRCCon = CAppletManager::GetInstance()->GetIRCConnection(toTstring(gcd->pszModule));
 +	if(!pIRCCon)
 +	{
 +		TRACE(_T("<< [%s] IRC connection not found, skipping event\n"),toTstring(gcd->pszModule).c_str());
 +		return 0;
 +	}
 +
 +	// fetch the network name
 +	if(gcd->iType == GC_EVENT_CHANGESESSIONAME)
 +	{
 +		if(!_tcsicmp(gcd->ptszID,_T("Network log")))
 +		{
 +			pIRCCon->strNetwork = toTstring(gce->ptszText);
 +			TRACE(_T("\t Found network identifier: %s\n"),pIRCCon->strNetwork.c_str());
 +			return 0;
 +		}	
 +	}
 +	
 +	CEvent Event;
 +	if(gce->bIsMe)
 +		Event.eType = EVENT_IRC_SENT;
 +	else
 +		Event.eType = EVENT_IRC_RECEIVED;
 +	Event.iValue = gcd->iType;
 +	Event.hValue = (HANDLE)lParam;
 +	
 +	CIRCHistory *pHistory = NULL;
 +	if(gcd->ptszID)
 +	{
 +		tstring strChannel = toTstring(gcd->ptszID);
 +		tstring::size_type pos = strChannel.find('-');
 +		if(pos != tstring::npos)
 +			strChannel = strChannel.substr(0,pos-1);
 +		else
 +		{
 +			if(_tcsicmp(gcd->ptszID,_T("Network log")))
 +				TRACE(_T("\t WARNING: ignoring unknown event!\n"));
 +			return 0;
 +		}
 +		pHistory = CAppletManager::GetInstance()->GetIRCHistoryByName(pIRCCon->strProtocol,strChannel);
 +		if(!pHistory)
 +		{
 +			if(gcd->iType == GC_EVENT_JOIN)
 +			{
 +				pHistory = CAppletManager::GetInstance()->CreateIRCHistoryByName(pIRCCon->strProtocol,strChannel);
 +				if(pHistory)
 +					pHistory->LUsers.push_back(toTstring(gce->ptszNick));
 +			}
 +			return 0;
 +		}
 +		Event.hContact = pHistory->hContact;
 +	}
 +	else if(gcd->iType != GC_EVENT_INFORMATION)
 +	{
 +		TRACE(_T("\t WARNING: ignoring unknown event!\n"));
 +		return 0;
 +	}
 +	else
 +		Event.hContact = NULL;
 +	
 +	// Ignore events from hidden chatrooms, except for join events
 +	if(gcd->ptszID != NULL && DBGetContactSettingByte(Event.hContact,"CList","Hidden",0))
 +	{
 +		if(gcd->iType == GC_EVENT_JOIN && pHistory)
 +			pHistory->LUsers.push_back(toTstring(gce->ptszNick));
 +
 +		TRACE(_T("\t Chatroom is hidden, skipping event!\n"));
 +		return 0;
 +	}
 +	
 +	tstring strText = StripIRCFormatting(toTstring(gce->ptszText));
 +	tstring strNick = toTstring(gce->ptszNick);
 +	tstring strStatus = toTstring(gce->ptszStatus);
 +
 +	if(CConfig::GetBoolSetting(NOTIFY_NICKCUTOFF) && strNick.length() > CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET))
 +		strNick = strNick.erase(CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET)) + _T("...");
 +	
 +	TRACE(_T("\t Handling event...\t"));
 +
 +	switch(gcd->iType)
 +	{
 +	case GC_EVENT_INFORMATION:
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_CHANNEL))
 +			Event.bNotification = true;
 +		
 +		if(strText.find(_T("CTCP")) == 0)
 +			Event.strValue = _T("--> ") + strText;
 +		else
 +			Event.strValue = strText;
 +
 +		break;
 +	case GC_EVENT_ACTION:
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_EMOTES))
 +			Event.bNotification = true;
 +		Event.strValue = strNick + _T(" ") + strText;
 +		break;
 +	case GC_EVENT_MESSAGE:
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_MESSAGES))
 +			Event.bNotification = true;
 +		Event.strValue = strNick + _T(": ") + strText;
 +		break;
 +	case GC_EVENT_JOIN:
 +		// Add the user to the list
 +		pHistory->LUsers.push_back(toTstring(gce->ptszNick));
 +
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_USERS))
 +			Event.bNotification = true;
 +		// Skip join event for user
 +		if(gce->bIsMe)
 +			return 0;
 +		Event.strValue = TranslateString(_T("%s has joined the channel"),strNick.c_str());
 +		
 +		break;
 +	case GC_EVENT_PART:
 +		{
 +			if(CConfig::GetBoolSetting(NOTIFY_IRC_USERS))
 +				Event.bNotification = true;
 +			tstring strFullNick = toTstring(gce->ptszNick);
 +			Event.strValue = TranslateString(strText.empty()?_T("%s has left"):_T("%s has left: %s"),strNick.c_str(),strText.c_str());
 +			if(pHistory)
 +			{
 +				// Remove the user from the list
 +				list<tstring>::iterator iter = pHistory->LUsers.begin();
 +				while(iter != pHistory->LUsers.end())
 +				{
 +					if((*iter) == strFullNick)
 +					{
 +						pHistory->LUsers.erase(iter);
 +						break;
 +					}
 +					iter++;
 +				}	
 +			}
 +			break;
 +		}
 +	case GC_EVENT_QUIT:
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_USERS))
 +			Event.bNotification = true;
 +		Event.strValue = TranslateString(strText.empty()?_T("%s has disconnected"):_T("%s has disconnected: %s"),strNick.c_str(),strText.c_str());
 +		break;
 +	case GC_EVENT_KICK:
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_USERS))
 +			Event.bNotification = true;
 +		Event.strValue = TranslateString(_T("%s has kicked %s: %s"),strStatus.c_str(),strNick.c_str(),strText.c_str());
 +		break;
 +	case GC_EVENT_NICK:
 +		{
 +			if(CConfig::GetBoolSetting(NOTIFY_IRC_USERS))
 +				Event.bNotification = true;
 +			tstring strFullNick = toTstring(gce->ptszNick);
 +			
 +			if(CConfig::GetBoolSetting(NOTIFY_NICKCUTOFF) && strText.length() > CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET))
 +				strText = strText.erase(CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET)) + _T("...");
 +	
 +			Event.strValue =  TranslateString(_T("%s is now known as %s"),strNick.c_str(),strText.c_str());
 +			if(pHistory)
 +			{
 +				// change the nick in the userlist
 +				list<tstring>::iterator iter = pHistory->LUsers.begin();
 +				while(iter != pHistory->LUsers.end())
 +				{
 +					if((*iter) == strFullNick)
 +						(*iter) = strText;
 +					iter++;
 +				}
 +			}
 +			break;
 +		}
 +	case GC_EVENT_NOTICE:
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_NOTICES))
 +			Event.bNotification = true;
 +		Event.strValue = TranslateString(_T("Notice from %s: %s"),strNick.c_str(),strText.c_str());
 +		break;
 +	case GC_EVENT_TOPIC:
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_CHANNEL))
 +			Event.bNotification = true;
 +		Event.strValue = TranslateString(_T("Topic is now '%s' (set by %s)"),strText.c_str(),strNick.c_str());
 +		break;
 +	case GC_EVENT_ADDSTATUS:
 +	{
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_STATUS))
 +			Event.bNotification = true;
 +		tstring strNick2 = toTstring(gce->ptszStatus);
 +		if(CConfig::GetBoolSetting(NOTIFY_NICKCUTOFF) && strNick2.length() > CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET))
 +			strNick2 = strNick2.erase(CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET)) + _T("...");
 +
 +		Event.strValue = TranslateString(_T("%s enables '%s' for %s"),strText.c_str(),strNick2.c_str(),strNick.c_str());
 +		break;
 +	}
 +	case GC_EVENT_REMOVESTATUS:
 +	{
 +		if(CConfig::GetBoolSetting(NOTIFY_IRC_STATUS))
 +		Event.bNotification = true;
 +		tstring strNick2 = toTstring(gce->ptszStatus);
 +		if(CConfig::GetBoolSetting(NOTIFY_NICKCUTOFF) && strNick2.length() > CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET))
 +			strNick2 = strNick2.erase(CConfig::GetIntSetting(NOTIFY_NICKCUTOFF_OFFSET)) + _T("...");
 +
 +		Event.strValue = TranslateString(_T("%s disables '%s' for %s"),strText.c_str(),strNick2.c_str(),strNick.c_str());
 +		break;
 +	}
 +	default:
 +		TRACE(_T("OK!\n"));
 +		return 0;
 +	}
 +	if(gce->bIsMe || gcd->ptszID == NULL)
 +		Event.bNotification = false;
 +
 +	// set the event's timestamp
 +	Event.bTime = true;
 +	time_t now;
 +	time(&now);
 +	localtime_s(&Event.Time,&now);
 +	
 +	SIRCMessage IRCMsg;
 +	IRCMsg.bIsMe = gce->bIsMe;
 +	IRCMsg.strMessage = Event.strValue;
 +	IRCMsg.Time = Event.Time;
 +
 +	if(pHistory)
 +	{
 +		pHistory->LMessages.push_back(IRCMsg);
 +
 +		// Limit the size to the session logsize
 +		if(pHistory->LMessages.size() > CConfig::GetIntSetting(SESSION_LOGSIZE))
 +			pHistory->LMessages.pop_front();
 +	}
 +	else if(gce->ptszNick && gcd->iType == GC_EVENT_QUIT)
 +	{
 +		tstring strNick = toTstring(gce->ptszNick);
 +		
 +		if(!CAppletManager::GetInstance()->m_LIRCHistorys.empty())
 +		{
 +			list<CIRCHistory*>::iterator iter = CAppletManager::GetInstance()->m_LIRCHistorys.begin();
 +			list<tstring>::iterator nickiter;
 +			while(iter != CAppletManager::GetInstance()->m_LIRCHistorys.end())
 +			{
 +				nickiter = (*iter)->LUsers.begin();
 +				while(nickiter != (*iter)->LUsers.end())
 +				{
 +					if((*nickiter) == strNick)
 +					{
 +						(*iter)->LMessages.push_back(IRCMsg);
 +						// Limit the size to the session logsize
 +						if((*iter)->LMessages.size() > CConfig::GetIntSetting(SESSION_LOGSIZE))
 +							(*iter)->LMessages.pop_front();
 +
 +						(*iter)->LUsers.erase(nickiter);
 +						
 +						Event.hContact = (*iter)->hContact;
 +						tstring strName = CAppletManager::GetContactDisplayname((*iter)->hContact,true);
 +						Event.strDescription = strName + _T(" - ")+Event.strValue;
 +						Event.strSummary = _T("(") + toTstring(gcd->pszModule) + _T(") ")+strName;
 +						CAppletManager::GetInstance()->HandleEvent(&Event);
 +						break;
 +					}
 +					nickiter++;
 +				}
 +				iter++;
 +			}
 +		}
 +		TRACE(_T("OK!\n"));
 +		return 0;
 +	}
 +	else if(gcd->ptszID != NULL)
 +	{
 +		TRACE(_T("OK!\n"));
 +		return 0;
 +	}
 +
 +	if(pHistory)
 +	{
 +		tstring strChannel = pHistory->strChannel;
 +		if(CConfig::GetBoolSetting(NOTIFY_CHANNELCUTOFF) && strNick.length() > CConfig::GetIntSetting(NOTIFY_CHANNELCUTOFF_OFFSET)) {
 +			strChannel = strChannel.erase(CConfig::GetIntSetting(NOTIFY_CHANNELCUTOFF_OFFSET)) + _T("...");
 +		}
 +		Event.strDescription = strChannel + _T(" - ")+Event.strValue;
 +		Event.strSummary = _T("(") + toTstring(gcd->pszModule) + _T(") ")+pHistory->strChannel;
 +	}
 +	else
 +		Event.strDescription = Event.strValue;
 +
 +	TRACE(_T("OK!\n"));
 +	
 +	CAppletManager::GetInstance()->HandleEvent(&Event);
 +
 +	return 0;
 +}
 +
 +//************************************************************************
 +// message window event hook function
 +//************************************************************************
 +int CAppletManager::HookMessageWindowEvent(WPARAM wParam, LPARAM lParam)
 +{
 +	MessageWindowEventData *mwed = (MessageWindowEventData*)lParam;
 +	CEvent Event;
 +
 +	Event.eType = EVENT_MESSAGEWINDOW;
 +	Event.hContact = mwed->hContact;
 +	Event.iValue = mwed->uType;
 +
 +	CAppletManager::GetInstance()->HandleEvent(&Event);
 +
 +	return 0;
 +}
 +
 +
 +//************************************************************************
 +// contact typing notification hook function
 +//************************************************************************
 +int CAppletManager::HookContactIsTyping(WPARAM wParam, LPARAM lParam)
 +{
 +	HANDLE hContact = (HANDLE)wParam;
 +	int iState = (int)lParam;
 +
 +	CEvent Event;
 +
 +	Event.eType = EVENT_TYPING_NOTIFICATION;
 +	Event.hContact = hContact;
 +	Event.iValue = iState;
 +
 +	CAppletManager::GetInstance()->HandleEvent(&Event);
 +	return 0;
 +}
 +
 +//************************************************************************
 +// new event hook function
 +//************************************************************************
 +int CAppletManager::HookEventAdded(WPARAM wParam, LPARAM lParam)
 +{
 +	CEvent Event;
 +
 +	if(CAppletManager::TranslateDBEvent(&Event,wParam,lParam))
 +		CAppletManager::GetInstance()->HandleEvent(&Event);
 +
 +	return 0;
 +} 
 +
 +//************************************************************************
 +// contact status change hook function
 +//************************************************************************
 +int CAppletManager::HookStatusChanged(WPARAM wParam, LPARAM lParam)
 +{
 +	DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
 +
 +	if ((wParam == 0) || (strcmp(cws->szSetting,"Status") != NULL))
 +		return 0;
 +
 +
 +	// Prepare message and append to queue
 +	CEvent Event;
 +	Event.hContact = (HANDLE)wParam;
 +	int iStatus = cws->value.wVal;
 +	Event.iValue = iStatus;
 +
 +	int iOldStatus = CAppletManager::GetInstance()->m_ContactlistScreen.GetContactStatus(Event.hContact);
 +
 +	char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)Event.hContact, 0);
 +	tstring strProto = toTstring(szProto);
 +
 +	CProtocolData *pProtocolData = CAppletManager::GetInstance()->GetProtocolData(toTstring(szProto));
 +	if(pProtocolData == NULL)
 +		return false;
 +	
 +	// Fetch the contacts name
 +	tstring strName = CAppletManager::GetContactDisplayname(Event.hContact,true);
 +	
 +	// Get status String
 +	Event.strValue = toTstring((char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, 0));
 +	
 +	// check if this is an irc protocol
 +	CIRCConnection *pIRCCon = CAppletManager::GetInstance()->GetIRCConnection(strProto);
 +
 +	// Contact signed on
 +	if(iOldStatus == ID_STATUS_OFFLINE && iStatus != ID_STATUS_OFFLINE)
 +	{
 +		if(CConfig::GetBoolSetting(NOTIFY_SIGNOFF))
 +			Event.bNotification = true;
 +
 +		Event.eType = EVENT_SIGNED_ON;
 +		if(pIRCCon && DBGetContactSettingByte(Event.hContact, szProto, "ChatRoom", 0) != 0)
 +		{
 +			Event.strDescription = TranslateString(_T("Joined %s"),strName.c_str());
 +			
 +			DBVARIANT dbv;
 +			if (DBGetContactSettingTString(Event.hContact, szProto, "Nick", &dbv)) 
 +				return 0;
 +			CAppletManager::GetInstance()->CreateIRCHistory(Event.hContact,dbv.ptszVal);
 +			DBFreeVariant(&dbv);
 +		}
 +		else
 +			Event.strDescription = TranslateString(_T("%s signed on (%s)"),strName.c_str(),Event.strValue.c_str());
 +	}
 +	// Contact signed off
 +	else if(iStatus == ID_STATUS_OFFLINE && iOldStatus != ID_STATUS_OFFLINE)
 +	{
 +		if(CConfig::GetBoolSetting(NOTIFY_SIGNON))
 +			Event.bNotification = true;
 +
 +		Event.eType = EVENT_SIGNED_OFF;
 +		if(pIRCCon &&  DBGetContactSettingByte(Event.hContact, szProto, "ChatRoom", 0) != 0)
 +		{
 +			Event.strDescription = TranslateString(_T("Left %s"),strName.c_str());
 +			// delete IRC-Channel history
 +			CAppletManager::GetInstance()->DeleteIRCHistory(Event.hContact);
 +		}
 +		else
 +			Event.strDescription = TranslateString(_T("%s signed off"),strName.c_str());
 +	}
 +	// Contact changed status
 +	else if(iStatus != iOldStatus)
 +	{	
 +		if(CConfig::GetBoolSetting(NOTIFY_STATUS))
 +			Event.bNotification = true;
 +
 +		Event.eType = EVENT_STATUS;
 +		Event.strDescription = TranslateString(_T("%s is now %s"),strName.c_str(),Event.strValue.c_str());
 +	}
 +	// ignore remaining events
 +	else
 +		return 0;
 +
 +	if(CConfig::GetBoolSetting(NOTIFY_SHOWPROTO))
 +		Event.strDescription = _T("(")+strProto+_T(") ") + Event.strDescription;
 +
 +	
 +
 +	Event.strSummary = TranslateString(_T("Contactlist event"));
 +
 +	// Block notifications after connecting/disconnecting
 +	if(pProtocolData->iStatus == ID_STATUS_OFFLINE ||
 +		pProtocolData->lTimeStamp + PROTOCOL_NOTIFY_DELAY > GetTickCount())
 +		Event.bNotification = false;
 +
 +	//CAppletManager::GetInstance()->ActivateNotificationScreen(&Event);
 +	CAppletManager::GetInstance()->HandleEvent(&Event);
 +
 +	return 0;
 +}
 +
 +//************************************************************************
 +// protocoll ack hook function
 +//************************************************************************
 +int CAppletManager::HookProtoAck(WPARAM wParam, LPARAM lParam)
 +{
 +	ACKDATA *pAck = (ACKDATA *) lParam;
 +  
 +    if(lParam == 0)
 +		return 0;
 +	
 +	// Prepare message and append to queue
 +	CEvent Event;
 +
 +	// Message job handling
 +	if(pAck->type == ACKTYPE_MESSAGE)
 +	{
 +		list<SMessageJob*>::iterator iter = CAppletManager::GetInstance()->m_MessageJobs.begin();
 +		while(iter != CAppletManager::GetInstance()->m_MessageJobs.end())
 +		{
 +			if((*iter)->hEvent == pAck->hProcess && (*iter)->hContact == pAck->hContact)
 +			{
 +				Event.eType = EVENT_MESSAGE_ACK;
 +				Event.hValue = pAck->hProcess;
 +				Event.hContact = pAck->hContact;
 +				Event.iValue = pAck->result;
 +				if(pAck->lParam != 0)
 +					Event.strValue = toTstring((char*)pAck->lParam);
 +				else 
 +					Event.strValue = _T("");
 +
 +				if(Event.iValue == ACKRESULT_SUCCESS)
 +					CAppletManager::GetInstance()->FinishMessageJob((*iter));
 +				else
 +					CAppletManager::GetInstance()->CancelMessageJob((*iter));
 +
 +				CAppletManager::GetInstance()->HandleEvent(&Event);
 +
 +				return 0;
 +			}
 +			iter++;
 +		}
 +	}
 +	// protocol status changes
 +	else if(pAck->type == ACKTYPE_STATUS && pAck->result == ACKRESULT_SUCCESS)
 +	{
 +		int iOldStatus = (int)pAck->hProcess;
 +		int iNewStatus = pAck->lParam;
 +		
 +		tstring strProto = toTstring(pAck->szModule);
 +		
 +		// ignore metacontacts status changes
 +		if(toLower(strProto) == _T("metacontacts"))
 +			return 0;
 +
 +		CProtocolData *pProtoData = CAppletManager::GetInstance()->GetProtocolData(strProto);
 +		if(pProtoData == NULL)
 +			return 0;
 +
 +		if(iNewStatus == ID_STATUS_CONNECTING)
 +			return 0;
 +
 +		if(iNewStatus == ID_STATUS_OFFLINE)
 +		{
 +			if(CConfig::GetBoolSetting(NOTIFY_PROTO_SIGNOFF))
 +				Event.bNotification = true;
 +			Event.eType = EVENT_PROTO_DISCONNECTED;
 +		}
 +		else if(iNewStatus != ID_STATUS_OFFLINE && iOldStatus == ID_STATUS_CONNECTING)
 +		{
 +			if(CConfig::GetBoolSetting(NOTIFY_PROTO_SIGNON))
 +				Event.bNotification = true;
 +			Event.eType = EVENT_PROTO_CONNECTED;
 +		}
 +		else
 +		{
 +			if(CConfig::GetBoolSetting(NOTIFY_PROTO_STATUS))
 +				Event.bNotification = true;
 +			Event.eType = EVENT_PROTO_STATUS;
 +		}
 +
 +		// Skip connecting status
 +		if(iNewStatus == ID_STATUS_CONNECTING)
 +			return 0;
 +
 +		pProtoData->iStatus = iNewStatus;
 +
 +		Event.iValue = iNewStatus;
 +		Event.strValue = strProto;
 +
 +		// set the event description / summary
 +		tstring strStatus = toTstring((char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iNewStatus, 0));
 +		Event.strDescription = _T("(") + Event.strValue + _T(") ")+ TranslateString(_T("You are now %s"),strStatus.c_str());
 +		Event.strSummary = TranslateString(_T("Protocol status change"));
 +
 +		if(Event.eType != EVENT_PROTO_STATUS)
 +			pProtoData->lTimeStamp = GetTickCount();
 +
 +		CAppletManager::GetInstance()->HandleEvent(&Event);
 +		//CAppletManager::GetInstance()->ActivateNotificationScreen(&Event);
 +	}
 +
 +	return 0;
 +}
 +
 +//************************************************************************
 +// contact added hook function
 +//************************************************************************
 +int CAppletManager::HookContactAdded(WPARAM wParam, LPARAM lParam)
 +{
 +	CEvent Event;
 +	Event.eType = EVENT_CONTACT_ADDED;
 +	Event.hContact = (HANDLE)wParam;
 +
 +	CAppletManager::GetInstance()->HandleEvent(&Event);
 +	return 0;
 +}
 +
 +//************************************************************************
 +// contact deleted hook function
 +//************************************************************************
 +int CAppletManager::HookContactDeleted(WPARAM wParam, LPARAM lParam)
 +{
 +	CEvent Event;
 +	Event.eType = EVENT_CONTACT_DELETED;
 +	Event.hContact = (HANDLE)wParam;
 +	Event.bNotification = CConfig::GetBoolSetting(NOTIFY_CONTACTS);
 +	Event.bLog = Event.bNotification;
 +
 +	tstring strName = CAppletManager::GetContactDisplayname(Event.hContact,true);
 +	
 +	Event.strDescription = TranslateString(_T("%s was deleted from contactlist!"),strName.c_str());
 +
 +	CAppletManager::GetInstance()->HandleEvent(&Event);
 +	return 0;
 +}
 +
 +//************************************************************************
 +// setting changed hook function
 +//************************************************************************
 +int CAppletManager::HookSettingChanged(WPARAM wParam,LPARAM lParam)
 +{
 +	DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING*)lParam;
 +	
 +	CEvent Event;
 +	Event.hContact = (HANDLE)wParam;
 +
 +	if(!lstrcmpA(dbcws->szModule,"MetaContacts"))
 +	{
 +		//if(!lstrcmpA(dbcws->szSetting,"Enabled")) {
 +		//	CAppletManager::GetInstance()->OnConfigChanged();
 +		//	return 0;
 +		//} else
 +		if(!lstrcmpA(dbcws->szSetting,"IsSubcontact")) {
 +			Event.eType = EVENT_CONTACT_GROUP;
 +			DBVARIANT dbv;
 +			int res = DBGetContactSettingTString((HANDLE)wParam, "CList", "Group",	&dbv);
 +			if(!res)
 +					Event.strValue = dbv.ptszVal;
 +			DBFreeVariant(&dbv);
 +		} else {
 +			return 0;
 +		}
 +	}
 +	else if(!lstrcmpA(dbcws->szSetting,"Nick") || !lstrcmpA(dbcws->szSetting,"MyHandle"))
 +	{
 +		DBVARIANT dbv={0};
 +		// if the protocol nick has changed, check if a custom handle is set
 +		if(!lstrcmpA(dbcws->szSetting,"Nick"))
 +		{
 +			if (!DBGetContactSettingTString(Event.hContact, "CList", "MyHandle", &dbv)) 
 +			{
 +				// handle found, ignore this event
 +				if(dbv.pszVal && strlen(dbv.pszVal)>0)
 +					return 0;
 +			}
 +			DBFreeVariant(&dbv);
 +		}
 +
 +		Event.eType = EVENT_CONTACT_NICK;
 +		if(dbcws->value.type != DBVT_DELETED && dbcws->value.pszVal && strlen(dbcws->value.pszVal)>0)
 +		{
 +#ifdef _UNICODE
 +			if(dbcws->value.type == DBVT_UTF8)
 +				Event.strValue = Utf8_Decode(dbcws->value.pszVal);
 +			else
 +#endif
 +				Event.strValue = toTstring(dbcws->value.pszVal);
 +		}
 +		else
 +		{
 +			char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)Event.hContact, 0);
 +			if (DBGetContactSettingTString(Event.hContact, szProto, "Nick", &dbv)) 
 +				return 0;
 +			Event.strValue = dbv.ptszVal;
 +			DBFreeVariant(&dbv);
 +		}
 +	}
 +	else if(!lstrcmpA(dbcws->szModule,"CList"))
 +	{
 +		if(!lstrcmpA(dbcws->szSetting,"Hidden"))
 +		{
 +			Event.eType = EVENT_CONTACT_HIDDEN;
 +			Event.iValue = DBGetContactSettingByte((HANDLE)wParam,"CList","Hidden",0);
 +		}
 +		else if(!lstrcmpA(dbcws->szSetting,"Group"))
 +		{
 +			Event.eType = EVENT_CONTACT_GROUP;
 +			DBVARIANT dbv;
 +			int res = DBGetContactSettingTString((HANDLE)wParam, "CList", "Group",	&dbv);
 +			if(!res)
 +					Event.strValue = dbv.ptszVal;
 +			DBFreeVariant(&dbv);
 +		}
 +		else
 +			return 0;
 +	}
 +	else
 +		return 0;
 +	CAppletManager::GetInstance()->HandleEvent(&Event);
 +	return 0;
 +}
\ No newline at end of file | 
