summaryrefslogtreecommitdiff
path: root/src/modules/srawaymsg
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /src/modules/srawaymsg
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/srawaymsg')
-rw-r--r--src/modules/srawaymsg/awaymsg.cpp194
-rw-r--r--src/modules/srawaymsg/sendmsg.cpp637
2 files changed, 831 insertions, 0 deletions
diff --git a/src/modules/srawaymsg/awaymsg.cpp b/src/modules/srawaymsg/awaymsg.cpp
new file mode 100644
index 0000000000..39383e5367
--- /dev/null
+++ b/src/modules/srawaymsg/awaymsg.cpp
@@ -0,0 +1,194 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "commonheaders.h"
+
+int LoadAwayMessageSending(void);
+
+static HANDLE hAwayMsgMenuItem;
+static HANDLE hWindowList;
+
+struct AwayMsgDlgData {
+ HANDLE hContact;
+ HANDLE hSeq;
+ HANDLE hAwayMsgEvent;
+};
+#define HM_AWAYMSG (WM_USER+10)
+static INT_PTR CALLBACK ReadAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ AwayMsgDlgData *dat = (AwayMsgDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch(message)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ dat = (AwayMsgDlgData*)mir_alloc(sizeof(AwayMsgDlgData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+
+ dat->hContact = (HANDLE)lParam;
+ dat->hAwayMsgEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_AWAYMSG);
+ dat->hSeq = (HANDLE)CallContactService(dat->hContact, PSS_GETAWAYMSG, 0, 0);
+ WindowList_Add(hWindowList, hwndDlg, dat->hContact);
+
+ {
+ TCHAR str[256], format[128];
+ TCHAR* contactName = cli.pfnGetContactDisplayName(dat->hContact, 0);
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0);
+ WORD dwStatus = DBGetContactSettingWord(dat->hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ TCHAR* status = cli.pfnGetStatusModeDescription(dwStatus, 0);
+
+ GetWindowText(hwndDlg, format, SIZEOF(format));
+ mir_sntprintf(str, SIZEOF(str), format, status, contactName);
+ SetWindowText(hwndDlg, str);
+
+ GetDlgItemText(hwndDlg, IDC_RETRIEVING, format, SIZEOF(format));
+ mir_sntprintf(str, SIZEOF(str), format, status);
+ SetDlgItemText(hwndDlg, IDC_RETRIEVING, str);
+
+ Window_SetProtoIcon_IcoLib(hwndDlg, szProto, dwStatus);
+ }
+ if (dat->hSeq == NULL)
+ {
+ ACKDATA ack = {0};
+ ack.cbSize = sizeof(ack);
+ ack.hContact = dat->hContact;
+ ack.type = ACKTYPE_AWAYMSG;
+ ack.result = ACKRESULT_SUCCESS;
+ SendMessage(hwndDlg, HM_AWAYMSG, 0, (LPARAM)&ack);
+ }
+ Utils_RestoreWindowPosition(hwndDlg, (HANDLE)lParam, "SRAway", "AwayMsgDlg");
+ return TRUE;
+
+ case HM_AWAYMSG:
+ {
+ ACKDATA *ack = (ACKDATA*)lParam;
+ if (ack->hContact != dat->hContact || ack->type != ACKTYPE_AWAYMSG) break;
+ if (ack->result != ACKRESULT_SUCCESS) break;
+ if (dat->hAwayMsgEvent && ack->hProcess == dat->hSeq) { UnhookEvent(dat->hAwayMsgEvent); dat->hAwayMsgEvent = NULL; }
+
+#ifdef _UNICODE
+ DBVARIANT dbv;
+ bool unicode = !DBGetContactSetting(dat->hContact, "CList", "StatusMsg", &dbv) &&
+ (dbv.type == DBVT_UTF8 || dbv.type == DBVT_WCHAR);
+ DBFreeVariant(&dbv);
+ if (unicode)
+ {
+ DBGetContactSettingWString(dat->hContact, "CList", "StatusMsg", &dbv);
+ SetDlgItemText(hwndDlg, IDC_MSG, dbv.pwszVal);
+ }
+ else
+#endif
+ SetDlgItemTextA(hwndDlg, IDC_MSG, (const char*)ack->lParam);
+
+ ShowWindow(GetDlgItem(hwndDlg,IDC_RETRIEVING), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_MSG), SW_SHOW);
+ SetDlgItemText(hwndDlg, IDOK, TranslateT("&Close"));
+ break;
+ }
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDCANCEL:
+ case IDOK:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ if (dat->hAwayMsgEvent) UnhookEvent(dat->hAwayMsgEvent);
+ Utils_SaveWindowPosition(hwndDlg,dat->hContact,"SRAway","AwayMsgDlg");
+ WindowList_Remove(hWindowList,hwndDlg);
+ Window_FreeIcon_IcoLib(hwndDlg);
+ mir_free(dat);
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR GetMessageCommand(WPARAM wParam, LPARAM)
+{
+ HWND hwnd;
+ if(hwnd=WindowList_Find(hWindowList,(HANDLE)wParam)) {
+ SetForegroundWindow(hwnd);
+ SetFocus(hwnd);
+ }
+ else CreateDialogParam(hMirandaInst,MAKEINTRESOURCE(IDD_READAWAYMSG),NULL,ReadAwayMsgDlgProc,wParam);
+ return 0;
+}
+
+static int AwayMsgPreBuildMenu(WPARAM wParam, LPARAM)
+{
+ CLISTMENUITEM clmi;
+ TCHAR str[128];
+ char *szProto;
+
+ szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ ZeroMemory(&clmi,sizeof(clmi));
+ clmi.cbSize = sizeof(clmi);
+ clmi.flags = CMIM_FLAGS | CMIF_NOTOFFLINE | CMIF_HIDDEN | CMIF_TCHAR;
+
+ if ( szProto != NULL ) {
+ int chatRoom = szProto ? DBGetContactSettingByte((HANDLE)wParam, szProto, "ChatRoom", 0) : 0;
+ if ( !chatRoom ) {
+ int status = DBGetContactSettingWord((HANDLE)wParam,szProto,"Status",ID_STATUS_OFFLINE);
+ mir_sntprintf( str, SIZEOF(str), TranslateT("Re&ad %s Message"), cli.pfnGetStatusModeDescription( status, 0 ));
+ clmi.ptszName = str;
+ if ( CallProtoService( szProto, PS_GETCAPS, PFLAGNUM_1, 0 ) & PF1_MODEMSGRECV ) {
+ if ( CallProtoService( szProto, PS_GETCAPS, PFLAGNUM_3, 0 ) & Proto_Status2Flag( status )) {
+ clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIF_NOTOFFLINE | CMIM_ICON | CMIF_TCHAR;
+ clmi.hIcon = LoadSkinProtoIcon(szProto, status);
+ } } } }
+
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hAwayMsgMenuItem, ( LPARAM )&clmi );
+ IconLib_ReleaseIcon(clmi.hIcon,0);
+ return 0;
+}
+
+static int AwayMsgPreShutdown(WPARAM, LPARAM)
+{
+ if (hWindowList) WindowList_BroadcastAsync(hWindowList,WM_CLOSE,0,0);
+ return 0;
+}
+
+int LoadAwayMsgModule(void)
+{
+ CLISTMENUITEM mi = { 0 };
+
+ hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
+ CreateServiceFunction(MS_AWAYMSG_SHOWAWAYMSG,GetMessageCommand);
+
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000005000;
+ mi.flags = CMIF_NOTOFFLINE;
+ mi.pszName = LPGEN("Re&ad Status Message");
+ mi.pszService = MS_AWAYMSG_SHOWAWAYMSG;
+ hAwayMsgMenuItem = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU,AwayMsgPreBuildMenu);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN,AwayMsgPreShutdown);
+ return LoadAwayMessageSending();
+}
diff --git a/src/modules/srawaymsg/sendmsg.cpp b/src/modules/srawaymsg/sendmsg.cpp
new file mode 100644
index 0000000000..09cfcc77ad
--- /dev/null
+++ b/src/modules/srawaymsg/sendmsg.cpp
@@ -0,0 +1,637 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "commonheaders.h"
+
+extern bool prochotkey;
+
+static DWORD protoModeMsgFlags;
+static HWND hwndStatusMsg;
+
+static const TCHAR *GetDefaultMessage(int status)
+{
+ switch(status) {
+ case ID_STATUS_AWAY: return TranslateT("I've been away since %time%.");
+ case ID_STATUS_NA: return TranslateT("Give it up, I'm not in!");
+ case ID_STATUS_OCCUPIED: return TranslateT("Not right now.");
+ case ID_STATUS_DND: return TranslateT("Give a guy some peace, would ya?");
+ case ID_STATUS_FREECHAT: return TranslateT("I'm a chatbot!");
+ case ID_STATUS_ONLINE: return TranslateT("Yep, I'm here.");
+ case ID_STATUS_OFFLINE: return TranslateT("Nope, not here.");
+ case ID_STATUS_INVISIBLE: return TranslateT("I'm hiding from the mafia.");
+ case ID_STATUS_ONTHEPHONE: return TranslateT("That'll be the phone.");
+ case ID_STATUS_OUTTOLUNCH: return TranslateT("Mmm...food.");
+ case ID_STATUS_IDLE: return TranslateT("idleeeeeeee");
+ }
+ return NULL;
+}
+
+static const char *StatusModeToDbSetting(int status, const char *suffix)
+{
+ const char *prefix;
+ static char str[64];
+
+ switch(status)
+ {
+ case ID_STATUS_AWAY: prefix = "Away"; break;
+ case ID_STATUS_NA: prefix = "Na"; break;
+ case ID_STATUS_DND: prefix = "Dnd"; break;
+ case ID_STATUS_OCCUPIED: prefix = "Occupied"; break;
+ case ID_STATUS_FREECHAT: prefix = "FreeChat"; break;
+ case ID_STATUS_ONLINE: prefix = "On"; break;
+ case ID_STATUS_OFFLINE: prefix = "Off"; break;
+ case ID_STATUS_INVISIBLE: prefix = "Inv"; break;
+ case ID_STATUS_ONTHEPHONE: prefix = "Otp"; break;
+ case ID_STATUS_OUTTOLUNCH: prefix = "Otl"; break;
+ case ID_STATUS_IDLE: prefix = "Idl"; break;
+ default: return NULL;
+ }
+ mir_snprintf(str, SIZEOF(str), "%s%s", prefix, suffix);
+ return str;
+}
+
+static TCHAR* GetAwayMessage(int statusMode, char *szProto)
+{
+ DBVARIANT dbv;
+
+ if (szProto && !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(statusMode)))
+ return NULL;
+
+ if (DBGetContactSettingByte(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Ignore"), 0))
+ return NULL;
+
+ if (DBGetContactSettingByte(NULL, "SRAway", StatusModeToDbSetting(statusMode, "UsePrev"),0))
+ {
+ if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Msg"), &dbv))
+ dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusMode));
+ }
+ else {
+ int i;
+ TCHAR substituteStr[128];
+ if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusMode,"Default"), &dbv))
+ dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusMode));
+
+ for (i=0; dbv.ptszVal[i]; i++)
+ {
+ if (dbv.ptszVal[i] != '%') continue;
+ if (!_tcsnicmp(dbv.ptszVal + i, _T("%time%"), 6))
+ {
+ MIRANDA_IDLE_INFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii);
+
+ if (mii.idleType == 1)
+ {
+ int mm;
+ SYSTEMTIME t;
+ GetLocalTime(&t);
+ mm = t.wMinute + t.wHour * 60 - mii.idleTime;
+ if (mm < 0) mm += 60 * 24;
+ t.wMinute = mm % 60;
+ t.wHour = mm / 60;
+ GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &t, NULL, substituteStr, SIZEOF(substituteStr));
+ }
+ else GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, NULL, NULL, substituteStr, SIZEOF(substituteStr));
+ }
+ else if (!_tcsnicmp(dbv.ptszVal + i, _T("%date%"), 6))
+ GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, substituteStr, SIZEOF(substituteStr));
+ else continue;
+ if (lstrlen(substituteStr) > 6)
+ dbv.ptszVal = (TCHAR*)mir_realloc(dbv.ptszVal, (lstrlen(dbv.ptszVal) + 1 + lstrlen(substituteStr) - 6) * sizeof(TCHAR));
+ MoveMemory(dbv.ptszVal + i + lstrlen(substituteStr), dbv.ptszVal + i + 6, (lstrlen(dbv.ptszVal) - i - 5) * sizeof(TCHAR));
+ CopyMemory(dbv.ptszVal+i, substituteStr, lstrlen(substituteStr) * sizeof(TCHAR));
+ }
+ }
+ return dbv.ptszVal;
+}
+
+static WNDPROC OldMessageEditProc;
+
+static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_CHAR:
+ if(wParam == '\n' && GetKeyState(VK_CONTROL) & 0x8000)
+ {
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) //ctrl-a
+ {
+ SendMessage(hwnd, EM_SETSEL, 0, -1);
+ return 0;
+ }
+ if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) // ctrl-w
+ {
+ SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
+ return 0;
+ }
+ if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000) //ctrl-backspace
+ {
+ DWORD start, end;
+ TCHAR *text;
+ int textLen;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&end, 0);
+ SendMessage(hwnd, WM_KEYDOWN, VK_LEFT, 0);
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&start, 0);
+ textLen = GetWindowTextLength(hwnd);
+ text = (TCHAR *)alloca(sizeof(TCHAR) * (textLen + 1));
+ GetWindowText(hwnd, text, textLen + 1);
+ memmove(text + start, text + end, sizeof(TCHAR) * (textLen + 1 - end));
+ SetWindowText(hwnd, text);
+ SendMessage(hwnd, EM_SETSEL, start, start);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd);
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProc(OldMessageEditProc, hwnd, msg, wParam, lParam);
+}
+
+void ChangeAllProtoMessages(char *szProto, int statusMode, TCHAR *msg)
+{
+ if (szProto == NULL)
+ {
+ for (int i=0; i < accounts.getCount(); i++)
+ {
+ PROTOACCOUNT* pa = accounts[i];
+ if (!Proto_IsAccountEnabled(pa)) continue;
+ if ((CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) &&
+ !Proto_IsAccountLocked(pa))
+ CallProtoService(pa->szModuleName, PS_SETAWAYMSGT, statusMode, (LPARAM)msg);
+ }
+ }
+ else
+ CallProtoService(szProto, PS_SETAWAYMSGT, statusMode,(LPARAM)msg);
+}
+
+struct SetAwayMsgData
+{
+ int statusMode;
+ int countdown;
+ TCHAR okButtonFormat[64];
+ char *szProto;
+ HANDLE hPreshutdown;
+};
+struct SetAwasMsgNewData
+{
+ char *szProto;
+ int statusMode;
+};
+
+#define DM_SRAWAY_SHUTDOWN WM_USER+10
+
+static INT_PTR CALLBACK SetAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ SetAwayMsgData* dat = (SetAwayMsgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch(message)
+ {
+ case WM_INITDIALOG:
+ {
+ SetAwasMsgNewData *newdat = (SetAwasMsgNewData*)lParam;
+ TranslateDialogDefault(hwndDlg);
+ dat = (SetAwayMsgData*)mir_alloc(sizeof(SetAwayMsgData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ dat->statusMode = newdat->statusMode;
+ dat->szProto = newdat->szProto;
+ mir_free(newdat);
+ SendDlgItemMessage(hwndDlg, IDC_MSG, EM_LIMITTEXT, 1024, 0);
+ OldMessageEditProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_MSG), GWLP_WNDPROC, (LONG_PTR)MessageEditSubclassProc);
+ {
+ TCHAR str[256], format[128];
+ GetWindowText(hwndDlg, format, SIZEOF(format));
+ mir_sntprintf(str, SIZEOF(str), format, cli.pfnGetStatusModeDescription(dat->statusMode, 0));
+ SetWindowText(hwndDlg, str );
+ }
+ GetDlgItemText(hwndDlg, IDOK, dat->okButtonFormat, SIZEOF(dat->okButtonFormat));
+ {
+ TCHAR *msg = GetAwayMessage(dat->statusMode, dat->szProto);
+ SetDlgItemText(hwndDlg, IDC_MSG, msg);
+ mir_free(msg);
+ }
+ dat->countdown = 6;
+ SendMessage(hwndDlg, WM_TIMER, 0, 0);
+ Window_SetProtoIcon_IcoLib(hwndDlg, dat->szProto, dat->statusMode);
+ Utils_RestoreWindowPosition(hwndDlg,NULL,"SRAway","AwayMsgDlg");
+ SetTimer(hwndDlg, 1, 1000, 0);
+ dat->hPreshutdown = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, DM_SRAWAY_SHUTDOWN);
+ }
+ return TRUE;
+
+ case WM_TIMER:
+ if (--dat->countdown >= 0)
+ {
+ TCHAR str[64];
+ mir_sntprintf(str, SIZEOF(str), dat->okButtonFormat, dat->countdown);
+ SetDlgItemText(hwndDlg, IDOK, str);
+ }
+ else
+ {
+ KillTimer(hwndDlg, 1);
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ }
+ break;
+
+ case WM_CLOSE:
+ {
+ TCHAR *msg = GetAwayMessage(dat->statusMode, dat->szProto);
+ ChangeAllProtoMessages(dat->szProto, dat->statusMode, msg);
+ mir_free(msg);
+ }
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ if (dat->countdown < 0)
+ {
+ TCHAR str[1024];
+ GetDlgItemText(hwndDlg, IDC_MSG, str, SIZEOF(str));
+ ChangeAllProtoMessages(dat->szProto, dat->statusMode, str);
+ DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(dat->statusMode, "Msg"), str);
+ DestroyWindow(hwndDlg);
+ }
+ else
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ break;
+
+ case IDC_MSG:
+ if (dat->countdown >= 0)
+ {
+ KillTimer(hwndDlg, 1);
+ SetDlgItemText(hwndDlg, IDOK, TranslateT("OK"));
+ dat->countdown = -1;
+ }
+ break;
+ }
+ break;
+
+ case DM_SRAWAY_SHUTDOWN:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ Utils_SaveWindowPosition(hwndDlg,NULL,"SRAway","AwayMsgDlg");
+ KillTimer(hwndDlg, 1);
+ UnhookEvent(dat->hPreshutdown);
+ Window_FreeIcon_IcoLib(hwndDlg);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_MSG), GWLP_WNDPROC, (LONG_PTR)OldMessageEditProc);
+ mir_free(dat);
+ hwndStatusMsg = NULL;
+ break;
+ }
+ return FALSE;
+}
+
+static int StatusModeChange(WPARAM wParam, LPARAM lParam)
+{
+ BOOL bScreenSaverRunning = FALSE;
+ int statusMode = (int)wParam;
+ char *szProto = (char*)lParam;
+
+ if (protoModeMsgFlags == 0) return 0;
+
+ // If its a global change check the complete PFLAGNUM_3 flags to see if a popup might be needed
+ if (!szProto)
+ {
+ if (!(protoModeMsgFlags & Proto_Status2Flag(statusMode)))
+ return 0;
+ }
+ else
+ {
+ // If its a single protocol check the PFLAGNUM_3 for the single protocol
+ if (!(CallProtoService(szProto, PS_GETCAPS,PFLAGNUM_1, 0) & PF1_MODEMSGSEND) ||
+ !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(statusMode)))
+ return 0;
+ }
+
+ SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &bScreenSaverRunning, FALSE);
+ if (DBGetContactSettingByte(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Ignore"), 0))
+ {
+ ChangeAllProtoMessages(szProto, statusMode, NULL);
+ }
+ else if (bScreenSaverRunning || ((!GetAsyncKeyState(VK_CONTROL) || prochotkey) &&
+ DBGetContactSettingByte(NULL, "SRAway", StatusModeToDbSetting(statusMode, "NoDlg"), 0)))
+ {
+ TCHAR *msg = GetAwayMessage(statusMode, szProto);
+ ChangeAllProtoMessages(szProto, statusMode, msg);
+ mir_free(msg);
+ }
+ else {
+ SetAwasMsgNewData *newdat = (SetAwasMsgNewData*)mir_alloc(sizeof(SetAwasMsgNewData));
+ newdat->szProto = szProto;
+ newdat->statusMode = statusMode;
+ if (hwndStatusMsg)
+ DestroyWindow(hwndStatusMsg);
+ hwndStatusMsg = CreateDialogParam(hMirandaInst, MAKEINTRESOURCE(IDD_SETAWAYMSG),
+ NULL, SetAwayMsgDlgProc, (LPARAM)newdat);
+ }
+ return 0;
+}
+
+static const int statusModes[] =
+{
+ ID_STATUS_OFFLINE, ID_STATUS_ONLINE, ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND,
+ ID_STATUS_FREECHAT,ID_STATUS_INVISIBLE,ID_STATUS_OUTTOLUNCH,ID_STATUS_ONTHEPHONE, ID_STATUS_IDLE
+};
+
+struct AwayMsgInfo
+{
+ int ignore;
+ int noDialog;
+ int usePrevious;
+ TCHAR msg[1024];
+};
+struct AwayMsgDlgData
+{
+ struct AwayMsgInfo info[ SIZEOF(statusModes) ];
+ int oldPage;
+};
+
+static INT_PTR CALLBACK DlgProcAwayMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct AwayMsgDlgData *dat;
+
+ HWND hLst = GetDlgItem(hwndDlg, IDC_LST_STATUS);
+
+ dat=(struct AwayMsgDlgData*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ dat = (AwayMsgDlgData*)mir_alloc(sizeof(AwayMsgDlgData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ dat->oldPage = -1;
+ for (int i = 0; i < SIZEOF(statusModes); i++)
+ {
+ int j;
+ if (!(protoModeMsgFlags & Proto_Status2Flag(statusModes[i])))
+ continue;
+
+ if (hLst)
+ {
+ j = SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_ADDSTRING, 0, (LPARAM)cli.pfnGetStatusModeDescription(statusModes[i], 0));
+ SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_SETITEMDATA, j, statusModes[i]);
+ }
+ else
+ {
+ j = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)cli.pfnGetStatusModeDescription(statusModes[i], 0));
+ SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, j, statusModes[i]);
+ }
+
+ dat->info[j].ignore = DBGetContactSettingByte(NULL, "SRAway",
+ StatusModeToDbSetting(statusModes[i], "Ignore"), 0);
+ dat->info[j].noDialog = DBGetContactSettingByte(NULL, "SRAway",
+ StatusModeToDbSetting(statusModes[i], "NoDlg"), 0);
+ dat->info[j].usePrevious = DBGetContactSettingByte(NULL, "SRAway",
+ StatusModeToDbSetting(statusModes[i], "UsePrev"), 0);
+
+ DBVARIANT dbv;
+ if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusModes[i], "Default"), &dbv))
+ if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusModes[i], "Msg"), &dbv))
+ dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusModes[i]));
+ lstrcpy(dat->info[j].msg, dbv.ptszVal);
+ mir_free(dbv.ptszVal);
+ }
+ if (hLst)
+ SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_SETCURSEL, 0, 0);
+ else
+ SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WM_COMMAND, hLst ? MAKEWPARAM(IDC_LST_STATUS, LBN_SELCHANGE) : MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0);
+ return TRUE;
+ }
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT)lParam;
+ if (mis->CtlID == IDC_LST_STATUS)
+ mis->itemHeight = 20;
+ break;
+ }
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
+ if (dis->CtlID != IDC_LST_STATUS) break;
+ if (dis->itemID < 0) break;
+
+ TCHAR buf[128];
+ SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETTEXT, dis->itemID, (LPARAM)buf);
+
+ if (dis->itemState & (ODS_SELECTED|ODS_FOCUS))
+ {
+ FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ }
+ else
+ {
+ FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_WINDOW));
+ SetTextColor(dis->hDC, GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+ RECT rc = dis->rcItem;
+ DrawIconEx(dis->hDC, 3, (rc.top + rc.bottom - 16) / 2, LoadSkinnedProtoIcon(NULL, dis->itemData), 16, 16, 0, NULL, DI_NORMAL);
+ rc.left += 25;
+ SetBkMode(dis->hDC, TRANSPARENT);
+ DrawText(dis->hDC, buf, -1, &rc, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX);
+ break;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case IDC_LST_STATUS:
+ case IDC_STATUS:
+ if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == LBN_SELCHANGE))
+ {
+ int i = hLst ?
+ SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETCURSEL, 0, 0) :
+ SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0);
+ if (dat->oldPage != -1)
+ {
+ dat->info[dat->oldPage].ignore = IsDlgButtonChecked(hwndDlg, IDC_DONTREPLY);
+ dat->info[dat->oldPage].noDialog = IsDlgButtonChecked(hwndDlg, IDC_NODIALOG);
+ dat->info[dat->oldPage].usePrevious = IsDlgButtonChecked(hwndDlg, IDC_USEPREVIOUS);
+ GetDlgItemText(hwndDlg, IDC_MSG, dat->info[dat->oldPage].msg, SIZEOF(dat->info[dat->oldPage].msg));
+ }
+ CheckDlgButton(hwndDlg, IDC_DONTREPLY, i < 0 ? 0 : dat->info[i].ignore);
+ CheckDlgButton(hwndDlg, IDC_NODIALOG, i < 0 ? 0 : dat->info[i].noDialog);
+ CheckDlgButton(hwndDlg, IDC_USEPREVIOUS, i < 0 ? 0 : dat->info[i].usePrevious);
+ CheckDlgButton(hwndDlg, IDC_USESPECIFIC, i < 0 ? 0 : !dat->info[i].usePrevious);
+
+ SetDlgItemText(hwndDlg,IDC_MSG, i < 0 ? _T("") : dat->info[i].msg);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_NODIALOG), i < 0 ? 0 : !dat->info[i].ignore);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_USEPREVIOUS), i < 0 ? 0 : !dat->info[i].ignore);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_USESPECIFIC), i < 0 ? 0 : !dat->info[i].ignore);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_MSG), i < 0 ? 0 : !(dat->info[i].ignore || dat->info[i].usePrevious));
+ dat->oldPage = i;
+ }
+ return 0;
+
+ case IDC_DONTREPLY:
+ case IDC_USEPREVIOUS:
+ case IDC_USESPECIFIC:
+ SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_STATUS,CBN_SELCHANGE),0);
+ break;
+
+ case IDC_MSG:
+ if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return 0;
+ break;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch(((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ { int i, status;
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS,CBN_SELCHANGE), 0);
+ i = hLst ?
+ (SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETCOUNT, 0, 0) - 1) :
+ (SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCOUNT, 0, 0) - 1);
+ for (; i>=0; i--)
+ {
+ status = hLst ?
+ SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETITEMDATA, i, 0):
+ SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETITEMDATA, i, 0);
+ DBWriteContactSettingByte(NULL, "SRAway", StatusModeToDbSetting(status,"Ignore"), (BYTE)dat->info[i].ignore);
+ DBWriteContactSettingByte(NULL, "SRAway", StatusModeToDbSetting(status,"NoDlg"), (BYTE)dat->info[i].noDialog);
+ DBWriteContactSettingByte(NULL, "SRAway", StatusModeToDbSetting(status,"UsePrev"),(BYTE)dat->info[i].usePrevious);
+ DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(status,"Default"), dat->info[i].msg);
+ }
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ mir_free(dat);
+ break;
+ }
+ return FALSE;
+}
+
+static int AwayMsgOptInitialise(WPARAM wParam, LPARAM)
+{
+ if (protoModeMsgFlags == 0)
+ return 0;
+
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.position = 870000000;
+ odp.hInstance = hMirandaInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AWAYMSG);
+ odp.pszTitle = LPGEN("Status Messages");
+ odp.pszGroup = LPGEN("Status");
+ odp.pfnDlgProc = DlgProcAwayMsgOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ return 0;
+}
+
+static int AwayMsgSendModernOptInit(WPARAM wParam, LPARAM)
+{
+ if (protoModeMsgFlags == 0)
+ return 0;
+
+ static const int iBoldControls[] =
+ {
+ IDC_TXT_TITLE1, IDC_TXT_TITLE2, IDC_TXT_TITLE3,
+ MODERNOPT_CTRL_LAST
+ };
+
+ MODERNOPTOBJECT obj = {0};
+ obj.cbSize = sizeof(obj);
+ obj.hInstance = hMirandaInst;
+ obj.dwFlags = MODEROPT_FLG_TCHAR | MODEROPT_FLG_NORESIZE;
+ obj.iSection = MODERNOPT_PAGE_STATUS;
+ obj.iType = MODERNOPT_TYPE_SECTIONPAGE;
+ obj.iBoldControls = (int*)iBoldControls;
+ obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_STATUS);
+ obj.pfnDlgProc = DlgProcAwayMsgOpts;
+// obj.lpzClassicGroup = "Status";
+// obj.lpzClassicPage = "Messages";
+ obj.lpzHelpUrl = "http://wiki.miranda-im.org/";
+ CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj);
+ return 0;
+}
+
+static int AwayMsgSendAccountsChanged(WPARAM, LPARAM)
+{
+ protoModeMsgFlags = 0;
+ for (int i=0; i < accounts.getCount(); i++)
+ {
+ if (!Proto_IsAccountEnabled(accounts[i])) continue;
+ protoModeMsgFlags |= CallProtoService(accounts[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0);
+ }
+
+ return 0;
+}
+
+static int AwayMsgSendModulesLoaded(WPARAM, LPARAM)
+{
+ AwayMsgSendAccountsChanged(0, 0);
+
+ HookEvent(ME_CLIST_STATUSMODECHANGE, StatusModeChange);
+ HookEvent(ME_MODERNOPT_INITIALIZE, AwayMsgSendModernOptInit);
+ HookEvent(ME_OPT_INITIALISE, AwayMsgOptInitialise);
+ return 0;
+}
+
+//remember to mir_free() the return value
+static INT_PTR sttGetAwayMessageT(WPARAM wParam, LPARAM lParam)
+{
+ return (INT_PTR)GetAwayMessage((int)wParam, (char*)lParam);
+}
+
+#ifdef UNICODE
+static INT_PTR sttGetAwayMessage(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR* msg = GetAwayMessage((int)wParam, (char*)lParam);
+ char* res = mir_t2a(msg);
+ mir_free(msg);
+ return (INT_PTR)res;
+}
+#endif
+
+int LoadAwayMessageSending(void)
+{
+ HookEvent(ME_SYSTEM_MODULESLOADED,AwayMsgSendModulesLoaded);
+ HookEvent(ME_PROTO_ACCLISTCHANGED, AwayMsgSendAccountsChanged);
+
+#ifdef UNICODE
+ CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSG, sttGetAwayMessage);
+ CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSGW, sttGetAwayMessageT);
+#else
+ CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSG, sttGetAwayMessageT);
+#endif
+ return 0;
+}