summaryrefslogtreecommitdiff
path: root/plugins/NewXstatusNotify/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/NewXstatusNotify/src')
-rw-r--r--plugins/NewXstatusNotify/src/common.h154
-rw-r--r--plugins/NewXstatusNotify/src/indsnd.cpp681
-rw-r--r--plugins/NewXstatusNotify/src/indsnd.h41
-rw-r--r--plugins/NewXstatusNotify/src/main.cpp1369
-rw-r--r--plugins/NewXstatusNotify/src/options.cpp1074
-rw-r--r--plugins/NewXstatusNotify/src/options.h90
-rw-r--r--plugins/NewXstatusNotify/src/popup.cpp175
-rw-r--r--plugins/NewXstatusNotify/src/popup.h54
-rw-r--r--plugins/NewXstatusNotify/src/resource.h147
-rw-r--r--plugins/NewXstatusNotify/src/utils.cpp124
-rw-r--r--plugins/NewXstatusNotify/src/utils.h33
-rw-r--r--plugins/NewXstatusNotify/src/version.h4
-rw-r--r--plugins/NewXstatusNotify/src/xstatus.cpp524
-rw-r--r--plugins/NewXstatusNotify/src/xstatus.h106
14 files changed, 4576 insertions, 0 deletions
diff --git a/plugins/NewXstatusNotify/src/common.h b/plugins/NewXstatusNotify/src/common.h
new file mode 100644
index 0000000000..3cc765af4d
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/common.h
@@ -0,0 +1,154 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ 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
+*/
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#pragma once
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#define _CRT_SECURE_NO_WARNINGS
+
+#define _WIN32_WINNT 0x0500
+#define WINVER 0x0600
+#define MIRANDA_VER 0x0A00
+
+//Standard Windows "libraries"
+#include <windows.h>
+#include <mmsystem.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <shellapi.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <tchar.h>
+#include <malloc.h>
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <statusmodes.h>
+#include <win2k.h>
+
+#include "m_awaymsg.h"
+#include "m_button.h"
+#include "m_clc.h"
+#include "m_database.h"
+#include "m_genmenu.h"
+#include "m_history.h"
+#include "m_icolib.h"
+#include "m_ignore.h"
+#include "m_langpack.h"
+#include "m_message.h"
+#include "m_options.h"
+#include "m_popup.h"
+#include "m_protosvc.h"
+#include "m_skin.h"
+#include "m_system.h"
+#include "m_userinfo.h"
+#include "m_utils.h"
+#include "m_icq.h"
+
+#include "m_metacontacts.h"
+#include "m_toptoolbar.h"
+#include "resource.h"
+
+#define MIID_NXSN { 0xebf19652, 0xe434, 0x4d79, { 0x98, 0x97, 0x91, 0xa0, 0xff, 0x22, 0x6f, 0x51 } }
+
+#define MODULE "NewStatusNotify"
+
+#define WM_AWAYMSG WM_USER + 0x0192
+
+#define MAX_STATUSTEXT 36
+#define MAX_STANDARDTEXT 36
+#define MAX_SKINSOUNDNAME 36
+#define MAX_SKINSOUNDDESC 36
+
+#define GENDER_UNSPECIFIED 0
+#define GENDER_MALE 1
+#define GENDER_FEMALE 2
+
+#define ID_STATUS_FROMOFFLINE 1
+#define ID_STATUS_EXTRASTATUS 40081
+#define ID_STATUS_MIN ID_STATUS_OFFLINE
+#define ID_STATUS_MAX ID_STATUS_OUTTOLUNCH
+#define ID_STATUS_MAX2 ID_STATUS_EXTRASTATUS + 1
+#define STATUS_COUNT ID_STATUS_MAX2 - ID_STATUS_MIN
+#define Index(ID_STATUS) ID_STATUS - ID_STATUS_OFFLINE
+
+#define COLOR_BG_AVAILDEFAULT RGB(173,206,247)
+#define COLOR_BG_NAVAILDEFAULT RGB(255,189,189)
+#define COLOR_TX_DEFAULT RGB(0,0,0)
+
+#define ICO_NOTIFICATION_OFF "notification_off"
+#define ICO_NOTIFICATION_ON "notification_on"
+
+#define JS_PARSE_XMPP_URI "/ParseXmppURI"
+
+typedef struct tagSTATUS
+{
+ int ID;
+ int icon;
+ TCHAR lpzMStatusText[MAX_STATUSTEXT];
+ TCHAR lpzFStatusText[MAX_STATUSTEXT];
+ TCHAR lpzUStatusText[MAX_STATUSTEXT];
+ TCHAR lpzStandardText[MAX_STANDARDTEXT];
+ char lpzSkinSoundName[MAX_SKINSOUNDNAME];
+ char lpzSkinSoundDesc[MAX_SKINSOUNDDESC];
+ char lpzSkinSoundFile[MAX_PATH];
+ COLORREF colorBack;
+ COLORREF colorText;
+} STATUS;
+
+typedef struct tagPLUGINDATA
+{
+ WORD newStatus;
+ WORD oldStatus;
+ HANDLE hAwayMsgProcess;
+ HANDLE hAwayMsgHook;
+} PLUGINDATA;
+
+typedef struct {
+ HANDLE hContact;
+ TCHAR *cust;
+ TCHAR *oldstatusmsg;
+ TCHAR *newstatusmsg;
+ char *proto;
+ int compare;
+} STATUSMSGINFO;
+
+/*
+HANDLE hContact = (HANDLE)wParam;
+WORD oldStatus = LOWORD(lParam);
+WORD newStatus = HIWORD(lParam);
+oldStatus is the status the contact was before the change.
+newStatus is the status the contact is now.
+Cast them to (int) if you need them that way.
+*/
+#define ME_STATUSCHANGE_CONTACTSTATUSCHANGED "Miranda/StatusChange/ContactStatusChanged"
+
+#define MS_STATUSCHANGE_MENUCOMMAND "NewStatusNotify/EnableDisableMenuCommand"
+
+#define TMR_CONNECTIONTIMEOUT 10000
+
+#endif //COMMON_H
diff --git a/plugins/NewXstatusNotify/src/indsnd.cpp b/plugins/NewXstatusNotify/src/indsnd.cpp
new file mode 100644
index 0000000000..27a8b9a02a
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/indsnd.cpp
@@ -0,0 +1,681 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "common.h"
+#include "options.h"
+#include "indsnd.h"
+#include "utils.h"
+
+extern STATUS StatusList[];
+extern OPTIONS opt;
+extern HINSTANCE hInst;
+
+void PreviewSound(HWND hList)
+{
+ TCHAR buff[MAX_PATH], stzSoundPath[MAX_PATH];
+
+ LVITEM lvi = {0};
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = ListView_GetNextItem(hList, -1, LVNI_SELECTED);
+ ListView_GetItem(hList, &lvi);
+
+ int hlpStatus = lvi.lParam;
+
+ ListView_GetItemText(hList, lvi.iItem, 1, buff, SIZEOF(buff));
+ if (_tcscmp(buff, TranslateT(DEFAULT_SOUND)) == 0)
+ {
+ if (hlpStatus == ID_STATUS_FROMOFFLINE)
+ SkinPlaySound("UserFromOffline");
+ else
+ SkinPlaySound(StatusList[Index(hlpStatus)].lpzSkinSoundName);
+ }
+ else
+ {
+ CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)buff, (LPARAM)stzSoundPath);
+ PlaySound(stzSoundPath, NULL, SND_ASYNC | SND_FILENAME);
+ }
+}
+
+BOOL RemoveSoundFromList(HWND hList)
+{
+ int iSel = ListView_GetSelectionMark(hList);
+ if (iSel != -1)
+ {
+ iSel = -1;
+ while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1)
+ ListView_SetItemText(hList, iSel, 1, TranslateT(DEFAULT_SOUND));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+TCHAR *SelectSound(HWND hwndDlg, TCHAR *buff)
+{
+ OPENFILENAME ofn = {0};
+
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+ ListView_GetItemText(hList, ListView_GetNextItem(hList,- 1, LVNI_SELECTED), 1, buff, SIZEOF(buff));
+
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = GetParent(hwndDlg);
+ ofn.hInstance = hInst;
+ TCHAR filter[MAX_PATH];
+ mir_sntprintf(filter, SIZEOF(filter), _T("%s (*.wav)%c*.WAV%c%s (*.*)%c*%c"), TranslateT("Wave Files"), 0, 0, TranslateT("All Files"), 0, 0);
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = buff;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = _T("wav");
+ if (GetOpenFileName(&ofn))
+ return buff;
+
+ return NULL;
+}
+
+HIMAGELIST GetStatusIconsImgList(char *szProto)
+{
+ HIMAGELIST hList = NULL;
+ if (szProto)
+ {
+ hList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16 | ILC_MASK, STATUS_COUNT, 0);
+ if (hList != NULL)
+ {
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++)
+ ImageList_AddIcon(hList, LoadSkinnedProtoIcon(szProto, StatusList[Index(i)].ID));
+ ImageList_AddIcon(hList, LoadSkinnedIcon(SKINICON_OTHER_USERONLINE));
+ }
+ }
+
+ return hList;
+}
+
+INT_PTR CALLBACK DlgProcSoundUIPage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static HANDLE hContact = NULL;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ hContact = (HANDLE)lParam;
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+
+ ListView_SetImageList(hList, GetStatusIconsImgList(szProto), LVSIL_SMALL);
+ ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
+
+ RECT rc = {0};
+ GetClientRect(hList, &rc);
+
+ LV_COLUMN lvc = {0};
+ lvc.mask = LVCF_WIDTH | LVCF_TEXT;
+ lvc.cx = STATUS_COLUMN;
+ lvc.pszText = TranslateT("Status");
+ ListView_InsertColumn(hList, 0, &lvc);
+
+ lvc.cx = rc.right - STATUS_COLUMN - GetSystemMetrics(SM_CXVSCROLL);
+ lvc.pszText = TranslateT("Sound for the status");
+ ListView_InsertColumn(hList, 1, &lvc);
+
+ if (szProto)
+ {
+ DBVARIANT dbv;
+ TCHAR buff[MAX_PATH];
+
+ for (int i = ID_STATUS_MAX; i >= ID_STATUS_MIN; i--)
+ {
+ int flags = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_2, 0);
+ if (flags == 0)
+ flags = PF2_ONLINE|PF2_INVISIBLE|PF2_SHORTAWAY|PF2_LONGAWAY|PF2_LIGHTDND|PF2_HEAVYDND|PF2_FREECHAT|PF2_OUTTOLUNCH|PF2_ONTHEPHONE;
+
+ if ((flags & Proto_Status2Flag(i)) || i == ID_STATUS_OFFLINE)
+ {
+ LV_ITEM lvi = {0};
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
+ lvi.iItem = 0;
+ lvi.iSubItem = 0;
+ lvi.iImage = Index(i);
+ lvi.lParam = (LPARAM)i;
+ lvi.pszText = TranslateTS(StatusList[Index(i)].lpzStandardText);
+ lvi.iItem = ListView_InsertItem(hList, &lvi);
+
+ if (!DBGetContactSettingTString(hContact, MODULE, StatusList[Index(i)].lpzSkinSoundName, &dbv))
+ {
+ _tcscpy(buff, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ else
+ _tcscpy(buff, TranslateT(DEFAULT_SOUND));
+
+ ListView_SetItemText(hList, lvi.iItem, 1, buff);
+ }
+ }
+
+ LV_ITEM lvi = {0};
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
+ lvi.iItem = 0;
+ lvi.iSubItem = 0;
+ lvi.iImage = Index(ID_STATUS_MAX) + 1; // additional icon
+ lvi.lParam = (LPARAM)ID_STATUS_FROMOFFLINE;
+ lvi.pszText = TranslateT("From offline");
+ lvi.iItem = ListView_InsertItem(hList, &lvi);
+
+ if (!DBGetContactSettingTString(hContact, MODULE, "UserFromOffline", &dbv))
+ {
+ _tcscpy(buff, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ else
+ _tcscpy(buff, TranslateT(DEFAULT_SOUND));
+
+ ListView_SetItemText(hList, lvi.iItem, 1, buff);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_CHECK_NOTIFYSOUNDS, DBGetContactSettingByte(hContact, MODULE, "EnableSounds", 1));
+ CheckDlgButton(hwndDlg, IDC_CHECK_NOTIFYPOPUPS, DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1));
+
+ ShowWindow(GetDlgItem(hwndDlg, IDC_INDSNDLIST), opt.UseIndSnd ? SW_SHOW : SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_TEXT_ENABLE_IS), opt.UseIndSnd ? SW_HIDE : SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_CHANGE), opt.UseIndSnd ? SW_SHOW : SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), opt.UseIndSnd ? SW_SHOW : SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_DELETE), opt.UseIndSnd ? SW_SHOW : SW_HIDE);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_PREVIEW:
+ {
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+ if (ListView_GetSelectionMark(hList) != -1)
+ PreviewSound(hList);
+ break;
+ }
+ case IDC_CHANGE:
+ {
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+ int iSel = ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_INDSNDLIST), -1, LVNI_SELECTED);
+ if (iSel != -1)
+ {
+ TCHAR stzFilePath[MAX_PATH];
+ if (SelectSound(hwndDlg, stzFilePath) != NULL)
+ {
+ iSel = -1;
+ while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1)
+ ListView_SetItemText(hList, iSel, 1, stzFilePath);
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ }
+ case IDC_DELETE:
+ {
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+ if (ListView_GetSelectionMark(hList) != -1)
+ {
+ if (RemoveSoundFromList(GetDlgItem(hwndDlg, IDC_INDSNDLIST)))
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ }
+ case IDC_CHECK_NOTIFYSOUNDS:
+ {
+ DBWriteContactSettingByte(hContact, MODULE, "EnableSounds", IsDlgButtonChecked(hwndDlg, IDC_CHECK_NOTIFYSOUNDS) ? 1 : 0);
+ break;
+ }
+ case IDC_CHECK_NOTIFYPOPUPS:
+ {
+ DBWriteContactSettingByte(hContact, MODULE, "EnablePopups", IsDlgButtonChecked(hwndDlg, IDC_CHECK_NOTIFYPOPUPS) ? 1 : 0);
+ break;
+ }
+ }
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR pParam = (LPNMHDR)lParam;
+ if (pParam->code == PSN_APPLY)
+ {
+ TCHAR buff[MAX_PATH];
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+
+ LVITEM lvi = {0};
+ lvi.mask = LVIF_PARAM;
+ //Cycle through the list reading the text associated to each status.
+ for (lvi.iItem = ListView_GetItemCount(hList) - 1; lvi.iItem >= 0; lvi.iItem--)
+ {
+ ListView_GetItem(hList, &lvi);
+ ListView_GetItemText(hList, lvi.iItem, 1, buff, SIZEOF(buff));
+
+ if (!_tcscmp(buff, TranslateT(DEFAULT_SOUND)))
+ {
+ if (lvi.lParam == ID_STATUS_FROMOFFLINE)
+ DBDeleteContactSetting(hContact, MODULE, "UserFromOffline");
+ else
+ DBDeleteContactSetting(hContact, MODULE, StatusList[Index(lvi.lParam)].lpzSkinSoundName);
+ }
+ else
+ {
+ TCHAR stzSoundPath[MAX_PATH] = { 0 };
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)buff, (LPARAM)stzSoundPath);
+ if (lvi.lParam == ID_STATUS_FROMOFFLINE)
+ DBWriteContactSettingTString(hContact, MODULE, "UserFromOffline", stzSoundPath);
+ else
+ DBWriteContactSettingTString(hContact, MODULE, StatusList[Index(lvi.lParam)].lpzSkinSoundName, stzSoundPath);
+ }
+ }
+
+ return TRUE;
+ }
+
+ int hlpControlID = (int)wParam;
+ switch (hlpControlID)
+ {
+ case IDC_INDSNDLIST:
+ {
+ if (pParam->code == NM_DBLCLK)
+ {
+ TCHAR stzFilePath[MAX_PATH];
+ if (SelectSound(hwndDlg, stzFilePath) != NULL)
+ {
+ int iSel = -1;
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+ while ((iSel = ListView_GetNextItem(hList, iSel, LVNI_SELECTED)) != -1)
+ ListView_SetItemText(hList, iSel, 1, stzFilePath);
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ return TRUE;
+ }
+ else if (pParam->code == LVN_KEYDOWN)
+ {
+ LPNMLVKEYDOWN pnkd = (LPNMLVKEYDOWN)lParam;
+ if (pnkd->wVKey == VK_DELETE)
+ RemoveSoundFromList(GetDlgItem(hwndDlg, IDC_INDSNDLIST));
+ }
+
+ break;
+ }
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+int UserInfoInitialise(WPARAM wParam, LPARAM lParam)
+{
+ if (lParam == NULL)
+ return 0;
+
+ OPTIONSDIALOGPAGE odp = {0};
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_INFO_SOUNDS);
+ odp.pszTitle = LPGEN("Status Notify");
+ odp.pfnDlgProc = DlgProcSoundUIPage;
+ UserInfo_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+void ResetListOptions(HWND hwndList)
+{
+ SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)NULL);
+ SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendMessage(hwndList, CLM_SETLEFTMARGIN, 4, 0);
+ SendMessage(hwndList, CLM_SETINDENT, 10, 0);
+
+ for (int i = 0; i <= FONTID_MAX; i++)
+ SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+
+ SetWindowLongPtr(hwndList, GWL_STYLE, GetWindowLongPtr(hwndList,GWL_STYLE) | CLS_SHOWHIDDEN);
+}
+
+__inline int GetExtraImage(HWND hwndList, HANDLE hItem, int column)
+{
+ return SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(column, 0));
+}
+
+__inline void SetExtraImage(HWND hwndList, HANDLE hItem, int column, int imageID)
+{
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(column, imageID));
+}
+
+void SetAllContactsIcons(HWND hwndList)
+{
+ BYTE EnableSounds, EnablePopups, EnableXStatus, EnableLogging;
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ HANDLE hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+ if (szProto)
+ {
+ EnableSounds = DBGetContactSettingByte(hContact, MODULE, "EnableSounds", 1);
+ EnablePopups = DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1);
+ EnableXStatus = DBGetContactSettingByte(hContact, MODULE, "EnableXStatusNotify", 1);
+ EnableLogging = DBGetContactSettingByte(hContact, MODULE, "EnableLogging", 1);
+ }
+ else
+ EnableSounds = EnablePopups = EnableXStatus = EnableLogging = 0;
+
+ SetExtraImage(hwndList, hItem, EXTRA_IMAGE_SOUND, EnableSounds ? EXTRA_IMAGE_SOUND : EXTRA_IMAGE_DOT);
+ SetExtraImage(hwndList, hItem, EXTRA_IMAGE_POPUP, EnablePopups? EXTRA_IMAGE_POPUP : EXTRA_IMAGE_DOT);
+ SetExtraImage(hwndList, hItem, EXTRA_IMAGE_XSTATUS, EnableXStatus ? EXTRA_IMAGE_XSTATUS : EXTRA_IMAGE_DOT);
+ SetExtraImage(hwndList, hItem, EXTRA_IMAGE_LOGGING, EnableLogging ? EXTRA_IMAGE_LOGGING : EXTRA_IMAGE_DOT);
+ SetExtraImage(hwndList, hItem, EXTRA_IMAGE_DISABLEALL, EXTRA_IMAGE_DISABLEALL);
+ SetExtraImage(hwndList, hItem, EXTRA_IMAGE_ENABLEALL, EXTRA_IMAGE_ENABLEALL);
+ }
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+}
+
+void SetGroupsIcons(HWND hwndList, HANDLE hFirstItem, HANDLE hParentItem, int *groupChildCount)
+{
+ int iconOn[6] = {1,1,1,1,1,1};
+ int childCount[6] = {0};
+ HANDLE hItem;
+
+ int typeOfFirst = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hFirstItem, 0);
+ if (typeOfFirst == CLCIT_GROUP)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hFirstItem);
+
+ while (hItem)
+ {
+ HANDLE hChildItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if (hChildItem)
+ SetGroupsIcons(hwndList, hChildItem, hItem, childCount);
+
+ for (int i = 0; i < SIZEOF(iconOn); i++)
+ {
+ if (iconOn[i] && GetExtraImage(hwndList, hItem, i) == EXTRA_IMAGE_DOT)
+ iconOn[i] = 0;
+ }
+
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem);
+ }
+
+ //check contacts
+ if (typeOfFirst == CLCIT_CONTACT)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem);
+
+ while(hItem)
+ {
+ for (int i = 0; i < SIZEOF(iconOn); i++)
+ {
+ int image = GetExtraImage(hwndList, hItem, i);
+ if (iconOn[i] && image == EXTRA_IMAGE_DOT)
+ iconOn[i] = 0;
+
+ if (image != EXTRA_IMAGE_BLANK)
+ childCount[i]++;
+ }
+
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+
+ //set icons
+ for(int i = 0; i < SIZEOF(iconOn); i++)
+ {
+ SetExtraImage(hwndList, hParentItem, i, childCount[i] ? (iconOn[i] ? i : EXTRA_IMAGE_DOT) : EXTRA_IMAGE_BLANK);
+ if (groupChildCount)
+ groupChildCount[i] += childCount[i];
+ }
+}
+
+void SetAllChildrenIcons(HWND hwndList, HANDLE hFirstItem, int column, int image)
+{
+ HANDLE hItem, hChildItem;
+
+ int typeOfFirst = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hFirstItem, 0);
+ if (typeOfFirst == CLCIT_GROUP)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hFirstItem);
+
+ while(hItem)
+ {
+ hChildItem = (HANDLE)SendMessage(hwndList ,CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if (hChildItem)
+ SetAllChildrenIcons(hwndList, hChildItem, column, image);
+
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem);
+ }
+
+ if (typeOfFirst == CLCIT_CONTACT)
+ hItem = hFirstItem;
+ else
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem);
+
+ while(hItem)
+ {
+ int oldIcon = GetExtraImage(hwndList, hItem, column);
+ if (oldIcon != EXTRA_IMAGE_BLANK && oldIcon != image)
+ SetExtraImage(hwndList, hItem, column, image);
+
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+}
+
+INT_PTR CALLBACK DlgProcFiltering(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static HANDLE hItemAll;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ HIMAGELIST hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16 | ILC_MASK, 3, 3);
+
+ ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_SOUND)));
+ SendDlgItemMessage(hwndDlg,IDC_SOUNDICON,STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_SOUND, ILD_NORMAL), 0);
+ ImageList_AddIcon(hImageList, LoadIcon(hInst, MAKEINTRESOURCE(IDI_POPUP)));
+ SendDlgItemMessage(hwndDlg, IDC_POPUPICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_POPUP, ILD_NORMAL), 0);
+ ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_XSTATUS)));
+ SendDlgItemMessage(hwndDlg, IDC_XSTATUSICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_XSTATUS, ILD_NORMAL), 0);
+ ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_LOGGING)));
+ SendDlgItemMessage(hwndDlg, IDC_LOGGINGICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_LOGGING, ILD_NORMAL), 0);
+ ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_DISABLEALL)));
+ SendDlgItemMessage(hwndDlg, IDC_DISABLEALLICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_DISABLEALL, ILD_NORMAL), 0);
+ ImageList_AddIcon(hImageList, LoadIcon(hInst,MAKEINTRESOURCE(IDI_ENABLEALL)));
+ SendDlgItemMessage(hwndDlg, IDC_ENABLEALLICON, STM_SETICON, (WPARAM)ImageList_GetIcon(hImageList, EXTRA_IMAGE_ENABLEALL, ILD_NORMAL), 0);
+
+ ImageList_AddIcon(hImageList, LoadSkinnedIcon(SKINICON_OTHER_SMALLDOT));
+
+ SendDlgItemMessage(hwndDlg, IDC_INDSNDLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hImageList);
+ SendDlgItemMessage(hwndDlg, IDC_INDSNDLIST, CLM_SETEXTRACOLUMNS, 6, 0);
+
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+ ResetListOptions(hList);
+
+ CLCINFOITEM cii = {0};
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT;
+ cii.pszText = TranslateT("** All contacts **");
+ hItemAll = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_INDSNDLIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+
+ return TRUE;
+ }
+ case WM_SETFOCUS:
+ {
+ SetFocus(GetDlgItem(hwndDlg, IDC_INDSNDLIST));
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ HWND hList = GetDlgItem(hwndDlg, IDC_INDSNDLIST);
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case IDC_INDSNDLIST:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ SetAllContactsIcons(hList);
+ //fall through
+ case CLN_CONTACTMOVED:
+ SetGroupsIcons(hList, (HANDLE)SendMessage(hList, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ break;
+ case CLN_OPTIONSCHANGED:
+ ResetListOptions(hList);
+ break;
+ case NM_CLICK:
+ {
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+ DWORD hitFlags;
+
+ // Make sure we have an extra column
+ if (nm->iColumn == -1) break;
+
+ // Find clicked item
+ HANDLE hItem = (HANDLE)SendMessage(hList, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y));
+ if (hItem == NULL) break;
+ if (!(hitFlags & CLCHT_ONITEMEXTRA)) break;
+
+ int itemType = SendMessage(hList, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
+
+ // Get image in clicked column
+ int image = GetExtraImage(hList, hItem, nm->iColumn);
+ if (image == EXTRA_IMAGE_DOT)
+ image = nm->iColumn;
+ else if (image >= EXTRA_IMAGE_SOUND && image <= EXTRA_IMAGE_LOGGING)
+ image = EXTRA_IMAGE_DOT;
+
+ // Get item type (contact, group, etc...)
+ if (itemType == CLCIT_CONTACT)
+ {
+ if (image == EXTRA_IMAGE_DISABLEALL)
+ {
+ for (int i = 0; i < 4; i++)
+ SetExtraImage(hList, hItem, i, EXTRA_IMAGE_DOT);
+ }
+ else if (image == EXTRA_IMAGE_ENABLEALL)
+ {
+ for (int i = 0; i < 4; i++)
+ SetExtraImage(hList, hItem, i, i);
+ }
+ else
+ {
+ SetExtraImage(hList, hItem, nm->iColumn, image);
+ }
+ }
+ else if (itemType == CLCIT_INFO || itemType == CLCIT_GROUP)
+ {
+ if (itemType == CLCIT_GROUP)
+ hItem = (HANDLE)SendMessage(hList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+
+ if (hItem)
+ {
+ if (image == EXTRA_IMAGE_DISABLEALL)
+ {
+ for (int i = 0; i < 4; i++)
+ SetAllChildrenIcons(hList, hItem, i, EXTRA_IMAGE_DOT);
+ }
+ else if (image == EXTRA_IMAGE_ENABLEALL)
+ {
+ for (int i = 0; i < 4; i++)
+ SetAllChildrenIcons(hList, hItem, i, i);
+ }
+ else
+ {
+ SetAllChildrenIcons(hList, hItem, nm->iColumn, image);
+ }
+ }
+ }
+
+ // Update the all/none icons
+ SetGroupsIcons(hList, (HANDLE)SendMessage(hList, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ // Activate Apply button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ do
+ {
+ HANDLE hItem = (HANDLE)SendMessage(hList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ if (GetExtraImage(hList, hItem, EXTRA_IMAGE_SOUND) == EXTRA_IMAGE_SOUND)
+ DBDeleteContactSetting(hContact, MODULE, "EnableSounds");
+ else
+ DBWriteContactSettingByte(hContact, MODULE, "EnableSounds", 0);
+
+ if (GetExtraImage(hList, hItem, EXTRA_IMAGE_POPUP) == EXTRA_IMAGE_POPUP)
+ DBDeleteContactSetting(hContact, MODULE, "EnablePopups");
+ else
+ DBWriteContactSettingByte(hContact, MODULE, "EnablePopups", 0);
+
+ if(GetExtraImage(hList, hItem, EXTRA_IMAGE_XSTATUS) == EXTRA_IMAGE_XSTATUS)
+ DBDeleteContactSetting(hContact, MODULE, "EnableXStatusNotify");
+ else
+ DBWriteContactSettingByte(hContact, MODULE, "EnableXStatusNotify", 0);
+
+ if (GetExtraImage(hList, hItem, EXTRA_IMAGE_LOGGING) == EXTRA_IMAGE_LOGGING)
+ DBDeleteContactSetting(hContact, MODULE, "EnableLogging");
+ else
+ DBWriteContactSettingByte(hContact, MODULE, "EnableLogging", 0);
+
+ }
+ } while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0));
+
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ case WM_DESTROY:
+ {
+ HIMAGELIST hImageList = (HIMAGELIST)SendMessage(GetDlgItem(hwndDlg, IDC_INDSNDLIST), CLM_GETEXTRAIMAGELIST, 0, 0);
+ for (int i = 0; i < ImageList_GetImageCount(hImageList); i++)
+ DestroyIcon(ImageList_GetIcon(hImageList, i, ILD_NORMAL));
+ ImageList_Destroy(hImageList);
+ break;
+ }
+ }
+ return FALSE;
+}
+
diff --git a/plugins/NewXstatusNotify/src/indsnd.h b/plugins/NewXstatusNotify/src/indsnd.h
new file mode 100644
index 0000000000..c4dde34ea1
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/indsnd.h
@@ -0,0 +1,41 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ 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
+*/
+
+#ifndef INDSND_H
+#define INDSND_H
+
+#define EXTRA_IMAGE_SOUND 0
+#define EXTRA_IMAGE_POPUP 1
+#define EXTRA_IMAGE_XSTATUS 2
+#define EXTRA_IMAGE_LOGGING 3
+#define EXTRA_IMAGE_DISABLEALL 4
+#define EXTRA_IMAGE_ENABLEALL 5
+#define EXTRA_IMAGE_DOT 6
+#define EXTRA_IMAGE_BLANK 0xFF
+
+#define STATUS_COLUMN 110
+
+#define DEFAULT_SOUND "(default sound)"
+
+int UserInfoInitialise(WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcFiltering(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#endif \ No newline at end of file
diff --git a/plugins/NewXstatusNotify/src/main.cpp b/plugins/NewXstatusNotify/src/main.cpp
new file mode 100644
index 0000000000..82370f15f5
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/main.cpp
@@ -0,0 +1,1369 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "common.h"
+#include "indsnd.h"
+#include "options.h"
+#include "popup.h"
+#include "utils.h"
+#include "version.h"
+#include "xstatus.h"
+
+HINSTANCE hInst;
+
+
+LIST<DBEVENT> eventList( 10 );
+LIST<XSTATUSCHANGE> xstatusList( 10 );
+
+HANDLE hStatusModeChange, hServiceMenu, hHookContactStatusChanged, hEnableDisableMenu;
+HANDLE hToolbarButton;
+
+char szMetaModuleName[256] = {0};
+STATUS StatusList[STATUS_COUNT];
+DWORD LoadTime = 0;
+int hLangpack;
+
+extern OPTIONS opt;
+
+PLUGININFOEX pluginInfoEx = {
+ sizeof(PLUGININFOEX),
+ "NewXstatusNotify YM",
+ __VERSION_DWORD,
+ "Notifies you when a contact changes his/her (X)status or status message.",
+ "Luca Santarelli, Vasilich, yaho",
+ "yaho@miranda-easy.net",
+ "© 2001-2004 Luca Santarelli, 2005-2007 Vasilich, 2007-2011 yaho",
+ "http://miranda-easy.net/mods.php",
+ UNICODE_AWARE,
+ MIID_NXSN
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ DisableThreadLibraryCalls(hInst);
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfoEx;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_USERONLINE, MIID_LAST};
+
+BYTE GetGender(HANDLE hContact)
+{
+ char *szProto =(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (szProto)
+ {
+ switch (DBGetContactSettingByte(hContact, szProto, "Gender", 0))
+ {
+ case 'M': case 'm':
+ return GENDER_MALE;
+ case 'F': case 'f':
+ return GENDER_FEMALE;
+ default:
+ return GENDER_UNSPECIFIED;
+ }
+ }
+
+ return GENDER_UNSPECIFIED;
+}
+
+HANDLE GetIconHandle(char *szIcon)
+{
+ char szSettingName[64];
+ mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", MODULE, szIcon);
+ return (HANDLE)CallService(MS_SKIN2_GETICONHANDLE, 0, (LPARAM)szSettingName);
+}
+
+__inline void AddXSC(XSTATUSCHANGE *xsc)
+{
+ xstatusList.insert(xsc);
+}
+
+__inline void RemoveXSC(XSTATUSCHANGE *xsc)
+{
+ int id = xstatusList.getIndex(xsc);
+ if (id != -1)
+ xstatusList.remove(id);
+}
+
+XSTATUSCHANGE *FindXSC(HANDLE hContact)
+{
+ for (int i = 0; i < xstatusList.getCount(); i++) {
+ XSTATUSCHANGE* xsc = xstatusList[i];
+ if (xsc->hContact == hContact)
+ return xsc;
+ }
+
+ return NULL;
+}
+
+XSTATUSCHANGE *FindAndRemoveXSC(HANDLE hContact)
+{
+ XSTATUSCHANGE *result = FindXSC(hContact);
+ if (result) RemoveXSC(result);
+ return result;
+}
+
+bool IsNewExtraStatus(HANDLE hContact, char *szSetting, TCHAR *newStatusTitle)
+{
+ DBVARIANT dbv;
+ bool result = true;
+
+ if (!DBGetContactSettingTString(hContact, MODULE, szSetting, &dbv))
+ {
+ result = _tcscmp(newStatusTitle, dbv.ptszVal) ? true : false;
+ DBFreeVariant(&dbv);
+ }
+
+ return result;
+}
+
+int ProcessExtraStatus(DBCONTACTWRITESETTING *cws, HANDLE hContact)
+{
+ XSTATUSCHANGE *xsc;
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if (ProtoServiceExists(szProto, JS_PARSE_XMPP_URI))
+ {
+ if (cws->value.type == DBVT_DELETED)
+ return 0;
+
+ if (hContact == NULL)
+ return 0;
+
+ if (strstr(cws->szSetting, "/mood/") || strstr(cws->szSetting, "/activity/")) // Jabber mood or activity changed
+ {
+ char *szSetting;
+ int type;
+
+ if (strstr(cws->szSetting, "/mood/"))
+ {
+ type = TYPE_JABBER_MOOD;
+ szSetting = "LastJabberMood";
+ }
+ else
+ {
+ type = TYPE_JABBER_ACTIVITY;
+ szSetting = "LastJabberActivity";
+ }
+
+ if (strstr(cws->szSetting, "title"))
+ {
+ TCHAR *stzValue = db2t(&cws->value);
+ if (stzValue)
+ {
+ if (!IsNewExtraStatus(hContact, szSetting, stzValue))
+ {
+ mir_free(stzValue);
+ return 0;
+ }
+
+ xsc = NewXSC(hContact, szProto, type, NOTIFY_NEW_XSTATUS, stzValue, NULL);
+ DBWriteContactSettingTString(hContact, MODULE, szSetting, stzValue);
+ }
+ else
+ {
+ xsc = NewXSC(hContact, szProto, type, NOTIFY_REMOVE, NULL, NULL);
+ DBWriteContactSettingTString(hContact, MODULE, szSetting, _T(""));
+ }
+
+ AddXSC(xsc);
+ if (xsc != NULL)
+ {
+ ExtraStatusChanged(xsc);
+ FreeXSC(xsc);
+ }
+ }
+ else if (strstr(cws->szSetting, "text"))
+ {
+ xsc = FindAndRemoveXSC(hContact);
+ TCHAR *stzValue = db2t(&cws->value);
+ if (stzValue)
+ {
+ if (xsc != NULL)
+ xsc->stzText = stzValue;
+ else
+ xsc = NewXSC(hContact, szProto, type, NOTIFY_NEW_MESSAGE, NULL, stzValue);
+ }
+
+ if (xsc != NULL)
+ {
+ ExtraStatusChanged(xsc);
+ FreeXSC(xsc);
+ }
+ }
+
+ return 1;
+ }
+ }
+ else if (strstr(cws->szSetting, "XStatus") || strcmp(cws->szSetting, "StatusNote") == 0)
+ {
+ if (strcmp(cws->szSetting, "XStatusName") == 0)
+ {
+ xsc = FindAndRemoveXSC(hContact);
+ if (xsc) FreeXSC(xsc);
+
+ if (cws->value.type == DBVT_DELETED)
+ {
+ xsc = NewXSC(hContact, szProto, TYPE_ICQ_XSTATUS, NOTIFY_REMOVE, NULL, NULL);
+ }
+ else
+ {
+ TCHAR *stzValue = db2t(&cws->value);
+ if (!stzValue)
+ {
+ TCHAR buff[64];
+ int statusID = DBGetContactSettingByte(hContact, szProto, "XStatusId", -1);
+ GetDefaultXstatusName(statusID, szProto, buff, SIZEOF(buff));
+ stzValue = mir_tstrdup(buff);
+ }
+
+ xsc = NewXSC(hContact, szProto, TYPE_ICQ_XSTATUS, NOTIFY_NEW_XSTATUS, stzValue, NULL);
+ }
+
+ AddXSC(xsc);
+ if (xsc != NULL)
+ {
+ ExtraStatusChanged(xsc);
+ FreeXSC(xsc);
+ }
+ }
+ else if (strstr(cws->szSetting, "XStatusMsg") || strcmp(cws->szSetting, "StatusNote") == 0)
+ {
+ if (cws->value.type == DBVT_DELETED)
+ return 1;
+
+ TCHAR *stzValue = db2t(&cws->value);
+ xsc = FindXSC(hContact);
+ if (xsc)
+ {
+ if (xsc->action == NOTIFY_NEW_XSTATUS)
+ xsc->stzText = stzValue;
+ }
+ else
+ {
+ xsc = NewXSC(hContact, szProto, TYPE_ICQ_XSTATUS, NOTIFY_NEW_MESSAGE, NULL, stzValue);
+ AddXSC(xsc);
+ }
+ if (xsc != NULL)
+ {
+ ExtraStatusChanged(xsc);
+ FreeXSC(xsc);
+ }
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int __inline CheckStr(char *str, int not_empty, int empty) {
+ if (str == NULL || str[0] == '\0')
+ return empty;
+ else
+ return not_empty;
+}
+
+
+static int __inline CheckStrW(WCHAR *str, int not_empty, int empty) {
+ if (str == NULL || str[0] == L'\0')
+ return empty;
+ else
+ return not_empty;
+}
+
+
+WCHAR *mir_dupToUnicodeEx(char *ptr, UINT CodePage)
+{
+ if (ptr == NULL)
+ return NULL;
+
+ size_t size = strlen(ptr) + 1;
+ WCHAR *tmp = (WCHAR *) mir_alloc(size * sizeof(WCHAR));
+
+ MultiByteToWideChar(CodePage, 0, ptr, -1, tmp, (int)size * sizeof(WCHAR));
+ return tmp;
+}
+
+static int CompareStatusMsg(STATUSMSGINFO *smi, DBCONTACTWRITESETTING *cws_new) {
+ DBVARIANT dbv_old;
+ int ret;
+
+ switch (cws_new->value.type)
+ {
+ case DBVT_DELETED:
+ smi->newstatusmsg = NULL;
+ break;
+ case DBVT_ASCIIZ:
+
+ smi->newstatusmsg = (CheckStr(cws_new->value.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(cws_new->value.pszVal, CP_ACP));
+ break;
+ case DBVT_UTF8:
+ smi->newstatusmsg = (CheckStr(cws_new->value.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(cws_new->value.pszVal, CP_UTF8));
+ break;
+ case DBVT_WCHAR:
+ smi->newstatusmsg = (CheckStrW(cws_new->value.pwszVal, 0, 1) ? NULL : mir_wstrdup(cws_new->value.pwszVal));
+
+ break;
+ default:
+ smi->newstatusmsg = NULL;
+ break;
+ }
+
+ if (!
+
+ DBGetContactSettingW(smi->hContact, "UserOnline", "OldStatusMsg", &dbv_old)
+
+ )
+ {
+ switch (dbv_old.type)
+ {
+ case DBVT_ASCIIZ:
+
+ smi->oldstatusmsg = (CheckStr(dbv_old.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(dbv_old.pszVal, CP_ACP));
+ break;
+ case DBVT_UTF8:
+ smi->oldstatusmsg = (CheckStr(dbv_old.pszVal, 0, 1) ? NULL : mir_dupToUnicodeEx(dbv_old.pszVal, CP_UTF8));
+ break;
+ case DBVT_WCHAR:
+ smi->oldstatusmsg = (CheckStrW(dbv_old.pwszVal, 0, 1) ? NULL : mir_wstrdup(dbv_old.pwszVal));
+
+ break;
+ default:
+ smi->oldstatusmsg = NULL;
+ break;
+ }
+
+ if (cws_new->value.type == DBVT_DELETED)
+ if (
+
+ dbv_old.type == DBVT_WCHAR)
+ ret = CheckStrW(dbv_old.pwszVal, 2, 0);
+ else if (dbv_old.type == DBVT_UTF8 ||
+
+ dbv_old.type == DBVT_ASCIIZ)
+ ret = CheckStr(dbv_old.pszVal, 2, 0);
+ else
+ ret = 2;
+ else if (dbv_old.type != cws_new->value.type)
+
+ ret = (lstrcmpW(smi->newstatusmsg, smi->oldstatusmsg) ? CheckStrW(smi->newstatusmsg, 1, 2) : 0);
+
+ else if (dbv_old.type == DBVT_ASCIIZ)
+ ret = (lstrcmpA(cws_new->value.pszVal, dbv_old.pszVal) ? CheckStr(cws_new->value.pszVal, 1, 2) : 0);
+
+ else if (dbv_old.type == DBVT_UTF8)
+ ret = (lstrcmpA(cws_new->value.pszVal, dbv_old.pszVal) ? CheckStr(cws_new->value.pszVal, 1, 2) : 0);
+ else if (dbv_old.type == DBVT_WCHAR)
+ ret = (lstrcmpW(cws_new->value.pwszVal, dbv_old.pwszVal) ? CheckStrW(cws_new->value.pwszVal, 1, 2) : 0);
+
+ DBFreeVariant(&dbv_old);
+ }
+ else
+ {
+ if (cws_new->value.type == DBVT_DELETED)
+ ret = 0;
+ else if (
+
+ cws_new->value.type == DBVT_WCHAR)
+ ret = CheckStrW(cws_new->value.pwszVal, 1, 0);
+ else if (cws_new->value.type == DBVT_UTF8 ||
+
+ cws_new->value.type == DBVT_ASCIIZ)
+ ret = CheckStr(cws_new->value.pszVal, 1, 0);
+ else
+ ret = 1;
+
+ smi->oldstatusmsg = NULL;
+ }
+
+ return ret;
+}
+
+BOOL FreeSmiStr(STATUSMSGINFO *smi)
+{
+ mir_free(smi->newstatusmsg);
+ mir_free(smi->oldstatusmsg);
+ return 0;
+}
+
+// return TRUE if timeout is over
+BOOL TimeoutCheck()
+{
+ if (GetTickCount() - LoadTime > TMR_CONNECTIONTIMEOUT)
+ return TRUE;
+ return FALSE;
+}
+
+TCHAR* AddCR(const TCHAR *statusmsg) {
+ TCHAR *tmp;
+ const TCHAR *found;
+ int i = 0, len = lstrlen(statusmsg), j;
+ tmp = (TCHAR*)mir_alloc(1024 * sizeof(TCHAR));
+ *tmp = _T('\0');
+ while((found = _tcsstr((statusmsg + i), _T("\n"))) != NULL && _tcslen(tmp) + 1 < 1024){
+ j = (int)(found - statusmsg);
+ if(lstrlen(tmp) + j - i + 2 < 1024){
+ tmp = _tcsncat(tmp, statusmsg + i, j - i);
+ }
+ else {
+ break;
+ }
+ if(j == 0 || *(statusmsg + j - 1) != _T('\r')) {
+ tmp = lstrcat(tmp, _T("\r"));
+ }
+ tmp = lstrcat(tmp, _T("\n"));
+ i = j + 1;
+ }
+ if(lstrlen(tmp) + len - i + 1 < 1024){
+ tmp = lstrcat(tmp, statusmsg + i);
+ }
+
+ return tmp;
+}
+
+TCHAR* GetStr(STATUSMSGINFO *n, const TCHAR *tmplt) {
+ TCHAR tmp[1024];
+ TCHAR *str;
+ int i;
+ int len;
+
+ if (tmplt == NULL || tmplt[0] == _T('\0'))
+ return NULL;
+
+ str = (TCHAR*)mir_alloc(2048 * sizeof(TCHAR));
+ str[0] = _T('\0');
+ len = lstrlen(tmplt);
+
+ for (i = 0; i < len; i++)
+ {
+ tmp[0] = _T('\0');
+
+ if (tmplt[i] == _T('%'))
+ {
+ i++;
+ switch (tmplt[i])
+ {
+ case 'n':
+ if (n->compare == 2 || _tcscmp(n->newstatusmsg, TranslateT("<no status message>")) == 0)
+ lstrcpyn(tmp, TranslateT("<no status message>"), SIZEOF(tmp));
+ else {
+ TCHAR *_tmp = AddCR(n->newstatusmsg);
+ lstrcpyn(tmp, _tmp, SIZEOF(tmp));
+ mir_free(_tmp);
+ }
+ break;
+ case 'o':
+ if (n->oldstatusmsg == NULL || n->oldstatusmsg[0] == _T('\0') || _tcscmp(n->oldstatusmsg, TranslateT("<no status message>")) == 0)
+ lstrcpyn(tmp, TranslateT("<no status message>"), SIZEOF(tmp));
+ else {
+ TCHAR *_tmp = AddCR(n->oldstatusmsg);
+ lstrcpyn(tmp, _tmp, SIZEOF(tmp));
+ mir_free(_tmp);
+ }
+ break;
+ case 'c':
+ if (n->cust == NULL || n->cust[0] == _T('\0')) lstrcpyn(tmp, TranslateT("Contact"), SIZEOF(tmp));
+ else lstrcpyn(tmp, n->cust, SIZEOF(tmp));
+ break;
+ default:
+ //lstrcpyn(tmp, _T("%"), TMPMAX);
+ i--;
+ tmp[0] = tmplt[i]; tmp[1] = _T('\0');
+ break;
+ }
+ }
+ else if (tmplt[i] == _T('\\'))
+ {
+ i++;
+ switch (tmplt[i])
+ {
+ case 'n':
+ //_tcscat_s(tmp, TMPMAX, _T("\r\n"));
+ tmp[0] = _T('\r'); tmp[1] = _T('\n'); tmp[2] = _T('\0');
+ break;
+ case 't':
+ //_tcscat_s(tmp, TMPMAX, _T("\t"));
+ tmp[0] = _T('\t'); tmp[1] = _T('\0');
+ break;
+ default:
+ //lstrcpyn(tmp, _T("\\"), TMPMAX);
+ i--;
+ tmp[0] = tmplt[i]; tmp[1] = _T('\0');
+ break;
+ }
+ }
+ else
+ {
+ tmp[0] = tmplt[i]; tmp[1] = _T('\0');
+ }
+
+ if (tmp[0] != _T('\0'))
+ {
+ if (lstrlen(tmp) + lstrlen(str) < 2044)
+ {
+ lstrcat(str, tmp);
+ }
+ else
+ {
+ lstrcat(str, _T("..."));
+ break;
+ }
+ }
+ }
+
+ return str;
+}
+
+int ProcessStatus(DBCONTACTWRITESETTING *cws, HANDLE hContact)
+{
+ if (strcmp(cws->szSetting, "Status") == 0)
+ {
+ WORD newStatus = cws->value.wVal;
+ if (newStatus < ID_STATUS_MIN || newStatus > ID_STATUS_MAX)
+ return 0;
+
+ DBVARIANT dbv;
+ if (!DBGetContactSettingString(hContact, "Protocol", "p", &dbv))
+ {
+ BOOL temp = strcmp(cws->szModule, dbv.pszVal) != 0;
+ DBFreeVariant(&dbv);
+ if (temp) return 0;
+ }
+
+ WORD oldStatus = DBGetContactSettingRangedWord(hContact, "UserOnline", "OldStatus", ID_STATUS_OFFLINE, ID_STATUS_MIN, ID_STATUS_MAX);
+ if (oldStatus == newStatus)
+ return 0;
+
+ //If we get here, the two stauses differ, so we can proceed.
+ DBWriteContactSettingWord(hContact, "UserOnline", "OldStatus", newStatus);
+
+ //If *Miranda* ignores the UserOnline event, exit!
+ if (CallService(MS_IGNORE_ISIGNORED, (WPARAM)hContact, IGNOREEVENT_USERONLINE))
+ return 0;
+
+ //If we get here, we have to notify the Hooks.
+ NotifyEventHooks(hHookContactStatusChanged, (WPARAM)hContact, (LPARAM)MAKELPARAM(oldStatus, newStatus));
+ return 1;
+ }
+
+ if (!lstrcmpA(cws->szModule, "CList") && !lstrcmpA(cws->szSetting, "StatusMsg"))
+ {
+ STATUSMSGINFO smi;
+ BOOL retem = TRUE, rettime = TRUE;
+
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingString(hContact, "Protocol", "p", &dbv)) {
+ char dbSetting[128];
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_enabled", dbv.pszVal);
+ db_free(&dbv);
+
+ if (!DBGetContactSettingByte(NULL, MODULE, dbSetting, 1))
+ return 0;
+ }
+ smi.proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ //don't show popup when mradio connecting and disconnecting
+ if (_stricmp(smi.proto, "mRadio") == 0 && !cws->value.type == DBVT_DELETED)
+ {
+ TCHAR buf[MAX_PATH];
+ mir_sntprintf(buf, SIZEOF(buf), _T(" (%s)"), TranslateT("connecting"));
+ char* pszUtf = mir_utf8encodeT(buf);
+ mir_sntprintf(buf, SIZEOF(buf), _T(" (%s)"), TranslateT("aborting"));
+ char* pszUtf2 = mir_utf8encodeT(buf);
+ mir_sntprintf(buf, SIZEOF(buf), _T(" (%s)"), TranslateT("playing"));
+ char* pszUtf3 = mir_utf8encodeT(buf);
+ if (_stricmp(cws->value.pszVal, pszUtf) == 0 || _stricmp(cws->value.pszVal, pszUtf2) == 0 || _stricmp(cws->value.pszVal, pszUtf3) == 0)
+ {
+ mir_free(pszUtf);
+ mir_free(pszUtf2);
+ mir_free(pszUtf3);
+ return 0;
+ }
+ else
+ {
+ mir_free(pszUtf);
+ mir_free(pszUtf2);
+ mir_free(pszUtf3);
+ }
+ }
+
+ if (smi.proto != NULL && CallProtoService(smi.proto, PS_GETSTATUS, 0, 0) != ID_STATUS_OFFLINE)
+ {
+ smi.hContact = hContact;
+ smi.compare = CompareStatusMsg(&smi, cws);
+ if ((smi.compare == 0) || (opt.IgnoreEmpty && (smi.compare == 2)))
+ return FreeSmiStr(&smi);
+
+ if (cws->value.type == DBVT_DELETED)
+ {
+ DBDeleteContactSetting(smi.hContact, "UserOnline", "OldStatusMsg");
+ }
+ else
+ {
+ DBCONTACTWRITESETTING cws_old;
+ cws_old.szModule = "UserOnline";
+ cws_old.szSetting = "OldStatusMsg";
+ cws_old.value = cws->value;
+ CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)smi.hContact, (LPARAM)&cws_old);
+ }
+ smi.cust = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)smi.hContact, GCDNF_TCHAR);
+
+ if (opt.IgnoreEmpty && (smi.compare == 2))
+ retem = FALSE;
+ else if (!TimeoutCheck() && !opt.PopupOnConnect)
+ rettime = FALSE;
+
+ char status[8];
+ mir_snprintf(status, SIZEOF(status), "%d", IDC_CHK_STATUS_MESSAGE);
+ if (DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1) && DBGetContactSettingByte(0, MODULE, status, 1) && retem && rettime)
+ {
+ POPUPDATAT ppd = {0};
+ char* protoname = (char*)CallService(MS_PROTO_GETCONTACTBASEACCOUNT, (WPARAM)smi.hContact, 0);
+ PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)protoname);
+ protoname = mir_t2a(pdescr->tszAccountName);
+ protoname = (char*)mir_realloc(protoname, lstrlenA(protoname) + lstrlenA("_TSMChange") + 1);
+ lstrcatA(protoname, "_TSMChange");
+ TCHAR *str;
+ DBVARIANT dbVar = {0};
+ DBGetContactSettingTString(NULL, MODULE, protoname, &dbVar);
+ if (lstrcmp(dbVar.ptszVal, NULL) == 0)
+ {
+ DBFreeVariant(&dbVar);
+ str = GetStr(&smi, TranslateT(DEFAULT_POPUP_STATUSMESSAGE));
+ }
+ else
+ {
+ str = GetStr(&smi, dbVar.ptszVal);
+ }
+ mir_free(protoname);
+
+ ppd.lchContact = smi.hContact;
+ ppd.lchIcon = LoadSkinnedProtoIcon(smi.proto, DBGetContactSettingWord(smi.hContact, smi.proto, "Status", ID_STATUS_ONLINE));
+ lstrcpyn(ppd.lptzContactName, smi.cust, MAX_CONTACTNAME);
+ lstrcpyn(ppd.lptzText, str, MAX_SECONDLINE);
+ switch (opt.Colors)
+ {
+ case POPUP_COLOR_OWN:
+ ppd.colorBack = StatusList[Index(DBGetContactSettingWord(smi.hContact, smi.proto, "Status", ID_STATUS_ONLINE))].colorBack;
+ ppd.colorText = StatusList[Index(DBGetContactSettingWord(smi.hContact, smi.proto, "Status", ID_STATUS_ONLINE))].colorText;
+ break;
+ case POPUP_COLOR_WINDOWS:
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ break;
+ case POPUP_COLOR_POPUP:
+ ppd.colorBack = ppd.colorText = 0;
+ break;
+ }
+ ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ ppd.PluginData = NULL;
+ ppd.iSeconds = opt.PopupTimeout;
+ PUAddPopUpT(&ppd);
+ mir_free(str);
+ }
+ mir_free(smi.newstatusmsg);
+ mir_free(smi.oldstatusmsg);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int ContactSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *)lParam;
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (hContact == NULL)
+ return 0;
+
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (szProto == NULL)
+ return 0;
+
+ if (DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
+ {
+ if (ProcessExtraStatus(cws, hContact))
+ return 0;
+ }
+
+ ProcessStatus(cws, hContact);
+ return 0;
+}
+
+int StatusModeChanged(WPARAM wParam, LPARAM lParam)
+{
+ char *szProto = (char *)lParam;
+ if (opt.AutoDisable && (!opt.OnlyGlobalChanges || szProto == NULL))
+ {
+ if (opt.DisablePopupGlobally && ServiceExists(MS_POPUP_QUERY))
+ {
+ char szSetting[12];
+ wsprintfA(szSetting, "p%d", wParam);
+ BYTE hlpDisablePopup = DBGetContactSettingByte(0, MODULE, szSetting, 0);
+
+ if (hlpDisablePopup != opt.PopupAutoDisabled)
+ {
+ BYTE hlpPopupStatus = (BYTE)CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0);
+ opt.PopupAutoDisabled = hlpDisablePopup;
+
+ if (hlpDisablePopup)
+ {
+ DBWriteContactSettingByte(0, MODULE, "OldPopupStatus", hlpPopupStatus);
+ CallService(MS_POPUP_QUERY, PUQS_DISABLEPOPUPS, 0);
+ }
+ else
+ {
+ if (hlpPopupStatus == FALSE)
+ {
+ if (DBGetContactSettingByte(0, MODULE, "OldPopupStatus", TRUE) == TRUE)
+ CallService(MS_POPUP_QUERY, PUQS_ENABLEPOPUPS, 0);
+ else
+ CallService(MS_POPUP_QUERY, PUQS_DISABLEPOPUPS, 0);
+ }
+ }
+ }
+ }
+
+ if (opt.DisableSoundGlobally)
+ {
+ char szSetting[12];
+ wsprintfA(szSetting, "s%d", wParam);
+ BYTE hlpDisableSound = DBGetContactSettingByte(0, MODULE, szSetting, 0);
+
+ if (hlpDisableSound != opt.SoundAutoDisabled)
+ {
+ BYTE hlpUseSound = DBGetContactSettingByte(NULL, "Skin", "UseSound", 1);
+ opt.SoundAutoDisabled = hlpDisableSound;
+
+ if (hlpDisableSound)
+ {
+ DBWriteContactSettingByte(0, MODULE, "OldUseSound", hlpUseSound);
+ DBWriteContactSettingByte(0, "Skin", "UseSound", FALSE);
+ }
+ else
+ {
+ if (hlpUseSound == FALSE)
+ DBWriteContactSettingByte(0, "Skin", "UseSound", DBGetContactSettingByte(0, MODULE, "OldUseSound", 1));
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+void ShowStatusChangePopup(HANDLE hContact, char *szProto, WORD oldStatus, WORD newStatus)
+{
+ TCHAR stzStatusText[MAX_SECONDLINE] = {0};
+ WORD myStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, (WPARAM)0, (LPARAM)0);
+
+ POPUPDATAT ppd = {0};
+ ppd.lchContact = hContact;
+ ppd.lchIcon = LoadSkinnedProtoIcon(szProto, newStatus);
+ _tcscpy(ppd.lptzContactName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GSMDF_TCHAR));
+
+ if (opt.ShowGroup) //add group name to popup title
+ {
+ DBVARIANT dbv;
+ if (!DBGetContactSettingTString(hContact, "CList", "Group", &dbv))
+ {
+ _tcscat(ppd.lptzContactName, _T(" ("));
+ _tcscat(ppd.lptzContactName, dbv.ptszVal);
+ _tcscat(ppd.lptzContactName, _T(")"));
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ if (opt.ShowStatus)
+ {
+ if (opt.UseAlternativeText)
+ {
+ switch (GetGender(hContact))
+ {
+ case GENDER_MALE:
+ _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzMStatusText, MAX_STATUSTEXT);
+ break;
+ case GENDER_FEMALE:
+ _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzFStatusText, MAX_STATUSTEXT);
+ break;
+ case GENDER_UNSPECIFIED:
+ _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzUStatusText, MAX_STATUSTEXT);
+ break;
+ }
+ }
+ else
+ {
+ _tcsncpy(stzStatusText, StatusList[Index(newStatus)].lpzStandardText, MAX_STATUSTEXT);
+ }
+
+ if (opt.ShowPreviousStatus)
+ {
+ TCHAR buff[MAX_STATUSTEXT];
+ wsprintf(buff, TranslateTS(STRING_SHOWPREVIOUSSTATUS), StatusList[Index(oldStatus)].lpzStandardText);
+ _tcscat(_tcscat(stzStatusText, _T(" ")), buff);
+ }
+ }
+
+ if (opt.ReadAwayMsg &&
+ myStatus != ID_STATUS_INVISIBLE &&
+ StatusHasAwayMessage(szProto, newStatus))
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "LastPopupText", stzStatusText);
+ }
+
+ _tcscpy(ppd.lptzText, stzStatusText);
+
+ switch (opt.Colors)
+ {
+ case POPUP_COLOR_OWN:
+ ppd.colorBack = StatusList[Index(newStatus)].colorBack;
+ ppd.colorText = StatusList[Index(newStatus)].colorText;
+ break;
+ case POPUP_COLOR_WINDOWS:
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ break;
+ case POPUP_COLOR_POPUP:
+ ppd.colorBack = ppd.colorText = 0;
+ break;
+ }
+
+ ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+
+ PLUGINDATA *pdp = (PLUGINDATA *)mir_alloc(sizeof(PLUGINDATA));
+ pdp->oldStatus = oldStatus;
+ pdp->newStatus = newStatus;
+ pdp->hAwayMsgHook = NULL;
+ pdp->hAwayMsgProcess = NULL;
+ ppd.PluginData = pdp;
+ ppd.iSeconds = opt.PopupTimeout;
+ PUAddPopUpT(&ppd);
+}
+
+void BlinkIcon(HANDLE hContact, char* szProto, WORD status)
+{
+ CLISTEVENT cle = {0};
+ TCHAR stzTooltip[256];
+
+ cle.cbSize = sizeof(cle);
+ cle.flags = CLEF_ONLYAFEW | CLEF_TCHAR;
+ cle.hContact = hContact;
+ cle.hDbEvent = hContact;
+ if (opt.BlinkIcon_Status)
+ cle.hIcon = LoadSkinnedProtoIcon(szProto, status);
+ else
+ cle.hIcon = LoadSkinnedIcon(SKINICON_OTHER_USERONLINE);
+ cle.pszService = "UserOnline/Description";
+ cle.ptszTooltip = stzTooltip;
+
+ TCHAR *hlpName = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+ mir_sntprintf(stzTooltip, SIZEOF(stzTooltip), TranslateT("%s is now %s"), hlpName, StatusList[Index(status)].lpzStandardText);
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle);
+}
+
+void PlayChangeSound(HANDLE hContact, WORD oldStatus, WORD newStatus)
+{
+ DBVARIANT dbv;
+ if (opt.UseIndSnd)
+ {
+ TCHAR stzSoundFile[MAX_PATH] = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "UserFromOffline", &dbv) &&
+ oldStatus == ID_STATUS_OFFLINE)
+ {
+ _tcscpy(stzSoundFile, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ else if (!DBGetContactSettingTString(hContact, MODULE, StatusList[Index(newStatus)].lpzSkinSoundName, &dbv))
+ {
+ lstrcpy(stzSoundFile, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ if (stzSoundFile[0])
+ {
+ //Now make path to IndSound absolute, as it isn't registered
+ TCHAR stzSoundPath[MAX_PATH];
+ CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)stzSoundFile, (LPARAM)stzSoundPath);
+ PlaySound(stzSoundPath, NULL, SND_ASYNC | SND_FILENAME | SND_NOSTOP);
+ return;
+ }
+ }
+
+ char szSoundFile[MAX_PATH] = {0};
+
+ if (!DBGetContactSettingByte(0, "SkinSoundsOff", "UserFromOffline", 0) &&
+ !DBGetContactSettingString(0,"SkinSounds", "UserFromOffline", &dbv) &&
+ oldStatus == ID_STATUS_OFFLINE)
+ {
+ strcpy(szSoundFile, "UserFromOffline");
+ DBFreeVariant(&dbv);
+ }
+ else if (!DBGetContactSettingByte(0, "SkinSoundsOff", StatusList[Index(newStatus)].lpzSkinSoundName, 0) &&
+ !DBGetContactSetting(0, "SkinSounds", StatusList[Index(newStatus)].lpzSkinSoundName, &dbv))
+ {
+ strcpy(szSoundFile, StatusList[Index(newStatus)].lpzSkinSoundName);
+ DBFreeVariant(&dbv);
+ }
+
+ if (szSoundFile[0])
+ SkinPlaySound(szSoundFile);
+}
+
+int ContactStatusChanged(WPARAM wParam, LPARAM lParam)
+{
+ WORD oldStatus = LOWORD(lParam);
+ WORD newStatus = HIWORD(lParam);
+ HANDLE hContact = (HANDLE)wParam;
+ char buff[8], szProto[64], szSubProto[64];
+ bool bEnablePopup = true, bEnableSound = true;
+
+ char *hlpProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (hlpProto == NULL || opt.TempDisabled)
+ return 0;
+
+ strcpy(szProto, hlpProto);
+ WORD myStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, (WPARAM)0, (LPARAM)0);
+
+ if (strcmp(szProto, szMetaModuleName) == 0) //this contact is Meta
+ {
+ HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0);
+ strcpy(szSubProto, (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hSubContact,0));
+
+ if (newStatus == ID_STATUS_OFFLINE)
+ {
+ // read last online proto for metaconatct if exists,
+ // to avoid notifying when meta went offline but default contact's proto still online
+ DBVARIANT dbv;
+ if (!DBGetContactSettingString(hContact, szProto, "LastOnline", &dbv))
+ {
+ strcpy(szSubProto, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ else
+ DBWriteContactSettingString(hContact, szProto, "LastOnline", szSubProto);
+
+ if (!DBGetContactSettingByte(0, MODULE, szSubProto, 1))
+ return 0;
+
+ strcpy(szProto, szSubProto);
+ }
+ else
+ {
+ if (myStatus == ID_STATUS_OFFLINE)
+ return 0;
+ }
+
+ if (!opt.FromOffline || oldStatus != ID_STATUS_OFFLINE) // Either it wasn't a change from Offline or we didn't enable that.
+ {
+ wsprintfA(buff, "%d", newStatus);
+ if (DBGetContactSettingByte(0, MODULE, buff, 1) == 0)
+ return 0; // "Notify when a contact changes to one of..." is unchecked
+ }
+
+ if (!opt.HiddenContactsToo && (DBGetContactSettingByte(hContact, "CList", "Hidden", 0) == 1))
+ return 0;
+
+ // we don't want to be notified if new chatroom comes online
+ if (DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0) == 1)
+ return 0;
+
+ // check if that proto from which we received statuschange notification, isn't in autodisable list
+ char statusIDs[12], statusIDp[12];
+ if (opt.AutoDisable)
+ {
+ wsprintfA(statusIDs, "s%d", myStatus);
+ wsprintfA(statusIDp, "p%d", myStatus);
+ bEnableSound = DBGetContactSettingByte(0, MODULE, statusIDs, 1) ? FALSE : TRUE;
+ bEnablePopup = DBGetContactSettingByte(0, MODULE, statusIDp, 1) ? FALSE : TRUE;
+ }
+
+ if (bEnablePopup && DBGetContactSettingByte(hContact, MODULE, "EnablePopups", 1) && TimeoutCheck())
+ ShowStatusChangePopup(hContact, szProto, oldStatus, newStatus);
+
+ if (opt.BlinkIcon)
+ BlinkIcon(hContact, szProto, newStatus);
+
+ if (bEnableSound &&
+ DBGetContactSettingByte(0, "Skin", "UseSound", TRUE) &&
+ DBGetContactSettingByte(hContact, MODULE, "EnableSounds", 1))
+ {
+ PlayChangeSound(hContact, oldStatus, newStatus);
+ }
+
+ if (opt.Log)
+ {
+ TCHAR stzName[64], stzStatus[MAX_STATUSTEXT], stzOldStatus[MAX_STATUSTEXT];
+ TCHAR stzDate[MAX_STATUSTEXT], stzTime[MAX_STATUSTEXT];
+ TCHAR stzText[1024];
+
+ _tcscpy(stzName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+ _tcsncpy(stzStatus, StatusList[Index(newStatus)].lpzStandardText, MAX_STATUSTEXT);
+ _tcsncpy(stzOldStatus, StatusList[Index(oldStatus)].lpzStandardText, MAX_STATUSTEXT);
+ GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("HH':'mm"), stzTime, SIZEOF(stzTime));
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("dd/MM/yyyy"), stzDate, SIZEOF(stzDate));
+ wsprintf(stzText, TranslateT("%s, %s. %s changed to: %s (was: %s).\r\n"), stzDate, stzTime, stzName, stzStatus, stzOldStatus);
+ LogToFile(stzText);
+ }
+
+ return 0;
+}
+
+void InitStatusList()
+{
+ int index = 0;
+ //Online
+ index = Index(ID_STATUS_ONLINE);
+ StatusList[index].ID = ID_STATUS_ONLINE;
+ StatusList[index].icon = SKINICON_STATUS_ONLINE;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) is back online!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) is back online!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) is back online!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Online"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOnline", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Online"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "global.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40072bg", COLOR_BG_AVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40072tx", COLOR_TX_DEFAULT);
+
+ //Offline
+ index = Index(ID_STATUS_OFFLINE);
+ StatusList[index].ID = ID_STATUS_OFFLINE;
+ StatusList[index].icon = SKINICON_STATUS_OFFLINE;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) went offline! :("), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) went offline! :("), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) went offline! :("), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Offline"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOffline", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Offline"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "offline.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40071bg", COLOR_BG_NAVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40071tx", COLOR_TX_DEFAULT);
+
+ //Invisible
+ index = Index(ID_STATUS_INVISIBLE);
+ StatusList[index].ID = ID_STATUS_INVISIBLE;
+ StatusList[index].icon = SKINICON_STATUS_INVISIBLE;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) hides in shadows..."), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) hides in shadows..."), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) hides in shadows..."), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Invisible"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserInvisible", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Invisible"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "invisible.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40078bg", COLOR_BG_AVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40078tx", COLOR_TX_DEFAULT);
+
+ //Free for chat
+ index = Index(ID_STATUS_FREECHAT);
+ StatusList[index].ID = ID_STATUS_FREECHAT;
+ StatusList[index].icon = SKINICON_STATUS_FREE4CHAT;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) feels talkative!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) feels talkative!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) feels talkative!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Free for chat"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserFreeForChat", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Free For Chat"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "free4chat.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40077bg", COLOR_BG_AVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40077tx", COLOR_TX_DEFAULT);
+
+ //Away
+ index = Index(ID_STATUS_AWAY);
+ StatusList[index].ID = ID_STATUS_AWAY;
+ StatusList[index].icon = SKINICON_STATUS_AWAY;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) went Away"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) went Away"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) went Away"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Away"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserAway", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Away"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "away.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40073bg", COLOR_BG_NAVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40073tx", COLOR_TX_DEFAULT);
+
+ //NA
+ index = Index(ID_STATUS_NA);
+ StatusList[index].ID = ID_STATUS_NA;
+ StatusList[index].icon = SKINICON_STATUS_NA;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) isn't there anymore!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) isn't there anymore!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) isn't there anymore!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("NA"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserNA", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Not Available"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "na.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40075bg", COLOR_BG_NAVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40075tx", COLOR_TX_DEFAULT);
+
+ //Occupied
+ index = Index(ID_STATUS_OCCUPIED);
+ StatusList[index].ID = ID_STATUS_OCCUPIED;
+ StatusList[index].icon = SKINICON_STATUS_OCCUPIED;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) has something else to do."), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) has something else to do."), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) has something else to do."), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Occupied"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOccupied", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Occupied"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "occupied.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40076bg", COLOR_BG_NAVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40076tx", COLOR_TX_DEFAULT);
+
+ //DND
+ index = Index(ID_STATUS_DND);
+ StatusList[index].ID = ID_STATUS_DND;
+ StatusList[index].icon = SKINICON_STATUS_DND;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) doesn't want to be disturbed!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) doesn't want to be disturbed!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) doesn't want to be disturbed!"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("DND"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserDND", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Do Not Disturb"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "dnd.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40074bg", COLOR_BG_NAVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40074tx", COLOR_TX_DEFAULT);
+
+ //OutToLunch
+ index = Index(ID_STATUS_OUTTOLUNCH);
+ StatusList[index].ID = ID_STATUS_OUTTOLUNCH;
+ StatusList[index].icon = SKINICON_STATUS_OUTTOLUNCH;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) is eating something"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) is eating something"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) is eating something"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("Out to lunch"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOutToLunch", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: Out To Lunch"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "lunch.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40080bg", COLOR_BG_NAVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40080tx", COLOR_TX_DEFAULT);
+
+ //OnThePhone
+ index = Index(ID_STATUS_ONTHEPHONE);
+ StatusList[index].ID = ID_STATUS_ONTHEPHONE;
+ StatusList[index].icon = SKINICON_STATUS_ONTHEPHONE;
+ lstrcpyn(StatusList[index].lpzMStatusText, TranslateT("(M) had to answer the phone"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzFStatusText, TranslateT("(F) had to answer the phone"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzUStatusText, TranslateT("(U) had to answer the phone"), MAX_STATUSTEXT);
+ lstrcpyn(StatusList[index].lpzStandardText, TranslateT("On the phone"), MAX_STANDARDTEXT);
+ lstrcpynA(StatusList[index].lpzSkinSoundName, "UserOnThePhone", MAX_SKINSOUNDNAME);
+ lstrcpynA(StatusList[index].lpzSkinSoundDesc, Translate("User: On The Phone"), MAX_SKINSOUNDDESC);
+ lstrcpynA(StatusList[index].lpzSkinSoundFile, "phone.wav", MAX_PATH);
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40079bg", COLOR_BG_NAVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40079tx", COLOR_TX_DEFAULT);
+
+ //Extra status
+ index = Index(ID_STATUS_EXTRASTATUS);
+ StatusList[index].ID = ID_STATUS_EXTRASTATUS;
+ StatusList[index].colorBack = DBGetContactSettingDword(NULL, MODULE, "40081bg", COLOR_BG_AVAILDEFAULT);
+ StatusList[index].colorText = DBGetContactSettingDword(NULL, MODULE, "40081tx", COLOR_TX_DEFAULT);
+}
+
+int ProtoAck(WPARAM wParam,LPARAM lParam)
+{
+ ACKDATA *ack = (ACKDATA *)lParam;
+
+ if (ack->type == ACKTYPE_STATUS)
+ {
+ WORD newStatus = (WORD)ack->lParam;
+ WORD oldStatus = (WORD)ack->hProcess;
+ char *szProto = (char *)ack->szModule;
+
+ if (oldStatus == newStatus)
+ return 0;
+
+ if (newStatus == ID_STATUS_OFFLINE)
+ {
+ //The protocol switched to offline. Disable the popups for this protocol
+ DBWriteContactSettingByte(NULL, MODULE, szProto, 0);
+ }
+ else if (oldStatus < ID_STATUS_ONLINE && newStatus >= ID_STATUS_ONLINE)
+ {
+ //The protocol changed from a disconnected status to a connected status.
+ //Enable the popups for this protocol.
+ LoadTime = GetTickCount();
+ }
+ }
+
+ return 0;
+}
+
+INT_PTR EnableDisableMenuCommand(WPARAM wParam, LPARAM lParam)
+{
+ opt.TempDisabled = !opt.TempDisabled;
+ DBWriteContactSettingByte(0, MODULE, "TempDisable", opt.TempDisabled);
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON | CMIM_NAME | CMIF_TCHAR;
+ if (opt.TempDisabled)
+ {
+ mi.ptszName = _T("Enable status notification");
+ mi.icolibItem = GetIconHandle(ICO_NOTIFICATION_OFF);
+ }
+ else
+ {
+ mi.ptszName = _T("Disable status notification");
+ mi.icolibItem = GetIconHandle(ICO_NOTIFICATION_ON);
+ }
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hEnableDisableMenu, (LPARAM)&mi);
+ CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hToolbarButton, opt.TempDisabled ? TTBST_PUSHED : TTBST_RELEASED);
+ return 0;
+}
+
+void InitMainMenuItem()
+{
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_TCHAR | CMIF_ICONFROMICOLIB;
+ mi.ptszPopupName = ServiceExists(MS_POPUP_ADDPOPUP) ? _T("PopUps") : NULL;
+ mi.pszService = MS_STATUSCHANGE_MENUCOMMAND;
+ hEnableDisableMenu = Menu_AddMainMenuItem(&mi);
+
+ opt.TempDisabled = !opt.TempDisabled;
+ EnableDisableMenuCommand(0, 0);
+
+ hServiceMenu = (HANDLE)CreateServiceFunction(MS_STATUSCHANGE_MENUCOMMAND, EnableDisableMenuCommand);
+}
+
+struct _tag_iconList
+{
+ char *szDescr;
+ char *szName;
+ int iIconID;
+}
+static const iconList[] =
+{
+ { "Notification enabled", ICO_NOTIFICATION_OFF, IDI_NOTIFICATION_OFF },
+ { "Notification disabled", ICO_NOTIFICATION_ON, IDI_NOTIFICATION_ON }
+};
+
+void InitIcolib()
+{
+ char szFile[MAX_PATH];
+ char szSettingName[100];
+ SKINICONDESC sid = {0};
+
+ sid.cbSize = sizeof(sid);
+ sid.cx = sid.cy = 16;
+ sid.pszDefaultFile = szFile;
+ sid.pszName = szSettingName;
+ sid.pszSection = MODULE;
+
+ GetModuleFileNameA(hInst, szFile, MAX_PATH);
+
+ for (int i = 0; i < SIZEOF(iconList); i++)
+ {
+ mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", MODULE, iconList[i].szName);
+ sid.pszDescription = Translate(iconList[i].szDescr);
+ sid.iDefaultIndex = -iconList[i].iIconID;
+ Skin_AddIcon(&sid);
+ }
+}
+
+void InitSound()
+{
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++)
+ SkinAddNewSoundEx(StatusList[Index(i)].lpzSkinSoundName, LPGEN("Status Notify"), StatusList[Index(i)].lpzSkinSoundDesc);
+
+ SkinAddNewSoundEx("UserFromOffline", LPGEN("Status Notify"), LPGEN("User: from offline (has priority!)"));
+ SkinAddNewSoundEx(XSTATUS_SOUND_CHANGED, LPGEN("Status Notify"), LPGEN("Extra status changed"));
+ SkinAddNewSoundEx(XSTATUS_SOUND_MSGCHANGED, LPGEN("Status Notify"), LPGEN("Extra status message changed"));
+ SkinAddNewSoundEx(XSTATUS_SOUND_REMOVED, LPGEN("Status Notify"), LPGEN("Extra status removed"));
+}
+
+int InitTopToolbar(WPARAM, LPARAM)
+{
+ TTBButton tbb = {0};
+ tbb.cbSize = sizeof(TTBButton);
+ tbb.pszService = MS_STATUSCHANGE_MENUCOMMAND;
+ tbb.name = LPGEN("Toggle status notification");
+ tbb.pszTooltipUp = LPGEN("Status notification enabled");
+ tbb.pszTooltipDn = LPGEN("Status notification disabled");
+ tbb.hIconHandleUp = GetIconHandle(ICO_NOTIFICATION_ON);
+ tbb.hIconHandleDn = GetIconHandle(ICO_NOTIFICATION_OFF);
+ tbb.dwFlags = (opt.TempDisabled ? TTBBF_PUSHED : 0);
+ hToolbarButton = TopToolbar_AddButton(&tbb);
+ return 0;
+}
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ InitMainMenuItem();
+
+ HookEvent(ME_USERINFO_INITIALISE, UserInfoInitialise);
+ HookEvent(ME_STATUSCHANGE_CONTACTSTATUSCHANGED, ContactStatusChanged);
+ HookEvent(ME_MSG_WINDOWEVENT, OnWindowEvent);
+ HookEvent(ME_TTB_MODULELOADED, InitTopToolbar);
+
+ int count = 0;
+ PROTOACCOUNT **accounts = NULL;
+ CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&count, (LPARAM)&accounts);
+ for (int i = 0; i < count; i++)
+ if (IsAccountEnabled(accounts[i]))
+ DBWriteContactSettingByte(NULL, MODULE, accounts[i]->szModuleName, 0);
+
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME))
+ strcpy(szMetaModuleName, (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0));
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ mir_getLP(&pluginInfoEx);
+
+ //"Service" Hook, used when the DB settings change: we'll monitor the "status" setting.
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged);
+ //We create this Hook which will notify everyone when a contact changes his status.
+ hHookContactStatusChanged = CreateHookableEvent(ME_STATUSCHANGE_CONTACTSTATUSCHANGED);
+ HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+ //We add the option page and the user info page (it's needed because options are loaded after plugins)
+ HookEvent(ME_OPT_INITIALISE, OptionsInitialize);
+ //This is needed for "NoSound"-like routines.
+ HookEvent(ME_CLIST_STATUSMODECHANGE, StatusModeChanged);
+ HookEvent(ME_PROTO_ACK, ProtoAck);
+
+ LoadOptions();
+ InitStatusList();
+ InitIcolib();
+ InitSound();
+
+ CallService(MS_DB_SETSETTINGRESIDENT, (WPARAM)TRUE, (LPARAM)"MetaContacts/LastOnline");
+ CallService(MS_DB_SETSETTINGRESIDENT, (WPARAM)TRUE, (LPARAM)"NewStatusNotify/LastPopupText");
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ DestroyHookableEvent(hHookContactStatusChanged);
+ DestroyServiceFunction(hServiceMenu);
+ xstatusList.destroy();
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/NewXstatusNotify/src/options.cpp b/plugins/NewXstatusNotify/src/options.cpp
new file mode 100644
index 0000000000..808092d498
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/options.cpp
@@ -0,0 +1,1074 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "common.h"
+#include "indsnd.h"
+#include "options.h"
+#include "popup.h"
+#include "xstatus.h"
+#include "utils.h"
+
+OPTIONS opt = {0};
+TEMPLATES templates = {0};
+BOOL UpdateListFlag = FALSE;
+LIST<PROTOTEMPLATE> ProtoTemplates(10);
+int LastItem = 0;
+
+extern HINSTANCE hInst;
+extern HANDLE hEnableDisableMenu;
+extern STATUS StatusList[STATUS_COUNT];
+
+INT_PTR CALLBACK DlgProcAutoDisableOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void LoadTemplates()
+{
+ DBGetStringDefault(0, MODULE, "TPopupDelimiter", templates.PopupDelimiter, SIZEOF(templates.PopupDelimiter), DEFAULT_POPUP_DELIMITER);
+ DBGetStringDefault(0, MODULE, "TPopupChange", templates.PopupNewXstatus, SIZEOF(templates.PopupNewXstatus), DEFAULT_POPUP_NEW);
+ DBGetStringDefault(0, MODULE, "TPopupChangeMsg", templates.PopupNewMsg, SIZEOF(templates.PopupNewMsg), DEFAULT_POPUP_CHANGEMSG);
+ DBGetStringDefault(0, MODULE, "TPopupRemoval", templates.PopupRemove, SIZEOF(templates.PopupRemove), DEFAULT_POPUP_REMOVE);
+
+ DBGetStringDefault(0, MODULE, "TLogDelimiter", templates.LogDelimiter, SIZEOF(templates.LogDelimiter), DEFAULT_LOG_DELIMITER);
+ DBGetStringDefault(0, MODULE, "TLogChange", templates.LogNewXstatus, SIZEOF(templates.LogNewXstatus), DEFAULT_LOG_NEW);
+ DBGetStringDefault(0, MODULE, "TLogChangeMsg", templates.LogNewMsg, SIZEOF(templates.LogNewMsg), DEFAULT_LOG_CHANGEMSG);
+ DBGetStringDefault(0, MODULE, "TLogRemoval", templates.LogRemove, SIZEOF(templates.LogRemove), DEFAULT_LOG_REMOVE);
+ DBGetStringDefault(0, MODULE, "TLogOpening", templates.LogOpening, SIZEOF(templates.LogOpening), DEFAULT_LOG_OPENING);
+ templates.PopupFlags = DBGetContactSettingByte(0, MODULE, "TPopupFlags", NOTIFY_NEW_XSTATUS | NOTIFY_NEW_MESSAGE);
+ templates.LogFlags = DBGetContactSettingByte(0, MODULE, "TLogFlags", NOTIFY_NEW_XSTATUS | NOTIFY_NEW_MESSAGE | NOTIFY_OPENING_ML);
+}
+
+void LoadOptions()
+{
+ // IDD_OPT_POPUP
+ opt.Colors = DBGetContactSettingByte(0,MODULE, "Colors", DEFAULT_COLORS);
+ opt.ShowGroup = DBGetContactSettingByte(0, MODULE, "ShowGroup", 0);
+ opt.ShowStatus = DBGetContactSettingByte(0, MODULE, "ShowStatus", 1);
+ opt.UseAlternativeText = DBGetContactSettingByte(0, MODULE, "UseAlternativeText", 0);
+ opt.ShowPreviousStatus = DBGetContactSettingByte(0, MODULE, "ShowPreviousStatus", 0);
+ opt.ReadAwayMsg = DBGetContactSettingByte(0, MODULE, "ReadAwayMsg", 0);
+ opt.PopupTimeout = DBGetContactSettingDword(0, MODULE, "PopupTimeout", 0);
+ opt.LeftClickAction= DBGetContactSettingByte(0, MODULE, "LeftClickAction", 5);
+ opt.RightClickAction = DBGetContactSettingByte(0, MODULE, "RightClickAction", 1);
+ // IDD_OPT_XPOPUP
+ opt.PDisableForMusic = DBGetContactSettingByte(0, MODULE, "PDisableForMusic", 1);
+ opt.PTruncateMsg = DBGetContactSettingByte(0, MODULE, "PTruncateMsg", 0);
+ opt.PMsgLen = DBGetContactSettingDword(0, MODULE, "PMsgLen", 64);
+ // IDD_OPT_GENERAL
+ opt.FromOffline = DBGetContactSettingByte(0, MODULE, "FromOffline", 1);
+ opt.AutoDisable = DBGetContactSettingByte(0, MODULE, "AutoDisable", 1);
+ opt.HiddenContactsToo = DBGetContactSettingByte(0, MODULE, "HiddenContactsToo", 1);
+ opt.UseIndSnd = DBGetContactSettingByte(0, MODULE, "UseIndSounds", 1);
+ opt.BlinkIcon = DBGetContactSettingByte(0, MODULE, "BlinkIcon", 0);
+ opt.BlinkIcon_Status = DBGetContactSettingByte(0, MODULE, "BlinkIcon_Status", 0);
+ opt.Log = DBGetContactSettingByte(0, MODULE, "Log", 0);
+ DBGetStringDefault(0, MODULE, "LogFilePath", opt.LogFilePath, MAX_PATH, _T(""));
+ // IDD_AUTODISABLE
+ opt.OnlyGlobalChanges = DBGetContactSettingByte(0, MODULE, "OnlyGlobalChanges", 1);
+ opt.DisablePopupGlobally = DBGetContactSettingByte(0, MODULE, "DisablePopupGlobally", 1);
+ opt.DisableSoundGlobally = DBGetContactSettingByte(0, MODULE, "DisableSoundGlobally", 1);
+ // IDD_OPT_XLOG
+ opt.EnableLogging = DBGetContactSettingByte(0, MODULE, "EnableLogging", 0);
+ opt.PreventIdentical = DBGetContactSettingByte(0, MODULE, "PreventIdentical", 1);
+ opt.KeepInHistory = DBGetContactSettingByte(0, MODULE, "KeepInHistory", 0);
+ opt.LDisableForMusic = DBGetContactSettingByte(0, MODULE, "LDisableForMusic", 1);
+ opt.LTruncateMsg = DBGetContactSettingByte(0, MODULE, "LTruncateMsg", 0);
+ opt.LMsgLen = DBGetContactSettingDword(0, MODULE, "LMsgLen", 128);
+ //IDD_OPT_SMPOPUP
+ opt.IgnoreEmpty = DBGetContactSettingByte(0, MODULE, "IgnoreEmpty", 1);
+ opt.PopupOnConnect = DBGetContactSettingByte(0, MODULE, "PopupOnConnect", 0);
+ // OTHER
+ opt.TempDisabled = DBGetContactSettingByte(0, MODULE, "TempDisable", 0);
+
+ LoadTemplates();
+
+ return;
+}
+
+void SaveTemplates()
+{
+ DBWriteContactSettingTString(0, MODULE, "TPopupDelimiter", templates.PopupDelimiter);
+ DBWriteContactSettingTString(0, MODULE, "TPopupChange", templates.PopupNewXstatus);
+ DBWriteContactSettingTString(0, MODULE, "TPopupChangeMsg", templates.PopupNewMsg);
+ DBWriteContactSettingTString(0, MODULE, "TPopupRemoval", templates.PopupRemove);
+ DBWriteContactSettingTString(0, MODULE, "TLogDelimiter", templates.LogDelimiter);
+ DBWriteContactSettingTString(0, MODULE, "TLogChange", templates.LogNewXstatus);
+ DBWriteContactSettingTString(0, MODULE, "TLogChangeMsg", templates.LogNewMsg);
+ DBWriteContactSettingTString(0, MODULE, "TLogRemoval", templates.LogRemove);
+ DBWriteContactSettingTString(0, MODULE, "TLogOpening", templates.LogOpening);
+ DBWriteContactSettingByte(0, MODULE, "TPopupFlags", templates.PopupFlags);
+ DBWriteContactSettingByte(0, MODULE, "TLogFlags", templates.LogFlags);
+
+ for (int i = 0; i < ProtoTemplates.getCount(); i++) {
+ PROTOTEMPLATE *prototemplate = ProtoTemplates[i];
+ TCHAR str[MAX_PATH];
+ mir_sntprintf(str, SIZEOF(str), _T("%s_TSMChange"), prototemplate->ProtoName);
+ char *szstr = mir_t2a(str);
+ DBWriteContactSettingTString(0, MODULE, szstr, prototemplate->ProtoTemplate);
+ }
+}
+
+void SaveOptions()
+{
+ // IDD_OPT_POPUP
+ DBWriteContactSettingByte(0, MODULE, "Colors", opt.Colors);
+ DBWriteContactSettingByte(0, MODULE, "ShowGroup", opt.ShowGroup);
+ DBWriteContactSettingByte(0, MODULE, "ShowStatus", opt.ShowStatus);
+ DBWriteContactSettingByte(0, MODULE, "UseAlternativeText", opt.UseAlternativeText);
+ DBWriteContactSettingByte(0, MODULE, "ShowPreviousStatus", opt.ShowPreviousStatus);
+ DBWriteContactSettingByte(0, MODULE, "ReadAwayMsg", opt.ReadAwayMsg);
+ DBWriteContactSettingDword(0, MODULE, "PopupTimeout", opt.PopupTimeout);
+ DBWriteContactSettingByte(0, MODULE, "LeftClickAction", opt.LeftClickAction);
+ DBWriteContactSettingByte(0, MODULE, "RightClickAction", opt.RightClickAction);
+ // IDD_OPT_XPOPUP
+ DBWriteContactSettingByte(0, MODULE, "PDisableForMusic", opt.PDisableForMusic);
+ DBWriteContactSettingByte(0, MODULE, "PTruncateMsg", opt.PTruncateMsg);
+ DBWriteContactSettingDword(0, MODULE, "PMsgLen", opt.PMsgLen);
+ // IDD_OPT_GENERAL
+ DBWriteContactSettingByte(0, MODULE, "FromOffline", opt.FromOffline);
+ DBWriteContactSettingByte(0, MODULE, "AutoDisable", opt.AutoDisable);
+ DBWriteContactSettingByte(0, MODULE, "HiddenContactsToo", opt.HiddenContactsToo);
+ DBWriteContactSettingByte(0, MODULE, "UseIndSounds", opt.UseIndSnd);
+ DBWriteContactSettingByte(0, MODULE, "BlinkIcon", opt.BlinkIcon);
+ DBWriteContactSettingByte(0, MODULE, "BlinkIcon_Status", opt.BlinkIcon_Status);
+ DBWriteContactSettingByte(0, MODULE, "Log", opt.Log);
+ DBWriteContactSettingTString(0, MODULE, "LogFilePath", opt.LogFilePath);
+ // IDD_AUTODISABLE
+ DBWriteContactSettingByte(0, MODULE, "OnlyGlobalChanges", opt.OnlyGlobalChanges);
+ DBWriteContactSettingByte(0, MODULE, "DisablePopupGlobally", opt.DisablePopupGlobally);
+ DBWriteContactSettingByte(0, MODULE, "DisableSoundGlobally", opt.DisableSoundGlobally);
+ // IDD_OPT_XLOG
+ DBWriteContactSettingByte(0, MODULE, "EnableLogging", opt.EnableLogging);
+ DBWriteContactSettingByte(0, MODULE, "PreventIdentical", opt.PreventIdentical);
+ DBWriteContactSettingByte(0, MODULE, "KeepInHistory", opt.KeepInHistory);
+ DBWriteContactSettingByte(0, MODULE, "LDisableForMusic", opt.LDisableForMusic);
+ DBWriteContactSettingByte(0, MODULE, "LTruncateMsg", opt.LTruncateMsg);
+ DBWriteContactSettingDword(0, MODULE, "LMsgLen", opt.LMsgLen);
+ //IDD_OPT_SMPOPUP
+ DBWriteContactSettingByte(0, MODULE, "IgnoreEmpty", opt.IgnoreEmpty);
+ DBWriteContactSettingByte(0, MODULE, "PopupOnConnect", opt.PopupOnConnect);
+}
+
+INT_PTR CALLBACK DlgProcGeneralOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ CheckDlgButton(hwndDlg, IDC_AUTODISABLE, opt.AutoDisable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGUREAUTODISABLE), opt.AutoDisable);
+
+ CheckDlgButton(hwndDlg, IDC_HIDDENCONTACTSTOO, opt.HiddenContactsToo);
+ CheckDlgButton(hwndDlg, IDC_USEINDIVSOUNDS, opt.UseIndSnd);
+ CheckDlgButton(hwndDlg, IDC_BLINKICON, opt.BlinkIcon);
+ CheckDlgButton(hwndDlg, IDC_BLINKICON_STATUS, opt.BlinkIcon_Status);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKICON_STATUS), opt.BlinkIcon);
+
+ CheckDlgButton(hwndDlg, IDC_LOG, opt.Log);
+ SetDlgItemText(hwndDlg, IDC_LOGFILE, opt.LogFilePath);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGFILE), opt.Log);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BT_CHOOSELOGFILE), opt.Log);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BT_VIEWLOG), opt.Log);
+
+ //Statuses notified
+ char status[8];
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2; i++)
+ {
+ wsprintfA(status, "%d", i);
+ CheckDlgButton(hwndDlg, i, DBGetContactSettingByte(0, MODULE, status, 1));
+ }
+ CheckDlgButton(hwndDlg, IDC_CHK_FROMOFFLINE, opt.FromOffline);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+ case IDC_CONFIGUREAUTODISABLE:
+ CreateDialog(hInst, MAKEINTRESOURCE(IDD_AUTODISABLE), hwndDlg, DlgProcAutoDisableOpts);
+ return FALSE;
+ case IDC_AUTODISABLE:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIGUREAUTODISABLE), IsDlgButtonChecked(hwndDlg, IDC_AUTODISABLE));
+ break;
+ case IDC_BLINKICON:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BLINKICON_STATUS), IsDlgButtonChecked(hwndDlg, IDC_BLINKICON));
+ break;
+ case IDC_BT_VIEWLOG:
+ ShowLog(opt.LogFilePath);
+ return FALSE;
+ case IDC_BT_CHOOSELOGFILE:
+ {
+ TCHAR buff[MAX_PATH];
+ OPENFILENAME ofn = {0};
+
+ GetDlgItemText(hwndDlg, IDC_LOGFILE, buff, MAX_PATH);
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.lpstrFile = buff;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.hwndOwner = hwndDlg;
+ TCHAR filter[MAX_PATH];
+ mir_sntprintf(filter, SIZEOF(filter), _T("%s (*.*)%c*.*%c%s (*.log)%c*.log%c%s (*.txt)%c*.txt%c"), TranslateT("All Files"), 0, 0, TranslateT("Log"), 0, 0, TranslateT("Text"), 0, 0);
+ ofn.lpstrFilter = filter;
+ ofn.nFilterIndex = 2;
+ ofn.lpstrInitialDir = buff;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.lpstrDefExt = _T("log");
+ if (GetSaveFileName(&ofn))
+ SetDlgItemText(hwndDlg, IDC_LOGFILE, buff);
+
+ break;
+ }
+ case IDC_LOG:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGFILE), IsDlgButtonChecked(hwndDlg, IDC_LOG));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BT_CHOOSELOGFILE), IsDlgButtonChecked(hwndDlg, IDC_LOG));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BT_VIEWLOG), IsDlgButtonChecked(hwndDlg, IDC_LOG));
+ break;
+ case IDC_HYPERLINK:
+ {
+ OPENOPTIONSDIALOG ood = {0};
+ ood.cbSize = sizeof(ood);
+ ood.pszGroup = "Customize";
+ ood.pszPage = "Sounds";
+ CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&ood);
+ return FALSE;
+ }
+ }
+
+ if (HIWORD(wParam) == BN_CLICKED || (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus()))
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ if (((LPNMHDR)lParam)->code == PSN_APPLY)
+ {
+ opt.AutoDisable = IsDlgButtonChecked(hwndDlg, IDC_AUTODISABLE);
+ opt.BlinkIcon = IsDlgButtonChecked(hwndDlg, IDC_BLINKICON);
+ opt.BlinkIcon_Status = IsDlgButtonChecked(hwndDlg, IDC_BLINKICON_STATUS);
+ opt.HiddenContactsToo = IsDlgButtonChecked(hwndDlg, IDC_HIDDENCONTACTSTOO);
+ opt.UseIndSnd = IsDlgButtonChecked(hwndDlg, IDC_USEINDIVSOUNDS);
+
+ opt.Log = IsDlgButtonChecked(hwndDlg, IDC_LOG);
+ GetDlgItemText(hwndDlg, IDC_LOGFILE, opt.LogFilePath, SIZEOF(opt.LogFilePath));
+
+ //Notified statuses
+ char status[8];
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2; i++)
+ {
+ wsprintfA(status, "%d", i);
+ DBWriteContactSettingByte(NULL, MODULE, status, (BYTE)IsDlgButtonChecked(hwndDlg, i));
+ }
+ opt.FromOffline = IsDlgButtonChecked(hwndDlg, IDC_CHK_FROMOFFLINE);
+
+ SaveOptions();
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void EnablePopupTextControls(HWND hwndDlg, BOOL bEnable)
+{
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWALTDESCS), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPREVIOUSSTATUS), bEnable);
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_READAWAYMSG), bEnable);
+}
+
+INT_PTR CALLBACK DlgProcPopUpOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ CheckDlgButton(hwndDlg, IDC_USEOWNCOLORS, (opt.Colors == POPUP_COLOR_OWN) ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_USEPOPUPCOLORS, (opt.Colors == POPUP_COLOR_POPUP) ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_USEWINCOLORS, (opt.Colors == POPUP_COLOR_WINDOWS) ? 1 : 0);
+
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2 - 1; i++)
+ {
+ SendDlgItemMessage(hwndDlg, (i+2000), CPM_SETCOLOUR, 0, StatusList[Index(i)].colorBack);
+ SendDlgItemMessage(hwndDlg, (i+1000), CPM_SETCOLOUR, 0, StatusList[Index(i)].colorText);
+ EnableWindow(GetDlgItem(hwndDlg, (i+2000)), (opt.Colors == POPUP_COLOR_OWN));
+ EnableWindow(GetDlgItem(hwndDlg, (i+1000)), (opt.Colors == POPUP_COLOR_OWN));
+ }
+
+ CheckDlgButton(hwndDlg, IDC_SHOWSTATUS, opt.ShowStatus);
+ CheckDlgButton(hwndDlg, IDC_SHOWALTDESCS, opt.UseAlternativeText);
+ CheckDlgButton(hwndDlg, IDC_READAWAYMSG, opt.ReadAwayMsg);
+ CheckDlgButton(hwndDlg, IDC_SHOWPREVIOUSSTATUS, opt.ShowPreviousStatus);
+ CheckDlgButton(hwndDlg, IDC_SHOWGROUP, opt.ShowGroup);
+
+ SendDlgItemMessage(hwndDlg, IDC_TIMEOUT_VALUE, EM_LIMITTEXT, 3, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TIMEOUT_VALUE_SPIN, UDM_SETRANGE32, -1, 999);
+ SetDlgItemInt(hwndDlg, IDC_TIMEOUT_VALUE, opt.PopupTimeout, TRUE);
+
+ //Mouse actions
+ for (int i = 0; i < SIZEOF(PopupActions); i++)
+ {
+ SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_LC), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_LC), CB_ADDSTRING, 0, (LPARAM)TranslateTS(PopupActions[i].Text)), PopupActions[i].Action);
+ SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_RC), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_STATUS_RC), CB_ADDSTRING, 0, (LPARAM)TranslateTS(PopupActions[i].Text)), PopupActions[i].Action);
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_STATUS_LC, CB_SETCURSEL, opt.LeftClickAction, 0);
+ SendDlgItemMessage(hwndDlg, IDC_STATUS_RC, CB_SETCURSEL, opt.RightClickAction, 0);
+
+ EnablePopupTextControls(hwndDlg, opt.ShowStatus);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ WORD idCtrl = LOWORD(wParam);
+ if (HIWORD(wParam) == CPN_COLOURCHANGED)
+ {
+ if(idCtrl > 40070)
+ {
+ COLORREF colour = SendDlgItemMessage(hwndDlg, idCtrl, CPM_GETCOLOUR, 0, 0);
+ if ((idCtrl > 41070) && (idCtrl < 42070)) //Text colour
+ StatusList[Index(idCtrl - 1000)].colorText = colour;
+ else //Background colour
+ StatusList[Index(idCtrl - 2000)].colorBack = colour;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+ }
+ }
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ switch(idCtrl)
+ {
+ case IDC_USEOWNCOLORS:
+ case IDC_USEWINCOLORS:
+ case IDC_USEPOPUPCOLORS:
+ {
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2 - 1; i++)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, (i+2000)), idCtrl == IDC_USEOWNCOLORS); //Background
+ EnableWindow(GetDlgItem(hwndDlg, (i+1000)), idCtrl == IDC_USEOWNCOLORS); //Text
+ }
+
+ break;
+ }
+ case IDC_SHOWSTATUS:
+ {
+ EnablePopupTextControls(hwndDlg, IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS));
+ break;
+ }
+ case IDC_PREVIEW:
+ {
+ POPUPDATAT ppd = {0};
+ ppd.iSeconds = opt.PopupTimeout;
+
+ for (int i = ID_STATUS_MIN; i <= (ID_STATUS_MAX+1); i++)
+ {
+ WORD status = i <= ID_STATUS_MAX2 ? i : ID_STATUS_MIN;
+ ppd.lchIcon = LoadSkinnedIcon(StatusList[Index(status)].icon);
+
+ _tcscpy(ppd.lptzContactName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)NULL, GSMDF_TCHAR));
+ _tcscpy(ppd.lptzText, _T(""));
+
+ if (opt.ShowStatus)
+ {
+ if (opt.UseAlternativeText == 1)
+ _tcscpy(ppd.lptzText, StatusList[Index(status)].lpzUStatusText);
+ else
+ _tcscpy(ppd.lptzText, StatusList[Index(status)].lpzStandardText);
+
+ if (opt.ShowPreviousStatus)
+ {
+ TCHAR buff[MAX_STATUSTEXT];
+ mir_sntprintf(buff, SIZEOF(buff), TranslateTS(STRING_SHOWPREVIOUSSTATUS), StatusList[Index(status)].lpzStandardText);
+ mir_sntprintf(ppd.lptzText, SIZEOF(ppd.lptzText), _T("%s %s"), ppd.lptzText, buff);
+ }
+ }
+
+ if (opt.ReadAwayMsg)
+ {
+ if (ppd.lptzText[0]) _tcscat(ppd.lptzText, _T("\n"));
+ _tcscat(ppd.lptzText, TranslateT("This is status message"));
+ }
+
+ switch (opt.Colors)
+ {
+ case POPUP_COLOR_WINDOWS:
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ break;
+ case POPUP_COLOR_OWN:
+ ppd.colorBack = StatusList[Index(status)].colorBack;
+ ppd.colorText = StatusList[Index(status)].colorText;
+ break;
+ case POPUP_COLOR_POPUP:
+ ppd.colorBack = ppd.colorText = 0;
+ break;
+ }
+
+ PUAddPopUpT(&ppd);
+ }
+
+ return FALSE;
+ }
+ }
+ }
+
+ if ((HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == EN_CHANGE) && (HWND)lParam == GetFocus())
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ if (((LPNMHDR)lParam)->code == PSN_APPLY)
+ {
+ char str[8];
+ DWORD ctlColour = 0;
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX2 - 1; i++)
+ {
+ ctlColour = SendDlgItemMessage(hwndDlg, (i+2000), CPM_GETCOLOUR, 0, 0);
+ StatusList[Index(i)].colorBack = SendDlgItemMessage(hwndDlg, (i+2000), CPM_GETCOLOUR, 0, 0);
+ wsprintfA(str, "%ibg", i);
+ DBWriteContactSettingDword(0, MODULE, str, ctlColour);
+
+ ctlColour = SendDlgItemMessage(hwndDlg, (i+1000), CPM_GETCOLOUR, 0, 0);
+ StatusList[Index(i)].colorText = ctlColour;
+ wsprintfA(str, "%itx", i);
+ DBWriteContactSettingDword(0, MODULE, str, ctlColour);
+ }
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_USEOWNCOLORS))
+ opt.Colors = POPUP_COLOR_OWN;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_USEPOPUPCOLORS))
+ opt.Colors = POPUP_COLOR_POPUP;
+ else
+ opt.Colors = POPUP_COLOR_WINDOWS;
+
+ opt.ShowStatus = IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS);
+ opt.UseAlternativeText = IsDlgButtonChecked(hwndDlg, IDC_SHOWALTDESCS);
+ opt.ReadAwayMsg = IsDlgButtonChecked(hwndDlg, IDC_READAWAYMSG);
+ opt.ShowPreviousStatus = IsDlgButtonChecked(hwndDlg, IDC_SHOWPREVIOUSSTATUS);
+ opt.ShowGroup = IsDlgButtonChecked(hwndDlg, IDC_SHOWGROUP);
+ opt.PopupTimeout = GetDlgItemInt(hwndDlg, IDC_TIMEOUT_VALUE, 0, TRUE);
+ opt.LeftClickAction = (BYTE)SendDlgItemMessage(hwndDlg, IDC_STATUS_LC, CB_GETCURSEL, 0, 0);
+ opt.RightClickAction = (BYTE)SendDlgItemMessage(hwndDlg, IDC_STATUS_RC, CB_GETCURSEL, 0, 0);
+
+ SaveOptions();
+ return TRUE;
+ }
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK DlgProcAutoDisableOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_CHK_PGLOBAL, opt.DisablePopupGlobally);
+ CheckDlgButton(hwndDlg, IDC_CHK_SGLOBAL, opt.DisableSoundGlobally);
+ CheckDlgButton(hwndDlg, IDC_CHK_ONLYGLOBAL, opt.OnlyGlobalChanges);
+
+ char str[8];
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++)
+ {
+ wsprintfA(str, "p%d", i);
+ CheckDlgButton(hwndDlg, i, DBGetContactSettingByte(0, MODULE, str, 0));
+ }
+
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++)
+ {
+ wsprintfA(str, "s%d", i);
+ CheckDlgButton(hwndDlg, (i+2000),DBGetContactSettingByte(NULL, MODULE, str, 0));
+ }
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_OK:
+ char str[8];
+ opt.DisablePopupGlobally = IsDlgButtonChecked(hwndDlg, IDC_CHK_PGLOBAL);
+ opt.DisableSoundGlobally = IsDlgButtonChecked(hwndDlg, IDC_CHK_SGLOBAL);
+ opt.OnlyGlobalChanges = IsDlgButtonChecked(hwndDlg, IDC_CHK_ONLYGLOBAL);
+
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++)
+ {
+ wsprintfA(str, "p%d", i);
+ DBWriteContactSettingByte(NULL, MODULE, str, IsDlgButtonChecked(hwndDlg, i));
+ }
+ for (int i = ID_STATUS_MIN; i <= ID_STATUS_MAX; i++)
+ {
+ wsprintfA(str, "s%d", i);
+ DBWriteContactSettingByte(NULL, MODULE, str, IsDlgButtonChecked(hwndDlg, i+2000));
+ }
+
+ SaveOptions();
+ //Fall through
+ case IDC_CANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+ }
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+int ResetTemplatesToDefault(HWND hwndDlg)
+{
+ int result = MessageBox(hwndDlg,
+ TranslateT("Do you want to reset all templates to default?"),
+ TranslateT("Reset templates"),
+ MB_ICONQUESTION | MB_YESNO);
+ if (result == IDYES)
+ {
+ SetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, DEFAULT_POPUP_DELIMITER);
+ SetDlgItemText(hwndDlg, IDC_ED_TCHANGE, DEFAULT_POPUP_NEW);
+ SetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, DEFAULT_POPUP_CHANGEMSG);
+ SetDlgItemText(hwndDlg, IDC_ED_TREMOVE, DEFAULT_POPUP_REMOVE);
+ SetDlgItemText(hwndDlg, IDC_POPUPTEXT, TranslateT(DEFAULT_POPUP_STATUSMESSAGE));
+ CheckDlgButton(hwndDlg, IDC_CHK_XSTATUSCHANGE, 1);
+ CheckDlgButton(hwndDlg, IDC_CHK_MSGCHANGE, 1);
+ CheckDlgButton(hwndDlg, IDC_CHK_REMOVE, 1);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), TRUE);
+ }
+
+ return result;
+}
+
+INT_PTR CALLBACK DlgProcXPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ SendDlgItemMessage(hwndDlg, IDC_ED_MSGLEN, EM_LIMITTEXT, 3, 0);
+ SendDlgItemMessage(hwndDlg, IDC_UD_MSGLEN, UDM_SETRANGE, 0, MAKELONG(999, 1));
+
+ CheckDlgButton(hwndDlg, IDC_CHK_DISABLEMUSIC, opt.PDisableForMusic);
+ CheckDlgButton(hwndDlg, IDC_CHK_CUTMSG, opt.PTruncateMsg);
+ SetDlgItemInt(hwndDlg, IDC_ED_MSGLEN, opt.PMsgLen, FALSE);
+
+ // Templates
+ CheckDlgButton(hwndDlg, IDC_CHK_XSTATUSCHANGE, templates.PopupFlags & NOTIFY_NEW_XSTATUS ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_CHK_MSGCHANGE, templates.PopupFlags & NOTIFY_NEW_MESSAGE ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_CHK_REMOVE, templates.PopupFlags & NOTIFY_REMOVE ? 1 : 0);
+
+ SetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, templates.PopupDelimiter);
+ SetDlgItemText(hwndDlg, IDC_ED_TCHANGE, templates.PopupNewXstatus);
+ SetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, templates.PopupNewMsg);
+ SetDlgItemText(hwndDlg, IDC_ED_TREMOVE, templates.PopupRemove);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), templates.PopupFlags & NOTIFY_NEW_XSTATUS);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), templates.PopupFlags & NOTIFY_NEW_MESSAGE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), templates.PopupFlags & NOTIFY_REMOVE);
+
+ // Buttons
+ SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Show available variables"), BATF_TCHAR);
+ HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VARIABLES));
+ SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Reset all templates to default"), BATF_TCHAR);
+ hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESET));
+ SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (HIWORD(wParam))
+ {
+ case BN_CLICKED:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHK_CUTMSG:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_MSGLEN), IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG));
+ break;
+ case IDC_CHK_XSTATUSCHANGE:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE));
+ break;
+ case IDC_CHK_MSGCHANGE:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE));
+ break;
+ case IDC_CHK_REMOVE:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE));
+ break;
+ case IDC_BT_VARIABLES:
+ MessageBox(hwndDlg, VARIABLES_HELP_TEXT, TranslateT("Variables"), MB_OK | MB_ICONINFORMATION);
+ break;
+ case IDC_BT_RESET:
+ if (ResetTemplatesToDefault(hwndDlg) == IDYES) break;
+ else return FALSE;
+ }
+
+ if (LOWORD(wParam) != IDC_BT_VARIABLES)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+ }
+ case EN_CHANGE:
+ {
+ if ((HWND)lParam == GetFocus())
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ }
+
+ return TRUE;
+ }
+ case WM_NOTIFY:
+ {
+ if (((LPNMHDR)lParam)->code == PSN_APPLY )
+ {
+ opt.PDisableForMusic = IsDlgButtonChecked(hwndDlg, IDC_CHK_DISABLEMUSIC);
+ opt.PTruncateMsg = IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG);
+ opt.PMsgLen = GetDlgItemInt(hwndDlg, IDC_ED_MSGLEN, 0, FALSE);
+
+ templates.PopupFlags = 0;
+ templates.PopupFlags |= (IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE) ? NOTIFY_NEW_XSTATUS : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE) ? NOTIFY_NEW_MESSAGE : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE) ? NOTIFY_REMOVE : 0);
+
+ // Templates
+ GetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, templates.PopupDelimiter, SIZEOF(templates.PopupDelimiter));
+ GetDlgItemText(hwndDlg, IDC_ED_TCHANGE, templates.PopupNewXstatus, SIZEOF(templates.PopupNewXstatus));
+ GetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, templates.PopupNewMsg, SIZEOF(templates.PopupNewMsg));
+ GetDlgItemText(hwndDlg, IDC_ED_TREMOVE, templates.PopupRemove, SIZEOF(templates.PopupRemove));
+
+ // Save options to db
+ SaveOptions();
+ SaveTemplates();
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+bool IsSuitableProto( PROTOACCOUNT* pa )
+{
+ if ( pa == NULL )
+ return false;
+
+ if ( pa->bDynDisabled || !pa->bIsEnabled )
+ return false;
+
+ if ( CallProtoService( pa->szProtoName, PS_GETCAPS, PFLAGNUM_2, 0 ) == 0 )
+ return false;
+
+ return true;
+}
+
+INT_PTR CALLBACK DlgProcSMPopupOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ {
+ CheckDlgButton(hwndDlg, IDC_ONCONNECT, opt.PopupOnConnect);
+ CheckDlgButton(hwndDlg, IDC_PUIGNOREREMOVE, opt.IgnoreEmpty);
+
+ // Buttons
+ SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Show available variables"), BATF_TCHAR);
+ HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VARIABLES));
+ SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Reset all templates to default"), BATF_TCHAR);
+ hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESET));
+ SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ // proto list
+ HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST);
+ SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
+ LVCOLUMN lvCol = {0};
+ lvCol.mask = LVCF_WIDTH|LVCF_TEXT;
+ lvCol.pszText=TranslateT("Protocol");
+ lvCol.cx = 118;
+ ListView_InsertColumn(hList, 0, &lvCol);
+ // fill the list
+ LVITEM lvItem = {0};
+ lvItem.mask=LVIF_TEXT|LVIF_PARAM;
+ lvItem.iItem=0;
+ lvItem.iSubItem=0;
+
+ int count;
+ PROTOACCOUNT** protos;
+ ProtoEnumAccounts( &count, &protos );
+
+ for(int i=0; i < count; i++) {
+ if ( !IsSuitableProto( protos[i] ))
+ continue;
+
+ UpdateListFlag = TRUE;
+ lvItem.pszText = protos[i]->tszAccountName;
+ lvItem.lParam = (LPARAM)protos[i]->szModuleName;
+ PROTOTEMPLATE *prototemplate = (PROTOTEMPLATE *)mir_alloc(sizeof(PROTOTEMPLATE));
+ prototemplate->ProtoName = protos[i]->tszAccountName;
+ TCHAR protoname[MAX_PATH] = {0};
+ mir_sntprintf(protoname, SIZEOF(protoname), _T("%s_TSMChange"), protos[i]->tszAccountName);
+ char *szprotoname = mir_t2a(protoname);
+ DBVARIANT dbVar = {0};
+ DBGetContactSettingTString(NULL, MODULE, szprotoname, &dbVar);
+ if (lstrcmp(dbVar.ptszVal, NULL) == 0) {
+ DBFreeVariant(&dbVar);
+ _tcsncpy(prototemplate->ProtoTemplate, TranslateT(DEFAULT_POPUP_STATUSMESSAGE), SIZEOF(prototemplate->ProtoTemplate));
+ }
+ else _tcsncpy(prototemplate->ProtoTemplate, dbVar.ptszVal, SIZEOF(prototemplate->ProtoTemplate));
+
+ mir_free(szprotoname);
+ ListView_InsertItem(hList,&lvItem);
+ ProtoTemplates.insert(prototemplate, ProtoTemplates.getCount());
+
+ char dbSetting[128];
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_enabled", protos[i]->szModuleName);
+ ListView_SetCheckState(hList, lvItem.iItem, DBGetContactSettingByte(NULL, MODULE, dbSetting, TRUE));
+ lvItem.iItem++;
+ }
+ UpdateListFlag = FALSE;
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (HIWORD(wParam)) {
+ case BN_CLICKED:
+ switch (LOWORD(wParam)) {
+ case IDC_BT_VARIABLES:
+ MessageBox(0, VARIABLES_SM_HELP_TEXT, TranslateT("Variables"), MB_OK | MB_ICONINFORMATION);
+ break;
+
+ case IDC_BT_RESET:
+ if (ResetTemplatesToDefault(hwndDlg) == IDYES) break;
+ else return FALSE;
+ }
+
+ if (LOWORD(wParam) != IDC_BT_VARIABLES)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+
+ case EN_CHANGE:
+ if ((HWND)lParam == GetFocus())
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ return TRUE;
+
+ case WM_NOTIFY:
+ if (((NMHDR*)lParam)->idFrom == IDC_PROTOCOLLIST) {
+ switch(((NMHDR*)lParam)->code) {
+ case LVN_ITEMCHANGED:
+ {
+ NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;
+ if (nmlv->uNewState == 3 && !UpdateListFlag)
+ {
+ HWND hList = GetDlgItem(hwndDlg,IDC_PROTOCOLLIST);
+ PROTOTEMPLATE *prototemplate;
+ if (ListView_GetHotItem(hList) != ListView_GetSelectionMark(hList)) {
+ prototemplate = ProtoTemplates[ListView_GetSelectionMark(hList)];
+ GetDlgItemText(hwndDlg, IDC_POPUPTEXT, prototemplate->ProtoTemplate, MAX_PATH);
+ ProtoTemplates.remove( ListView_GetSelectionMark(hList));
+ ProtoTemplates.insert(prototemplate, ListView_GetSelectionMark(hList));
+
+ }
+ LastItem = ListView_GetHotItem(hList);
+ prototemplate = ProtoTemplates[LastItem];
+ SetDlgItemText(hwndDlg, IDC_POPUPTEXT, prototemplate->ProtoTemplate);
+ }
+ if ((nmlv->uNewState^nmlv->uOldState)&LVIS_STATEIMAGEMASK && !UpdateListFlag)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ }
+ }
+
+ if (((LPNMHDR)lParam)->code == PSN_APPLY ) {
+ opt.IgnoreEmpty = IsDlgButtonChecked(hwndDlg, IDC_PUIGNOREREMOVE);
+ opt.PopupOnConnect = IsDlgButtonChecked(hwndDlg, IDC_ONCONNECT);
+
+ // Templates
+ PROTOTEMPLATE *prototemplate = ProtoTemplates[LastItem];
+ GetDlgItemText(hwndDlg, IDC_POPUPTEXT, prototemplate->ProtoTemplate, MAX_PATH);
+ ProtoTemplates.remove(LastItem);
+ ProtoTemplates.insert(prototemplate, LastItem);
+
+ // Save options to db
+ SaveOptions();
+ SaveTemplates();
+ HWND hList = GetDlgItem(hwndDlg,IDC_PROTOCOLLIST);
+ LVITEM lvItem = {0};
+ lvItem.mask=LVIF_PARAM;
+ for (int i=0;i<ListView_GetItemCount(hList);i++) {
+ lvItem.iItem=i;
+ lvItem.iSubItem=0;
+ ListView_GetItem(hList, &lvItem);
+
+ char dbSetting[128];
+ mir_snprintf(dbSetting, SIZEOF(dbSetting), "%s_enabled", (char *)lvItem.lParam);
+ DBWriteContactSettingByte(NULL, MODULE, dbSetting, (BYTE)ListView_GetCheckState(hList, lvItem.iItem));
+ }
+ }
+
+ return TRUE;
+
+ case WM_DESTROY:
+ ProtoTemplates.destroy();
+ break;
+ }
+
+ return FALSE;
+}
+
+void EnableLogControls(HWND hwndDlg, BOOL state)
+{
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_SAVETOHISTORY), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_PREVENTIDENTICAL), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_DISABLEMUSIC), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_CUTMSG), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_MSGLEN), state & IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_XSTATUSCHANGE), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_MSGCHANGE), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_REMOVE), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_OPENING), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TDELIMITER), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), state & IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), state & IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), state & IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TOPENING), state & IsDlgButtonChecked(hwndDlg, IDC_CHK_OPENING));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BT_VARIABLES), state);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BT_RESET), state);
+}
+
+INT_PTR CALLBACK DlgProcXLogOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_LOGGING, opt.EnableLogging);
+ CheckDlgButton(hwndDlg, IDC_CHK_SAVETOHISTORY, opt.KeepInHistory);
+ CheckDlgButton(hwndDlg, IDC_CHK_PREVENTIDENTICAL, opt.PreventIdentical);
+ CheckDlgButton(hwndDlg, IDC_CHK_DISABLEMUSIC, opt.LDisableForMusic);
+ CheckDlgButton(hwndDlg, IDC_CHK_CUTMSG, opt.LTruncateMsg);
+
+ SendDlgItemMessage(hwndDlg, IDC_ED_MSGLEN, EM_LIMITTEXT, 3, 0);
+ SendDlgItemMessage(hwndDlg, IDC_UD_MSGLEN, UDM_SETRANGE, 0, MAKELONG(999, 1));
+ SetDlgItemInt(hwndDlg, IDC_ED_MSGLEN, opt.LMsgLen, FALSE);
+
+ //Templates
+ CheckDlgButton(hwndDlg, IDC_CHK_XSTATUSCHANGE, (templates.LogFlags & NOTIFY_NEW_XSTATUS) ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_CHK_MSGCHANGE, (templates.LogFlags & NOTIFY_NEW_MESSAGE) ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_CHK_REMOVE, (templates.LogFlags & NOTIFY_REMOVE) ? 1 : 0);
+ CheckDlgButton(hwndDlg, IDC_CHK_OPENING, (templates.LogFlags & NOTIFY_OPENING_ML) ? 1 : 0);
+
+ SetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, templates.LogDelimiter);
+ SetDlgItemText(hwndDlg, IDC_ED_TCHANGE, templates.LogNewXstatus);
+ SetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, templates.LogNewMsg);
+ SetDlgItemText(hwndDlg, IDC_ED_TREMOVE, templates.LogRemove);
+ SetDlgItemText(hwndDlg, IDC_ED_TOPENING, templates.LogOpening);
+
+ // Buttons
+ SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Show available variables"), BATF_TCHAR);
+ HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_VARIABLES));
+ SendDlgItemMessage(hwndDlg, IDC_BT_VARIABLES, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Reset all templates to default"), BATF_TCHAR);
+ hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESET));
+ SendDlgItemMessage(hwndDlg, IDC_BT_RESET, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+
+ EnableLogControls(hwndDlg, opt.EnableLogging);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (HIWORD(wParam))
+ {
+ case BN_CLICKED:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHK_LOGGING:
+ EnableLogControls(hwndDlg, IsDlgButtonChecked(hwndDlg, IDC_CHK_LOGGING) ? TRUE : FALSE);
+ break;
+ case IDC_CHK_CUTMSG:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_MSGLEN), IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG));
+ break;
+ case IDC_CHK_XSTATUSCHANGE:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGE), IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE));
+ break;
+ case IDC_CHK_MSGCHANGE:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TCHANGEMSG), IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE));
+ break;
+ case IDC_CHK_REMOVE:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TREMOVE), IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE));
+ break;
+ case IDC_CHK_OPENING:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TOPENING), IsDlgButtonChecked(hwndDlg, IDC_CHK_OPENING));
+ break;
+ case IDC_BT_VARIABLES:
+ MessageBox(hwndDlg, VARIABLES_HELP_TEXT, TranslateT("Variables"), MB_OK | MB_ICONINFORMATION);
+ break;
+ case IDC_BT_RESET:
+ if (ResetTemplatesToDefault(hwndDlg) == IDYES)
+ {
+ SetDlgItemText(hwndDlg, IDC_ED_TOPENING, DEFAULT_LOG_OPENING);
+ CheckDlgButton(hwndDlg, IDC_CHK_OPENING, 1);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_TOPENING), TRUE);
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ break;
+ }
+
+ if (LOWORD(wParam) != IDC_BT_VARIABLES)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+ }
+
+ case EN_CHANGE:
+ {
+ if ((HWND)lParam == GetFocus())
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ return TRUE;
+ }
+ case WM_NOTIFY:
+ {
+ if (((LPNMHDR)lParam)->code == PSN_APPLY )
+ {
+ opt.EnableLogging = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOGGING);
+ opt.KeepInHistory = IsDlgButtonChecked(hwndDlg, IDC_CHK_SAVETOHISTORY);
+ opt.PreventIdentical = IsDlgButtonChecked(hwndDlg, IDC_CHK_PREVENTIDENTICAL);
+ opt.LDisableForMusic = IsDlgButtonChecked(hwndDlg, IDC_CHK_DISABLEMUSIC);
+ opt.LTruncateMsg = IsDlgButtonChecked(hwndDlg, IDC_CHK_CUTMSG);
+ opt.LMsgLen = GetDlgItemInt(hwndDlg, IDC_ED_MSGLEN, 0, FALSE);
+
+ templates.LogFlags = 0;
+ templates.LogFlags |= (IsDlgButtonChecked(hwndDlg, IDC_CHK_XSTATUSCHANGE) ? NOTIFY_NEW_XSTATUS : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_CHK_MSGCHANGE) ? NOTIFY_NEW_MESSAGE : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_CHK_REMOVE) ? NOTIFY_REMOVE : 0) |
+ (IsDlgButtonChecked(hwndDlg, IDC_CHK_OPENING) ? NOTIFY_OPENING_ML : 0);
+
+ // Templates
+ GetDlgItemText(hwndDlg, IDC_ED_TDELIMITER, templates.LogDelimiter, SIZEOF(templates.LogDelimiter));
+ GetDlgItemText(hwndDlg, IDC_ED_TCHANGE, templates.LogNewXstatus, SIZEOF(templates.LogNewXstatus));
+ GetDlgItemText(hwndDlg, IDC_ED_TCHANGEMSG, templates.LogNewMsg, SIZEOF(templates.LogNewMsg));
+ GetDlgItemText(hwndDlg, IDC_ED_TREMOVE, templates.LogRemove, SIZEOF(templates.LogRemove));
+ GetDlgItemText(hwndDlg, IDC_ED_TOPENING, templates.LogOpening, SIZEOF(templates.LogOpening));
+
+ SaveOptions();
+ SaveTemplates();
+ }
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+int OptionsInitialize(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ odp.cbSize = sizeof(odp);
+ odp.position = -100000000;
+ odp.hInstance = hInst;
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pszTitle = LPGEN("Status Notify");
+ odp.pszGroup = LPGEN("Status");
+ odp.pszTab = LPGEN("General");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENERAL);
+ odp.pfnDlgProc = DlgProcGeneralOpts;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTab = LPGEN("Filtering");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FILTERS);
+ odp.pfnDlgProc = DlgProcFiltering;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTab = LPGEN("Message log");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_XLOG);
+ odp.pfnDlgProc = DlgProcXLogOpts;
+ Options_AddPage(wParam, &odp);
+
+ if (ServiceExists(MS_POPUP_ADDPOPUP)) {
+ odp.pszTitle = LPGEN("Status Notify");
+ odp.pszGroup = LPGEN("Popups");
+ odp.pszTab = LPGEN("General");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP);
+ odp.pfnDlgProc = DlgProcPopUpOpts;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTab = LPGEN("Extra status");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_XPOPUP);
+ odp.pfnDlgProc = DlgProcXPopupOpts;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTab = LPGEN("Status message");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SMPOPUP);
+ odp.pfnDlgProc = DlgProcSMPopupOpts;
+ Options_AddPage(wParam, &odp);
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/NewXstatusNotify/src/options.h b/plugins/NewXstatusNotify/src/options.h
new file mode 100644
index 0000000000..59c1bfff4f
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/options.h
@@ -0,0 +1,90 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ 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
+*/
+
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
+#include "common.h"
+
+#define DEFAULT_LOGFILE "NewStatusNotify.log"
+
+typedef struct tagOPTIONS {
+ // IDD_OPT_POPUP
+ BYTE Colors;
+ BYTE ShowGroup;
+ BYTE ShowStatus;
+ BYTE UseAlternativeText;
+ BYTE ShowPreviousStatus;
+ BYTE ReadAwayMsg;
+ int PopupTimeout;
+ BYTE LeftClickAction;
+ BYTE RightClickAction;
+ // IDD_OPT_XPOPUP
+ BYTE PDisableForMusic;
+ BYTE PTruncateMsg;
+ DWORD PMsgLen;
+ // IDD_OPT_GENERAL
+ BYTE FromOffline;
+ BYTE AutoDisable;
+ BYTE HiddenContactsToo;
+ BYTE UseIndSnd;
+ BYTE BlinkIcon;
+ BYTE BlinkIcon_Status;
+ BYTE Log;
+ TCHAR LogFilePath[MAX_PATH];
+ // IDD_AUTODISABLE
+ BYTE OnlyGlobalChanges;
+ BYTE DisableSoundGlobally;
+ BYTE DisablePopupGlobally;
+ // IDD_OPT_XLOG
+ BYTE EnableLogging;
+ BYTE PreventIdentical;
+ BYTE KeepInHistory;
+ BYTE LDisableForMusic;
+ BYTE LTruncateMsg;
+ DWORD LMsgLen;
+ //IDD_OPT_SMPOPUP
+ BYTE PopupOnConnect;
+ BYTE IgnoreEmpty;
+ // OTHER
+ BYTE TempDisabled;
+ BYTE PopupAutoDisabled;
+ BYTE SoundAutoDisabled;
+} OPTIONS;
+
+typedef struct tagTEMPLATES {
+ BYTE PopupFlags;
+ BYTE LogFlags;
+ TCHAR PopupDelimiter[32];
+ TCHAR PopupNewXstatus[256];
+ TCHAR PopupNewMsg[256];
+ TCHAR PopupRemove[256];
+ TCHAR LogDelimiter[32];
+ TCHAR LogNewXstatus[256];
+ TCHAR LogNewMsg[256];
+ TCHAR LogRemove[256];
+ TCHAR LogOpening[256];
+} TEMPLATES;
+
+int OptionsInitialize(WPARAM wParam, LPARAM lParam);
+void LoadOptions();
+
+#endif \ No newline at end of file
diff --git a/plugins/NewXstatusNotify/src/popup.cpp b/plugins/NewXstatusNotify/src/popup.cpp
new file mode 100644
index 0000000000..c8e7d32e32
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/popup.cpp
@@ -0,0 +1,175 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "common.h"
+#include "popup.h"
+#include "options.h"
+#include "utils.h"
+
+extern OPTIONS opt;
+
+void QueryAwayMessage(HWND hWnd, PLUGINDATA *pdp)
+{
+ HANDLE hContact = PUGetContact(hWnd);
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (szProto)
+ {
+ if ((CallProtoService(szProto, PS_GETCAPS,PFLAGNUM_1, 0) & PF1_MODEMSGRECV) &&
+ (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(pdp->newStatus)))
+ {
+ //The following HookEventMessage will hook the ME_PROTO_ACK event and send a WM_AWAYMSG to hWnd when the hooks get notified.
+ pdp->hAwayMsgHook = HookEventMessage(ME_PROTO_ACK, hWnd, WM_AWAYMSG);
+ //The following instruction asks Miranda to retrieve the away message and associates a hProcess (handle) to this request. This handle will appear in the ME_PROTO_ACK event.
+ pdp->hAwayMsgProcess = (HANDLE)CallContactService(hContact, PSS_GETAWAYMSG, 0, 0);
+ }
+ }
+}
+
+void ReceivedAwayMessage(HWND hWnd, LPARAM lParam, PLUGINDATA * pdp)
+{
+ ACKDATA *ack = (ACKDATA *)lParam;
+ if (ack->type != ACKTYPE_AWAYMSG || ack->hProcess != pdp->hAwayMsgProcess)
+ return;
+
+ //The first thing we go is removing the hook from the chain to avoid useless calls.
+ UnhookEvent(pdp->hAwayMsgHook);
+ pdp->hAwayMsgHook = NULL;
+
+ if (ack->result != ACKRESULT_SUCCESS)
+ return;
+
+ DBVARIANT dbv;
+ HANDLE hContact = PUGetContact(hWnd);
+
+ if ( DBGetContactSettingTString(hContact, MODULE, "LastPopupText", &dbv))
+ return;
+
+ TCHAR stzText[MAX_SECONDLINE], *tszStatus = (TCHAR*)ack->lParam;
+ _tcscpy(stzText, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+
+ if (tszStatus == NULL || *tszStatus == 0)
+ return;
+
+ if (stzText[0])
+ _tcscat(stzText, _T("\n"));
+ _tcscat(stzText, tszStatus);
+ SendMessage(hWnd, WM_SETREDRAW, FALSE, 0);
+ PUChangeTextT(hWnd, stzText);
+ SendMessage(hWnd, WM_SETREDRAW, TRUE, 0);
+}
+
+void PopupAction(HWND hWnd, BYTE action)
+{
+ HANDLE hContact = PUGetContact(hWnd);
+ if (hContact && hContact != INVALID_HANDLE_VALUE) {
+ switch (action) {
+ case PCA_OPENMESSAGEWND:
+ CallServiceSync(ServiceExists("SRMsg/LaunchMessageWindow") ? "SRMsg/LaunchMessageWindow" : MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0);
+ break;
+
+ case PCA_OPENMENU:
+ {
+ POINT pt = {0};
+ HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)hContact, 0);
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hWnd, NULL);
+ DestroyMenu(hMenu);
+ }
+ return;
+
+ case PCA_OPENDETAILS:
+ CallServiceSync(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0);
+ break;
+
+ case PCA_OPENHISTORY:
+ CallServiceSync(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)hContact, 0);
+ break;
+
+ case PCA_CLOSEPOPUP:
+ break;
+
+ case PCA_DONOTHING:
+ return;
+ }
+
+ PUDeletePopUp(hWnd);
+ }
+}
+
+INT_PTR CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ PLUGINDATA *pdp = NULL;
+
+ switch(message)
+ {
+ case WM_MEASUREITEM: //Needed by the contact's context menu
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+
+ case WM_DRAWITEM: //Needed by the contact's context menu
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+
+ case WM_COMMAND:
+ //This one returns TRUE if it processed the menu command, and FALSE if it did not process it.
+ if (CallServiceSync(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)PUGetContact(hwnd)))
+ break;
+
+ PopupAction(hwnd, opt.LeftClickAction);
+ break;
+
+ case WM_CONTEXTMENU:
+ PopupAction(hwnd, opt.RightClickAction);
+ break;
+
+ case UM_FREEPLUGINDATA:
+ pdp = (PLUGINDATA *)PUGetPluginData(hwnd);
+ if (pdp != NULL) {
+ if (pdp->hAwayMsgHook != NULL) {
+ UnhookEvent(pdp->hAwayMsgHook);
+ pdp->hAwayMsgHook = NULL;
+ }
+
+ mir_free(pdp);
+ }
+ return FALSE;
+
+ case UM_INITPOPUP:
+ pdp = (PLUGINDATA *)PUGetPluginData(hwnd);
+ if (pdp != NULL) {
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)PUGetContact(hwnd), 0);
+ if (szProto && opt.ReadAwayMsg && StatusHasAwayMessage(szProto, pdp->newStatus)) {
+ WORD myStatus = (WORD)CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ if (myStatus != ID_STATUS_INVISIBLE)
+ QueryAwayMessage(hwnd, pdp);
+ }
+ }
+
+ return FALSE;
+
+ case WM_AWAYMSG: //We're here because ME_PROTO_ACK has been hooked to this window (too!).
+ pdp = (PLUGINDATA *)PUGetPluginData(hwnd);
+ if (pdp != NULL)
+ ReceivedAwayMessage(hwnd, lParam, pdp);
+ return FALSE;
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
diff --git a/plugins/NewXstatusNotify/src/popup.h b/plugins/NewXstatusNotify/src/popup.h
new file mode 100644
index 0000000000..e6e56f6c5b
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/popup.h
@@ -0,0 +1,54 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ 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
+*/
+
+#ifndef POPUP_H
+#define POPUP_H
+
+#define POPUP_COLOR_OWN 1
+#define POPUP_COLOR_WINDOWS 2
+#define POPUP_COLOR_POPUP 3
+#define DEFAULT_COLORS POPUP_COLOR_POPUP
+
+// Actions on popup click
+#define PCA_OPENMESSAGEWND 0 // open message window
+#define PCA_CLOSEPOPUP 1 // close popup
+#define PCA_OPENDETAILS 2 // open contact details window
+#define PCA_OPENMENU 3 // open contact menu
+#define PCA_OPENHISTORY 4 // open contact history
+#define PCA_DONOTHING 5 // do nothing
+
+#define STRING_SHOWPREVIOUSSTATUS _T("(was %s)")
+
+static struct {
+ TCHAR *Text;
+ int Action;
+} PopupActions[] = {
+ _T("Open message window"), PCA_OPENMESSAGEWND,
+ _T("Close popup"), PCA_CLOSEPOPUP,
+ _T("Open contact details window"), PCA_OPENDETAILS,
+ _T("Open contact menu"), PCA_OPENMENU,
+ _T("Open contact history"), PCA_OPENHISTORY,
+ _T("Do nothing"), PCA_DONOTHING
+};
+
+INT_PTR CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+#endif \ No newline at end of file
diff --git a/plugins/NewXstatusNotify/src/resource.h b/plugins/NewXstatusNotify/src/resource.h
new file mode 100644
index 0000000000..b68a263716
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/resource.h
@@ -0,0 +1,147 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDD_OPT_XPOPUP 101
+#define IDD_INFO_SOUNDS 102
+#define IDD_OPT_GENERAL 103
+#define IDI_RESET 109
+#define IDI_VARIABLES 110
+#define IDD_AUTODISABLE 113
+#define IDD_OPT_FILTERS 114
+#define IDD_OPT_POPUP 115
+#define IDD_OPT_XLOG 116
+#define IDI_POPUP 117
+#define IDD_OPT_SMPOPUP 117
+#define IDI_SOUND 118
+#define IDI_LOGGING 119
+#define IDI_XSTATUS 120
+#define IDI_DISABLEALL 121
+#define IDI_ENABLEALL 122
+#define IDI_NOTIFICATION_OFF 123
+#define IDI_NOTIFICATION_ON 124
+#define IDI_STATUS_MESSAGE 125
+#define IDC_STATUS_STATIC_INFINITE 1002
+#define IDC_STATUS_STATIC_DEFAULT 1003
+#define IDC_TIMEOUT_VALUE_SPIN 1004
+#define IDC_STATUS_STATIC_SEC 1005
+#define IDC_STATUS_LC 1006
+#define IDC_USEWINCOLORS 1007
+#define IDC_STATUS_RC 1008
+#define IDC_READAWAYMSG 1011
+#define IDC_CHK_DISABLEMUSIC 1011
+#define IDC_SHOWPREVIOUSSTATUS 1012
+#define IDC_CHK_CUTMSG 1012
+#define IDC_USEPOPUPCOLORS 1013
+#define IDC_ED_MSGLEN 1013
+#define IDC_ED_TOPENING 1018
+#define IDC_ED_TCHANGE 1024
+#define IDC_ED_TCHANGEMSG 1025
+#define IDC_BT_VARIABLES 1028
+#define IDC_BT_RESET 1029
+#define IDC_PREVIEW 1030
+#define IDC_CHANGE 1031
+#define IDC_CHK_MSGCHANGE 1031
+#define IDC_DELETE 1032
+#define IDC_CHK_XSTATUSCHANGE 1032
+#define IDC_CHK_OPENING 1033
+#define IDC_UD_MSGLEN 1034
+#define IDC_CHK_PGLOBAL 1035
+#define IDC_CHK_SGLOBAL 1036
+#define IDC_CHK_ONLYGLOBAL 1037
+#define IDC_HYPERLINK 1038
+#define IDC_CHK_REMOVE 1039
+#define IDC_ED_TREMOVE 1040
+#define IDC_ED_TDELIMITER 1042
+#define IDC_INDSNDLIST 1044
+#define IDC_HIDDENCONTACTSTOO 1052
+#define IDC_USEINDIVSOUNDS 1053
+#define IDC_OK 1055
+#define IDC_CANCEL 1056
+#define IDC_CONFIGUREAUTODISABLE 1057
+#define IDC_AUTODISABLE 1060
+#define IDC_LOG 1061
+#define IDC_TIMEOUT_VALUE 1066
+#define IDC_BLINKICON 1067
+#define IDC_BLINKICON_STATUS 1068
+#define IDC_SOUNDICON 1069
+#define IDC_POPUPICON 1070
+#define IDC_CHECK_NOTIFYSOUNDS 1071
+#define IDC_CHECK_NOTIFYPOPUPS 1073
+#define IDC_TEXT_ENABLE_IS 1074
+#define IDC_USEOWNCOLORS 1076
+#define IDC_SHOWALTDESCS 1077
+#define IDC_LOGGINGICON 1078
+#define IDC_SHOWSTATUS 1078
+#define IDC_XSTATUSICON 1079
+#define IDC_DISABLEALLICON 1080
+#define IDC_ENABLEALLICON 1081
+#define IDC_SHOWGROUP 1082
+#define IDC_STATUSMESSAGEICON 1082
+#define IDC_ONCONNECT 1101
+#define IDC_PUIGNOREREMOVE 1102
+#define IDC_POPUPTEXT 1115
+#define IDC_PROTOCOLLIST 1207
+#define IDC_LOGFILE 2029
+#define IDC_BT_CHOOSELOGFILE 2030
+#define IDC_BT_VIEWLOG 2031
+#define IDC_CHK_LOGGING 2034
+#define IDC_CHK_SAVETOHISTORY 2039
+#define IDC_CHK_PREVENTIDENTICAL 2040
+#define IDC_CHK_OFFLINE 40071
+#define IDC_CHK_ONLINE 40072
+#define IDC_CHK_AWAY 40073
+#define IDC_CHK_DND 40074
+#define IDC_CHK_NA 40075
+#define IDC_CHK_OCCUPIED 40076
+#define IDC_CHK_FREECHAT 40077
+#define IDC_CHK_INVISIBLE 40078
+#define IDC_CHK_ONTHEPHONE 40079
+#define IDC_CHK_OUTTOLUNCH 40080
+#define IDC_CHK_XSTATUS 40081
+#define IDC_CHK_STATUS_MESSAGE 40082
+#define IDC_CHK_FROMOFFLINE 40083
+#define IDC_OFFLINE_TX 41071
+#define IDC_ONLINE_TX 41072
+#define IDC_AWAY_TX 41073
+#define IDC_DND_TX 41074
+#define IDC_NA_TX 41075
+#define IDC_OCCUPIED_TX 41076
+#define IDC_FREEFORCHAT_TX 41077
+#define IDC_INVISIBLE_TX 41078
+#define IDC_ONTHEPHONE_TX 41079
+#define IDC_OUTTOLUNCH_TX 41080
+#define IDC_XSTATUS_TX 41081
+#define IDC_STATUSMESSAGE_TX 41082
+#define IDC_OFFLINE_BG 42071
+#define IDC_ONLINE_BG 42072
+#define IDC_CHK_ONLINE2 42072
+#define IDC_AWAY_BG 42073
+#define IDC_CHK_AWAY2 42073
+#define IDC_DND_BG 42074
+#define IDC_CHK_DND2 42074
+#define IDC_NA_BG 42075
+#define IDC_CHK_NA2 42075
+#define IDC_OCCUPIED_BG 42076
+#define IDC_CHK_OCCUPIED2 42076
+#define IDC_FREEFORCHAT_BG 42077
+#define IDC_CHK_FREECHAT2 42077
+#define IDC_INVISIBLE_BG 42078
+#define IDC_CHK_INVISIBLE2 42078
+#define IDC_ONTHEPHONE_BG 42079
+#define IDC_CHK_ONTHEPHONE2 42079
+#define IDC_OUTTOLUNCH_BG 42080
+#define IDC_CHK_OUTTOLUNCH2 42080
+#define IDC_XSTATUS_BG 42081
+#define IDC_STATUSMESSAGE_BG 42082
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 111
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1044
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/NewXstatusNotify/src/utils.cpp b/plugins/NewXstatusNotify/src/utils.cpp
new file mode 100644
index 0000000000..bfa8184ddf
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/utils.cpp
@@ -0,0 +1,124 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "common.h"
+#include "options.h"
+
+extern OPTIONS opt;
+extern STATUS StatusList[STATUS_COUNT];
+
+TCHAR *db2t(DBVARIANT *dbv)
+{
+ TCHAR *buff;
+ switch (dbv->type)
+ {
+ case DBVT_ASCIIZ: buff = mir_a2t(dbv->pszVal); break;
+ case DBVT_WCHAR: buff = mir_tstrdup(dbv->ptszVal); break;
+ case DBVT_UTF8: buff = mir_utf8decodeT(dbv->pszVal); break;
+ default: buff = mir_tstrdup(_T(""));
+ }
+
+ if (buff[0] == 0)
+ {
+ mir_free(buff);
+ buff = NULL;
+ }
+
+ return buff;
+}
+
+int DBGetStringDefault(HANDLE hContact, const char *szModule, const char *szSetting, TCHAR *setting, int size, const TCHAR *defaultValue)
+{
+ DBVARIANT dbv;
+ if (!DBGetContactSettingTString(hContact, szModule, szSetting, &dbv))
+ {
+ _tcsncpy(setting, dbv.ptszVal, size);
+ DBFreeVariant(&dbv);
+ return 0;
+ }
+
+ _tcsncpy(setting, defaultValue, size);
+ return 1;
+}
+
+void HigherLower(int maxValue, int minValue)
+{
+ TCHAR str[64] = { 0 };
+ wsprintf(str, TranslateT("You cannot specify a value lower than %d and higher than %d."), minValue, maxValue);
+}
+
+void ShowLog(TCHAR *file)
+{
+ int res = (int)ShellExecute(NULL, _T("open"), file, NULL, NULL, SW_SHOW);
+ if (res <= 32) // error
+ MessageBox(0, TranslateT("Can't open the log file!"), TranslateT("NewXstatusNotify"), MB_OK | MB_ICONERROR);
+}
+
+int ProtoServiceExists(const char *szModule, const char *szService)
+{
+ char str[MAXMODULELABELLENGTH];
+ if (szModule == NULL || szService == NULL)
+ return 0;
+
+ strcpy(str,szModule);
+ strcat(str,szService);
+ return ServiceExists(str);
+}
+
+BOOL StatusHasAwayMessage(char *szProto, int status)
+{
+ if (szProto != NULL)
+ {
+ unsigned long iSupportsSM = (unsigned long)CallProtoService(szProto, PS_GETCAPS, (WPARAM)PFLAGNUM_3, (LPARAM)0);
+ return (iSupportsSM & Proto_Status2Flag(status)) ? TRUE : FALSE;
+ }
+ else
+ {
+ switch (status)
+ {
+ case ID_STATUS_AWAY:
+ case ID_STATUS_NA:
+ case ID_STATUS_OCCUPIED:
+ case ID_STATUS_DND:
+ case ID_STATUS_FREECHAT:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ }
+}
+
+void LogToFile(TCHAR *stzText)
+{
+ FILE *fp = _tfopen(opt.LogFilePath, _T("a+b, ccs=UTF-8"));
+ if (fp)
+ {
+ char *encodedText = mir_utf8encodeT(stzText);
+ if (encodedText)
+ {
+ fprintf(fp, encodedText);
+ mir_free(encodedText);
+ }
+ fclose(fp);
+ }
+} \ No newline at end of file
diff --git a/plugins/NewXstatusNotify/src/utils.h b/plugins/NewXstatusNotify/src/utils.h
new file mode 100644
index 0000000000..0ff5c93e23
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/utils.h
@@ -0,0 +1,33 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2001-2004 Luca Santarelli
+ Copyright (c) 2005-2007 Vasilich
+ Copyright (c) 2007-2011 yaho
+
+ 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
+*/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+TCHAR *db2t(DBVARIANT *dbv);
+int DBGetStringDefault(HANDLE hContact, const char *szModule, const char *szSetting, TCHAR *setting, int size, const TCHAR *defaultValue);
+void HigherLower(int maxValue, int minValue);
+void ShowLog(TCHAR *file);
+int ProtoServiceExists(const char *szModule, const char *szService);
+BOOL StatusHasAwayMessage(char *szProto, int status);
+void LogToFile(TCHAR *stzText);
+
+#endif \ No newline at end of file
diff --git a/plugins/NewXstatusNotify/src/version.h b/plugins/NewXstatusNotify/src/version.h
new file mode 100644
index 0000000000..10ac34a753
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/version.h
@@ -0,0 +1,4 @@
+#define __FILEVERSION_STRING 1,4,0,9
+#define __VERSION_STRING "1.4.0.9"
+#define __VERSION_DWORD PLUGIN_MAKE_VERSION(1, 4, 0, 9)
+
diff --git a/plugins/NewXstatusNotify/src/xstatus.cpp b/plugins/NewXstatusNotify/src/xstatus.cpp
new file mode 100644
index 0000000000..4356af37fb
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/xstatus.cpp
@@ -0,0 +1,524 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2007-2011 yaho
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "common.h"
+#include "options.h"
+#include "popup.h"
+#include "utils.h"
+#include "xstatus.h"
+
+extern LIST<DBEVENT> eventList;
+extern OPTIONS opt;
+extern TEMPLATES templates;
+
+XSTATUSCHANGE *NewXSC(HANDLE hContact, char *szProto, int xstatusType, int action, TCHAR *stzTitle, TCHAR *stzText)
+{
+ XSTATUSCHANGE *xsc = (XSTATUSCHANGE *)mir_alloc(sizeof(XSTATUSCHANGE));
+ xsc->hContact = hContact;
+ xsc->szProto = szProto;
+ xsc->type = xstatusType;
+ xsc->action = action;
+ xsc->stzTitle = stzTitle;
+ xsc->stzText = stzText;
+ return xsc;
+}
+
+void FreeXSC(XSTATUSCHANGE *xsc)
+{
+ if (xsc)
+ {
+ if (xsc->stzTitle) mir_free(xsc->stzTitle);
+ if (xsc->stzText) mir_free(xsc->stzText);
+ mir_free(xsc);
+ xsc = NULL;
+ }
+}
+
+void RemoveLoggedEvents(HANDLE hContact)
+{
+ for (int i = eventList.getCount()-1; i >= 0; i--)
+ {
+ DBEVENT *dbevent = eventList[i];
+ if (dbevent->hContact == hContact)
+ {
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)dbevent->hContact, (LPARAM)dbevent->hDBEvent);
+ eventList.remove(i);
+ mir_free(dbevent);
+ }
+ }
+}
+
+TCHAR *GetStatusTypeAsString(int type, TCHAR *buff)
+{
+ switch (type) {
+ case TYPE_JABBER_MOOD:
+ _tcscpy(buff, TranslateT("Mood")); break;
+ case TYPE_JABBER_ACTIVITY:
+ _tcscpy(buff, TranslateT("Activity")); break;
+ case TYPE_ICQ_XSTATUS:
+ _tcscpy(buff, TranslateT("Xstatus")); break;
+ default:
+ _tcscpy(buff, TranslateT("<unknown>"));
+ }
+
+ return buff;
+}
+
+void ReplaceVars(XSTATUSCHANGE *xsc , TCHAR *Template, TCHAR *delimiter, TCHAR *buff)
+{
+ buff[0] = 0;
+ TCHAR *pch = _tcschr(Template, _T('%'));
+ while (pch != NULL)
+ {
+ size_t len = _tcslen(buff);
+ _tcsncat(buff, Template, pch - Template);
+ buff[len + pch - Template] = 0;
+
+ if (pch[1] == _T('N') || pch[1] == _T('T') || pch[1] == _T('I') || pch[1] == _T('D') || pch[1] == _T('B'))
+ {
+ switch (pch[1])
+ {
+ case _T('N'):
+ {
+ TCHAR stzType[32];
+ _tcscat(buff, GetStatusTypeAsString(xsc->type, stzType));
+ break;
+ }
+ case _T('T'):
+ {
+ if (xsc->stzTitle)
+ _tcscat(buff, xsc->stzTitle);
+ break;
+ }
+ case _T('I'):
+ {
+ if (xsc->stzText)
+ _tcscat(buff, xsc->stzText);
+ break;
+ }
+ case _T('D'):
+ {
+ if (xsc->stzText)
+ {
+ if (_tcscmp(delimiter, _T("%B")) == 0)
+ _tcscat(buff, _T("\r\n"));
+ else
+ _tcscat(buff, delimiter);
+ }
+ break;
+ }
+ case _T('B'):
+ {
+ _tcscat(buff, _T("\r\n"));
+ break;
+ }
+ }
+
+ Template = pch + 2;
+ }
+ else
+ {
+ _tcscat(buff, _T("%"));
+ Template = pch + 1;
+ }
+
+ pch = _tcschr(Template, _T('%'));
+ }
+
+ // append rest of the text
+ if (Template != NULL)
+ _tcscat(buff, Template);
+}
+
+void ShowPopup(XSTATUSCHANGE *xsc)
+{
+ DBVARIANT dbv;
+ char szSetting[64];
+
+ POPUPDATAT ppd = {0};
+ ppd.lchContact = xsc->hContact;
+
+ switch(xsc->type)
+ {
+ case TYPE_JABBER_MOOD:
+ case TYPE_JABBER_ACTIVITY:
+ {
+ mir_snprintf(szSetting, SIZEOF(szSetting), "%s/%s/%s", xsc->szProto, (xsc->type == TYPE_JABBER_MOOD) ? "mood" : "activity", "icon");
+ if (!DBGetContactSettingString(xsc->hContact, "AdvStatus", szSetting, &dbv))
+ {
+ ppd.lchIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ break;
+ }
+ case TYPE_ICQ_XSTATUS:
+ {
+ int statusId = DBGetContactSettingByte(xsc->hContact, xsc->szProto, "XStatusId", 0);
+ ppd.lchIcon = (HICON)CallProtoService(xsc->szProto, PS_ICQ_GETCUSTOMSTATUSICON, statusId, LR_SHARED);
+ }
+ }
+
+ if (ppd.lchIcon == NULL)
+ ppd.lchIcon = LoadSkinnedProtoIcon(xsc->szProto, DBGetContactSettingWord(xsc->hContact, xsc->szProto, "Status", ID_STATUS_ONLINE));
+
+ switch (opt.Colors)
+ {
+ case POPUP_COLOR_OWN:
+ ppd.colorBack = DBGetContactSettingDword(0, MODULE, "40081bg", COLOR_BG_AVAILDEFAULT);
+ ppd.colorText = DBGetContactSettingDword(0, MODULE, "40081tx", COLOR_TX_DEFAULT);
+ break;
+ case POPUP_COLOR_WINDOWS:
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ break;
+ case POPUP_COLOR_POPUP:
+ ppd.colorBack = ppd.colorText = 0;
+ break;
+ }
+
+ TCHAR *ptszGroup = NULL,
+ *ptszNick = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)xsc->hContact, GSMDF_TCHAR);
+ if (opt.ShowGroup) { //add group name to popup title
+ if (!DBGetContactSettingTString(xsc->hContact, "CList", "Group", &dbv)) {
+ ptszGroup = NEWTSTR_ALLOCA(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ if (ptszGroup)
+ mir_sntprintf(ppd.lptzContactName, SIZEOF(ppd.lptzContactName),_T("%s (%s)"), ptszNick, ptszGroup);
+ else
+ _tcsncpy(ppd.lptzContactName, ptszNick, SIZEOF(ppd.lptzContactName));
+
+ // cut message if needed
+ if (opt.PTruncateMsg && (opt.PMsgLen > 0) && xsc->stzText && (_tcslen(xsc->stzText) > opt.PMsgLen))
+ {
+ TCHAR buff[MAX_TEXT_LEN + 3];
+ _tcsncpy(buff, xsc->stzText, opt.PMsgLen);
+ buff[opt.PMsgLen] = 0;
+ _tcscat(buff, _T("..."));
+ mir_free(xsc->stzText);
+ xsc->stzText = mir_tstrdup(buff);
+ }
+
+ TCHAR *Template = _T("");
+ switch (xsc->action)
+ {
+ case NOTIFY_NEW_XSTATUS:
+ Template = templates.PopupNewXstatus; break;
+ case NOTIFY_NEW_MESSAGE:
+ Template = templates.PopupNewMsg; break;
+ case NOTIFY_REMOVE:
+ Template = templates.PopupRemove; break;
+ case NOTIFY_OPENING_ML:
+ Template = templates.LogOpening; break;
+ }
+
+ TCHAR stzPopupText[2*MAX_TEXT_LEN];
+ ReplaceVars(xsc, Template, templates.PopupDelimiter, stzPopupText);
+ _tcsncpy(ppd.lptzText, stzPopupText, SIZEOF(ppd.lptzText));
+ ppd.lptzText[SIZEOF(ppd.lptzText) - 1] = 0;
+
+ ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ ppd.iSeconds = opt.PopupTimeout;
+ PUAddPopUpT(&ppd);
+}
+
+void PlayXStatusSound(int action)
+{
+ switch (action)
+ {
+ case NOTIFY_NEW_XSTATUS:
+ SkinPlaySound(XSTATUS_SOUND_CHANGED); break;
+ case NOTIFY_NEW_MESSAGE:
+ SkinPlaySound(XSTATUS_SOUND_MSGCHANGED); break;
+ case NOTIFY_REMOVE:
+ SkinPlaySound(XSTATUS_SOUND_REMOVED); break;
+ }
+}
+
+void LogToMessageWindow(XSTATUSCHANGE *xsc, BOOL opening)
+{
+ // cut message if needed
+ if (opt.LTruncateMsg && (opt.LMsgLen > 0) && xsc->stzText && (_tcslen(xsc->stzText) > opt.LMsgLen))
+ {
+ TCHAR buff[MAX_TEXT_LEN + 3];
+ _tcsncpy(buff, xsc->stzText, opt.LMsgLen);
+ buff[opt.LMsgLen] = 0;
+ _tcscat(buff, _T("..."));
+ mir_free(xsc->stzText);
+ xsc->stzText = mir_tstrdup(buff);
+ }
+
+ TCHAR *Template = _T("");
+ switch (xsc->action)
+ {
+ case NOTIFY_NEW_XSTATUS:
+ Template = templates.LogNewXstatus; break;
+ case NOTIFY_NEW_MESSAGE:
+ Template = templates.LogNewMsg; break;
+ case NOTIFY_REMOVE:
+ Template = templates.LogRemove; break;
+ case NOTIFY_OPENING_ML:
+ Template = templates.LogOpening; break;
+ }
+
+ TCHAR stzLogText[2*MAX_TEXT_LEN];
+ TCHAR stzLastLog[2*MAX_TEXT_LEN];
+ ReplaceVars(xsc, Template, templates.LogDelimiter, stzLogText);
+ DBGetStringDefault(xsc->hContact, MODULE, DB_LASTLOG, stzLastLog, SIZEOF(stzLastLog), _T(""));
+
+ if (!opt.KeepInHistory || !(opt.PreventIdentical && _tcscmp(stzLastLog, stzLogText) == 0))
+ {
+ DBWriteContactSettingTString(xsc->hContact, MODULE, DB_LASTLOG, stzLogText);
+
+ char *blob;
+
+ blob = mir_utf8encodeT(stzLogText);
+
+
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = (DWORD)strlen(blob) + 1;
+ dbei.pBlob = (PBYTE) blob;
+ dbei.eventType = EVENTTYPE_STATUSCHANGE;
+ dbei.flags = DBEF_READ;
+
+ dbei.flags |= DBEF_UTF;
+
+ dbei.timestamp = (DWORD)time(NULL);
+ dbei.szModule = xsc->szProto;
+ HANDLE hDBEvent = (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)xsc->hContact, (LPARAM)&dbei);
+ mir_free(blob);
+
+ if (!opt.KeepInHistory)
+ {
+ DBEVENT *dbevent = (DBEVENT *)mir_alloc(sizeof(DBEVENT));
+ dbevent->hContact = xsc->hContact;
+ dbevent->hDBEvent = hDBEvent;
+ eventList.insert(dbevent);
+ }
+ }
+}
+
+void LogChangeToFile(XSTATUSCHANGE *xsc)
+{
+ TCHAR stzName[256], stzType[32];
+ TCHAR stzDate[32], stzTime[32];
+ TCHAR stzText[MAX_TEXT_LEN];
+
+ GetStatusTypeAsString(xsc->type, stzType);
+
+ _tcscpy(stzName, (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)xsc->hContact, GCDNF_TCHAR));
+ GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("HH':'mm"), stzTime, SIZEOF(stzTime));
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL,_T("dd/MM/yyyy"), stzDate, SIZEOF(stzDate));
+
+ if (xsc->action == NOTIFY_REMOVE)
+ mir_sntprintf(stzText, SIZEOF(stzText), TranslateT("%s, %s. %s removed %s.\r\n"), stzDate, stzTime, stzName, stzType);
+ else
+ mir_sntprintf(stzText, SIZEOF(stzText), TranslateT("%s, %s. %s changed %s to: %s.\r\n"), stzDate, stzTime, stzName, stzType, xsc->stzTitle);
+
+ LogToFile(stzText);
+}
+
+void ExtraStatusChanged(XSTATUSCHANGE *xsc)
+{
+ BOOL bEnablePopup = true, bEnableSound = true;
+ char buff[12] = {0};
+
+ wsprintfA(buff, "%d", ID_STATUS_EXTRASTATUS);
+
+ if ((DBGetContactSettingByte(0, MODULE, buff, 1) == 0) ||
+ (DBGetContactSettingWord(xsc->hContact, xsc->szProto, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE) ||
+ (!opt.HiddenContactsToo && DBGetContactSettingByte(xsc->hContact, "CList", "Hidden", 0)) ||
+ (opt.TempDisabled))
+ {
+ return;
+ }
+
+ char statusIDs[12], statusIDp[12];
+ if (opt.AutoDisable)
+ {
+ WORD myStatus = (WORD)CallProtoService(xsc->szProto, PS_GETSTATUS, 0, 0);
+ wsprintfA(statusIDs, "s%d", myStatus);
+ wsprintfA(statusIDp, "p%d", myStatus);
+ bEnableSound = DBGetContactSettingByte(0, MODULE, statusIDs, 1) ? FALSE : TRUE;
+ bEnablePopup = DBGetContactSettingByte(0, MODULE, statusIDp, 1) ? FALSE : TRUE;
+ }
+
+ if (!(templates.PopupFlags & xsc->action))
+ bEnableSound = bEnablePopup = false;
+
+ int xstatusID = DBGetContactSettingByte(xsc->hContact, xsc->szProto, "XStatusId", 0);
+ if (opt.PDisableForMusic && xsc->type == TYPE_ICQ_XSTATUS && xstatusID == XSTATUS_MUSIC)
+ bEnableSound = bEnablePopup = false;
+
+ if (bEnablePopup && DBGetContactSettingByte(xsc->hContact, MODULE, "EnableXStatusNotify", 1) && TimeoutCheck())
+ ShowPopup(xsc);
+
+ if (bEnableSound && DBGetContactSettingByte(xsc->hContact, MODULE, "EnableXStatusNotify", 1))
+ PlayXStatusSound(xsc->action);
+
+ BYTE enableLog = opt.EnableLogging;
+ if (opt.LDisableForMusic && xsc->type == TYPE_ICQ_XSTATUS && xstatusID == XSTATUS_MUSIC)
+ enableLog = FALSE;
+
+ if (!(templates.LogFlags & xsc->action))
+ enableLog = FALSE;
+
+ if (enableLog && DBGetContactSettingByte(xsc->hContact, MODULE, "EnableLogging", 1) &&
+ CallService(MS_MSG_MOD_MESSAGEDIALOGOPENED, (WPARAM)xsc->hContact, 0))
+ {
+ LogToMessageWindow(xsc, FALSE);
+ }
+
+ if (opt.Log)
+ LogChangeToFile(xsc);
+}
+
+TCHAR *GetDefaultXstatusName(int statusID, char *szProto, TCHAR *buff, int bufflen)
+{
+ TCHAR nameBuff[64];
+ buff[0] = 0;
+
+ ICQ_CUSTOM_STATUS xstatus = {0};
+ xstatus.cbSize = sizeof(ICQ_CUSTOM_STATUS);
+ xstatus.flags = CSSF_MASK_NAME | CSSF_DEFAULT_NAME | CSSF_TCHAR;
+ xstatus.ptszName = nameBuff;
+ xstatus.wParam = (WPARAM *)&statusID;
+ if (!CallProtoService(szProto, PS_ICQ_GETCUSTOMSTATUSEX, 0, (LPARAM)&xstatus))
+ {
+ _tcsncpy(buff, TranslateTS(nameBuff), bufflen);
+ buff[bufflen - 1] = 0;
+ }
+
+ return buff;
+}
+
+TCHAR *GetIcqXStatus(HANDLE hContact, char *szProto, char *szValue, TCHAR *buff, int bufflen)
+{
+ DBVARIANT dbv;
+ buff[0] = 0;
+
+ int statusID = DBGetContactSettingByte(hContact, szProto, "XStatusId", -1);
+ if (statusID != -1)
+ {
+ if (!DBGetContactSettingTString(hContact, szProto, szValue, &dbv))
+ {
+ if ((strcmp(szValue, "XStatusName") == 0) && dbv.ptszVal[0] == 0)
+ GetDefaultXstatusName(statusID, szProto, buff, bufflen);
+ else
+ _tcsncpy(buff, dbv.ptszVal, bufflen);
+
+ buff[bufflen - 1] = 0;
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ return buff;
+}
+
+TCHAR *GetJabberAdvStatusText(HANDLE hContact, char *szProto, char *szSlot, char *szValue, TCHAR *buff, int bufflen)
+{
+ DBVARIANT dbv;
+ char szSetting[128];
+ buff[0] = 0;
+
+ mir_snprintf(szSetting, SIZEOF(szSetting), "%s/%s/%s", szProto, szSlot, szValue);
+ if (!DBGetContactSettingTString(hContact, "AdvStatus", szSetting, &dbv))
+ {
+ _tcsncpy(buff, dbv.ptszVal, bufflen);
+ buff[bufflen - 1] = 0;
+ DBFreeVariant(&dbv);
+ }
+
+ return buff;
+}
+
+void LogXstatusChange(HANDLE hContact, char *szProto, int xstatusType, TCHAR *stzTitle, TCHAR *stzText)
+{
+ XSTATUSCHANGE *xsc =
+ NewXSC(
+ hContact,
+ szProto,
+ xstatusType,
+ NOTIFY_OPENING_ML,
+ stzTitle[0] ? mir_tstrdup(stzTitle): NULL,
+ stzText[0] ? mir_tstrdup(stzText) : NULL
+ );
+
+ LogToMessageWindow(xsc, TRUE);
+ FreeXSC(xsc);
+}
+
+void AddEventThread(void *arg)
+{
+ HANDLE hContact = (HANDLE)arg;
+ TCHAR stzTitle[MAX_TITLE_LEN], stzText[MAX_TEXT_LEN];
+
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (szProto == NULL) return;
+
+ if (ProtoServiceExists(szProto, JS_PARSE_XMPP_URI))
+ {
+ GetJabberAdvStatusText(hContact, szProto, "mood", "title", stzTitle, SIZEOF(stzTitle));
+ if (stzTitle[0])
+ {
+ GetJabberAdvStatusText(hContact, szProto, "mood", "text", stzText, SIZEOF(stzText));
+ LogXstatusChange(hContact, szProto, TYPE_JABBER_MOOD, stzTitle, stzText);
+ }
+
+ GetJabberAdvStatusText(hContact, szProto, "activity", "title", stzTitle, SIZEOF(stzTitle));
+ if (stzTitle[0])
+ {
+ GetJabberAdvStatusText(hContact, szProto, "activity", "text", stzText, SIZEOF(stzText));
+ LogXstatusChange(hContact, szProto, TYPE_JABBER_ACTIVITY, stzTitle, stzText);
+ }
+ }
+ else
+ {
+ GetIcqXStatus(hContact, szProto, "XStatusName", stzTitle, SIZEOF(stzTitle));
+ if (stzTitle[0])
+ {
+ GetIcqXStatus(hContact, szProto, "XStatusMsg", stzText, SIZEOF(stzText));
+ LogXstatusChange(hContact, szProto, TYPE_ICQ_XSTATUS, stzTitle, stzText);
+ }
+ }
+}
+
+int OnWindowEvent(WPARAM wParam, LPARAM lParam)
+{
+ MessageWindowEventData *mwed = (MessageWindowEventData *)lParam;
+
+ if (mwed->uType == MSG_WINDOW_EVT_CLOSE && !opt.KeepInHistory)
+ {
+ RemoveLoggedEvents(mwed->hContact);
+ return 0;
+ }
+
+ if (opt.EnableLogging &&
+ (mwed->uType == MSG_WINDOW_EVT_OPEN) &&
+ (templates.LogFlags & NOTIFY_OPENING_ML) &&
+ (DBGetContactSettingByte(mwed->hContact, MODULE, "EnableLogging", 1) == 1))
+ {
+ mir_forkthread(AddEventThread, mwed->hContact);
+ }
+
+ return 0;
+}
diff --git a/plugins/NewXstatusNotify/src/xstatus.h b/plugins/NewXstatusNotify/src/xstatus.h
new file mode 100644
index 0000000000..d5a76acb52
--- /dev/null
+++ b/plugins/NewXstatusNotify/src/xstatus.h
@@ -0,0 +1,106 @@
+/*
+ NewXstatusNotify YM - Plugin for Miranda IM
+ Copyright (c) 2007-2011 yaho
+
+ 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
+*/
+
+#ifndef XSTATUS_H
+#define XSTATUS_H
+
+#define NOTIFY_NEW_XSTATUS 1
+#define NOTIFY_NEW_MESSAGE 2
+#define NOTIFY_REMOVE 4
+#define NOTIFY_OPENING_ML 8
+
+#define TYPE_ICQ_XSTATUS 1
+#define TYPE_JABBER_MOOD 2
+#define TYPE_JABBER_ACTIVITY 3
+
+#define XSTATUS_MUSIC 11
+
+#define MAX_TITLE_LEN 256
+#define MAX_TEXT_LEN 2048
+
+// Database setting names
+#define DB_LASTLOG "LastLog"
+
+// Sounds
+#define XSTATUS_SOUND_CHANGED "XStatusChanged"
+#define XSTATUS_SOUND_MSGCHANGED "XStatusMsgChanged"
+#define XSTATUS_SOUND_REMOVED "XStatusRemove"
+
+// tabSRMM stuff (logging to message window)
+#define EVENTTYPE_STATUSCHANGE 25368
+#define MS_MSG_MOD_MESSAGEDIALOGOPENED "SRMsg_MOD/MessageDialogOpened"
+
+// Default templates
+#define DEFAULT_POPUP_DELIMITER _T("%B")
+#define DEFAULT_POPUP_NEW TranslateT("changed %N to: %T%D%I")
+#define DEFAULT_POPUP_CHANGEMSG TranslateT("changed %N message to:%D%I")
+#define DEFAULT_POPUP_REMOVE TranslateT("removed %N")
+#define DEFAULT_POPUP_STATUSMESSAGE "changed his/her status message to %n"
+
+#define DEFAULT_LOG_DELIMITER _T(": ")
+#define DEFAULT_LOG_NEW TranslateT("changed %N @ %T%D%I")
+#define DEFAULT_LOG_CHANGEMSG TranslateT("changed %N message @ %I")
+#define DEFAULT_LOG_REMOVE TranslateT("removed %N")
+#define DEFAULT_LOG_OPENING TranslateT("has %N @ %T%D%I")
+
+// Variables help text
+#define VARIABLES_HELP_TEXT TranslateT("These variables are available:\r\n\r\n\
+%N\textra status name (Xstatus, Mood, Activity)\r\n\
+%T\textra status title\r\n\
+%I\textra status text\r\n\
+%D\tdelimiter\r\n\
+%B\tline break (can be used as delimiter)")
+
+#define VARIABLES_SM_HELP_TEXT TranslateT("These variables are available:\r\n\r\n\
+%n\tNew Status Message\r\n\
+%o\tOld Status Message\r\n\
+%c\tCustom Nickname\r\n\
+\\n\tline break\r\n\
+\\t\ttab stop")
+
+typedef struct tagXSTATUSCHANGE
+{
+ HANDLE hContact;
+ char *szProto;
+ int type;
+ int action;
+ TCHAR *stzTitle;
+ TCHAR *stzText;
+} XSTATUSCHANGE;
+
+typedef struct tagDBEVENT
+{
+ HANDLE hContact;
+ HANDLE hDBEvent;
+} DBEVENT;
+
+typedef struct tagPROTOTEMPLATE
+{
+ TCHAR *ProtoName;
+ TCHAR ProtoTemplate[MAX_PATH];
+} PROTOTEMPLATE;
+
+TCHAR *GetDefaultXstatusName(int statusID, char *szProto, TCHAR *buff, int bufflen);
+XSTATUSCHANGE *NewXSC(HANDLE hContact, char *szProto, int xstatusType, int action, TCHAR *stzTitle, TCHAR *stzText);
+void FreeXSC(XSTATUSCHANGE *xsc);
+void ExtraStatusChanged(XSTATUSCHANGE *xsc);
+int OnWindowEvent(WPARAM wParam, LPARAM lParam);
+BOOL TimeoutCheck();
+
+#endif \ No newline at end of file