/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-12 Miranda IM, 2012-13 Miranda NG 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" static DWORD protoModeMsgFlags; static HWND hwndStatusMsg; static bool Proto_IsAccountEnabled(PROTOACCOUNT* pa) { return pa && ((pa->bIsEnabled && !pa->bDynDisabled) || pa->bOldProto); } static bool Proto_IsAccountLocked(PROTOACCOUNT* pa) { return pa && db_get_b(NULL, pa->szModuleName, "LockMainStatus", 0) != 0; } 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 bool GetStatusModeByte(int status, const char *suffix, bool bDefault = false) { return db_get_b(NULL, "SRAway", StatusModeToDbSetting(status, suffix), bDefault) != 0; } static void SetStatusModeByte(int status, const char *suffix, BYTE value) { db_set_b(NULL, "SRAway", StatusModeToDbSetting(status, suffix), value); } static TCHAR* GetAwayMessage(int statusMode, char *szProto) { if (szProto && !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(statusMode))) return NULL; if ( GetStatusModeByte(statusMode, "Ignore")) return NULL; DBVARIANT dbv; if ( GetStatusModeByte(statusMode, "UsePrev")) { if ( db_get_ts(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Msg"), &dbv)) dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusMode)); } else { if ( db_get_ts(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Default"), &dbv)) dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusMode)); for (int i=0; dbv.ptszVal[i]; i++) { if (dbv.ptszVal[i] != '%') continue; TCHAR substituteStr[128]; if ( !_tcsnicmp(dbv.ptszVal + i, _T("%time%"), 6)) { MIRANDA_IDLE_INFO mii = { 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 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 mir_callNextSubclass(hwnd, MessageEditSubclassProc, msg, wParam, lParam); } void ChangeAllProtoMessages(char *szProto, int statusMode, TCHAR *msg) { if (szProto == NULL) { int nAccounts; PROTOACCOUNT** accounts; ProtoEnumAccounts(&nAccounts, &accounts); for (int i=0; i < nAccounts; 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); mir_subclassWindow( GetDlgItem(hwndDlg, IDC_MSG), MessageEditSubclassProc); { TCHAR str[256], format[128]; GetWindowText(hwndDlg, format, SIZEOF(format)); mir_sntprintf(str, SIZEOF(str), format, pcli->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); db_set_ts(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); mir_free(dat); hwndStatusMsg = NULL; break; } return FALSE; } static int StatusModeChange(WPARAM wParam, LPARAM lParam) { 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; } BOOL bScreenSaverRunning = IsScreenSaverRunning(); if (GetStatusModeByte(statusMode, "Ignore")) ChangeAllProtoMessages(szProto, statusMode, NULL); else if (bScreenSaverRunning || GetStatusModeByte(statusMode, "NoDlg", true)) { 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(hInst, 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) { AwayMsgDlgData *dat = (AwayMsgDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); HWND hLst = GetDlgItem(hwndDlg, IDC_LST_STATUS); 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++) { if ( !(protoModeMsgFlags & Proto_Status2Flag(statusModes[i]))) continue; int j; if (hLst) { j = SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_ADDSTRING, 0, (LPARAM)pcli->pfnGetStatusModeDescription(statusModes[i], 0)); SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_SETITEMDATA, j, statusModes[i]); } else { j = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)pcli->pfnGetStatusModeDescription(statusModes[i], 0)); SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, j, statusModes[i]); } dat->info[j].ignore = GetStatusModeByte(statusModes[i], "Ignore"); dat->info[j].noDialog = GetStatusModeByte(statusModes[i], "NoDlg", true); dat->info[j].usePrevious = GetStatusModeByte(statusModes[i], "UsePrev"); DBVARIANT dbv; if (db_get_ts(NULL, "SRAway", StatusModeToDbSetting(statusModes[i], "Default"), &dbv)) if (db_get_ts(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: SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); { int 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--) { int status = hLst ? SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETITEMDATA, i, 0): SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETITEMDATA, i, 0); SetStatusModeByte(status, "Ignore", (BYTE)dat->info[i].ignore); SetStatusModeByte(status, "NoDlg", (BYTE)dat->info[i].noDialog); SetStatusModeByte(status, "UsePrev", (BYTE)dat->info[i].usePrevious); db_set_ts(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 = { sizeof(odp) }; odp.position = 870000000; odp.hInstance = hInst; odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AWAYMSG); odp.pszTitle = LPGEN("Status Messages"); odp.pszGroup = LPGEN("Status"); odp.pfnDlgProc = DlgProcAwayMsgOpts; odp.flags = ODPF_BOLDGROUPS; Options_AddPage(wParam, &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 = hInst; 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.lpzHelpUrl = "http://wiki.miranda-im.org/"; CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); return 0; } static int AwayMsgSendAccountsChanged(WPARAM, LPARAM) { protoModeMsgFlags = 0; int nAccounts; PROTOACCOUNT** accounts; ProtoEnumAccounts(&nAccounts, &accounts); for (int i=0; i < nAccounts; 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); } 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; } int LoadAwayMessageSending(void) { HookEvent(ME_SYSTEM_MODULESLOADED, AwayMsgSendModulesLoaded); HookEvent(ME_PROTO_ACCLISTCHANGED, AwayMsgSendAccountsChanged); CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSG, sttGetAwayMessage); CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSGW, sttGetAwayMessageT); return 0; }