diff options
Diffstat (limited to 'plugins/TabSRMM/src/globals.cpp')
| -rw-r--r-- | plugins/TabSRMM/src/globals.cpp | 967 | 
1 files changed, 967 insertions, 0 deletions
diff --git a/plugins/TabSRMM/src/globals.cpp b/plugins/TabSRMM/src/globals.cpp new file mode 100644 index 0000000000..689b4cb53b --- /dev/null +++ b/plugins/TabSRMM/src/globals.cpp @@ -0,0 +1,967 @@ +/*
 + * 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-2010 by silvercircle _at_ gmail _dot_ com and contributors
 + *
 + * $Id: globals.cpp 13447 2011-03-14 19:55:07Z george.hazan $
 + *
 + * Plugin configuration variables and functions. Implemented as a class
 + * though there will always be only a single instance.
 + *
 + */
 +
 +#include "commonheaders.h"
 +extern PLUGININFOEX pluginInfo;
 +
 +CGlobals 	PluginConfig;
 +CGlobals*	pConfig = &PluginConfig;
 +
 +static TContainerSettings _cnt_default = {
 +		false,
 +		CNT_FLAGS_DEFAULT,
 +		CNT_FLAGSEX_DEFAULT,
 +		255,
 +		CInfoPanel::DEGRADE_THRESHOLD,
 +		60,
 +		_T("%n (%s)"),
 +		1,
 +		0
 +};
 +
 +HANDLE		CGlobals::m_event_ModulesLoaded = 0, CGlobals::m_event_PrebuildMenu = 0, CGlobals::m_event_SettingChanged = 0;
 +HANDLE		CGlobals::m_event_ContactDeleted = 0, CGlobals::m_event_Dispatch = 0, CGlobals::m_event_EventAdded = 0;
 +HANDLE		CGlobals::m_event_IconsChanged = 0, CGlobals::m_event_TypingEvent = 0, CGlobals::m_event_ProtoAck = 0;
 +HANDLE		CGlobals::m_event_PreShutdown = 0, CGlobals::m_event_OkToExit = 0;
 +HANDLE		CGlobals::m_event_IcoLibChanged = 0, CGlobals::m_event_AvatarChanged = 0, CGlobals::m_event_MyAvatarChanged = 0, CGlobals::m_event_FontsChanged = 0;
 +HANDLE		CGlobals::m_event_SmileyAdd = 0, CGlobals::m_event_IEView = 0, CGlobals::m_event_FoldersChanged = 0;
 +HANDLE 		CGlobals::m_event_ME_MC_SUBCONTACTSCHANGED = 0, CGlobals::m_event_ME_MC_FORCESEND = 0, CGlobals::m_event_ME_MC_UNFORCESEND = 0;
 +TCHAR*		CGlobals::m_default_container_name = _T("default");
 +
 +extern 		HANDLE 	hHookButtonPressedEvt;
 +extern		HANDLE 	hHookToolBarLoadedEvt;
 +
 +EXCEPTION_RECORD CGlobals::m_exRecord = {0};
 +CONTEXT		 	 CGlobals::m_exCtx = {0};
 +LRESULT			 CGlobals::m_exLastResult = 0;
 +char			 CGlobals::m_exSzFile[MAX_PATH] = "\0";
 +wchar_t			 CGlobals::m_exReason[256] = L"\0";
 +int				 CGlobals::m_exLine = 0;
 +bool			 CGlobals::m_exAllowContinue = false;
 +
 +#if defined(_WIN64)
 +	static char szCurrentVersion[30];
 +	static char *szVersionUrl = "http://download.miranda.or.at/tabsrmm/3/version.txt";
 +	static char *szUpdateUrl = "http://silvercircle.googlecode.com/files/tabsrmm-3_x64.zip";
 +	static char *szFLVersionUrl = "http://addons.miranda-im.org/details.php?action=viewfile&id=3699";
 +	static char *szFLUpdateurl = "http://addons.miranda-im.org/feed.php?dlfile=3699";
 +#else
 +	static char szCurrentVersion[30];
 +	static char *szVersionUrl = "http://download.miranda.or.at/tabsrmm/3/version.txt";
 +	static char *szUpdateUrl = "http://silvercircle.googlecode.com/files/tabsrmm-3_x86.zip";
 +	static char *szFLVersionUrl = ADDONS_UPDATE_URL;
 +	static char *szFLUpdateurl =  ADDONS_DL_URL;
 +#endif
 +	static char *szPrefix = "tabsrmm ";
 +
 +
 +CRTException::CRTException(const char *szMsg, const TCHAR *szParam) : std::runtime_error(std::string(szMsg))
 +{
 +	mir_sntprintf(m_szParam, MAX_PATH, szParam);
 +}
 +
 +void CRTException::display() const
 +{
 +	TCHAR*	tszMsg = mir_a2t(what());
 +	TCHAR  	tszBoxMsg[500];
 +
 +	mir_sntprintf(tszBoxMsg, 500, _T("%s\n\n(%s)"), tszMsg, m_szParam);
 +	::MessageBox(0, tszBoxMsg, _T("TabSRMM runtime error"), MB_OK | MB_ICONERROR);
 +	mir_free(tszMsg);
 +}
 +
 +void CGlobals::RegisterWithUpdater()
 +{
 +	Update 		upd = {0};
 +
 + 	if (!ServiceExists(MS_UPDATE_REGISTER))
 + 		return;
 +
 + 	upd.cbSize 				=	sizeof(upd);
 + 	upd.szComponentName 	=	pluginInfo.shortName;
 + 	upd.pbVersion 			=	(BYTE *)CreateVersionString(pluginInfo.version, szCurrentVersion);
 + 	upd.cpbVersion 			=	(int)(strlen((char *)upd.pbVersion));
 +	upd.szVersionURL 		=	szFLVersionUrl;
 +	upd.szUpdateURL 		=	szFLUpdateurl;
 +	upd.pbVersionPrefix 	= 	(BYTE *)"<span class=\"fileNameHeader\">tabSRMM Unicode 2.0 ";
 +	upd.cpbVersionPrefix 	= 	(int)(strlen((char *)upd.pbVersionPrefix));
 +
 + 	upd.szBetaUpdateURL 	=	szUpdateUrl;
 + 	upd.szBetaVersionURL 	=	szVersionUrl;
 +	upd.pbVersion 			=	(unsigned char *)szCurrentVersion;
 +	upd.cpbVersion 			= 	lstrlenA(szCurrentVersion);
 + 	upd.pbBetaVersionPrefix	= 	(BYTE *)szPrefix;
 + 	upd.cpbBetaVersionPrefix= 	(int)(strlen((char *)upd.pbBetaVersionPrefix));
 + 	upd.szBetaChangelogURL  =	"http://blog.miranda.or.at/tabsrmm-articles/tabsrmm-version-3-changelog";
 +
 + 	CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
 +}
 +/**
 + * reload system values. These are read ONCE and are not allowed to change
 + * without a restart
 + */
 +void CGlobals::reloadSystemStartup()
 +{
 +	HDC			hScrnDC;
 +	DBVARIANT 	dbv = {0};
 +
 +	m_WinVerMajor = 					WinVerMajor();
 +	m_WinVerMinor = 					WinVerMinor();
 +	m_bIsXP = 							IsWinVerXPPlus();
 +	m_bIsVista = 						IsWinVerVistaPlus();
 +	m_bIsWin7 = 						IsWinVer7Plus();
 +
 +	::LoadTSButtonModule();
 +	::RegisterTabCtrlClass();
 +	CTip::registerClass();
 +
 +	dwThreadID = 						GetCurrentThreadId();
 +
 +	PluginConfig.g_hMenuContext = 		LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_TABCONTEXT));
 +	CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)g_hMenuContext, 0);
 +
 +	SkinAddNewSoundEx("RecvMsgActive", "Instant messages", "Incoming (Focused Window)");
 +	SkinAddNewSoundEx("RecvMsgInactive", "Instant messages", "Incoming (Unfocused Window)");
 +	SkinAddNewSoundEx("AlertMsg", "Instant messages", "Incoming (New Session)");
 +	SkinAddNewSoundEx("SendMsg", "Instant messages", "Outgoing");
 +	SkinAddNewSoundEx("SendError", "Instant messages", "Message send error");
 +
 +	hCurSplitNS = LoadCursor(NULL, IDC_SIZENS);
 +	hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE);
 +	hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND);
 +	if (hCurHyperlinkHand == NULL)
 +		hCurHyperlinkHand = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_HYPERLINKHAND));
 +
 +	hScrnDC = GetDC(0);
 +	g_DPIscaleX = 						GetDeviceCaps(hScrnDC, LOGPIXELSX) / 96.0;
 +	g_DPIscaleY = 						GetDeviceCaps(hScrnDC, LOGPIXELSY) / 96.0;
 +	ReleaseDC(0, hScrnDC);
 +
 +	reloadSettings(false);
 +	reloadAdv();
 +	hookSystemEvents();
 +}
 +
 +/**
 + * this runs ONCE at startup when the Modules Loaded event is fired
 + * by the core. all plugins are loaded and ready to use.
 + * 
 + * any initialation for 3rd party plugins must go here.
 + */
 +void CGlobals::reloadSystemModulesChanged()
 +{
 +	BOOL				bIEView = FALSE;
 +	CLISTMENUITEM 		mi = { 0 };
 +
 +	m_MathModAvail = 					ServiceExists(MATH_RTF_REPLACE_FORMULAE);
 +
 +	/*
 +	 * smiley add
 +	 */
 +	if (ServiceExists(MS_SMILEYADD_REPLACESMILEYS)) {
 +		PluginConfig.g_SmileyAddAvail = 1;
 +		m_event_SmileyAdd = HookEvent(ME_SMILEYADD_OPTIONSCHANGED, ::SmileyAddOptionsChanged);
 +	}
 +	else
 +		m_event_SmileyAdd = 0;
 +
 +	/*
 +	 * Flashavatars
 +	 */
 +
 +	g_FlashAvatarAvail = (ServiceExists(MS_FAVATAR_GETINFO) ? 1 : 0);
 +
 +	/*
 +	 * ieView
 +	 */
 +
 +	bIEView = ServiceExists(MS_IEVIEW_WINDOW);
 +	if (bIEView) {
 +		BOOL bOldIEView = M->GetByte("ieview_installed", 0);
 +		if (bOldIEView != bIEView)
 +			M->WriteByte(SRMSGMOD_T, "default_ieview", 1);
 +		M->WriteByte(SRMSGMOD_T, "ieview_installed", 1);
 +		m_event_IEView = HookEvent(ME_IEVIEW_OPTIONSCHANGED, ::IEViewOptionsChanged);
 +	} else {
 +		M->WriteByte(SRMSGMOD_T, "ieview_installed", 0);
 +		m_event_IEView = 0;
 +	}
 +
 +	g_iButtonsBarGap = 							M->GetByte("ButtonsBarGap", 1);
 +	m_hwndClist = 								(HWND)CallService(MS_CLUI_GETHWND, 0, 0);
 +	m_MathModAvail = 							(ServiceExists(MATH_RTF_REPLACE_FORMULAE) ? 1 : 0);
 +	if (m_MathModAvail) {
 +		char *szDelim = (char *)CallService(MATH_GET_STARTDELIMITER, 0, 0);
 +		if (szDelim) {
 +			MultiByteToWideChar(CP_ACP, 0, szDelim, -1, PluginConfig.m_MathModStartDelimiter, safe_sizeof(PluginConfig.m_MathModStartDelimiter));
 +			CallService(MTH_FREE_MATH_BUFFER, 0, (LPARAM)szDelim);
 +		}
 +	}
 +	else
 +		PluginConfig.m_MathModStartDelimiter[0] = 0;
 +
 +	g_MetaContactsAvail = (ServiceExists(MS_MC_GETDEFAULTCONTACT) ? 1 : 0);
 +
 +
 +	if(g_MetaContactsAvail) {
 +		mir_snprintf(szMetaName, 256, "%s", (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0));
 +		bMetaEnabled = abs(M->GetByte(0, szMetaName, "Enabled", -1));
 +	}
 +	else {
 +		szMetaName[0] = 0;
 +		bMetaEnabled = 0;
 +	}
 +
 +	g_PopupAvail = (ServiceExists(MS_POPUP_ADDPOPUPEX) ? 1 : 0);
 +	g_PopupWAvail = (ServiceExists(MS_POPUP_ADDPOPUPW) ? 1 : 0);
 +
 +	mi.cbSize = sizeof(mi);
 +	mi.position = -2000090000;
 +	if (ServiceExists(MS_SKIN2_GETICONBYHANDLE)) {
 +		mi.flags = CMIF_ICONFROMICOLIB | CMIF_DEFAULT;
 +		mi.icolibItem = LoadSkinnedIconHandle(SKINICON_EVENT_MESSAGE);
 +	} else {
 +		mi.flags = CMIF_DEFAULT;
 +		mi.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
 +	}
 +	mi.pszName = LPGEN("&Message");
 +	mi.pszService = MS_MSG_SENDMESSAGE;
 +	PluginConfig.m_hMenuItem = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
 +
 +	m_useAeroPeek = M->GetByte("useAeroPeek", 1);
 +}
 +
 +/**
 + * reload plugin settings on startup and runtime. Most of these setttings can be
 + * changed while plugin is running.
 + */
 +void CGlobals::reloadSettings(bool fReloadSkins)
 +{
 +	m_ncm.cbSize = sizeof(NONCLIENTMETRICS);
 +	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &m_ncm, 0);
 +
 +	DWORD dwFlags = 					M->GetDword("mwflags", MWF_LOG_DEFAULT);
 +
 +	m_SendOnShiftEnter = 				(int)M->GetByte("sendonshiftenter", 0);
 +	m_SendOnEnter = 					(int)M->GetByte(SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER);
 +	m_SendOnDblEnter = 					(int)M->GetByte("SendOnDblEnter", 0);
 +	m_AutoLocaleSupport = 				(int)M->GetByte("al", 0);
 +	m_AutoSwitchTabs = 					(int)M->GetByte("autoswitchtabs", 1);
 +	m_CutContactNameTo = 				(int) DBGetContactSettingWord(NULL, SRMSGMOD_T, "cut_at", 15);
 +	m_CutContactNameOnTabs = 			(int)M->GetByte("cuttitle", 0);
 +	m_StatusOnTabs = 					(int)M->GetByte("tabstatus", 1);
 +	m_LogStatusChanges = 				(int)dwFlags & MWF_LOG_STATUSCHANGES;
 +	m_UseDividers = 					(int)M->GetByte("usedividers", 0);
 +	m_DividersUsePopupConfig = 			(int)M->GetByte("div_popupconfig", 0);
 +	m_MsgTimeout = 						(int)M->GetDword(SRMSGMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT);
 +
 +	if (m_MsgTimeout < SRMSGSET_MSGTIMEOUT_MIN)
 +		m_MsgTimeout = SRMSGSET_MSGTIMEOUT_MIN;
 +
 +	m_EscapeCloses = 					(int)M->GetByte("escmode", 0);
 +
 +	m_HideOnClose =						(int) M->GetByte("hideonclose", 0);
 +	m_AllowTab =						(int) M->GetByte("tabmode", 0);
 +
 +	m_FlashOnClist = 					(int)M->GetByte("flashcl", 0);
 +	m_AlwaysFullToolbarWidth = 			(int)M->GetByte("alwaysfulltoolbar", 1);
 +	m_LimitStaticAvatarHeight = 		(int)M->GetDword("avatarheight", 96);
 +	m_SendFormat = 						(int)M->GetByte("sendformat", 0);
 +	m_FormatWholeWordsOnly = 1;
 +	m_RTLDefault = 						(int)M->GetByte("rtldefault", 0);
 +	m_TabAppearance = 					(int)M->GetDword("tabconfig", TCF_FLASHICON | TCF_SINGLEROWTABCONTROL);
 +	m_panelHeight = 					(DWORD)M->GetDword("panelheight", CInfoPanel::DEGRADE_THRESHOLD);
 +	m_MUCpanelHeight = 					M->GetDword("Chat", "panelheight", CInfoPanel::DEGRADE_THRESHOLD);
 +	m_IdleDetect = 						(int)M->GetByte("dimIconsForIdleContacts", 1);
 +	m_smcxicon = 16;
 +	m_smcyicon = 16;
 +	m_PasteAndSend = 					(int)M->GetByte("pasteandsend", 1);
 +	m_szNoStatus = 						const_cast<TCHAR *>(CTranslator::get(CTranslator::GEN_NO_STATUS));
 +	m_LangPackCP = 						ServiceExists(MS_LANGPACK_GETCODEPAGE) ? CallService(MS_LANGPACK_GETCODEPAGE, 0, 0) : CP_ACP;
 +	m_visualMessageSizeIndicator = 		M->GetByte("msgsizebar", 0);
 +	m_autoSplit = 						M->GetByte("autosplit", 0);
 +	m_FlashOnMTN = 						M->GetByte(SRMSGMOD, SRMSGSET_SHOWTYPINGWINFLASH, SRMSGDEFSET_SHOWTYPINGWINFLASH);
 +	if(m_MenuBar == 0) {
 +		m_MenuBar = ::LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENUBAR));
 +		CallService(MS_LANGPACK_TRANSLATEMENU, WPARAM(m_MenuBar), 0);
 +	}
 +
 +	m_ipBackgroundGradient = 			M->GetDword(FONTMODULE, "ipfieldsbg", 0x62caff);
 +	if(0 == m_ipBackgroundGradient)
 +		m_ipBackgroundGradient = 0x62caff;
 +
 +	m_ipBackgroundGradientHigh = 		M->GetDword(FONTMODULE, "ipfieldsbgHigh", 0xf0f0f0);
 +	if(0 == m_ipBackgroundGradientHigh)
 +		m_ipBackgroundGradientHigh = 0xf0f0f0;
 +
 +	m_tbBackgroundHigh = 				M->GetDword(FONTMODULE, "tbBgHigh", 0);
 +	m_tbBackgroundLow = 				M->GetDword(FONTMODULE, "tbBgLow", 0);
 +	m_fillColor =						M->GetDword(FONTMODULE, "fillColor", 0);
 +	if(CSkin::m_BrushFill) {
 +		::DeleteObject(CSkin::m_BrushFill);
 +		CSkin::m_BrushFill = 0;
 +	}
 +	m_genericTxtColor = 				M->GetDword(FONTMODULE, "genericTxtClr", GetSysColor(COLOR_BTNTEXT));
 +	m_cRichBorders =					M->GetDword(FONTMODULE, "cRichBorders", 0);
 +
 +	::CopyMemory(&globalContainerSettings, &_cnt_default, sizeof(TContainerSettings));
 +	Utils::ReadContainerSettingsFromDB(0, &globalContainerSettings);
 +	globalContainerSettings.fPrivate = false;
 +	if(fReloadSkins)
 +		Skin->setupAeroSkins();
 +}
 +
 +/**
 + * reload "advanced tweaks" that can be applied w/o a restart
 + */
 +void CGlobals::reloadAdv()
 +{
 +	g_bDisableAniAvatars=				M->GetByte("adv_DisableAniAvatars", 0);
 +	g_bSoundOnTyping = 					M->GetByte("adv_soundontyping", 0);
 +	m_dontUseDefaultKbd=				M->GetByte("adv_leaveKeyboardAlone", 1);
 +	g_bClientInStatusBar = 				M->GetByte("adv_ClientIconInStatusBar", 0);
 +
 +	if(g_bSoundOnTyping && m_TypingSoundAdded == false) {
 +		SkinAddNewSoundEx("SoundOnTyping", "Other", "TABSRMM: Typing");
 +		m_TypingSoundAdded = true;
 +	}
 +	m_AllowOfflineMultisend =			M->GetByte("AllowOfflineMultisend", 0);
 +}
 +
 +const HMENU CGlobals::getMenuBar()
 +{
 +	if(m_MenuBar == 0) {
 +		m_MenuBar = ::LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENUBAR));
 +		CallService(MS_LANGPACK_TRANSLATEMENU, WPARAM(m_MenuBar), 0);
 +	}
 +	return(m_MenuBar);
 +}
 +
 +/**
 + * hook core events. This runs in LoadModule()
 + * only core events and services are guaranteed to exist at this time
 + */
 +void CGlobals::hookSystemEvents()
 +{
 +	m_event_ModulesLoaded 	= 	HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
 +	m_event_IconsChanged 	= 	HookEvent(ME_SKIN_ICONSCHANGED, ::IconsChanged);
 +	m_event_TypingEvent 	= 	HookEvent(ME_PROTO_CONTACTISTYPING, CMimAPI::TypingMessage);
 +	m_event_ProtoAck 		= 	HookEvent(ME_PROTO_ACK, CMimAPI::ProtoAck);
 +	m_event_PreShutdown 	= 	HookEvent(ME_SYSTEM_PRESHUTDOWN, PreshutdownSendRecv);
 +	m_event_OkToExit 		= 	HookEvent(ME_SYSTEM_OKTOEXIT, OkToExit);
 +
 +	m_event_PrebuildMenu 	= 	HookEvent(ME_CLIST_PREBUILDCONTACTMENU, CMimAPI::PrebuildContactMenu);
 +
 +	m_event_IcoLibChanged 	= 	HookEvent(ME_SKIN2_ICONSCHANGED, ::IcoLibIconsChanged);
 +	m_event_AvatarChanged 	= 	HookEvent(ME_AV_AVATARCHANGED, ::AvatarChanged);
 +	m_event_MyAvatarChanged = 	HookEvent(ME_AV_MYAVATARCHANGED, ::MyAvatarChanged);
 +}
 +
 +/**
 + * second part of the startup initialisation. All plugins are now fully loaded
 + */
 +
 +int CGlobals::ModulesLoaded(WPARAM wParam, LPARAM lParam)
 +{
 +	int 				i;
 +	MENUITEMINFOA 		mii = {0};
 +	HMENU 				submenu;
 +	CLISTMENUITEM 		mi = { 0 };
 +
 +	::UnhookEvent(m_event_ModulesLoaded);
 +
 +	M->configureCustomFolders();
 +
 +	Skin->Init(true);
 +	CSkin::initAeroEffect();
 +
 +	for (i = 0; i < NR_BUTTONBARICONS; i++)
 +		PluginConfig.g_buttonBarIcons[i] = 0;
 +	::LoadIconTheme();
 +	::CreateImageList(TRUE);
 +
 +	mii.cbSize = sizeof(mii);
 +	mii.fMask = MIIM_BITMAP;
 +	mii.hbmpItem = HBMMENU_CALLBACK;
 +	submenu = GetSubMenu(PluginConfig.g_hMenuContext, 7);
 +	for (i = 0; i <= 8; i++)
 +		SetMenuItemInfoA(submenu, (UINT_PTR)i, TRUE, &mii);
 +
 +	PluginConfig.reloadSystemModulesChanged();
 +
 +	::BuildContainerMenu();
 +
 +	::CB_InitDefaultButtons();
 +	::ModPlus_Init(wParam, lParam);
 +	::NotifyEventHooks(hHookToolBarLoadedEvt, (WPARAM)0, (LPARAM)0);
 +	//
 +
 +	if (M->GetByte("avatarmode", -1) == -1)
 +		M->WriteByte(SRMSGMOD_T, "avatarmode", 2);
 +
 +	PluginConfig.g_hwndHotkeyHandler = CreateWindowEx(0, _T("TSHK"), _T(""), WS_POPUP,
 +								  0, 0, 40, 40, 0, 0, g_hInst, NULL);
 +
 +	::CreateTrayMenus(TRUE);
 +	if (nen_options.bTraySupport)
 +		::CreateSystrayIcon(TRUE);
 +
 +	mi.cbSize = sizeof(mi);
 +	mi.position = -500050005;
 +	mi.hIcon = PluginConfig.g_iconContainer;
 +	mi.pszContactOwner = NULL;
 +	mi.pszName = LPGEN("&Messaging settings...");
 +	mi.pszService = MS_TABMSG_SETUSERPREFS;
 +	PluginConfig.m_UserMenuItem = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
 +
 +	if(sendLater->isAvail()) {
 +		mi.cbSize = sizeof(mi);
 +		mi.position = -500050006;
 +		mi.hIcon = 0;
 +		mi.pszContactOwner = NULL;
 +		mi.pszName = LPGEN("&Send later job list...");
 +		mi.pszService = MS_TABMSG_SLQMGR;
 +		PluginConfig.m_UserMenuItem = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM) & mi);
 +	}
 +	RestoreUnreadMessageAlerts();
 +
 +	RegisterWithUpdater();
 +
 +	::RegisterFontServiceFonts();
 +	::CacheLogFonts();
 +	::Chat_ModulesLoaded(wParam, lParam);
 +	if(PluginConfig.g_PopupWAvail||PluginConfig.g_PopupAvail)
 +		TN_ModuleInit();
 +
 +	m_event_SettingChanged 	= HookEvent(ME_DB_CONTACT_SETTINGCHANGED, DBSettingChanged);
 +	m_event_ContactDeleted 	= HookEvent(ME_DB_CONTACT_DELETED, DBContactDeleted);
 +
 +	m_event_Dispatch 		= HookEvent(ME_DB_EVENT_ADDED, CMimAPI::DispatchNewEvent);
 +	m_event_EventAdded 		= HookEvent(ME_DB_EVENT_ADDED, CMimAPI::MessageEventAdded);
 +	if(PluginConfig.g_MetaContactsAvail) {
 +		m_event_ME_MC_SUBCONTACTSCHANGED = HookEvent(ME_MC_SUBCONTACTSCHANGED, MetaContactEvent);
 +		m_event_ME_MC_FORCESEND			 = HookEvent(ME_MC_FORCESEND, MetaContactEvent);
 +		m_event_ME_MC_UNFORCESEND		 = HookEvent(ME_MC_UNFORCESEND, MetaContactEvent);
 +	}
 +	m_event_FontsChanged 	= 	HookEvent(ME_FONT_RELOAD, ::FontServiceFontsChanged);
 +	return 0;
 +}
 +
 +/**
 + * watches various important database settings and reacts accordingly
 + * needed to catch status, nickname and other changes in order to update open message
 + * sessions.
 + */
 +
 +int CGlobals::DBSettingChanged(WPARAM wParam, LPARAM lParam)
 +{
 +	DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam;
 +	const char 	*szProto = NULL;
 +	const char  *setting = cws->szSetting;
 +	HWND		hwnd = 0;
 +	CContactCache* c = 0;
 +	bool		fChanged = false, fNickChanged = false, fExtendedStatusChange = false;
 +
 +	hwnd = M->FindWindow((HANDLE)wParam);
 +
 +	if (hwnd == 0 && wParam != 0) {     // we are not interested in this event if there is no open message window/tab
 +		if(!strcmp(setting, "Status") || !strcmp(setting, "MyHandle") || !strcmp(setting, "Nick") || !strcmp(cws->szModule, SRMSGMOD_T)) {
 +			c = CContactCache::getContactCache((HANDLE)wParam);
 +			if(c) {
 +				fChanged = c->updateStatus();
 +				if(strcmp(setting, "Status"))
 +					c->updateNick();
 +				if(!strcmp(setting, "isFavorite") || !strcmp(setting, "isRecent"))
 +					c->updateFavorite();
 +			}
 +		}
 +		return(0);
 +	}
 +
 +	if (wParam == 0 && !strcmp("Nick", setting)) {
 +		M->BroadcastMessage(DM_OWNNICKCHANGED, 0, (LPARAM)cws->szModule);
 +		return(0);
 +	}
 +
 +	if(wParam) {
 +		c = CContactCache::getContactCache((HANDLE)wParam);
 +		if(c) {
 +			szProto = c->getProto();
 +			if(!strcmp(cws->szModule, SRMSGMOD_T)) {					// catch own relevant settings
 +				if(!strcmp(setting, "isFavorite") || !strcmp(setting, "isRecent"))
 +					c->updateFavorite();
 +			}
 +		}
 +	}
 +
 +	if(wParam == 0 && !lstrcmpA(setting, "Enabled")) {
 +		if(PluginConfig.g_MetaContactsAvail && !lstrcmpA(cws->szModule, PluginConfig.szMetaName)) { 		// catch the disabled meta contacts
 +			PluginConfig.bMetaEnabled = abs(M->GetByte(0, PluginConfig.szMetaName, "Enabled", -1));
 +			cacheUpdateMetaChanged();
 +		}
 +	}
 +
 +	if (lstrcmpA(cws->szModule, "CList") && (szProto == NULL || lstrcmpA(cws->szModule, szProto)))
 +		return(0);
 +
 +	if (PluginConfig.g_MetaContactsAvail && !lstrcmpA(cws->szModule, PluginConfig.szMetaName)) {
 +		if(wParam != 0 && !lstrcmpA(setting, "Nick"))      // filter out this setting to avoid infinite loops while trying to obtain the most online contact
 +			return(0);
 +	}
 +
 +	if (hwnd) {
 +		if(c) {
 +			fChanged = c->updateStatus();
 +			fNickChanged = c->updateNick();
 +		}
 +		if (lstrlenA(setting) > 6 && lstrlenA(setting) < 9 && !strncmp(setting, "Status", 6)) {
 +			fChanged = true;
 +			if(c) {
 +				c->updateMeta(true);
 +				c->updateUIN();
 +			}
 +		}
 +		else if (!strcmp(setting, "MirVer"))
 +			PostMessage(hwnd, DM_CLIENTCHANGED, 0, 0);
 +		else if (!strcmp(setting, "display_uid")) {
 +			if(c)
 +				c->updateUIN();
 +			PostMessage(hwnd, DM_UPDATEUIN, 0, 0);
 +		}
 +		else if(lstrlenA(setting) > 6 && strstr("StatusMsg,XStatusMsg,XStatusName,XStatusId,ListeningTo", setting)) {
 +			if(c) {
 +				c->updateStatusMsg(setting);
 +				fExtendedStatusChange = true;
 +			}
 +		}
 +		if(fChanged || fNickChanged || fExtendedStatusChange)
 +			PostMessage(hwnd, DM_UPDATETITLE, 0, 1);
 +		if(fExtendedStatusChange)
 +			PostMessage(hwnd, DM_UPDATESTATUSMSG, 0, 0);
 +		if(fChanged) {
 +			if(c && c->getStatus() == ID_STATUS_OFFLINE) {			// clear typing notification in the status bar when contact goes offline
 +				TWindowData* dat = c->getDat();
 +				if(dat) {
 +					dat->nTypeSecs = 0;
 +					dat->showTyping = 0;
 +					dat->szStatusBar[0] = 0;
 +					PostMessage(c->getHwnd(), DM_UPDATELASTMESSAGE, 0, 0);
 +				}
 +			}
 +			if(c)
 +				PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_LOGSTATUSCHANGE, MAKELONG(c->getStatus(), c->getOldStatus()), (LPARAM)c);
 +		}
 +	}
 +	return(0);
 +}
 +
 +/**
 + * event fired when a contact has been deleted. Make sure to close its message session
 + */
 +
 +int CGlobals::DBContactDeleted(WPARAM wParam, LPARAM lParam)
 +{
 +	if(wParam) {
 +		CContactCache *c = CContactCache::getContactCache((HANDLE)wParam);
 +		if(c)
 +			c->deletedHandler();
 +	}
 +	return 0;
 +}
 +
 +/**
 + * Handle events from metacontacts protocol. Basically, just update
 + * our contact cache and, if a message window exists, tell it to update
 + * relevant information.
 + */
 +int CGlobals::MetaContactEvent(WPARAM wParam, LPARAM lParam)
 +{
 +	if(wParam) {
 +		CContactCache *c = CContactCache::getContactCache((HANDLE)wParam);
 +		if(c) {
 +			c->updateMeta(true);
 +			if(c->getHwnd()) {
 +				c->updateUIN();								// only do this for open windows, not needed normally
 +				::PostMessage(c->getHwnd(), DM_UPDATETITLE, 0, 0);
 +			}
 +		}
 +	}
 +	return(0);
 +}
 +
 +int CGlobals::PreshutdownSendRecv(WPARAM wParam, LPARAM lParam)
 +{
 +	HANDLE 	hContact;
 +	int		i;
 +
 +#if defined(__USE_EX_HANDLERS)
 +	__try {
 +#endif
 +		if (PluginConfig.m_chat_enabled)
 +			::Chat_PreShutdown();
 +
 +		::TN_ModuleDeInit();
 +
 +		while(pFirstContainer){
 +			if (PluginConfig.m_HideOnClose)
 +				PluginConfig.m_HideOnClose = FALSE;
 +			::SendMessage(pFirstContainer->hwnd, WM_CLOSE, 0, 1);
 +		}
 +
 +		hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
 +		while (hContact) {
 +			M->WriteDword(hContact, SRMSGMOD_T, "messagecount", 0);
 +			hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
 +		}
 +
 +		for(i = 0; i < SERVICE_LAST; i++) {
 +			if(PluginConfig.hSvc[i])
 +				DestroyServiceFunction(PluginConfig.hSvc[i]);
 +		}
 +
 +		::SI_DeinitStatusIcons();
 +		::CB_DeInitCustomButtons();
 +		/*
 +		 * the event API
 +		 */
 +
 +		DestroyHookableEvent(PluginConfig.m_event_MsgWin);
 +		DestroyHookableEvent(PluginConfig.m_event_MsgPopup);
 +
 +		::NEN_WriteOptions(&nen_options);
 +		::DestroyWindow(PluginConfig.g_hwndHotkeyHandler);
 +
 +		::UnregisterClass(_T("TSStatusBarClass"), g_hInst);
 +		::UnregisterClass(_T("SideBarClass"), g_hInst);
 +		::UnregisterClassA("TSTabCtrlClass", g_hInst);
 +		::UnregisterClass(_T("RichEditTipClass"), g_hInst);
 +		::UnregisterClass(_T("TSHK"), g_hInst);
 +#if defined(__USE_EX_HANDLERS)
 +	}
 +	__except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"SHUTDOWN_STAGE2", false)) {
 +		return(0);
 +	}
 +#endif
 +	return 0;
 +}
 +
 +int CGlobals::OkToExit(WPARAM wParam, LPARAM lParam)
 +{
 +	UnhookEvent(m_event_OkToExit);
 +#if defined(__USE_EX_HANDLERS)
 +	__try {
 +#endif
 +		::CreateSystrayIcon(0);
 +		::CreateTrayMenus(0);
 +
 +		CWarning::destroyAll();
 +
 +		CMimAPI::m_shutDown = true;
 +		UnhookEvent(m_event_EventAdded);
 +		UnhookEvent(m_event_Dispatch);
 +		UnhookEvent(m_event_PrebuildMenu);
 +		UnhookEvent(m_event_SettingChanged);
 +		UnhookEvent(m_event_ContactDeleted);
 +		UnhookEvent(m_event_AvatarChanged);
 +		UnhookEvent(m_event_MyAvatarChanged);
 +		UnhookEvent(m_event_ProtoAck);
 +		UnhookEvent(m_event_TypingEvent);
 +		UnhookEvent(m_event_FontsChanged);
 +		UnhookEvent(m_event_IcoLibChanged);
 +		UnhookEvent(m_event_IconsChanged);
 +
 +		if(m_event_SmileyAdd)
 +			UnhookEvent(m_event_SmileyAdd);
 +
 +		if(m_event_IEView)
 +			UnhookEvent(m_event_IEView);
 +
 +		if(m_event_FoldersChanged)
 +			UnhookEvent(m_event_FoldersChanged);
 +
 +		if(m_event_ME_MC_FORCESEND) {
 +			UnhookEvent(m_event_ME_MC_FORCESEND);
 +			UnhookEvent(m_event_ME_MC_SUBCONTACTSCHANGED);
 +			UnhookEvent(m_event_ME_MC_UNFORCESEND);
 +		}
 +		::ModPlus_PreShutdown(wParam, lParam);
 +		PluginConfig.globalContainerSettings.fPrivate = false;
 +		::DBWriteContactSettingBlob(0, SRMSGMOD_T, CNT_KEYNAME, &PluginConfig.globalContainerSettings, sizeof(TContainerSettings));
 +#if defined(__USE_EX_HANDLERS)
 +	}
 +	__except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"SHUTDOWN_STAGE1", false)) {
 +		return(0);
 +	}
 +#endif
 +	return 0;
 +}
 +
 +/**
 + * used on startup to restore flashing tray icon if one or more messages are
 + * still "unread"
 + */
 +
 +void CGlobals::RestoreUnreadMessageAlerts(void)
 +{
 +	CLISTEVENT 	cle = { 0 };
 +	DBEVENTINFO dbei = { 0 };
 +	TCHAR		toolTip[256];
 +	int 		windowAlreadyExists;
 +	int 		usingReadNext = 0;
 +
 +	int autoPopup = M->GetByte(SRMSGMOD, SRMSGSET_AUTOPOPUP, SRMSGDEFSET_AUTOPOPUP);
 +	HANDLE hDbEvent, hContact;
 +
 +	dbei.cbSize = sizeof(dbei);
 +	cle.cbSize = sizeof(cle);
 +	cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
 +	cle.pszService = "SRMsg/ReadMessage";
 +	cle.flags = CLEF_TCHAR;
 +
 +	hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
 +	while (hContact) {
 +
 +		if(M->GetDword(hContact, "SendLater", "count", 0))
 +		   sendLater->addContact(hContact);
 +
 +		hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0);
 +		while (hDbEvent) {
 +			dbei.cbBlob = 0;
 +			CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei);
 +			if (!(dbei.flags & (DBEF_SENT | DBEF_READ)) && dbei.eventType == EVENTTYPE_MESSAGE) {
 +				windowAlreadyExists = M->FindWindow(hContact) != NULL;
 +				if (!usingReadNext && windowAlreadyExists)
 +					continue;
 +
 +				cle.hContact = hContact;
 +				cle.hDbEvent = hDbEvent;
 +				mir_sntprintf(toolTip, safe_sizeof(toolTip), CTranslator::get(CTranslator::GEN_STRING_MESSAGEFROM),
 +							  (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR));
 +				cle.ptszTooltip = toolTip;
 +				CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle);
 +			}
 +			hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hDbEvent, 0);
 +		}
 +		hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
 +	}
 +}
 +
 +void CGlobals::logStatusChange(WPARAM wParam, const CContactCache *c)
 +{
 +	if(c == 0)
 +		return;
 +
 +	HANDLE	hContact = c->getContact();
 +
 +	bool	fGlobal = PluginConfig.m_LogStatusChanges ? true : false;
 +	DWORD	dwMask = M->GetDword(hContact, SRMSGMOD_T, "mwmask", 0);
 +	DWORD	dwFlags = M->GetDword(hContact, SRMSGMOD_T, "mwflags", 0);
 +
 +	bool	fLocal = ((dwMask & MWF_LOG_STATUSCHANGES) ? (dwFlags & MWF_LOG_STATUSCHANGES ? true : false) : false);
 +
 +	if(fGlobal || fLocal) {
 +		/*
 +		 * don't log them if WE are logging off
 +		 */
 +		if(CallProtoService(c->getProto(), PS_GETSTATUS, 0, 0) == ID_STATUS_OFFLINE)
 +			return;
 +
 +		WORD	wStatus, wOldStatus;
 +
 +		wStatus = LOWORD(wParam);
 +		wOldStatus = HIWORD(wParam);
 +
 +		if(wStatus == wOldStatus)
 +			return;
 +
 +		DBEVENTINFO 	dbei;
 +		TCHAR 			buffer[450];
 +		HANDLE 			hNewEvent;
 +
 +		TCHAR*	szOldStatus = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)wOldStatus, GSMDF_TCHAR);
 +		TCHAR*	szNewStatus = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)wStatus, GSMDF_TCHAR);
 +
 +		if(szOldStatus == 0 || szNewStatus == 0)
 +			return;
 +
 +		if (c->isValid()) {
 +			if (wStatus == ID_STATUS_OFFLINE)
 +				mir_sntprintf(buffer, safe_sizeof(buffer), CTranslator::get(CTranslator::GEN_MSG_SIGNEDOFF));
 +			else if (wOldStatus == ID_STATUS_OFFLINE)
 +				mir_sntprintf(buffer, safe_sizeof(buffer), CTranslator::get(CTranslator::GEN_MSG_SIGNEDON), szNewStatus);
 +			else
 +				mir_sntprintf(buffer, safe_sizeof(buffer), CTranslator::get(CTranslator::GEN_MSG_CHANGEDSTATUS), szOldStatus, szNewStatus);
 +		}
 +
 +		char *szMsg = M->utf8_encodeT(buffer);
 +
 +		dbei.pBlob = (PBYTE)szMsg;
 +		dbei.cbBlob = lstrlenA(szMsg) + 1;
 +		dbei.flags = DBEF_UTF | DBEF_READ;
 +		dbei.cbSize = sizeof(dbei);
 +		dbei.eventType = EVENTTYPE_STATUSCHANGE;
 +		dbei.timestamp = time(NULL);
 +		dbei.szModule = const_cast<char *>(c->getProto());
 +		hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) hContact, (LPARAM) & dbei);
 +
 +		mir_free(szMsg);
 +	}
 +}
 +
 +/**
 + * when the state of the meta contacts protocol changes from enabled to disabled
 + * (or vice versa), this updates the contact cache
 + *
 + * it is ONLY called from the DBSettingChanged() event handler when the relevant
 + * database value is touched.
 + */
 +void CGlobals::cacheUpdateMetaChanged()
 +{
 +	CContactCache* 	c = CContactCache::m_cCache;
 +	bool			fMetaActive = (PluginConfig.g_MetaContactsAvail && PluginConfig.bMetaEnabled) ? true : false;
 +
 +	while(c) {
 +		if(c->isMeta() && PluginConfig.bMetaEnabled == false) {
 +			c->closeWindow();
 +			c->resetMeta();
 +		}
 +
 +		// meta contacts are enabled, but current contact is a subcontact - > close window
 +
 +		if(fMetaActive && c->isSubContact())
 +			c->closeWindow();
 +
 +		// reset meta contact information, if metacontacts protocol became avail
 +
 +		if(fMetaActive && !strcmp(c->getProto(), PluginConfig.szMetaName))
 +			c->resetMeta();
 +
 +		c = c->m_next;
 +	}
 +}
 +
 +/**
 + * on Windows 7, when using new task bar features (grouping mode and per tab
 + * previews), autoswitching does not work relieably, so it is disabled.
 + *
 + * @return: true if configuration dictates autoswitch
 + */
 +bool CGlobals::haveAutoSwitch()
 +{
 +	if(m_bIsWin7) {
 +		if(m_useAeroPeek && !CSkin::m_skinEnabled)
 +			return(false);
 +	}
 +	return(m_AutoSwitchTabs ? true : false);
 +}
 +/**
 + * exception handling - copy error message to clip board
 + * @param hWnd: 	window handle of the edit control containing the error message
 + */
 +void CGlobals::Ex_CopyEditToClipboard(HWND hWnd)
 +{
 +	SendMessage(hWnd, EM_SETSEL, 0, 65535L);
 +	SendMessage(hWnd, WM_COPY, 0 , 0);
 +	SendMessage(hWnd, EM_SETSEL, 0, 0);
 +}
 +
 +INT_PTR CALLBACK CGlobals::Ex_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 +{
 +	WORD wNotifyCode, wID;
 +
 +	switch(uMsg) {
 +		case WM_INITDIALOG: {
 +				char szBuffer[2048];
 +#ifdef _WIN64
 +				sprintf(szBuffer,
 +						"Exception %16.16X at address %16.16X occured in %s at line %d.\r\n\r\nEAX=%16.16X EBX=%16.16X ECX=%16.16X\r\nEDX=%16.16X ESI=%16.16X EDI=%16.16X\r\nEBP=%16.16X ESP=%16.16X EIP=%16.16X",
 +						m_exRecord.ExceptionCode, m_exRecord.ExceptionAddress, m_exSzFile, m_exLine,
 +						m_exCtx.Rax,m_exCtx.Rbx, m_exCtx.Rcx, m_exCtx.Rdx,
 +						m_exCtx.Rsi, m_exCtx.Rdi, m_exCtx.Rbp, m_exCtx.Rsp, m_exCtx.Rip);
 +#else
 +				sprintf(szBuffer,
 +						"Exception %8.8X at address %8.8X occured in %s at line %d.\r\n\r\nEAX=%8.8X EBX=%8.8X ECX=%8.8X\r\nEDX=%8.8X ESI=%8.8X EDI=%8.8X\r\nEBP=%8.8X ESP=%8.8X EIP=%8.8X",
 +						m_exRecord.ExceptionCode, m_exRecord.ExceptionAddress, m_exSzFile, m_exLine,
 +						m_exCtx.Eax,m_exCtx.Ebx, m_exCtx.Ecx, m_exCtx.Edx,
 +						m_exCtx.Esi, m_exCtx.Edi, m_exCtx.Ebp, m_exCtx.Esp, m_exCtx.Eip);
 +#endif
 +				SetDlgItemTextA(hwndDlg, IDC_EXCEPTION_DETAILS, szBuffer);
 +				SetFocus(GetDlgItem(hwndDlg, IDC_EXCEPTION_DETAILS));
 +				SendDlgItemMessage(hwndDlg, IDC_EXCEPTION_DETAILS, WM_SETFONT, (WPARAM)GetStockObject(OEM_FIXED_FONT), 0);
 +				SetDlgItemTextW(hwndDlg, IDC_EX_REASON, m_exReason);
 +				Utils::enableDlgControl(hwndDlg, IDOK, m_exAllowContinue ? TRUE : FALSE);
 +			}
 +			break;
 +
 +		case WM_COMMAND:
 +			wNotifyCode = HIWORD(wParam);
 +			wID = LOWORD(wParam);
 +			if (wNotifyCode == BN_CLICKED)
 +			{
 +				if (wID == IDOK || wID == IDCANCEL)
 +					EndDialog(hwndDlg, wID);
 +
 +				if (wID == IDC_COPY_EXCEPTION)
 +					Ex_CopyEditToClipboard(GetDlgItem(hwndDlg, IDC_EXCEPTION_DETAILS));
 +			}
 +
 +			break;
 +	}
 +	return FALSE;
 +}
 +
 +void CGlobals::Ex_Handler()
 +{
 +	if (m_exLastResult == IDCANCEL)
 +		ExitProcess(1);
 +}
 +
 +int CGlobals::Ex_ShowDialog(EXCEPTION_POINTERS *ep, const char *szFile, int line, wchar_t* szReason, bool fAllowContinue)
 +{
 +	char	szDrive[MAX_PATH], szDir[MAX_PATH], szName[MAX_PATH], szExt[MAX_PATH];
 +
 +	_splitpath(szFile, szDrive, szDir, szName, szExt);
 +	memcpy(&m_exRecord, ep->ExceptionRecord, sizeof(EXCEPTION_RECORD));
 +	memcpy(&m_exCtx, ep->ContextRecord, sizeof(CONTEXT));
 +
 +	_snprintf(m_exSzFile, MAX_PATH, "%s%s", szName, szExt);
 +	mir_sntprintf(m_exReason, 256, L"An application error has occured: %s", szReason);
 +	m_exLine = line;
 +	m_exLastResult = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EXCEPTION), 0, CGlobals::Ex_DlgProc, 0);
 +	m_exAllowContinue = fAllowContinue;
 +	if(IDCANCEL == m_exLastResult)
 +		ExitProcess(1);
 +	return 1;
 +}
  | 
