/**
 * obtain the UIN. This is only maintained for open message windows
 * it also run when the subcontact for a MC changes.
 */
bool CContactCache::updateUIN()
{
	bool		fChanged = false;

	if(m_Valid) {
		CONTACTINFO ci = {0};

		ci.hContact = getActiveContact();
		ci.szProto = const_cast<char *>(getActiveProto());
		ci.cbSize = sizeof(ci);

		ci.dwFlag = CNF_DISPLAYUID | CNF_TCHAR;
		if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
			switch (ci.type) {
				case CNFT_ASCIIZ:
					mir_sntprintf(m_szUIN, safe_sizeof(m_szUIN), _T("%s"), reinterpret_cast<TCHAR *>(ci.pszVal));
					mir_free((void *)ci.pszVal);
					break;
				case CNFT_DWORD:
					mir_sntprintf(m_szUIN, safe_sizeof(m_szUIN), _T("%u"), ci.dVal);
					break;
				default:
					m_szUIN[0] = 0;
					break;
			}
		} else
			m_szUIN[0] = 0;

	}
	else
		m_szUIN[0] = 0;

	return(fChanged);
}
예제 #2
0
int CompareContacts(WPARAM wParam, LPARAM lParam)
{
    HANDLE a = (HANDLE) wParam,b = (HANDLE) lParam;
    TCHAR namea[128], *nameb;
    int statusa, statusb;
    char *szProto1, *szProto2;
    int rc;

    szProto1 = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) a, 0);
    szProto2 = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) b, 0);
    statusa = DBGetContactSettingWord((HANDLE) a, SAFESTRING(szProto1), "Status", ID_STATUS_OFFLINE);
    statusb = DBGetContactSettingWord((HANDLE) b, SAFESTRING(szProto2), "Status", ID_STATUS_OFFLINE);

    if (sortByProto) {
    /* deal with statuses, online contacts have to go above offline */
        if ((statusa == ID_STATUS_OFFLINE) != (statusb == ID_STATUS_OFFLINE)) {
            return 2 * (statusa == ID_STATUS_OFFLINE) - 1;
        }
    /* both are online, now check protocols */
        rc = strcmp(SAFESTRING(szProto1), SAFESTRING(szProto2)); /* strcmp() doesn't like NULL so feed in "" as needed */
        if (rc != 0 && (szProto1 != NULL && szProto2 != NULL))
            return rc;
    /* protocols are the same, order by display name */
    }

    if (sortByStatus) {
        int ordera, orderb;
        ordera = GetStatusModeOrdering(statusa);
        orderb = GetStatusModeOrdering(statusb);
        if (ordera != orderb)
            return ordera - orderb;
    } else {
    //one is offline: offline goes below online
        if ((statusa == ID_STATUS_OFFLINE) != (statusb == ID_STATUS_OFFLINE)) {
            return 2 * (statusa == ID_STATUS_OFFLINE) - 1;
        }
    }

    nameb = GetContactDisplayNameW(a, 0);
    _tcsncpy(namea, nameb, safe_sizeof(namea));
    namea[safe_sizeof(namea) - 1] = 0;
    nameb = GetContactDisplayNameW(b, 0);

    //otherwise just compare names
    return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, namea, -1, nameb, -1) - 2;
    //return _tcsicmp(namea,nameb);
}
예제 #3
0
/**
 * extract the aero skin images from the DLL and store them in
 * the private data folder.
 * runs at every startup
 *
 * only overwrites the files when version number does not match or
 * one of the files is missing.
 */
void cfg::extractBaseSkin(bool fForceOverwrite)
{
	wchar_t 	wszBasePath[MAX_PATH], wszTest[MAX_PATH];
	bool		fChecksPassed = true;
	HANDLE		hFile;

	mir_sntprintf(wszBasePath, MAX_PATH, L"%s%s", szProfileDir, L"skin\\clng\\base\\");
	mir_sntprintf(wszTest, MAX_PATH, L"%s%s", wszBasePath, L"base.cng");

	/*
	 * version check, also fails when the file is simply missing
	 */
	int uVersion = GetPrivateProfileInt(L"SkinInfo", L"Version", 0, wszTest);
	if(uVersion < SKIN_REQUIRED_VERSION)
		fChecksPassed = false;

	/*
	 * version check passed, verify files are present
	 */
	if(fChecksPassed) {
		for(int i = 0; i < safe_sizeof(my_default_skin); i++) {
			mir_sntprintf(wszTest, MAX_PATH, L"%s%s", wszBasePath, my_default_skin[i].tszName);
			if((hFile = CreateFile(wszTest, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) {
				fChecksPassed  = false;
				break;
			}
			CloseHandle(hFile);
		}
	}

	// files are not present in skin dir, extract the default skin
	if(!fChecksPassed) {
		try {
			for(int i = 0; i < safe_sizeof(my_default_skin); i++)
				Utils::extractResource(g_hInst, my_default_skin[i].ulID, L"SKIN_GLYPH", wszBasePath, my_default_skin[i].tszName, true);

			fBaseSkinValid = true;
		} catch(CRTException& ex) {
			ex.display();
			fBaseSkinValid = false;
		}
	}
}
예제 #4
0
void TSAPI AddContactToFavorites(HANDLE hContact, const TCHAR *szNickname, const char *szProto, TCHAR *szStatus, WORD wStatus, HICON hIcon, BOOL mode, HMENU hMenu)
{
	MENUITEMINFO	mii = {0};
	TCHAR			szMenuEntry[80];
	TCHAR			szFinalNick[100];

	if (szNickname == NULL) {
		mir_sntprintf(szFinalNick, safe_sizeof(szFinalNick), _T("%s"), (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
	}
	else {
		_tcsncpy(szFinalNick, szNickname, 100);
		szFinalNick[99] = 0;
	}

	if (szProto == NULL)
		szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
	if (szProto) {
		if (wStatus == 0)
			wStatus = DBGetContactSettingWord((HANDLE)hContact, szProto, "Status", ID_STATUS_OFFLINE);
		if (szStatus == NULL)
			szStatus = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, wStatus, GSMDF_TCHAR);
	}
	else
		return;

	if (hIcon == 0)
		hIcon = LoadSkinnedProtoIcon(szProto, wStatus);

	PROTOACCOUNT *acc = (PROTOACCOUNT *)CallService(MS_PROTO_GETACCOUNT, (WPARAM)0, (LPARAM)szProto);

	if(acc && acc->tszAccountName) {
		mii.cbSize = sizeof(mii);
		mir_sntprintf(szMenuEntry, safe_sizeof(szMenuEntry), _T("%s: %s (%s)"), acc->tszAccountName, szFinalNick, szStatus);
		if (mode) {
			if (hMenu == PluginConfig.g_hMenuRecent) {
				if (CheckMenuItem(hMenu, (UINT_PTR)hContact, MF_BYCOMMAND | MF_UNCHECKED) == 0) {
					DeleteMenu(hMenu, (UINT_PTR)hContact, MF_BYCOMMAND);
					goto addnew;                                            // move to the end of the menu...
				}
				if (GetMenuItemCount(PluginConfig.g_hMenuRecent) > nen_options.wMaxRecent) {           // throw out oldest entry in the recent menu...
					UINT uid = GetMenuItemID(hMenu, 0);
					if (uid) {
						DeleteMenu(hMenu, (UINT_PTR)0, MF_BYPOSITION);
						M->WriteDword((HANDLE)uid, SRMSGMOD_T, "isRecent", 0);
					}
				}
	addnew:
				M->WriteDword(hContact, SRMSGMOD_T, "isRecent", time(NULL));
				AppendMenu(hMenu, MF_BYCOMMAND, (UINT_PTR)hContact, szMenuEntry);
			}
			else if (hMenu == PluginConfig.g_hMenuFavorites) {            // insert the item sorted...
				MENUITEMINFO mii2 = {0};
				TCHAR szBuffer[142];
				int i, c = GetMenuItemCount(PluginConfig.g_hMenuFavorites);
				mii2.fMask = MIIM_STRING;
				mii2.cbSize = sizeof(mii2);
				if (c == 0)
					InsertMenu(PluginConfig.g_hMenuFavorites, 0, MF_BYPOSITION, (UINT_PTR)hContact, szMenuEntry);
				else {
					for (i = 0; i <= c; i++) {
						mii2.cch = 0;
						mii2.dwTypeData = NULL;
						GetMenuItemInfo(PluginConfig.g_hMenuFavorites, i, TRUE, &mii2);
						mii2.cch++;
						mii2.dwTypeData = szBuffer;
						GetMenuItemInfo(PluginConfig.g_hMenuFavorites, i, TRUE, &mii2);
						if (_tcsncmp((TCHAR *)mii2.dwTypeData, szMenuEntry, 140) > 0 || i == c) {
							InsertMenu(PluginConfig.g_hMenuFavorites, i, MF_BYPOSITION, (UINT_PTR)hContact, szMenuEntry);
							break;
						}
					}
				}
			}
		}
		mii.fMask = MIIM_BITMAP | MIIM_DATA;
		if (!mode) {
			mii.fMask |= MIIM_STRING;
			mii.dwTypeData = (LPTSTR)szMenuEntry;
			mii.cch = lstrlen(szMenuEntry) + 1;
		}
		mii.hbmpItem = HBMMENU_CALLBACK;
		mii.dwItemData = (ULONG_PTR)hIcon;
		SetMenuItemInfo(hMenu, (UINT)hContact, FALSE, &mii);
	}
}
예제 #5
0
LONG_PTR CALLBACK HotkeyHandlerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static POINT ptLast;
	static int iMousedown;

	if (msg == WM_TASKBARCREATED) {
		CreateSystrayIcon(FALSE);
		if (nen_options.bTraySupport)
			CreateSystrayIcon(TRUE);
		return 0;
	}
	switch (msg) {
		case WM_CREATE:
			int i;

			for(i = 0; i < safe_sizeof(_hotkeydescs); i++) {
				_hotkeydescs[i].cbSize = sizeof(HOTKEYDESC);
				CallService(MS_HOTKEY_REGISTER, 0, (LPARAM)&_hotkeydescs[i]);
			}

			WM_TASKBARCREATED = RegisterWindowMessageA("TaskbarCreated");
			ShowWindow(hwndDlg, SW_HIDE);
			hSvcHotkeyProcessor = CreateServiceFunction(MS_TABMSG_HOTKEYPROCESS, HotkeyProcessor);
			SetTimer(hwndDlg, TIMERID_SENDLATER, TIMEOUT_SENDLATER, NULL);
			break;
		case WM_HOTKEY: {
			CLISTEVENT *cli = 0;

			cli = (CLISTEVENT *)CallService(MS_CLIST_GETEVENT, (WPARAM)INVALID_HANDLE_VALUE, (LPARAM)0);
			if (cli != NULL) {
				if (strncmp(cli->pszService, "SRMsg/TypingMessage", strlen(cli->pszService))) {
					CallService(cli->pszService, 0, (LPARAM)cli);
					break;
				}
			}
			if (wParam == 0xc001)
				SendMessage(hwndDlg, DM_TRAYICONNOTIFY, 101, WM_MBUTTONDOWN);

			break;
		}
		/*
		 * handle the popup menus (session list, favorites, recents...
		 * just draw some icons, nothing more :)
		 */
		case WM_MEASUREITEM: {
			LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT) lParam;
			lpmi->itemHeight = 0;
			lpmi->itemWidth = 6;
			return TRUE;
		}
		case WM_DRAWITEM: {
			LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
			struct TWindowData *dat = 0;
			if (dis->CtlType == ODT_MENU && (dis->hwndItem == (HWND)PluginConfig.g_hMenuFavorites || dis->hwndItem == (HWND)PluginConfig.g_hMenuRecent)) {
				HICON hIcon = (HICON)dis->itemData;

				DrawMenuItem(dis, hIcon, 0);
				return TRUE;
			} else if (dis->CtlType == ODT_MENU) {
				HWND hWnd = M->FindWindow((HANDLE)dis->itemID);
				DWORD idle = 0;

				if (hWnd == NULL) {
					SESSION_INFO *si = SM_FindSessionByHCONTACT((HANDLE)dis->itemID);

					hWnd = si ? si->hWnd : 0;
				}

				if (hWnd)
					dat = (struct TWindowData *)GetWindowLongPtr(hWnd, GWLP_USERDATA);

				if (dis->itemData >= 0) {
					HICON hIcon;
					BOOL fNeedFree = FALSE;

					if (dis->itemData > 0)
						hIcon = dis->itemData & 0x10000000 ? hIcons[ICON_HIGHLIGHT] : PluginConfig.g_IconMsgEvent;
					else if (dat != NULL) {
						hIcon = MY_GetContactIcon(dat);
						idle = dat->idle;
					} else
						hIcon = PluginConfig.g_iconContainer;

					DrawMenuItem(dis, hIcon, idle);
					if (fNeedFree)
						DestroyIcon(hIcon);

					return TRUE;
				}
			}
		}
		break;
		case DM_TRAYICONNOTIFY: {
			int iSelection;

			if (wParam == 100 || wParam == 101) {
				switch (lParam) {
					case WM_LBUTTONUP: {
						POINT pt;
						GetCursorPos(&pt);
						if (wParam == 100)
							SetForegroundWindow(hwndDlg);
						if (GetMenuItemCount(PluginConfig.g_hMenuTrayUnread) > 0) {
							iSelection = TrackPopupMenu(PluginConfig.g_hMenuTrayUnread, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
							HandleMenuEntryFromhContact(iSelection);
						} else
							TrackPopupMenu(GetSubMenu(PluginConfig.g_hMenuContext, 8), TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
						if (wParam == 100)
							PostMessage(hwndDlg, WM_NULL, 0, 0);
						break;
					}
					case WM_MBUTTONDOWN: {
						MENUITEMINFOA mii = {0};
						int i, iCount = GetMenuItemCount(PluginConfig.g_hMenuTrayUnread);

						if (wParam == 100)
							SetForegroundWindow(hwndDlg);

						if (iCount > 0) {
							UINT uid = 0;
							mii.fMask = MIIM_DATA;
							mii.cbSize = sizeof(mii);
							i = iCount - 1;
							do {
								GetMenuItemInfoA(PluginConfig.g_hMenuTrayUnread, i, TRUE, &mii);
								if (mii.dwItemData > 0) {
									uid = GetMenuItemID(PluginConfig.g_hMenuTrayUnread, i);
									HandleMenuEntryFromhContact(uid);
									break;
								}
							} while (--i >= 0);
							if (uid == 0 && pLastActiveContainer != NULL) {                // no session found, restore last active container
								if (IsIconic(pLastActiveContainer->hwnd) || !IsWindowVisible(pLastActiveContainer->hwnd)) {
									SendMessage(pLastActiveContainer->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
									SetForegroundWindow(pLastActiveContainer->hwnd);
								} else {
									if(PluginConfig.m_HideOnClose)
										ShowWindow(pLastActiveContainer->hwnd, SW_HIDE);
									else
										SendMessage(pLastActiveContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
								}
							}
						}
						if (wParam == 100)
							PostMessage(hwndDlg, WM_NULL, 0, 0);
						break;
					}
					case WM_RBUTTONUP: {
						HMENU submenu = PluginConfig.g_hMenuTrayContext;
						POINT pt;

						if (wParam == 100)
							SetForegroundWindow(hwndDlg);
						GetCursorPos(&pt);
						CheckMenuItem(submenu, ID_TRAYCONTEXT_DISABLEALLPOPUPS, MF_BYCOMMAND | (nen_options.iDisable ? MF_CHECKED : MF_UNCHECKED));
						CheckMenuItem(submenu, ID_TRAYCONTEXT_DON40223, MF_BYCOMMAND | (nen_options.iNoSounds ? MF_CHECKED : MF_UNCHECKED));
						CheckMenuItem(submenu, ID_TRAYCONTEXT_DON, MF_BYCOMMAND | (nen_options.iNoAutoPopup ? MF_CHECKED : MF_UNCHECKED));
						EnableMenuItem(submenu, ID_TRAYCONTEXT_HIDEALLMESSAGECONTAINERS, MF_BYCOMMAND | (nen_options.bTraySupport) ? MF_ENABLED : MF_GRAYED);
						CheckMenuItem(submenu, ID_TRAYCONTEXT_SHOWTHETRAYICON, MF_BYCOMMAND | (nen_options.bTraySupport ? MF_CHECKED : MF_UNCHECKED));
						iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);

						if (iSelection) {
							MENUITEMINFO mii = {0};

							mii.cbSize = sizeof(mii);
							mii.fMask = MIIM_DATA | MIIM_ID;
							GetMenuItemInfo(submenu, (UINT_PTR)iSelection, FALSE, &mii);
							if (mii.dwItemData != 0) {                      // this must be an itm of the fav or recent menu
								HandleMenuEntryFromhContact(iSelection);
							} else {
								switch (iSelection) {
									case ID_TRAYCONTEXT_SHOWTHETRAYICON:
										nen_options.bTraySupport = !nen_options.bTraySupport;
										CreateSystrayIcon(nen_options.bTraySupport ? TRUE : FALSE);
										break;
									case ID_TRAYCONTEXT_DISABLEALLPOPUPS:
										nen_options.iDisable ^= 1;
										break;
									case ID_TRAYCONTEXT_DON40223:
										nen_options.iNoSounds ^= 1;
										break;
									case ID_TRAYCONTEXT_DON:
										nen_options.iNoAutoPopup ^= 1;
										break;
									case ID_TRAYCONTEXT_HIDEALLMESSAGECONTAINERS: {
										struct TContainerData *pContainer = pFirstContainer;

										while (pContainer) {
											ShowWindow(pContainer->hwnd, SW_HIDE);
											pContainer = pContainer->pNextContainer;
										}
										break;
									}
									case ID_TRAYCONTEXT_RESTOREALLMESSAGECONTAINERS: {
										struct TContainerData *pContainer = pFirstContainer;

										while (pContainer) {
											ShowWindow(pContainer->hwnd, SW_SHOW);
											pContainer = pContainer->pNextContainer;
										}
										break;
									}
									case ID_TRAYCONTEXT_BE: {
										struct TContainerData *pContainer = pFirstContainer;

										nen_options.iDisable = 1;
										nen_options.iNoSounds = 1;
										nen_options.iNoAutoPopup = 1;

										while (pContainer) {
											SendMessage(pContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 1);
											pContainer = pContainer->pNextContainer;
										}
										break;
									}
								}
							}
						}
						if (wParam == 100)
							PostMessage(hwndDlg, WM_NULL, 0, 0);
						break;
					}
					default:
						break;
				}
			}
			break;
		}
		/*
		 * handle an event from the popup module (mostly window activation). Since popups may run in different threads, the message
		 * is posted to our invisible hotkey handler which does always run within the main thread.
		 * wParam is the hContact
		 * lParam the event handle
		 */
		case DM_HANDLECLISTEVENT: {
			CLISTEVENT *cle = (CLISTEVENT *)CallService(MS_CLIST_GETEVENT, wParam, 0);

			/*
			 * if lParam == NULL, don't consider clist events, just open the message tab
			 */

			if(lParam == 0) {
				HandleMenuEntryFromhContact((int)wParam);
				break;
			}

			/*
			 * first try, if the clist returned an event...
			 */
			if (cle) {
				if (ServiceExists(cle->pszService)) {
					CallService(cle->pszService, (WPARAM)NULL, (LPARAM)cle);
					CallService(MS_CLIST_REMOVEEVENT, (WPARAM)cle->hContact, (LPARAM)cle->hDbEvent);
				}
			} else {             // still, we got that message posted.. the event may be waiting in tabSRMMs tray...
				HandleMenuEntryFromhContact((int)wParam);
			}
			break;
		}
		case DM_DOCREATETAB: {
			HWND hWnd = M->FindWindow((HANDLE)lParam);
			if (hWnd && IsWindow(hWnd)) {
				struct TContainerData *pContainer = 0;

				SendMessage(hWnd, DM_QUERYCONTAINER, 0, (LPARAM)&pContainer);
				if (pContainer) {
					int iTabs = TabCtrl_GetItemCount(GetDlgItem(pContainer->hwnd, IDC_MSGTABS));
					if (iTabs == 1)
						SendMessage(pContainer->hwnd, WM_CLOSE, 0, 1);
					else
						SendMessage(hWnd, WM_CLOSE, 0, 1);

					CreateNewTabForContact((struct TContainerData *)wParam, (HANDLE)lParam, 0, NULL, TRUE, TRUE, FALSE, 0);
				}
			}
			break;
		}
		case DM_DOCREATETAB_CHAT: {
			SESSION_INFO *si = SM_FindSessionByHWND((HWND)lParam);

			if (si && IsWindow(si->hWnd)) {
				struct TContainerData *pContainer = 0;

				SendMessage(si->hWnd, DM_QUERYCONTAINER, 0, (LPARAM)&pContainer);
				if (pContainer) {
					int iTabs = TabCtrl_GetItemCount(GetDlgItem(pContainer->hwnd, 1159));
					if (iTabs == 1)
						SendMessage(pContainer->hwnd, WM_CLOSE, 0, 1);
					else
						SendMessage(si->hWnd, WM_CLOSE, 0, 1);

					si->hWnd = CreateNewRoom((struct TContainerData *)wParam, si, TRUE, 0, 0);
				}
			}
			break;
		}
		case DM_SENDMESSAGECOMMANDW:
			SendMessageCommand_W(wParam, lParam);
			if (lParam)
				free((void *)lParam);
			return(0);

		case DM_SENDMESSAGECOMMAND:
			SendMessageCommand(wParam, lParam);
			if (lParam)
				free((void *)lParam);
			return(0);
			/*
			* sent from the popup to "dismiss" the event. we should do this in the main thread
			*/
		case DM_REMOVECLISTEVENT:
			CallService(MS_CLIST_REMOVEEVENT, wParam, lParam);
			CallService(MS_DB_EVENT_MARKREAD, wParam, lParam);
			return(0);

		case DM_SETLOCALE: {
			HKL 	hkl = (HKL)lParam;
			HANDLE 	hContact = (HANDLE)wParam;

			HWND	hWnd = M->FindWindow(hContact);

			if(hWnd) {
				TWindowData *dat = (TWindowData *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
				if(dat) {
					DBVARIANT  dbv;

					if(hkl) {
						dat->hkl = hkl;
						PostMessage(dat->hwnd, DM_SETLOCALE, 0, 0);
					}
					if(0 == M->GetTString(hContact, SRMSGMOD_T, "locale", &dbv)) {
						GetLocaleID(dat, dbv.ptszVal);
						DBFreeVariant(&dbv);
						UpdateReadChars(dat);
					}
				}
			}
			return(0);
		}
		/*
		 * react to changes in the desktop composition state
		 * (enable/disable DWM, change to a non-aero visual style
		 * or classic Windows theme
		 */
		case WM_DWMCOMPOSITIONCHANGED: {
			bool fNewAero = M->getAeroState();					// refresh dwm state
			SendMessage(hwndDlg, WM_THEMECHANGED, 0, 0);
			TContainerData *pContainer = pFirstContainer;

			while (pContainer) {
				if(fNewAero)
					SetAeroMargins(pContainer);
				else {
					MARGINS m = {0};

					if(M->m_pfnDwmExtendFrameIntoClientArea)
						M->m_pfnDwmExtendFrameIntoClientArea(pContainer->hwnd, &m);
				}
				if(pContainer->SideBar->isActive())
					RedrawWindow(GetDlgItem(pContainer->hwnd, 5000), NULL, NULL, RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW);			// the container for the sidebar buttons
				RedrawWindow(pContainer->hwnd, NULL, NULL, RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
				pContainer = pContainer->pNextContainer;
			}
			M->BroadcastMessage(WM_DWMCOMPOSITIONCHANGED, 0, 0);
			break;
		}

		/*
		 * this message is fired when the user changes desktop color
		 * settings (Desktop->personalize)
		 * the handler reconfigures the aero-related skin images for
		 * tabs and buttons to match the new desktop color theme.
		 */
		case WM_DWMCOLORIZATIONCOLORCHANGED: {
			M->getAeroState();
			Skin->setupAeroSkins();
			CSkin::initAeroEffect();
			break;
		}
		
		/*
		 * user has changed the visual style or switched to/from
		 * classic Windows theme
		 */
		case WM_THEMECHANGED: {
			struct TContainerData *pContainer = pFirstContainer;

			M->getAeroState();
			Skin->setupTabCloseBitmap();
			CSkin::initAeroEffect();
			PluginConfig.m_ncm.cbSize = sizeof(NONCLIENTMETRICS);
			SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &PluginConfig.m_ncm, 0);
			FreeTabConfig();
			ReloadTabConfig();
			while (pContainer) {
				SendMessage(GetDlgItem(pContainer->hwnd, IDC_MSGTABS), EM_THEMECHANGED, 0, 0);
				BroadCastContainer(pContainer, EM_THEMECHANGED, 0, 0);
				pContainer = pContainer->pNextContainer;
			}
			break;
		}

		case DM_SPLITSENDACK: {
			ACKDATA ack = {0};
			struct SendJob *job = sendQueue->getJobByIndex((int)wParam);

			ack.hContact = job->hOwner;
			ack.hProcess = job->hSendId;
			ack.type = ACKTYPE_MESSAGE;
			ack.result = ACKRESULT_SUCCESS;

			if (job->hOwner && job->iAcksNeeded && job->hOwner && job->iStatus == SendQueue::SQ_INPROGRESS) {
				if (IsWindow(job->hwndOwner))
					::SendMessage(job->hwndOwner, HM_EVENTSENT, (WPARAM)MAKELONG(wParam, 0), (LPARAM)&ack);
				else
					sendQueue->ackMessage(0, (WPARAM)MAKELONG(wParam, 0), (LPARAM)&ack);
			}
			return 0;
		}

		case DM_LOGSTATUSCHANGE:
			CGlobals::logStatusChange(wParam, reinterpret_cast<CContactCache *>(lParam));
			return(0);

		case DM_MUCFLASHWORKER: {
			FLASH_PARAMS *p = reinterpret_cast<FLASH_PARAMS*>(lParam);

			if(1 == wParam) {
				CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)p->hContact, 1);
				p->bActiveTab = TRUE;
				p->bInactive = FALSE;
				p->bMustAutoswitch = p->bMustFlash = FALSE;
			}

			if(2 == wParam) {
				p->bActiveTab = TRUE;
				p->bInactive = FALSE;
				p->bMustAutoswitch = p->bMustFlash = FALSE;
				SendMessage(p->hWnd, DM_ACTIVATEME, 0, 0);
			}
			DoFlashAndSoundWorker(p);
			return(0);
		}

		case WM_POWERBROADCAST:
		case WM_DISPLAYCHANGE: {
			struct TContainerData *pContainer = pFirstContainer;

			while (pContainer) {
				if (CSkin::m_skinEnabled) {             // invalidate cached background DCs for skinned containers
					pContainer->oldDCSize.cx = pContainer->oldDCSize.cy = 0;
					SelectObject(pContainer->cachedDC, pContainer->oldHBM);
					DeleteObject(pContainer->cachedHBM);
					DeleteDC(pContainer->cachedDC);
					pContainer->cachedDC = 0;
					RedrawWindow(pContainer->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME);
				}
				pContainer = pContainer->pNextContainer;
			}
			break;
		}

		case WM_ACTIVATE:
			if (LOWORD(wParam) != WA_ACTIVE)
				SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);
			return 0;

		case WM_CLOSE:
			return 0;

		case WM_TIMER:
			if(wParam == TIMERID_SENDLATER) {
				/*
				 * send heartbeat to each open container (to manage autoclose
				 * feature)
				 */
				TContainerData *pContainer = pFirstContainer;
				/*
				 * send heartbeat to each container, they use this to update
				 * dynamic content (i.e. local time in the info panel).
				 */
				while(pContainer) {
					SendMessage(pContainer->hwnd, WM_TIMER, TIMERID_HEARTBEAT, 0);
					pContainer = pContainer->pNextContainer;
				}
				/*
				 * process send later contacts and jobs, if enough time has elapsed
				 */
				if(sendLater->isAvail() && !sendLater->isInteractive() && (time(0) - sendLater->lastProcessed()) > CSendLater::SENDLATER_PROCESS_INTERVAL) {
					sendLater->setLastProcessed(time(0));

					/*
					 * check the list of contacts that may have new send later jobs
					 * (added on user's request)
					 */
					sendLater->processContacts();

					/*
					 * start processing the job list
					 */
					if(!sendLater->isJobListEmpty()) {
						KillTimer(hwndDlg, wParam);
						sendLater->startJobListProcess();
						SetTimer(hwndDlg, TIMERID_SENDLATER_TICK, TIMEOUT_SENDLATER_TICK, 0);
					}
				}
			}
			/*
			 * process one entry per tick (default: 200ms)
			 * TODO better timings, possibly slow down when many jobs are in the
			 * queue.
			 */
			else if(wParam == TIMERID_SENDLATER_TICK) {
				if(!sendLater->haveJobs()) {
					KillTimer(hwndDlg, wParam);
					SetTimer(hwndDlg, TIMERID_SENDLATER, TIMEOUT_SENDLATER, 0);
					sendLater->qMgrUpdate(true);
				}
				else
					sendLater->processCurrentJob();
			}
			break;

		case WM_DESTROY: {
			KillTimer(hwndDlg, TIMERID_SENDLATER_TICK);
			KillTimer(hwndDlg, TIMERID_SENDLATER);
			DestroyServiceFunction(hSvcHotkeyProcessor);
			break;
		}
	}
	return(DefWindowProc(hwndDlg, msg, wParam, lParam));
}
예제 #6
0
/**
 * This just adds the message to the database for later delivery and
 * adds the contact to the list of contacts that have queued messages
 *
 * @param iJobIndex int: index of the send job
 * 		  dat: Message window data
 * 		  fAddHeader: add the "message was sent delayed" header (default = true)
 * 		  hContact  : contact to which the job should be added (default = hOwner of the send job)
 *
 * @return the index on success, -1 on failure
 */
int SendQueue::doSendLater(int iJobIndex, TWindowData *dat, HANDLE hContact, bool fIsSendLater)
{
	bool  fAvail = sendLater->isAvail();

	const TCHAR *szNote = 0;

	if(fIsSendLater && dat) {
		if(fAvail)
			szNote = CTranslator::get(CTranslator::GEN_SQ_QUEUED_MESSAGE);
		else
			szNote = CTranslator::get(CTranslator::GEN_SQ_QUEUING_NOT_AVAIL);

		char  *utfText = M->utf8_encodeT(szNote);
		DBEVENTINFO dbei;
		dbei.cbSize = sizeof(dbei);
		dbei.eventType = EVENTTYPE_MESSAGE;
		dbei.flags = DBEF_SENT | DBEF_UTF;
		dbei.szModule = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0);
		dbei.timestamp = time(NULL);
		dbei.cbBlob = lstrlenA(utfText) + 1;
		dbei.pBlob = (PBYTE) utfText;
		StreamInEvents(dat->hwnd,  0, 1, 1, &dbei);
		if (dat->hDbEventFirst == NULL)
			SendMessage(dat->hwnd, DM_REMAKELOG, 0, 0);
		dat->cache->saveHistory(0, 0);
		EnableSendButton(dat, FALSE);
		if (dat->pContainer->hwndActive == dat->hwnd)
			UpdateReadChars(dat);
		SendDlgItemMessage(dat->hwnd, IDC_SAVE, BM_SETIMAGE, IMAGE_ICON, (LPARAM) PluginConfig.g_buttonBarIcons[ICON_BUTTON_CANCEL]);
		SendDlgItemMessage(dat->hwnd, IDC_SAVE, BUTTONADDTOOLTIP, (WPARAM)pszIDCSAVE_close, 0);
		dat->dwFlags &= ~MWF_SAVEBTN_SAV;
		mir_free(utfText);

		if(!fAvail)
			return(0);
	}

	if(iJobIndex >= 0 && iJobIndex < NR_SENDJOBS) {
		SendJob*	job = &m_jobs[iJobIndex];
		char		szKeyName[20];
		TCHAR 		tszTimestamp[30], tszHeader[150];
		time_t 		now = time(0);

		if(fIsSendLater) {
			TCHAR *formatTime = _T("%Y.%m.%d - %H:%M");
			_tcsftime(tszTimestamp, 30, formatTime, _localtime32((__time32_t *)&now));
			tszTimestamp[29] = 0;
			mir_snprintf(szKeyName, 20, "S%d", now);
			mir_sntprintf(tszHeader, safe_sizeof(tszHeader), CTranslator::get(CTranslator::GEN_SQ_SENDLATER_HEADER), tszTimestamp);
		}
		else
			mir_sntprintf(tszHeader, safe_sizeof(tszHeader), _T("M%d|"), time(0));

		if(job->dwFlags & PREF_UTF || !(job->dwFlags & PREF_UNICODE)) {
			char *utf_header = M->utf8_encodeT(tszHeader);
			UINT required = lstrlenA(utf_header) + lstrlenA(job->sendBuffer) + 10;
			char *tszMsg = reinterpret_cast<char *>(mir_alloc(required));

			if(fIsSendLater) {
				mir_snprintf(tszMsg, required, "%s%s", job->sendBuffer, utf_header);
				DBWriteContactSettingString(hContact ? hContact : job->hOwner, "SendLater", szKeyName, tszMsg);
			}
			else {
				mir_snprintf(tszMsg, required, "%s%s", utf_header, job->sendBuffer);
				sendLater->addJob(tszMsg, (LPARAM)hContact);
			}
			mir_free(utf_header);
			mir_free(tszMsg);
		}
		else if(job->dwFlags & PREF_UNICODE) {
			int iLen = lstrlenA(job->sendBuffer);
			wchar_t *wszMsg = (wchar_t *)&job->sendBuffer[iLen + 1];

			UINT required = sizeof(TCHAR) * (lstrlen(tszHeader) + lstrlenW(wszMsg) + 10);

			TCHAR *tszMsg = reinterpret_cast<TCHAR *>(mir_alloc(required));
			if(fIsSendLater)
				mir_sntprintf(tszMsg, required, _T("%s%s"), wszMsg, tszHeader);
			else
				mir_sntprintf(tszMsg, required, _T("%s%s"), tszHeader, wszMsg);
			char *utf = M->utf8_encodeT(tszMsg);
			if(fIsSendLater)
				DBWriteContactSettingString(hContact ? hContact : job->hOwner, "SendLater", szKeyName, utf);
			else
				sendLater->addJob(utf, (LPARAM)hContact);
			mir_free(utf);
			mir_free(tszMsg);
		}
		if(fIsSendLater) {
			int iCount = M->GetDword(hContact ? hContact : job->hOwner, "SendLater", "count", 0);
			iCount++;
			M->WriteDword(hContact ? hContact : job->hOwner, "SendLater", "count", iCount);
			sendLater->addContact(hContact ? hContact : job->hOwner);
		}
		return(iJobIndex);
	}
	return(-1);
}
예제 #7
0
int SendQueue::ackMessage(TWindowData *dat, WPARAM wParam, LPARAM lParam)
{
	ACKDATA				*ack = (ACKDATA *) lParam;
	DBEVENTINFO			dbei = { 0};
	HANDLE				hNewEvent;
	int					iFound = SendQueue::NR_SENDJOBS, iNextFailed;
	TContainerData *m_pContainer = 0;
	if (dat)
		m_pContainer = dat->pContainer;

	iFound = (int)(LOWORD(wParam));
	//i = (int)(HIWORD(wParam));

	if (m_jobs[iFound].iStatus == SQ_ERROR) {      // received ack for a job which is already in error state...
		if (dat) {                        // window still open
			if (dat->iCurrentQueueError == iFound) {
				dat->iCurrentQueueError = -1;
				showErrorControls(dat, FALSE);
			}
		}
		/*
		 * we must discard this job, because there is no message window open to handle the
		 * error properly. But we display a tray notification to inform the user about the problem.
		 */
		else
			goto inform_and_discard;
	}

	// failed acks are only handled when the window is still open. with no window open, they will be *silently* discarded

	if (ack->result == ACKRESULT_FAILED) {
		if (dat) {
			/*
			 * "hard" errors are handled differently in multisend. There is no option to retry - once failed, they
			 * are discarded and the user is notified with a small log message.
			 */
			if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND))
				SkinPlaySound("SendError");

			TCHAR *szAckMsg = mir_a2t((char *)ack->lParam);
			mir_sntprintf(m_jobs[iFound].szErrorMsg, safe_sizeof(m_jobs[iFound].szErrorMsg),
						 CTranslator::get(CTranslator::GEN_MSG_DELIVERYFAILURE), szAckMsg);
			m_jobs[iFound].iStatus = SQ_ERROR;
			mir_free(szAckMsg);
			KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound);
			if (!(dat->dwFlags & MWF_ERRORSTATE))
				handleError(dat, iFound);
			return 0;
		}
		else {
inform_and_discard:
			_DebugPopup(m_jobs[iFound].hOwner, CTranslator::get(CTranslator::GEN_SQ_DELIVERYFAILEDLATE));
			clearJob(iFound);
			return 0;
		}
	}

	dbei.cbSize = sizeof(dbei);
	dbei.eventType = EVENTTYPE_MESSAGE;
	dbei.flags = DBEF_SENT;
	dbei.szModule = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) m_jobs[iFound].hOwner, 0);
	dbei.timestamp = time(NULL);
	dbei.cbBlob = lstrlenA(m_jobs[iFound].sendBuffer) + 1;

	if (dat)
		dat->cache->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1);
	else {
		CContactCache *c = CContactCache::getContactCache(m_jobs[iFound].hOwner);
		if(c)
			c->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1);
	}

	if (m_jobs[iFound].dwFlags & PREF_UNICODE)
		dbei.cbBlob *= sizeof(TCHAR) + 1;
	if (m_jobs[iFound].dwFlags & PREF_RTL)
		dbei.flags |= DBEF_RTL;
	if (m_jobs[iFound].dwFlags & PREF_UTF)
		dbei.flags |= DBEF_UTF;
	dbei.pBlob = (PBYTE) m_jobs[iFound].sendBuffer;
	hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) m_jobs[iFound].hOwner, (LPARAM) & dbei);

	if (m_pContainer) {
		if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND))
			SkinPlaySound("SendMsg");
	}

	if (dat && (m_jobs[iFound].hOwner == dat->hContact)) {
		if (dat->hDbEventFirst == NULL) {
			dat->hDbEventFirst = hNewEvent;
			SendMessage(dat->hwnd, DM_REMAKELOG, 0, 0);
		}
	}

	m_jobs[iFound].hSendId = NULL;
	m_jobs[iFound].iAcksNeeded--;

	if (m_jobs[iFound].iAcksNeeded == 0) {              // everything sent
		//if (m_jobs[iFound].hOwner != 0 && dat)
		//	EnableSending(dat, TRUE);
		clearJob(iFound);
		if (dat) {
			KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound);
			dat->iOpenJobs--;
		}
		m_currentIndex--;
	}
	if (dat) {
		checkQueue(dat);
		if ((iNextFailed = findNextFailed(dat)) >= 0 && !(dat->dwFlags & MWF_ERRORSTATE))
			handleError(dat, iNextFailed);
		//MAD: close on send mode
		else {
			if (M->GetByte("AutoClose", 0)) {
				if(M->GetByte("adv_AutoClose_2", 0))
					SendMessage(dat->hwnd, WM_CLOSE, 0, 1);
				else
					SendMessage(dat->pContainer->hwnd, WM_CLOSE, 0, 0);
			}
		}
		//MAD_
	}
	return 0;
}
예제 #8
0
/**
 * dialog procedure for the user preferences dialog. Handles the top
 * level window (a tab control with 2 subpages)
 *
 * @params: like any Win32 window procedure
 *
 * @return LRESULT (ignored for dialog procs, use
 *  	   DWLP_MSGRESULT)
 */
INT_PTR CALLBACK DlgProcUserPrefsFrame(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);

	switch(msg) {
		case WM_INITDIALOG: {
			TCITEM tci = {0};
			RECT rcClient;
			TCHAR szBuffer[180];

			hContact = (HANDLE)lParam;
			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hContact);

			WindowList_Add(PluginConfig.hUserPrefsWindowList, hwndDlg, hContact);
			TranslateDialogDefault(hwndDlg);

			GetClientRect(hwndDlg, &rcClient);

			mir_sntprintf(szBuffer, safe_sizeof(szBuffer), CTranslator::getOpt(CTranslator::OPT_UPREFS_TITLE),
						  (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));

			SetWindowText(hwndDlg, szBuffer);

			tci.cchTextMax = 100;
			tci.mask = TCIF_PARAM | TCIF_TEXT;
			tci.lParam = (LPARAM)CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_USERPREFS), hwndDlg, DlgProcUserPrefs, (LPARAM)hContact);
			tci.pszText = const_cast<TCHAR *>(CTranslator::getOpt(CTranslator::OPT_UPREFS_GENERIC));
			TabCtrl_InsertItem(GetDlgItem(hwndDlg, IDC_OPTIONSTAB), 0, &tci);
			MoveWindow((HWND)tci.lParam, 6, DPISCALEY_S(32), rcClient.right - 12, rcClient.bottom - DPISCALEY_S(80), 1);
			ShowWindow((HWND)tci.lParam, SW_SHOW);
			if (CMimAPI::m_pfnEnableThemeDialogTexture)
				CMimAPI::m_pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);


			tci.lParam = (LPARAM)CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_USERPREFS1), hwndDlg, DlgProcUserPrefsLogOptions, (LPARAM)hContact);
			tci.pszText = const_cast<TCHAR *>(CTranslator::getOpt(CTranslator::OPT_UPREFS_MSGLOG));
			TabCtrl_InsertItem(GetDlgItem(hwndDlg, IDC_OPTIONSTAB), 1, &tci);
			MoveWindow((HWND)tci.lParam, 6, DPISCALEY_S(32), rcClient.right - 12, rcClient.bottom - DPISCALEY_S(80), 1);
			ShowWindow((HWND)tci.lParam, SW_HIDE);
			if (CMimAPI::m_pfnEnableThemeDialogTexture)
				CMimAPI::m_pfnEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB);
			TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_OPTIONSTAB), 0);
			ShowWindow(hwndDlg, SW_SHOW);
			return TRUE;
		}
		case WM_NOTIFY:
			switch (((LPNMHDR)lParam)->idFrom) {
				case IDC_OPTIONSTAB:
					switch (((LPNMHDR)lParam)->code) {
						case TCN_SELCHANGING: {
							TCITEM tci;
							tci.mask = TCIF_PARAM;

							TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_OPTIONSTAB)), &tci);
							ShowWindow((HWND)tci.lParam, SW_HIDE);
						}
						break;
						case TCN_SELCHANGE: {
							TCITEM tci;
							tci.mask = TCIF_PARAM;

							TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_OPTIONSTAB), TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_OPTIONSTAB)), &tci);
							ShowWindow((HWND)tci.lParam, SW_SHOW);
						}
						break;
					}
					break;
			}
			break;
		case WM_COMMAND: {
			switch(LOWORD(wParam)) {
				case IDOK: {
					TCITEM	tci;
					int		i, count;
					DWORD	dwActionToTake = 0;			// child pages request which action to take
					HWND	hwnd = M->FindWindow(hContact);

					tci.mask = TCIF_PARAM;

					count = TabCtrl_GetItemCount(GetDlgItem(hwndDlg, IDC_OPTIONSTAB));
					for (i = 0;i < count;i++) {
						TabCtrl_GetItem(GetDlgItem(hwndDlg, IDC_OPTIONSTAB), i, &tci);
						SendMessage((HWND)tci.lParam, WM_COMMAND, WM_USER + 100, (LPARAM)&dwActionToTake);
					}
					if(hwnd) {
						struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
						if(dat) {
							DWORD	dwOldFlags = (dat->dwFlags & MWF_LOG_ALL);

							SetDialogToType(hwnd);
#if defined(__FEAT_DEPRECATED_DYNAMICSWITCHLOGVIEWER)
							if(dwActionToTake & UPREF_ACTION_SWITCHLOGVIEWER) {
								unsigned int mode = GetIEViewMode(hwndDlg, dat->hContact);
								SwitchMessageLog(dat, mode);
							}
#endif
							LoadLocalFlags(hwnd, dat);
							if((dat->dwFlags & MWF_LOG_ALL) != dwOldFlags) {
								BOOL	fShouldHide = TRUE;

								if(IsIconic(dat->pContainer->hwnd))
									fShouldHide = FALSE;
								else
									ShowWindow(dat->pContainer->hwnd, SW_HIDE);
								SendMessage(hwnd, DM_OPTIONSAPPLIED, 0, 0);
								SendMessage(hwnd, DM_DEFERREDREMAKELOG, (WPARAM)hwnd, 0);
								if(fShouldHide)
									ShowWindow(dat->pContainer->hwnd, SW_SHOWNORMAL);
							}
						}
					}
					DestroyWindow(hwndDlg);
					break;
				}
				case IDCANCEL:
					DestroyWindow(hwndDlg);
					break;
			}
			break;
		}
		case WM_DESTROY:
			WindowList_Remove(PluginConfig.hUserPrefsWindowList, hwndDlg);
			break;
	}
	return FALSE;
}
예제 #9
0
INT_PTR CALLBACK DlgProcTemplateEditor(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	struct TWindowData *dat = 0;
	TemplateEditorInfo *teInfo = 0;
	TTemplateSet *tSet;
	int i;
	dat = (struct TWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
	/*
	* since this dialog needs a struct MessageWindowData * but has no container, we can store
	* the extended info struct in pContainer *)
	*/
	if (dat) {
		teInfo = (TemplateEditorInfo *)dat->pContainer;
		tSet = teInfo->rtl ? dat->pContainer->rtl_templates : dat->pContainer->ltr_templates;
	}

	switch (msg) {
		case WM_INITDIALOG: {
			TemplateEditorNew *teNew = (TemplateEditorNew *)lParam;
			COLORREF url_visited = RGB(128, 0, 128);
			COLORREF url_unvisited = RGB(0, 0, 255);
			dat = (struct TWindowData *) malloc(sizeof(struct TWindowData));

			TranslateDialogDefault(hwndDlg);

			ZeroMemory((void *) dat, sizeof(struct TWindowData));
			dat->pContainer = (struct TContainerData *)malloc(sizeof(struct TContainerData));
			ZeroMemory((void *)dat->pContainer, sizeof(struct TContainerData));
			teInfo = (TemplateEditorInfo *)dat->pContainer;
			ZeroMemory((void *)teInfo, sizeof(TemplateEditorInfo));
			teInfo->hContact = teNew->hContact;
			teInfo->rtl = teNew->rtl;
			teInfo->hwndParent = teNew->hwndParent;

			LoadOverrideTheme(dat->pContainer);
			/*
			* set hContact to the first found contact so that we can use the Preview window properly
			* also, set other parameters needed by the streaming function to display events
			*/

			SendDlgItemMessage(hwndDlg, IDC_PREVIEW, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK);
			SendDlgItemMessage(hwndDlg, IDC_PREVIEW, EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR);
			SendDlgItemMessage(hwndDlg, IDC_PREVIEW, EM_EXLIMITTEXT, 0, 0x80000000);

			dat->hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
			dat->szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0);
			while(dat->szProto == 0 && dat->hContact != 0) {
				dat->hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)dat->hContact, 0);
				dat->szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0);
			}
			dat->dwFlags = dat->pContainer->theme.dwFlags;

			dat->cache = CContactCache::getContactCache(dat->hContact);
			dat->cache->updateState();
			dat->cache->updateUIN();
			dat->cache->updateStats(TSessionStats::INIT_TIMER);
			GetMYUIN(dat);

			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dat);
			ShowWindow(hwndDlg, SW_SHOW);
			SendDlgItemMessage(hwndDlg, IDC_EDITTEMPLATE, EM_LIMITTEXT, (WPARAM)TEMPLATE_LENGTH - 1, 0);
			SetWindowText(hwndDlg, CTranslator::getOpt(CTranslator::OPT_TEMP_TITLE));
			Utils::enableDlgControl(hwndDlg, IDC_SAVETEMPLATE, FALSE);
			Utils::enableDlgControl(hwndDlg, IDC_REVERT, FALSE);
			Utils::enableDlgControl(hwndDlg, IDC_FORGET, FALSE);
			for (i = 0; i <= TMPL_ERRMSG; i++) {
				SendDlgItemMessageA(hwndDlg, IDC_TEMPLATELIST, LB_ADDSTRING, 0, (LPARAM)Translate(TemplateNames[i]));
				SendDlgItemMessage(hwndDlg, IDC_TEMPLATELIST, LB_SETITEMDATA, i, (LPARAM)i);
			}
			Utils::enableDlgControl(teInfo->hwndParent, IDC_MODIFY, FALSE);
			Utils::enableDlgControl(teInfo->hwndParent, IDC_RTLMODIFY, FALSE);

			SendDlgItemMessage(hwndDlg, IDC_COLOR1, CPM_SETCOLOUR, 0, M->GetDword("cc1", SRMSGDEFSET_BKGCOLOUR));
			SendDlgItemMessage(hwndDlg, IDC_COLOR2, CPM_SETCOLOUR, 0, M->GetDword("cc2", SRMSGDEFSET_BKGCOLOUR));
			SendDlgItemMessage(hwndDlg, IDC_COLOR3, CPM_SETCOLOUR, 0, M->GetDword("cc3", SRMSGDEFSET_BKGCOLOUR));
			SendDlgItemMessage(hwndDlg, IDC_COLOR4, CPM_SETCOLOUR, 0, M->GetDword("cc4", SRMSGDEFSET_BKGCOLOUR));
			SendDlgItemMessage(hwndDlg, IDC_COLOR5, CPM_SETCOLOUR, 0, M->GetDword("cc5", SRMSGDEFSET_BKGCOLOUR));
			SendMessage(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE), EM_SETREADONLY, TRUE, 0);
			return(TRUE);
		}
		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDCANCEL:
					DestroyWindow(hwndDlg);
					break;
				case IDC_RESETALLTEMPLATES:
					if (MessageBox(0, CTranslator::getOpt(CTranslator::OPT_TEMP_RESET),
								   CTranslator::getOpt(CTranslator::OPT_TEMP_TITLE), MB_YESNO | MB_ICONQUESTION) == IDYES) {
						M->WriteByte(teInfo->rtl ? RTLTEMPLATES_MODULE : TEMPLATES_MODULE, "setup", 0);
						LoadDefaultTemplates();
						MessageBox(0, CTranslator::getOpt(CTranslator::OPT_TEMP_WASRESET),
								   CTranslator::getOpt(CTranslator::OPT_TEMP_TITLE), MB_OK);
						DestroyWindow(hwndDlg);
					}
					break;
				case IDC_TEMPLATELIST:
					switch (HIWORD(wParam)) {
						case LBN_DBLCLK: {
							LRESULT iIndex = SendDlgItemMessage(hwndDlg, IDC_TEMPLATELIST, LB_GETCURSEL, 0, 0);
							if (iIndex != LB_ERR) {
								SetDlgItemText(hwndDlg, IDC_EDITTEMPLATE, tSet->szTemplates[iIndex]);
								teInfo->inEdit = iIndex;
								teInfo->changed = FALSE;
								teInfo->selchanging = FALSE;
								SetFocus(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE));
								SendMessage(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE), EM_SETREADONLY, FALSE, 0);
							}
							break;
						}
						case LBN_SELCHANGE: {
							LRESULT iIndex = SendDlgItemMessage(hwndDlg, IDC_TEMPLATELIST, LB_GETCURSEL, 0, 0);
							teInfo->selchanging = TRUE;
							if (iIndex != LB_ERR) {
								SetDlgItemText(hwndDlg, IDC_EDITTEMPLATE, tSet->szTemplates[iIndex]);
								teInfo->inEdit = iIndex;
								teInfo->changed = FALSE;
							}
							SendMessage(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE), EM_SETREADONLY, TRUE, 0);
							break;
						}
					}
					break;
				case IDC_VARIABLESHELP:
					CallService(MS_UTILS_OPENURL, 0, (LPARAM)"http://wiki.miranda.or.at/TabSRMM/Templates");
					break;
				case IDC_EDITTEMPLATE:
					if (HIWORD(wParam) == EN_CHANGE) {
						if (!teInfo->selchanging) {
							teInfo->changed = TRUE;
							teInfo->updateInfo[teInfo->inEdit] = TRUE;
							Utils::enableDlgControl(hwndDlg, IDC_SAVETEMPLATE, TRUE);
							Utils::enableDlgControl(hwndDlg, IDC_FORGET, TRUE);
							Utils::enableDlgControl(hwndDlg, IDC_TEMPLATELIST, FALSE);
							Utils::enableDlgControl(hwndDlg, IDC_REVERT, TRUE);
						}
						InvalidateRect(GetDlgItem(hwndDlg, IDC_TEMPLATELIST), NULL, FALSE);
					}
					break;
				case IDC_SAVETEMPLATE: {
					TCHAR newTemplate[TEMPLATE_LENGTH + 2];

					GetWindowText(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE), newTemplate, TEMPLATE_LENGTH);
					CopyMemory(tSet->szTemplates[teInfo->inEdit], newTemplate, sizeof(TCHAR) * TEMPLATE_LENGTH);
					teInfo->changed = FALSE;
					teInfo->updateInfo[teInfo->inEdit] = FALSE;
					Utils::enableDlgControl(hwndDlg, IDC_SAVETEMPLATE, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_FORGET, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_TEMPLATELIST, TRUE);
					Utils::enableDlgControl(hwndDlg, IDC_REVERT, FALSE);
					InvalidateRect(GetDlgItem(hwndDlg, IDC_TEMPLATELIST), NULL, FALSE);
					M->WriteTString(teInfo->hContact, teInfo->rtl ? RTLTEMPLATES_MODULE : TEMPLATES_MODULE, TemplateNames[teInfo->inEdit], newTemplate);
					SendMessage(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE), EM_SETREADONLY, TRUE, 0);
					break;
				}
				case IDC_FORGET: {
					teInfo->changed = FALSE;
					teInfo->updateInfo[teInfo->inEdit] = FALSE;
					teInfo->selchanging = TRUE;
					SetDlgItemText(hwndDlg, IDC_EDITTEMPLATE, tSet->szTemplates[teInfo->inEdit]);
					SetFocus(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE));
					InvalidateRect(GetDlgItem(hwndDlg, IDC_TEMPLATELIST), NULL, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_SAVETEMPLATE, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_FORGET, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_TEMPLATELIST, TRUE);
					Utils::enableDlgControl(hwndDlg, IDC_REVERT, FALSE);
					teInfo->selchanging = FALSE;
					SendMessage(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE), EM_SETREADONLY, TRUE, 0);
					break;
				}
				case IDC_REVERT: {
					teInfo->changed = FALSE;
					teInfo->updateInfo[teInfo->inEdit] = FALSE;
					teInfo->selchanging = TRUE;
					CopyMemory(tSet->szTemplates[teInfo->inEdit], LTR_Default.szTemplates[teInfo->inEdit], sizeof(TCHAR) * TEMPLATE_LENGTH);
					SetDlgItemText(hwndDlg, IDC_EDITTEMPLATE, tSet->szTemplates[teInfo->inEdit]);
					DBDeleteContactSetting(teInfo->hContact, teInfo->rtl ? RTLTEMPLATES_MODULE : TEMPLATES_MODULE, TemplateNames[teInfo->inEdit]);
					SetFocus(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE));
					InvalidateRect(GetDlgItem(hwndDlg, IDC_TEMPLATELIST), NULL, FALSE);
					teInfo->selchanging = FALSE;
					Utils::enableDlgControl(hwndDlg, IDC_SAVETEMPLATE, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_REVERT, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_FORGET, FALSE);
					Utils::enableDlgControl(hwndDlg, IDC_TEMPLATELIST, TRUE);
					SendMessage(GetDlgItem(hwndDlg, IDC_EDITTEMPLATE), EM_SETREADONLY, TRUE, 0);
					break;
				}
				case IDC_UPDATEPREVIEW:
					SendMessage(hwndDlg, DM_UPDATETEMPLATEPREVIEW, 0, 0);
					break;
			}
			break;
		case WM_DRAWITEM: {
			DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam;
			int iItem = dis->itemData;
			HBRUSH bkg, oldBkg;
			SetBkMode(dis->hDC, TRANSPARENT);
			FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_WINDOW));
			if (dis->itemState & ODS_SELECTED) {
				if (teInfo->updateInfo[iItem] == TRUE) {
					bkg = CreateSolidBrush(RGB(255, 0, 0));
					oldBkg = (HBRUSH)SelectObject(dis->hDC, bkg);
					FillRect(dis->hDC, &dis->rcItem, bkg);
					SelectObject(dis->hDC, oldBkg);
					DeleteObject(bkg);
				} else
					FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));

				SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
			} else {
				if (teInfo->updateInfo[iItem] == TRUE)
					SetTextColor(dis->hDC, RGB(255, 0, 0));
				else
					SetTextColor(dis->hDC, GetSysColor(COLOR_WINDOWTEXT));
			}
			char *pszName = Translate(TemplateNames[iItem]);
			TextOutA(dis->hDC, dis->rcItem.left, dis->rcItem.top, pszName, lstrlenA(pszName));
			return(TRUE);
		}
		case DM_UPDATETEMPLATEPREVIEW: {
			DBEVENTINFO dbei = {0};
			int iIndex = SendDlgItemMessage(hwndDlg, IDC_TEMPLATELIST, LB_GETCURSEL, 0, 0);
			TCHAR szTemp[TEMPLATE_LENGTH + 2];

			if (teInfo->changed) {
				CopyMemory(szTemp, tSet->szTemplates[teInfo->inEdit], TEMPLATE_LENGTH * sizeof(TCHAR));
				GetDlgItemText(hwndDlg, IDC_EDITTEMPLATE, tSet->szTemplates[teInfo->inEdit], TEMPLATE_LENGTH);
			}
			dbei.szModule = dat->szProto;
			dbei.timestamp = time(NULL);
			dbei.eventType = (iIndex == 6) ? EVENTTYPE_STATUSCHANGE : EVENTTYPE_MESSAGE;
			dbei.eventType = (iIndex == 7) ? EVENTTYPE_ERRMSG : dbei.eventType;
			if (dbei.eventType == EVENTTYPE_ERRMSG)
				dbei.szModule = "Sample error message";
			dbei.cbSize = sizeof(dbei);
			dbei.pBlob = (iIndex == 6) ? (BYTE *)"is now offline (was online)" : (BYTE *)"The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.";
			dbei.cbBlob = lstrlenA((char *)dbei.pBlob) + 1;
			dbei.flags = (iIndex == 1 || iIndex == 3 || iIndex == 5) ? DBEF_SENT : 0;
			dbei.flags |= (teInfo->rtl ? DBEF_RTL : 0);
			dat->lastEventTime = (iIndex == 4 || iIndex == 5) ? time(NULL) - 1 : 0;
			dat->iLastEventType = MAKELONG(dbei.flags, dbei.eventType);
			SetWindowText(GetDlgItem(hwndDlg, IDC_PREVIEW), _T(""));
			dat->dwFlags = MWF_LOG_ALL;
			dat->dwFlags = (teInfo->rtl ? dat->dwFlags | MWF_LOG_RTL : dat->dwFlags & ~MWF_LOG_RTL);
			dat->dwFlags = (iIndex == 0 || iIndex == 1) ? dat->dwFlags & ~MWF_LOG_GROUPMODE : dat->dwFlags | MWF_LOG_GROUPMODE;
			mir_sntprintf(dat->szMyNickname, safe_sizeof(dat->szMyNickname), _T("My Nickname"));
			StreamInEvents(hwndDlg, 0, 1, 1, &dbei);
			SendDlgItemMessage(hwndDlg, IDC_PREVIEW, EM_SETSEL, -1, -1);
			if (teInfo->changed)
				CopyMemory(tSet->szTemplates[teInfo->inEdit], szTemp, TEMPLATE_LENGTH * sizeof(TCHAR));
			break;
		}
		case WM_DESTROY:
			Utils::enableDlgControl(teInfo->hwndParent, IDC_MODIFY, TRUE);
			Utils::enableDlgControl(teInfo->hwndParent, IDC_RTLMODIFY, TRUE);
			if (dat->pContainer)
				free(dat->pContainer);
			if (dat)
				free(dat);

			M->WriteDword(SRMSGMOD_T, "cc1", SendDlgItemMessage(hwndDlg, IDC_COLOR1, CPM_GETCOLOUR, 0, 0));
			M->WriteDword(SRMSGMOD_T, "cc2", SendDlgItemMessage(hwndDlg, IDC_COLOR2, CPM_GETCOLOUR, 0, 0));
			M->WriteDword(SRMSGMOD_T, "cc3", SendDlgItemMessage(hwndDlg, IDC_COLOR3, CPM_GETCOLOUR, 0, 0));
			M->WriteDword(SRMSGMOD_T, "cc4", SendDlgItemMessage(hwndDlg, IDC_COLOR4, CPM_GETCOLOUR, 0, 0));
			M->WriteDword(SRMSGMOD_T, "cc5", SendDlgItemMessage(hwndDlg, IDC_COLOR5, CPM_GETCOLOUR, 0, 0));

			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
			break;
	}
	return(FALSE);
}
INT_PTR CALLBACK SelectContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HWND hwndMsgDlg = 0;

    hwndMsgDlg = (HWND) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);

    switch (msg) {
    case WM_INITDIALOG: {
        TCHAR szNewTitle[128];
        RECT rc, rcParent;
        struct TContainerData *pContainer = 0;

        SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) lParam);
        hwndMsgDlg = (HWND) lParam;

        TranslateDialogDefault(hwndDlg);

        if (lParam) {
            struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr((HWND)lParam, GWLP_USERDATA);
            if (dat) {
                mir_sntprintf(szNewTitle, safe_sizeof(szNewTitle), CTranslator::get(CTranslator::CNT_SELECT_FOR), dat->cache->getNick());
                SetWindowText(hwndDlg, szNewTitle);
            }
        }

        SendMessage(hwndDlg, DM_SC_BUILDLIST, 0, 0);
        SendDlgItemMessage(hwndDlg, IDC_NEWCONTAINERNAME, EM_LIMITTEXT, (WPARAM)CONTAINER_NAMELEN, 0);
        SendDlgItemMessage(hwndDlg, IDC_NEWCONTAINER, EM_LIMITTEXT, (WPARAM)CONTAINER_NAMELEN, 0);

        GetWindowRect(hwndDlg, &rc);
        GetWindowRect(GetParent(hwndDlg), &rcParent);
        SetWindowPos(hwndDlg, 0, (rcParent.left + rcParent.right - (rc.right - rc.left)) / 2, (rcParent.top + rcParent.bottom - (rc.bottom - rc.top)) / 2, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
        return TRUE;
    }

    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case IDOK: {
            TCHAR szName[CONTAINER_NAMELEN];
            LRESULT iItem;

            if ((iItem = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETCURSEL, 0, 0)) != LB_ERR) {
                SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETTEXT, (WPARAM) iItem, (LPARAM) szName);
                if (IsWindow(hwndMsgDlg))
                    SendMessage(hwndMsgDlg, DM_CONTAINERSELECTED, 0, (LPARAM) szName);
            }
            if (IsWindow(hwndDlg))
                DestroyWindow(hwndDlg);
            break;
        }
        case IDCANCEL:
            DestroyWindow(hwndDlg);
            break;
        case IDC_DELETECONTAINER: {
            TCHAR szName[CONTAINER_NAMELEN + 1];
            LRESULT iItem;

            if ((iItem = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETCURSEL, 0, 0)) != LB_ERR) {
                SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETTEXT, (WPARAM) iItem, (LPARAM) szName);
                if (!_tcsncmp(szName, _T("default"), CONTAINER_NAMELEN) || !_tcsncmp(szName, CTranslator::get(CTranslator::GEN_DEFAULT_CONTAINER_NAME), CONTAINER_NAMELEN))
                    MessageBox(hwndDlg, CTranslator::get(CTranslator::CNT_SELECT_DELETEERROR), _T("Error"), MB_OK | MB_ICONERROR);
                else {
                    int iIndex = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETITEMDATA, (WPARAM)iItem, 0);
                    DeleteContainer(iIndex);
                    SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_RESETCONTENT, 0, 0);
                    SendMessage(hwndDlg, DM_SC_BUILDLIST, 0, 0);
                    BuildContainerMenu();
                }
            }
            break;
        }
        case IDC_RENAMECONTAINER: {
            TCHAR szNewName[CONTAINER_NAMELEN], szName[CONTAINER_NAMELEN + 1];
            int iLen, iItem;
            struct TContainerData *pCurrent = pFirstContainer;

            iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_NEWCONTAINERNAME));
            if (iLen) {
                GetWindowText(GetDlgItem(hwndDlg, IDC_NEWCONTAINERNAME), szNewName, CONTAINER_NAMELEN);
                if(!_tcsncmp(szNewName, CGlobals::m_default_container_name, CONTAINER_NAMELEN) || !_tcsncmp(szNewName, CTranslator::get(CTranslator::GEN_DEFAULT_CONTAINER_NAME), CONTAINER_NAMELEN)) {
                    MessageBox(hwndDlg, CTranslator::get(CTranslator::CNT_SELECT_RENAMEERROR), _T("Error"), MB_OK | MB_ICONERROR);
                    break;
                }

                iItem = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_FINDSTRING, (WPARAM) - 1, (LPARAM) szNewName);
                if (iItem != LB_ERR) {
                    TCHAR szOldName[CONTAINER_NAMELEN + 1];
                    SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETTEXT, (WPARAM) iItem, (LPARAM) szOldName);
                    if (lstrlen(szOldName) == lstrlen(szNewName)) {
                        MessageBox(0, CTranslator::get(CTranslator::CNT_SELECT_INUSE), _T("Error"), MB_OK | MB_ICONERROR);
                        SetFocus(GetDlgItem(hwndDlg, IDC_NEWCONTAINERNAME));
                        break;
                    }
                }
                if ((iItem = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETCURSEL, 0, 0)) != LB_ERR) {
                    SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETTEXT, (WPARAM) iItem, (LPARAM) szName);
                    if (!_tcsncmp(szName, _T("default"), CONTAINER_NAMELEN) || !_tcsncmp(szName, CTranslator::get(CTranslator::GEN_DEFAULT_CONTAINER_NAME), CONTAINER_NAMELEN))
                        MessageBox(hwndDlg, CTranslator::get(CTranslator::CNT_SELECT_RENAMEERROR), _T("Error"), MB_OK | MB_ICONERROR);
                    else {
                        int iIndex = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETITEMDATA, (WPARAM)iItem, 0);
                        RenameContainer(iIndex, szNewName);
                        SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_RESETCONTENT, 0, 0);
                        while (pCurrent) {
                            if (!_tcsncmp(pCurrent->szName, szName, CONTAINER_NAMELEN) && lstrlen(pCurrent->szName) == lstrlen(szName)) {
                                _tcsncpy(pCurrent->szName, szNewName, CONTAINER_NAMELEN);
                                SendMessage(pCurrent->hwnd, DM_CONFIGURECONTAINER, 0, 0);
                            }
                            pCurrent = pCurrent->pNextContainer;
                        }
                        SendMessage(hwndDlg, DM_SC_BUILDLIST, 0, 0);
                        BuildContainerMenu();
                    }
                }
            }
            break;
        }
        case IDC_CREATENEW: {
            int iLen, iItem;
            TCHAR szNewName[CONTAINER_NAMELEN], szName[CONTAINER_NAMELEN + 1];

            iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_NEWCONTAINER));
            if (iLen) {
                GetWindowText(GetDlgItem(hwndDlg, IDC_NEWCONTAINER), szNewName, CONTAINER_NAMELEN);
                iItem = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_FINDSTRING, (WPARAM) - 1, (LPARAM) szNewName);
                if (iItem != LB_ERR || !_tcsncmp(szNewName, CGlobals::m_default_container_name, CONTAINER_NAMELEN)) {
                    SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_GETTEXT, (WPARAM)iItem, (LPARAM)szName);
                    if (lstrlen(szName) == lstrlen(szNewName) || !_tcsncmp(szNewName, CGlobals::m_default_container_name, CONTAINER_NAMELEN)) {
                        MessageBox(0, CTranslator::get(CTranslator::CNT_SELECT_INUSE), _T("Error"), MB_OK | MB_ICONERROR);
                        SetFocus(GetDlgItem(hwndDlg, IDC_NEWCONTAINER));
                        break;
                    }
                }
                if (IsWindow(hwndMsgDlg)) {
                    SendMessage(hwndMsgDlg, DM_CONTAINERSELECTED, 0, (LPARAM) szNewName);
                    if (IsWindow(hwndDlg))
                        DestroyWindow(hwndDlg);
                }
            }
            break;
        }
        case IDC_CNTLIST:
            if (HIWORD(wParam) == LBN_DBLCLK)
                SendMessage(hwndDlg, WM_COMMAND, IDOK, 0);
            break;
        }
        break;
    /*
     * fill the list box...
     */
    case DM_SC_BUILDLIST: {
        DBVARIANT dbv;
        int iCounter = 0, iItemNew;
        char *szKey = "TAB_ContainersW";
        char szValue[10];
        struct TContainerData *pContainer = 0;
        do {
            _snprintf(szValue, 8, "%d", iCounter);
            if (M->GetTString(NULL, szKey, szValue, &dbv))
                break;          // end of list
            if (dbv.type == DBVT_ASCIIZ || dbv.type == DBVT_WCHAR) {
                if (_tcsncmp(dbv.ptszVal, _T("**free**"), CONTAINER_NAMELEN)) {
                    iItemNew = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_ADDSTRING, 0, (LPARAM)(!_tcscmp(dbv.ptszVal, _T("default")) ?
                                                  CTranslator::get(CTranslator::GEN_DEFAULT_CONTAINER_NAME) : dbv.ptszVal));
                    if (iItemNew != LB_ERR)
                        SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_SETITEMDATA, (WPARAM)iItemNew, (LPARAM)iCounter);
                }
                DBFreeVariant(&dbv);
            }
        } while (++iCounter);

        /*
         * highlight the name of the container to which the message window currently is assigned
         */

        SendMessage(hwndMsgDlg, DM_QUERYCONTAINER, 0, (LPARAM)&pContainer);
        if (pContainer) {
            LRESULT iItem;

            iItem = SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_FINDSTRING, (WPARAM) - 1, (LPARAM)(!_tcscmp(pContainer->szName, _T("default")) ?
                                       CTranslator::get(CTranslator::GEN_DEFAULT_CONTAINER_NAME) : pContainer->szName));
            if (iItem != LB_ERR)
                SendDlgItemMessage(hwndDlg, IDC_CNTLIST, LB_SETCURSEL, (WPARAM) iItem, 0);
        }
    }
    break;
    }
    return FALSE;
}
예제 #11
0
int __fastcall CLVM_GetContactHiddenStatus(MCONTACT hContact, char *szProto, struct ClcData *dat)
{
    int dbHidden = cfg::getByte(hContact, "CList", "Hidden", 0);		// default hidden state, always respect it.
    int filterResult = 1;
    DBVARIANT dbv = {0};
    char szTemp[64];
    wchar_t szGroupMask[256];
    DWORD dwLocalMask;

    // always hide subcontacts (but show them on embedded contact lists)

    if(cfg::dat.bMetaAvail && dat != NULL && dat->bHideSubcontacts && cfg::dat.bMetaEnabled && cfg::getByte(hContact, cfg::dat.szMetaName, "IsSubcontact", 0))
        return 1;

    if(cfg::dat.bFilterEffective) {
		if (szProto == NULL)
			szProto = GetContactProto(hContact);
		// check stickies first (priority), only if we really have stickies defined (CLVM_STICKY_CONTACTS is set).
        if(cfg::dat.bFilterEffective & CLVM_STICKY_CONTACTS) {
            if((dwLocalMask = cfg::getDword(hContact, "CLVM", cfg::dat.current_viewmode, 0)) != 0) {
                if(cfg::dat.bFilterEffective & CLVM_FILTER_STICKYSTATUS) {
                    WORD wStatus = cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
                    return !((1 << (wStatus - ID_STATUS_OFFLINE)) & HIWORD(dwLocalMask));
                }
                return 0;
            }
        }
        // check the proto, use it as a base filter result for all further checks
		if(cfg::dat.bFilterEffective & CLVM_FILTER_PROTOS) {
            mir_snprintf(szTemp, sizeof(szTemp), "%s|", szProto);
            filterResult = strstr(cfg::dat.protoFilter, szTemp) ? 1 : 0;
        }
        if(cfg::dat.bFilterEffective & CLVM_FILTER_GROUPS) {
            if(!cfg::getTString(hContact, "CList", "Group", &dbv)) {
                _sntprintf(szGroupMask, safe_sizeof(szGroupMask), _T("%s|"), &dbv.ptszVal[1]);
                filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? (filterResult | (_tcsstr(cfg::dat.groupFilter, szGroupMask) ? 1 : 0)) : (filterResult & (_tcsstr(cfg::dat.groupFilter, szGroupMask) ? 1 : 0));
                mir_free(dbv.ptszVal);
            }
            else if(cfg::dat.filterFlags & CLVM_INCLUDED_UNGROUPED)
                filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 1;
            else
                filterResult = (cfg::dat.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 0;
        }
        if(cfg::dat.bFilterEffective & CLVM_FILTER_STATUS) {
            WORD wStatus = cfg::getWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
            filterResult = (cfg::dat.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & cfg::dat.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & cfg::dat.statusMaskFilter ? 1 : 0));
        }
		if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG) {
			DWORD now;
			int iEntry = cfg::getCache(hContact, szProto);
			if(iEntry >= 0 && iEntry <= cfg::nextCacheEntry) {
				now = cfg::dat.t_now;
				now -= cfg::dat.lastMsgFilter;
				if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG_OLDERTHAN)
					filterResult = filterResult & (cfg::eCache[iEntry].dwLastMsgTime < now);
				else if(cfg::dat.bFilterEffective & CLVM_FILTER_LASTMSG_NEWERTHAN)
					filterResult = filterResult & (cfg::eCache[iEntry].dwLastMsgTime > now);
			}
		}
        return (dbHidden | !filterResult);
    }
    else
        return dbHidden;
}