From a33833212f040272fc6c97047c8cb335b6f5405a Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 24 Jul 2012 06:41:19 +0000 Subject: SimpleAR, SimpleStatusMsg, SmileyAdd, SpellChecker: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1149 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/SimpleStatusMsg/src/awaymsg.cpp | 494 ++++++ plugins/SimpleStatusMsg/src/commonheaders.h | 65 + plugins/SimpleStatusMsg/src/main.cpp | 2176 +++++++++++++++++++++++++ plugins/SimpleStatusMsg/src/msgbox.cpp | 1798 ++++++++++++++++++++ plugins/SimpleStatusMsg/src/options.cpp | 1750 ++++++++++++++++++++ plugins/SimpleStatusMsg/src/resource.h | 126 ++ plugins/SimpleStatusMsg/src/simplestatusmsg.h | 105 ++ plugins/SimpleStatusMsg/src/utils.cpp | 226 +++ 8 files changed, 6740 insertions(+) create mode 100644 plugins/SimpleStatusMsg/src/awaymsg.cpp create mode 100644 plugins/SimpleStatusMsg/src/commonheaders.h create mode 100644 plugins/SimpleStatusMsg/src/main.cpp create mode 100644 plugins/SimpleStatusMsg/src/msgbox.cpp create mode 100644 plugins/SimpleStatusMsg/src/options.cpp create mode 100644 plugins/SimpleStatusMsg/src/resource.h create mode 100644 plugins/SimpleStatusMsg/src/simplestatusmsg.h create mode 100644 plugins/SimpleStatusMsg/src/utils.cpp (limited to 'plugins/SimpleStatusMsg/src') diff --git a/plugins/SimpleStatusMsg/src/awaymsg.cpp b/plugins/SimpleStatusMsg/src/awaymsg.cpp new file mode 100644 index 0000000000..705b860cc5 --- /dev/null +++ b/plugins/SimpleStatusMsg/src/awaymsg.cpp @@ -0,0 +1,494 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2010 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +Portions of this code modified for Simple Status Message plugin +Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "commonheaders.h" +#include "simplestatusmsg.h" + +static HANDLE hAwayMsgMenuItem; +static HANDLE hCopyMsgMenuItem; +static HANDLE hGoToURLMenuItem; +static HANDLE hWindowList; +static HANDLE hWindowList2; + +static char *StrNormNewlineA(char *szStr) +{ + if (szStr == NULL) return NULL; + + int nCR = 0; + for (int i = 0; szStr[i]; i++) + if (szStr[i] != 0x0D && szStr[i + 1] == 0x0A) nCR++; + + if (!nCR) return mir_strdup(szStr); + + char *szNewStr = (char*)mir_alloc(lstrlenA(szStr) + nCR + 1), *pszStr = szNewStr; + while (*szStr) + { + if (*szStr == 0x0A) + *pszStr++ = 0x0D; + *pszStr++ = *szStr++; + } + *pszStr++ = 0; + + return szNewStr; +} + + +static TCHAR *StrNormNewline(TCHAR *tszStr) +{ + if (tszStr == NULL) return NULL; + + int nCR = 0; + for (int i = 0; tszStr[i]; i++) + if (tszStr[i] != 0x0D && tszStr[i + 1] == 0x0A) nCR++; + + if (!nCR) return mir_tstrdup(tszStr); + + TCHAR *tszNewStr = (TCHAR*)mir_alloc((lstrlen(tszStr) + nCR + 1) * sizeof(TCHAR)), *ptszStr = tszNewStr; + while (*tszStr) + { + if (*tszStr == 0x0A) + *ptszStr++ = 0x0D; + *ptszStr++ = *tszStr++; + } + *ptszStr++ = 0; + + return tszNewStr; +} + + +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->hSeq = (HANDLE)CallContactService(dat->hContact, PSS_GETAWAYMSG, 0, 0); + dat->hAwayMsgEvent = dat->hSeq ? HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_AWAYMSG) : NULL; + WindowList_Add(hWindowList, hwndDlg, dat->hContact); + { + TCHAR str[256], format[128]; + TCHAR *contactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)dat->hContact, GCDNF_TCHAR); + char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0); + WORD dwStatus = DBGetContactSettingWord(dat->hContact, szProto, "Status", ID_STATUS_OFFLINE); + TCHAR *status = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dwStatus, GSMDF_TCHAR); + + GetWindowText(hwndDlg, format, SIZEOF(format)); + mir_sntprintf(str, SIZEOF(str), format, status, contactName); + SetWindowText(hwndDlg, str); + if (dat->hSeq) + { + GetDlgItemText(hwndDlg, IDC_RETRIEVING, format, SIZEOF(format)); + mir_sntprintf(str, SIZEOF(str), format, status); + } + else + { + mir_sntprintf(str, SIZEOF(str), TranslateT("Failed to retrieve %s message."), status); + SetDlgItemText(hwndDlg, IDOK, TranslateT("&Close")); + } + SetDlgItemText(hwndDlg, IDC_RETRIEVING, str); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIcon(szProto, dwStatus)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedProtoIcon(szProto, dwStatus)); + EnableWindow(GetDlgItem(hwndDlg, IDC_COPY), FALSE); + } + 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; } + + TCHAR *tszMsg = StrNormNewline((TCHAR*)ack->lParam); + SetDlgItemText(hwndDlg, IDC_MSG, tszMsg); + mir_free(tszMsg); + + if (ack->lParam && *((char*)ack->lParam) != '\0') + EnableWindow(GetDlgItem(hwndDlg, IDC_COPY), TRUE); + 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; + + case IDC_COPY: + if (!OpenClipboard(hwndDlg)) break; + if (EmptyClipboard()) + { + TCHAR msg[1024]; + int len = GetDlgItemText(hwndDlg, IDC_MSG, msg, SIZEOF(msg)); + if (len) + { + LPTSTR lptstrCopy; + HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(TCHAR)); + if (hglbCopy == NULL) + { + CloseClipboard(); + break; + } + lptstrCopy = (LPTSTR)GlobalLock(hglbCopy); + memcpy(lptstrCopy, msg, len * sizeof(TCHAR)); + lptstrCopy[len] = (TCHAR)0; + GlobalUnlock(hglbCopy); + + SetClipboardData(CF_UNICODETEXT, hglbCopy); + + } + } + CloseClipboard(); + 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); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)NULL), 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)NULL), 0); + mir_free(dat); + break; + } + return FALSE; +} + +static INT_PTR GetMessageCommand(WPARAM wParam, LPARAM) +{ + if (HWND hwnd = WindowList_Find(hWindowList, (HANDLE)wParam)) + { + SetForegroundWindow(hwnd); + SetFocus(hwnd); + } + else CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_READAWAYMSG), NULL, ReadAwayMsgDlgProc, wParam); + return 0; +} + +static INT_PTR CALLBACK CopyAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + AwayMsgDlgData *dat = (AwayMsgDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (message) + { + case WM_INITDIALOG: + { + TCHAR str[256], format[128]; + TCHAR *contactName; + + TranslateDialogDefault(hwndDlg); + dat = (AwayMsgDlgData*)mir_alloc(sizeof(AwayMsgDlgData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + + dat->hContact = (HANDLE)lParam; + dat->hSeq = (HANDLE)CallContactService(dat->hContact, PSS_GETAWAYMSG, 0, 0); + dat->hAwayMsgEvent = dat->hSeq ? HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_AWAYMSG) : NULL; + WindowList_Add(hWindowList2, hwndDlg, dat->hContact); + contactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)dat->hContact, GCDNF_TCHAR); + GetWindowText(hwndDlg, format, SIZEOF(format)); + mir_sntprintf(str, SIZEOF(str), format, contactName); + SetWindowText(hwndDlg, str); + if (!dat->hSeq) DestroyWindow(hwndDlg); + return TRUE; + } + + case HM_AWAYMSG: + { + ACKDATA *ack = (ACKDATA*)lParam; + if (ack->hContact != dat->hContact || ack->type != ACKTYPE_AWAYMSG) { DestroyWindow(hwndDlg); break; } + if (ack->result != ACKRESULT_SUCCESS) { DestroyWindow(hwndDlg); break; } + if (dat->hAwayMsgEvent && ack->hProcess == dat->hSeq) { UnhookEvent(dat->hAwayMsgEvent); dat->hAwayMsgEvent = NULL; } + + if (!OpenClipboard(hwndDlg)) { DestroyWindow(hwndDlg); break; } + if (EmptyClipboard()) + { + TCHAR msg[1024]; + TCHAR *tszMsg = StrNormNewline((TCHAR*)ack->lParam); + mir_sntprintf(msg, SIZEOF(msg), _T("%s"), tszMsg); + mir_free(tszMsg); + size_t len = lstrlen(msg); + if (len) + { + LPTSTR lptstrCopy; + HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(TCHAR)); + if (hglbCopy == NULL) { + CloseClipboard(); + DestroyWindow(hwndDlg); + break; + } + lptstrCopy = (LPTSTR)GlobalLock(hglbCopy); + memcpy(lptstrCopy, msg, len * sizeof(TCHAR)); + lptstrCopy[len] = (TCHAR)0; + GlobalUnlock(hglbCopy); + + SetClipboardData(CF_UNICODETEXT, hglbCopy); + } + } + CloseClipboard(); + DestroyWindow(hwndDlg); + 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); + WindowList_Remove(hWindowList2, hwndDlg); + mir_free(dat); + break; + } + return FALSE; +} + +static INT_PTR CopyAwayMsgCommand(WPARAM wParam, LPARAM) +{ + if (HWND hwnd = WindowList_Find(hWindowList2, (HANDLE)wParam)) + { + SetForegroundWindow(hwnd); + SetFocus(hwnd); + } + else CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_COPY), NULL, CopyAwayMsgDlgProc, wParam); + return 0; +} + +static char *StrFindURL(char *pszStr) +{ + char *pszURL = NULL; + + if (pszStr != NULL && *pszStr != '\0') + { + pszURL = strstr(pszStr, "www."); + if (pszURL == NULL) + pszURL = strstr(pszStr, "http://"); + if (pszURL == NULL) + pszURL = strstr(pszStr, "https://"); + if (pszURL == NULL) + pszURL = strstr(pszStr, "ftp://"); + } + + return pszURL; +} + +static INT_PTR GoToURLMsgCommand(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + char *szMsg; + + + int unicode = !DBGetContactSetting((HANDLE)wParam, "CList", "StatusMsg", &dbv) && (dbv.type == DBVT_UTF8 || dbv.type == DBVT_WCHAR); + DBFreeVariant(&dbv); + if (unicode) + { + DBGetContactSettingWString((HANDLE)wParam, "CList", "StatusMsg", &dbv); + szMsg = mir_u2a(dbv.pwszVal); + } + else + + { + DBGetContactSettingString((HANDLE)wParam, "CList", "StatusMsg", &dbv); + szMsg = mir_strdup(dbv.pszVal); + } + DBFreeVariant(&dbv); + + char *szURL = StrFindURL(szMsg); + if (szURL != NULL) + { + int i; + for (i = 0; szURL[i] != ' ' && szURL[i] != '\n' && szURL[i] != '\r' && + szURL[i] != '\t' && szURL[i] != '\0'; i++); + + char *szMsgURL = (char *)mir_alloc(i + 1); + if (szMsgURL) + { + lstrcpynA(szMsgURL, szURL, i + 1); + CallService(MS_UTILS_OPENURL, (WPARAM)1, (LPARAM)szMsgURL); + mir_free(szMsgURL); + } + } + mir_free(szMsg); + + return 0; +} + +static int AwayMsgPreBuildMenu(WPARAM wParam, LPARAM lParam) +{ + CLISTMENUITEM clmi = {0}; + TCHAR str[128]; + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + int iHidden = szProto ? DBGetContactSettingByte((HANDLE)wParam, szProto, "ChatRoom", 0) : 0; + char *szMsg; + int iStatus; + + clmi.cbSize = sizeof(clmi); + clmi.flags = CMIM_FLAGS | CMIF_HIDDEN | CMIF_TCHAR; + + if (!iHidden) + { + iHidden = 1; + iStatus = DBGetContactSettingWord((HANDLE)wParam, szProto, "Status", ID_STATUS_OFFLINE); + if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1,0) & PF1_MODEMSGRECV) + { + if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3,0) & Proto_Status2Flag(iStatus == ID_STATUS_OFFLINE ? ID_STATUS_INVISIBLE : iStatus)) + { + iHidden = 0; + clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIM_ICON | CMIF_TCHAR; + clmi.hIcon = LoadSkinnedProtoIcon(szProto, iStatus); + mir_sntprintf(str, SIZEOF(str), TranslateT("Re&ad %s Message"), (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, GSMDF_TCHAR)); + clmi.ptszName = str; + } + } + } + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hAwayMsgMenuItem, (LPARAM)&clmi); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)clmi.hIcon, (LPARAM)0); + clmi.flags = CMIM_FLAGS | CMIF_HIDDEN | CMIF_TCHAR; + + if (!iHidden) + { + DBVARIANT dbv; + + int unicode = !DBGetContactSetting((HANDLE)wParam, "CList", "StatusMsg", &dbv) && (dbv.type == DBVT_UTF8 || dbv.type == DBVT_WCHAR); + DBFreeVariant(&dbv); + if (unicode) + { + DBGetContactSettingWString((HANDLE)wParam, "CList", "StatusMsg", &dbv); + szMsg = mir_u2a(dbv.pwszVal); + } + else + + { + DBGetContactSettingString((HANDLE)wParam, "CList", "StatusMsg", &dbv); + szMsg = mir_strdup(dbv.pszVal); + } + DBFreeVariant(&dbv); + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowCopy", 1) && szMsg && *szMsg != '\0') + { + clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIF_TCHAR; + mir_sntprintf(str, SIZEOF(str), TranslateT("Copy %s Message"), (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, GSMDF_TCHAR)); + clmi.ptszName = str; + } + } + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hCopyMsgMenuItem, (LPARAM)&clmi); + clmi.flags = CMIM_FLAGS | CMIF_HIDDEN | CMIF_TCHAR; + + if (!iHidden) + { + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowGoToURL", 1) && StrFindURL(szMsg) != NULL) + { + clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIF_TCHAR; + mir_sntprintf(str, SIZEOF(str), TranslateT("&Go to URL in %s Message"), (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, GSMDF_TCHAR)); + clmi.ptszName = str; + } + mir_free(szMsg); + } + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hGoToURLMenuItem, (LPARAM)&clmi); + + return 0; +} + +int AwayMsgPreShutdown(void) +{ + if (hWindowList) WindowList_BroadcastAsync(hWindowList, WM_CLOSE, 0, 0); + if (hWindowList2) WindowList_BroadcastAsync(hWindowList2, WM_CLOSE, 0, 0); + + return 0; +} + +int LoadAwayMsgModule(void) +{ + CLISTMENUITEM mi = {0}; + + hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + hWindowList2 = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + mi.cbSize = sizeof(mi); + mi.flags = CMIF_TCHAR; + + CreateServiceFunctionEx(MS_AWAYMSG_SHOWAWAYMSG, GetMessageCommand); + mi.position = -2000005000; + mi.ptszName = LPGENT("Re&ad Away Message"); + mi.pszService = MS_AWAYMSG_SHOWAWAYMSG; + hAwayMsgMenuItem = Menu_AddContactMenuItem(&mi); + + mi.flags |= CMIF_ICONFROMICOLIB; + CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_COPYMSG, CopyAwayMsgCommand); + mi.position = -2000006000; + mi.icolibItem = GetIconHandle(IDI_COPY); + mi.ptszName = LPGENT("Copy Away Message"); + mi.pszService = MS_SIMPLESTATUSMSG_COPYMSG; + hCopyMsgMenuItem = Menu_AddContactMenuItem(&mi); + + CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_GOTOURLMSG, GoToURLMsgCommand); + mi.position = -2000007000; + mi.icolibItem = GetIconHandle(IDI_GOTOURL); + mi.ptszName = LPGENT("&Go to URL in Away Message"); + mi.pszService = MS_SIMPLESTATUSMSG_GOTOURLMSG; + hGoToURLMenuItem = Menu_AddContactMenuItem(&mi); + + HookEventEx(ME_CLIST_PREBUILDCONTACTMENU, AwayMsgPreBuildMenu); + + // Deprecated SimpleAway services + CreateServiceFunctionEx(MS_SA_COPYAWAYMSG, CopyAwayMsgCommand); + CreateServiceFunctionEx(MS_SA_GOTOURLMSG, GoToURLMsgCommand); + + return 0; +} diff --git a/plugins/SimpleStatusMsg/src/commonheaders.h b/plugins/SimpleStatusMsg/src/commonheaders.h new file mode 100644 index 0000000000..54bf654ca4 --- /dev/null +++ b/plugins/SimpleStatusMsg/src/commonheaders.h @@ -0,0 +1,65 @@ +/* + +Simple Status Message plugin for Miranda IM +Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +// to enable all 0.9.0 core functions +#define MIRANDA_VER 0x0A00 +// to enable custom langpacks +#define MIRANDA_CUSTOM_LP + +#define _WIN32_IE 0x0501 + +#define _CRT_SECURE_NO_WARNINGS + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../protocols/IcqOscarJ/icq_constants.h" +#include "m_fortunemsg.h" +#include "m_statusplugins.h" +#include "m_toptoolbar.h" +#include "m_variables.h" +#include "m_simpleaway.h" +#include "m_simplestatusmsg.h" + +#include "resource.h" diff --git a/plugins/SimpleStatusMsg/src/main.cpp b/plugins/SimpleStatusMsg/src/main.cpp new file mode 100644 index 0000000000..95212f4d59 --- /dev/null +++ b/plugins/SimpleStatusMsg/src/main.cpp @@ -0,0 +1,2176 @@ +/* + +Simple Status Message plugin for Miranda IM +Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "commonheaders.h" +#include "simplestatusmsg.h" +#include + +HINSTANCE g_hInst; + +int hLangpack; +PROTOACCOUNTS *accounts; + +static int g_iIdleTime = -1; +UINT_PTR g_uUpdateMsgTimer = 0, *g_uSetStatusTimer; +static TCHAR *g_ptszWinampSong; +HANDLE hTTBButton = 0, h_statusmodechange; +HWND hwndSAMsgDialog; +static HANDLE *hProtoStatusMenuItem; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + "Simple Status Message", + PLUGIN_MAKE_VERSION(1, 9, 0, 4), + "Provides a simple way to set status and away messages", + "Bartosz 'Dezeath' Białek, Harven", + "dezred"/*antispam*/"@"/*antispam*/"gmail"/*antispam*/"."/*antispam*/"com", + "© 2006-2011 Bartosz Białek, © 2005 Harven", + "http://code.google.com/p/dezeath", + UNICODE_AWARE, + // {768CE156-34AC-45a3-B53B-0083C47615C4} + { 0x768ce156, 0x34ac, 0x45a3, { 0xb5, 0x3b, 0x0, 0x83, 0xc4, 0x76, 0x15, 0xc4 } } +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + g_hInst = hinstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_SRAWAY, MIID_LAST}; + +#ifdef _DEBUG +void log2file(const char *fmt, ...) +{ + DWORD dwBytesWritten; + va_list va; + char szText[1024]; + HANDLE hFile = CreateFileA("simplestatusmsg.log", GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + SetFilePointer(hFile, 0, 0, FILE_END); + + strncpy(szText, "[\0", SIZEOF(szText)); + WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL); + + GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, szText, SIZEOF(szText)); + WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL); + + strncpy(szText, "] \0", SIZEOF(szText)); + + va_start(va, fmt); + mir_vsnprintf(szText + strlen(szText), SIZEOF(szText) - strlen(szText), fmt, va); + va_end(va); + + WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL); + + strncpy(szText, "\n\0", SIZEOF(szText)); + WriteFile(hFile, szText, (DWORD)strlen(szText), &dwBytesWritten, NULL); + + CloseHandle(hFile); +} +#endif + +static TCHAR *GetWinampSong(void) +{ + TCHAR *szTitle, *pstr, *res = NULL; + HWND hwndWinamp = FindWindow(_T("STUDIO"), NULL); + int iTitleLen; + + if (hwndWinamp == NULL) + hwndWinamp = FindWindow(_T("Winamp v1.x"), NULL); + + if (hwndWinamp == NULL) + return NULL; + + iTitleLen = GetWindowTextLength(hwndWinamp); + szTitle = (TCHAR *)mir_alloc((iTitleLen + 1) * sizeof(TCHAR)); + if (szTitle == NULL) + return NULL; + + if (GetWindowText(hwndWinamp, szTitle, iTitleLen + 1) == 0) + { + mir_free(szTitle); + return NULL; + } + + pstr = _tcsstr(szTitle, _T(" - Winamp")); + if (pstr == NULL) + { + mir_free(szTitle); + return NULL; + } + + if (pstr < szTitle + (iTitleLen / 2)) + { + MoveMemory(szTitle, pstr + 9, _tcslen(pstr + 9) * sizeof(TCHAR)); + pstr = _tcsstr(pstr + 1, _T(" - Winamp")); + if (pstr == NULL) + { + mir_free(szTitle); + return NULL; + } + } + *pstr = 0; + + pstr = _tcschr(szTitle, _T('.')); + if (pstr == NULL) + { + mir_free(szTitle); + return NULL; + } + + pstr += 2; + res = mir_tstrdup(pstr); + mir_free(szTitle); + + return res; +} + +TCHAR *InsertBuiltinVarsIntoMsg(TCHAR *in, const char *szProto, int status) +{ + int i, count = 0, len; + TCHAR substituteStr[1024], *msg = mir_tstrdup(in); + + for (i = 0; msg[i]; i++) + { + if (msg[i] == 0x0D && DBGetContactSettingByte(NULL, "SimpleStatusMsg", "RemoveCR", 0)) + { + TCHAR *p = msg + i; + if (i + 1 <= 1024 && msg[i + 1]) + { + if (msg[i + 1] == 0x0A) + { + if (i + 2 <= 1024 && msg[i + 2]) + { + count++; + MoveMemory(p, p + 1, (lstrlen(p) - 1) * sizeof(TCHAR)); + } + else + { + msg[i + 1] = 0; + msg[i] = 0x0A; + } + } + } + } + + if (msg[i] != '%') + continue; + + if (!_tcsnicmp(msg+i, _T("%winampsong%"), 12)) + { + TCHAR *ptszWinampTitle = GetWinampSong(); + + if (ptszWinampTitle != NULL) + { + mir_free(g_ptszWinampSong); + g_ptszWinampSong = mir_tstrdup(ptszWinampTitle); + } + else if (g_ptszWinampSong && lstrcmp(g_ptszWinampSong, _T("SimpleStatusMsg")) + && DBGetContactSettingByte(NULL, "SimpleStatusMsg", "AmpLeaveTitle", 1)) + { + ptszWinampTitle = mir_tstrdup(g_ptszWinampSong); + } + else + continue; + + if (lstrlen(ptszWinampTitle) > 12) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(ptszWinampTitle) - 12) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(ptszWinampTitle), msg + i + 12, (lstrlen(msg) - i - 11) * sizeof(TCHAR)); + CopyMemory(msg + i, ptszWinampTitle, lstrlen(ptszWinampTitle) * sizeof(TCHAR)); + + mir_free(ptszWinampTitle); + } + else if (!_tcsnicmp(msg+i, _T("%fortunemsg%"), 12)) + { + TCHAR *FortuneMsg; + + char *FortuneMsgA; + + + if (!ServiceExists(MS_FORTUNEMSG_GETMESSAGE)) + continue; + + + FortuneMsgA = (char*)CallService(MS_FORTUNEMSG_GETMESSAGE, 0, 0); + FortuneMsg = mir_a2u(FortuneMsgA); + + if (lstrlen(FortuneMsg) > 12) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(FortuneMsg) - 12) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(FortuneMsg), msg + i + 12, (lstrlen(msg) - i - 11) * sizeof(TCHAR)); + CopyMemory(msg + i, FortuneMsg, lstrlen(FortuneMsg) * sizeof(TCHAR)); + + + mir_free(FortuneMsg); + CallService(MS_FORTUNEMSG_FREEMEMORY, 0, (LPARAM)FortuneMsgA); + + } + else if (!_tcsnicmp(msg+i, _T("%protofortunemsg%"), 17)) + { + TCHAR *FortuneMsg; + + char *FortuneMsgA; + + + if (!ServiceExists(MS_FORTUNEMSG_GETPROTOMSG)) + continue; + + + FortuneMsgA = (char*)CallService(MS_FORTUNEMSG_GETPROTOMSG, (WPARAM)szProto, 0); + FortuneMsg = mir_a2u(FortuneMsgA); + + + if (lstrlen(FortuneMsg) > 17) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(FortuneMsg) - 17) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(FortuneMsg), msg + i + 17, (lstrlen(msg) - i - 16) * sizeof(TCHAR)); + CopyMemory(msg + i, FortuneMsg, lstrlen(FortuneMsg) * sizeof(TCHAR)); + + + mir_free(FortuneMsg); + CallService(MS_FORTUNEMSG_FREEMEMORY, 0, (LPARAM)FortuneMsgA); + + } + else if (!_tcsnicmp(msg+i, _T("%statusfortunemsg%"), 18)) + { + TCHAR *FortuneMsg; + + char *FortuneMsgA; + + + if (!ServiceExists(MS_FORTUNEMSG_GETSTATUSMSG)) + continue; + + + FortuneMsgA = (char*)CallService(MS_FORTUNEMSG_GETSTATUSMSG, (WPARAM)status, 0); + FortuneMsg = mir_a2u(FortuneMsgA); + + + if (lstrlen(FortuneMsg) > 18) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(FortuneMsg) - 18) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(FortuneMsg), msg + i + 18, (lstrlen(msg) - i - 17) * sizeof(TCHAR)); + CopyMemory(msg + i, FortuneMsg, lstrlen(FortuneMsg) * sizeof(TCHAR)); + + + mir_free(FortuneMsg); + CallService(MS_FORTUNEMSG_FREEMEMORY, 0, (LPARAM)FortuneMsgA); + + } + else if (!_tcsnicmp(msg + i, _T("%time%"), 6)) + { + MIRANDA_IDLE_INFO mii = {0}; + mii.cbSize = sizeof(mii); + CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii); + + if (mii.idleType) + { + int mm; + SYSTEMTIME t; + GetLocalTime(&t); + if ((mm = g_iIdleTime) == -1) + { + mm = t.wMinute + t.wHour * 60; + if (mii.idleType == 1) + { + mm -= mii.idleTime; + if (mm < 0) mm += 60 * 24; + } + g_iIdleTime = mm; + } + 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)); + + if (lstrlen(substituteStr) > 6) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(substituteStr) - 6) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(substituteStr), msg + i + 6, (lstrlen(msg) - i - 5) * sizeof(TCHAR)); + CopyMemory(msg + i, substituteStr, lstrlen(substituteStr) * sizeof(TCHAR)); + } + else if (!_tcsnicmp(msg + i, _T("%date%"), 6)) + { + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, substituteStr, SIZEOF(substituteStr)); + + if (lstrlen(substituteStr) > 6) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(substituteStr) - 6) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(substituteStr), msg + i + 6, (lstrlen(msg) - i - 5) * sizeof(TCHAR)); + CopyMemory(msg + i, substituteStr, lstrlen(substituteStr) * sizeof(TCHAR)); + } + else if (!_tcsnicmp(msg+i, _T("%rand("), 6)) + { + TCHAR *temp, *token; + int ran_from, ran_to, k; + + temp = mir_tstrdup(msg + i + 6); + token = _tcstok(temp, _T(",)")); + ran_from = _ttoi(token); + token = _tcstok(NULL, _T(",)%%")); + ran_to = _ttoi(token); + + if (ran_to > ran_from) + { + mir_sntprintf(substituteStr, SIZEOF(substituteStr), _T("%d"), GetRandom(ran_from, ran_to)); + for (k = i + 1; msg[k]; k++) if (msg[k] == '%') { k++; break; } + + if (lstrlen(substituteStr) > k - i) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(substituteStr) - (k - i)) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(substituteStr), msg + i + (k - i), (lstrlen(msg) - i - (k - i - 1)) * sizeof(TCHAR)); + CopyMemory(msg + i, substituteStr, lstrlen(substituteStr) * sizeof(TCHAR)); + } + mir_free(temp); + } + else if (!_tcsnicmp(msg+i, _T("%randmsg%"), 9)) + { + char buff[16]; + int k, maxk, k2 = 0; + DBVARIANT dbv; + BOOL rmark[25]; + + for (k = 0; k < 26; k++) rmark[k] = FALSE; + maxk = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "MaxHist", 10); + if (maxk == 0) rmark[0] = TRUE; + + while (!rmark[0]) + { + k = GetRandom(1, maxk); + if (rmark[k]) continue; + rmark[k] = TRUE; + k2++; + if (k2 == maxk || k2 > maxk) rmark[0] = TRUE; + + mir_snprintf(buff, SIZEOF(buff), "SMsg%d", k); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", buff, &dbv)) + { + if (dbv.ptszVal == NULL) + { + DBFreeVariant(&dbv); + continue; + } + lstrcpy(substituteStr, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else continue; + + if (!lstrlen(substituteStr)) continue; + if (_tcsstr(substituteStr, _T("%randmsg%")) != NULL || _tcsstr(substituteStr, _T("%randdefmsg%")) != NULL) + { + if (k == maxk) maxk--; + } + else rmark[0] = TRUE; + } + + if (k2 == maxk || k2 > maxk) lstrcpy(substituteStr, _T("")); + + if (lstrlen(substituteStr) > 9) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg) + 1 + lstrlen(substituteStr) - 9) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(substituteStr), msg + i + 9, (lstrlen(msg) - i - 8) * sizeof(TCHAR)); + CopyMemory(msg + i, substituteStr, lstrlen(substituteStr) * sizeof(TCHAR)); + } + else if (!_tcsnicmp(msg+i, _T("%randdefmsg%"), 12)) + { + char buff[16]; + int k, maxk, k2 = 0; + DBVARIANT dbv; + BOOL rmark[25]; + + for (k = 0; k < 26; k++) rmark[k] = FALSE; + maxk = DBGetContactSettingWord(NULL, "SimpleStatusMsg", "DefMsgCount", 0); + if (maxk == 0) rmark[0] = TRUE; + + while (!rmark[0]) + { + k = GetRandom(1, maxk); + if (rmark[k]) continue; + rmark[k] = TRUE; + k2++; + if (k2 == maxk || k2 > maxk) rmark[0] = TRUE; + + mir_snprintf(buff, SIZEOF(buff), "DefMsg%d", k); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", buff, &dbv)) + { + if (dbv.ptszVal == NULL) + { + DBFreeVariant(&dbv); + continue; + } + lstrcpy(substituteStr, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else continue; + + if (!lstrlen(substituteStr)) continue; + if (_tcsstr(substituteStr, _T("%randmsg%")) != NULL || _tcsstr(substituteStr, _T("%randdefmsg%")) != NULL) + { + if (k == maxk) maxk--; + } + else rmark[0] = TRUE; + } + + if (k2 == maxk || k2 > maxk) lstrcpy(substituteStr, _T("")); + + if (lstrlen(substituteStr) > 12) + msg = (TCHAR *)mir_realloc(msg, (lstrlen(msg)+1+lstrlen(substituteStr)-12) * sizeof(TCHAR)); + + MoveMemory(msg + i + lstrlen(substituteStr), msg + i + 12, (lstrlen(msg) - i - 11) * sizeof(TCHAR)); + CopyMemory(msg + i, substituteStr, lstrlen(substituteStr) * sizeof(TCHAR)); + } + } + + if (count) msg[lstrlen(msg) - count] = 0; + + if (szProto) + { + char szSetting[80]; + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sMaxLen", szProto); + len = DBGetContactSettingWord(NULL, "SimpleStatusMsg", szSetting, 1024); + if (len < lstrlen(msg)) + { + msg = (TCHAR *)mir_realloc(msg, len * sizeof(TCHAR)); + msg[len] = 0; + } + } + + return msg; +} + +TCHAR *InsertVarsIntoMsg(TCHAR *tszMsg, const char *szProto, int iStatus, HANDLE hContact) +{ + if (ServiceExists(MS_VARS_FORMATSTRING) && DBGetContactSettingByte(NULL, "SimpleStatusMsg", "EnableVariables", 1)) + { + FORMATINFO fInfo = {0}; + fInfo.cbSize = sizeof(fInfo); + fInfo.flags = FIF_TCHAR; + fInfo.tszFormat = tszMsg; + fInfo.hContact = hContact; + TCHAR *tszVarsMsg = (TCHAR *)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fInfo, 0); + if (tszVarsMsg != NULL) + { + TCHAR *format = InsertBuiltinVarsIntoMsg(tszVarsMsg, szProto, iStatus); + CallService(MS_VARS_FREEMEMORY, (WPARAM)tszVarsMsg, 0); + return format; + } + } + + return InsertBuiltinVarsIntoMsg(tszMsg, szProto, iStatus); +} + +static TCHAR *GetAwayMessageFormat(int iStatus, const char *szProto) +{ + DBVARIANT dbv, dbv2; + int flags; + char szSetting[80]; + TCHAR *format; + + mir_snprintf(szSetting, SIZEOF(szSetting), "%sFlags", szProto ? szProto : ""); + flags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", (char *)StatusModeToDbSetting(iStatus, szSetting), STATUS_DEFAULT); + + if (flags & STATUS_EMPTY_MSG) + return mir_tstrdup(_T("")); + + if (flags & STATUS_LAST_STATUS_MSG) + { + if (szProto) + mir_snprintf(szSetting, SIZEOF(szSetting), "%sMsg", szProto); + else + mir_snprintf(szSetting, SIZEOF(szSetting), "Msg"); + + if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(iStatus, szSetting), &dbv)) + return NULL; //mir_tstrdup(_T("")); + + format = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + else if (flags & STATUS_LAST_MSG) + { + if (szProto) + mir_snprintf(szSetting, SIZEOF(szSetting), "Last%sMsg", szProto); + else + mir_snprintf(szSetting, SIZEOF(szSetting), "LastMsg"); + + if (DBGetContactSetting(NULL, "SimpleStatusMsg", szSetting, &dbv2)) + return NULL; //mir_tstrdup(_T("")); + + if (DBGetContactSettingTString(NULL, "SimpleStatusMsg", dbv2.pszVal, &dbv)) + { + DBFreeVariant(&dbv2); + return NULL; //mir_tstrdup(_T("")); + } + + format = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + DBFreeVariant(&dbv2); + } + else if (flags & STATUS_THIS_MSG) + { + if (szProto) + mir_snprintf(szSetting, SIZEOF(szSetting), "%sDefault", szProto); + else + mir_snprintf(szSetting, SIZEOF(szSetting), "Default"); + + if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(iStatus, szSetting), &dbv)) + return mir_tstrdup(_T("")); + + format = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + format = mir_tstrdup(GetDefaultMessage(iStatus)); + + return format; +} + +void DBWriteMessage(char *szSetting, TCHAR *tszMsg) +{ + if (tszMsg && lstrlen(tszMsg)) + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", szSetting, tszMsg); + else + DBDeleteContactSetting(NULL, "SimpleStatusMsg", szSetting); +} + +void SaveMessageToDB(const char *szProto, TCHAR *tszMsg, BOOL bIsFormat) +{ + char szSetting[80]; + + if (!szProto) + { + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(szSetting, SIZEOF(szSetting), bIsFormat ? "FCur%sMsg" : "Cur%sMsg", accounts->pa[i]->szModuleName); + DBWriteMessage(szSetting, tszMsg); +#ifdef _DEBUG + if (bIsFormat) + log2file("SaveMessageToDB(): Set \"" TCHAR_STR_PARAM "\" status message (without inserted vars) for %s.", tszMsg, accounts->pa[i]->szModuleName); + else + log2file("SaveMessageToDB(): Set \"" TCHAR_STR_PARAM "\" status message for %s.", tszMsg, accounts->pa[i]->szModuleName); +#endif + } + } + else + { + if (!(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + return; + + mir_snprintf(szSetting, SIZEOF(szSetting), bIsFormat ? "FCur%sMsg" : "Cur%sMsg", szProto); + DBWriteMessage(szSetting, tszMsg); +#ifdef _DEBUG + if (bIsFormat) + log2file("SaveMessageToDB(): Set \"" TCHAR_STR_PARAM "\" status message (without inserted vars) for %s.", tszMsg, szProto); + else + log2file("SaveMessageToDB(): Set \"" TCHAR_STR_PARAM "\" status message for %s.", tszMsg, szProto); +#endif + } +} + +void SaveStatusAsCurrent(const char *szProto, int iStatus) +{ + char szSetting[80]; + mir_snprintf(szSetting, SIZEOF(szSetting), "Cur%sStatus", szProto); + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", szSetting, (WORD)iStatus); +} + +static TCHAR *GetAwayMessage(int iStatus, const char *szProto, BOOL bInsertVars, HANDLE hContact) +{ + TCHAR *format = NULL; + char szSetting[80]; + + if ((!iStatus || iStatus == ID_STATUS_CURRENT) && szProto) + { + DBVARIANT dbv; + mir_snprintf(szSetting, SIZEOF(szSetting), "FCur%sMsg", szProto); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + format = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + //else + // format = mir_tstrdup(_T("")); + } + else + { + int flags; + + if (!iStatus || iStatus == ID_STATUS_CURRENT) + iStatus = GetCurrentStatus(szProto); + + if (szProto && !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(iStatus))) + return NULL; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sFlags", szProto ? szProto : ""); + flags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", szSetting, PROTO_DEFAULT); + + //if (flags & PROTO_NO_MSG) + //{ + // format = mir_tstrdup(_T("")); + //} + //else + if (flags & PROTO_THIS_MSG) + { + DBVARIANT dbv; + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sDefault", szProto); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + format = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + format = mir_tstrdup(_T("")); + } + else if (flags & PROTO_NOCHANGE && szProto) + { + DBVARIANT dbv; + mir_snprintf(szSetting, SIZEOF(szSetting), "FCur%sMsg", szProto); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + format = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + //else + // format = mir_tstrdup(_T("")); + } + else if (flags & PROTO_POPUPDLG) + format = GetAwayMessageFormat(iStatus, szProto); + } +#ifdef _DEBUG + log2file("GetAwayMessage(): %s has %s status and \"" TCHAR_STR_PARAM "\" status message.", szProto, StatusModeToDbSetting(iStatus, ""), format); +#endif + + if (bInsertVars && format != NULL) + { + TCHAR *tszVarsMsg = InsertVarsIntoMsg(format, szProto, iStatus, hContact); // TODO random values not the same! + mir_free(format); + return tszVarsMsg; + } + + return format; +} + +int CheckProtoSettings(const char *szProto, int iInitialStatus) +{ + int iSetting = DBGetContactSettingWord(NULL, szProto, "LeaveStatus", -1); //GG settings + if (iSetting != -1) + return iSetting ? iSetting : iInitialStatus; + iSetting = DBGetContactSettingWord(NULL, szProto, "OfflineMessageOption", -1); //TLEN settings + if (iSetting != -1) + { + switch (iSetting) + { + case 1: return ID_STATUS_ONLINE; + case 2: return ID_STATUS_AWAY; + case 3: return ID_STATUS_NA; + case 4: return ID_STATUS_DND; + case 5: return ID_STATUS_FREECHAT; + case 6: return ID_STATUS_INVISIBLE; + default: return iInitialStatus; + } + } + return iInitialStatus; +} + +static void Proto_SetAwayMsgT(const char *szProto, int iStatus, TCHAR *tszMsg) +{ + if (!(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_INDIVMODEMSG)) + { + + if (CallProtoService(szProto, PS_SETAWAYMSGW, (WPARAM)iStatus, (LPARAM)tszMsg) == CALLSERVICE_NOTFOUND) + { + char *szMsg = mir_u2a(tszMsg); + CallProtoService(szProto, PS_SETAWAYMSG, (WPARAM)iStatus, (LPARAM)szMsg); + mir_free(szMsg); + } + + } +} + +static void Proto_SetStatus(const char *szProto, int iInitialStatus, int iStatus, TCHAR *tszMsg) +{ + if (iStatus == ID_STATUS_OFFLINE && iStatus != iInitialStatus) + { + // ugly hack to set offline status message + if (!(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_INDIVMODEMSG)) + { + int iMsgStatus = CheckProtoSettings(szProto, iInitialStatus); + + if (CallProtoService(szProto, PS_SETAWAYMSGW, (WPARAM)iMsgStatus, (LPARAM)tszMsg) == CALLSERVICE_NOTFOUND) + { + char *szMsg = mir_u2a(tszMsg); + CallProtoService(szProto, PS_SETAWAYMSG, (WPARAM)iMsgStatus, (LPARAM)szMsg); + mir_free(szMsg); + } + + CallProtoService(szProto, PS_SETSTATUS, (WPARAM)iMsgStatus, 0); + } + if (ServiceExists(MS_KS_ANNOUNCESTATUSCHANGE)) + announce_status_change((char*)szProto, ID_STATUS_OFFLINE, NULL); + CallProtoService(szProto, PS_SETSTATUS, ID_STATUS_OFFLINE, 0); + return; + } + + Proto_SetAwayMsgT(szProto, iStatus, tszMsg /* ? tszMsg : _T("")*/); + if (iStatus != iInitialStatus) + CallProtoService(szProto, PS_SETSTATUS, iStatus, 0); +} + +int HasProtoStaticStatusMsg(const char *szProto, int iInitialStatus, int iStatus) +{ + char szSetting[80]; + int flags; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sFlags", szProto); + flags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", szSetting, PROTO_DEFAULT); + + if (flags & PROTO_NO_MSG) + { + Proto_SetStatus(szProto, iInitialStatus, iStatus, NULL); + SaveMessageToDB(szProto, NULL, TRUE); + SaveMessageToDB(szProto, NULL, FALSE); + return 1; + } + else if (flags & PROTO_THIS_MSG) + { + DBVARIANT dbv; + TCHAR *msg; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sDefault", szProto); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + SaveMessageToDB(szProto, dbv.ptszVal, TRUE); + msg = InsertVarsIntoMsg(dbv.ptszVal, szProto, iStatus, NULL); + DBFreeVariant(&dbv); + Proto_SetStatus(szProto, iInitialStatus, iStatus, msg); + SaveMessageToDB(szProto, msg, FALSE); + mir_free(msg); + } + else + { + Proto_SetStatus(szProto, iInitialStatus, iStatus, _T("")); + SaveMessageToDB(szProto, _T(""), TRUE); + SaveMessageToDB(szProto, _T(""), FALSE); + } + return 1; + } + return 0; +} + +INT_PTR SetStatusModeFromExtern(WPARAM wParam, LPARAM lParam) +{ + if ((wParam < ID_STATUS_OFFLINE && wParam != 0) || (wParam > ID_STATUS_OUTTOLUNCH && wParam != ID_STATUS_CURRENT)) + return 0; + + int newStatus = (int)wParam; + + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) &~ CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + if (DBGetContactSettingByte(NULL, accounts->pa[i]->szModuleName, "LockMainStatus", 0)) + continue; + + if (wParam == ID_STATUS_CURRENT || wParam == 0) + newStatus = GetCurrentStatus(accounts->pa[i]->szModuleName); + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + { + CallProtoService(accounts->pa[i]->szModuleName, PS_SETSTATUS, newStatus, 0); + continue; + } + + int status_modes_msg = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + + if ((Proto_Status2Flag(newStatus) & status_modes_msg) || (newStatus == ID_STATUS_OFFLINE && (Proto_Status2Flag(ID_STATUS_INVISIBLE) & status_modes_msg))) + { + TCHAR *msg = NULL; + + if (HasProtoStaticStatusMsg(accounts->pa[i]->szModuleName, GetCurrentStatus(accounts->pa[i]->szModuleName), newStatus)) + continue; + + if (lParam) + msg = InsertVarsIntoMsg((TCHAR *)lParam, accounts->pa[i]->szModuleName, newStatus, NULL); + + SaveMessageToDB(accounts->pa[i]->szModuleName, (TCHAR *)lParam, TRUE); + SaveMessageToDB(accounts->pa[i]->szModuleName, msg, FALSE); + Proto_SetStatus(accounts->pa[i]->szModuleName, GetCurrentStatus(accounts->pa[i]->szModuleName), newStatus, msg /*? msg : _T("")*/); + mir_free(msg); + } + else + CallProtoService(accounts->pa[i]->szModuleName, PS_SETSTATUS, newStatus, 0); + } + + return 0; +} + +int ChangeStatusMessage(WPARAM wParam, LPARAM lParam); + +void SetStatusMessage(const char *szProto, int iInitialStatus, int iStatus, TCHAR *message, BOOL bOnStartup) +{ + TCHAR *msg = NULL; +#ifdef _DEBUG + log2file("SetStatusMessage(\"%s\", %d, %d, \"" TCHAR_STR_PARAM "\", %d)", szProto, iInitialStatus, iStatus, message, bOnStartup); +#endif + if (szProto) + { + if (bOnStartup && accounts->statusCount > 1) // TODO not only at startup? + { + int status; + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + status = iStatus == ID_STATUS_CURRENT ? GetStartupStatus(accounts->pa[i]->szModuleName) : iStatus; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) || + !(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + { + if (!(bOnStartup && status == ID_STATUS_OFFLINE) && GetCurrentStatus(accounts->pa[i]->szModuleName) != status) + CallProtoService(accounts->pa[i]->szModuleName, PS_SETSTATUS, (WPARAM)status, 0); + } + } + } + + if (message) + msg = InsertVarsIntoMsg(message, szProto, iStatus, NULL); + + SaveMessageToDB(szProto, message, TRUE); + SaveMessageToDB(szProto, msg, FALSE); + + if (iInitialStatus == ID_STATUS_CURRENT) + iInitialStatus = bOnStartup ? ID_STATUS_OFFLINE : GetCurrentStatus(szProto); + + Proto_SetStatus(szProto, iInitialStatus, iStatus, msg); + mir_free(msg); + } + else + { + int iProfileStatus = iStatus > ID_STATUS_CURRENT ? iStatus : 0; + BOOL bIsStatusCurrent = iStatus == ID_STATUS_CURRENT; + BOOL bIsInitialStatusCurrent = iInitialStatus == ID_STATUS_CURRENT; + + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + if (!bOnStartup && DBGetContactSettingByte(NULL, accounts->pa[i]->szModuleName, "LockMainStatus", 0)) + continue; + + if (iProfileStatus) + { + int iProfileNumber = iStatus - 40083; + char szSetting[128]; + mir_snprintf(szSetting, SIZEOF(szSetting), "%d_%s", iProfileNumber, accounts->pa[i]->szModuleName); + iStatus = DBGetContactSettingWord(NULL, "StartupStatus", szSetting, ID_STATUS_OFFLINE); + if (iStatus == ID_STATUS_IDLE) // the same as ID_STATUS_LAST in StartupStatus + { + mir_snprintf(szSetting, SIZEOF(szSetting), "last_%s", accounts->pa[i]->szModuleName); + iStatus = DBGetContactSettingWord(NULL, "StartupStatus", szSetting, ID_STATUS_OFFLINE); + } + else if (iStatus == ID_STATUS_CURRENT) + iStatus = GetCurrentStatus(accounts->pa[i]->szModuleName); + } + + if (bIsStatusCurrent) + iStatus = bOnStartup ? GetStartupStatus(accounts->pa[i]->szModuleName) : GetCurrentStatus(accounts->pa[i]->szModuleName); + + if (bIsInitialStatusCurrent) + iInitialStatus = bOnStartup ? ID_STATUS_OFFLINE : GetCurrentStatus(accounts->pa[i]->szModuleName); + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(iStatus)) || + !(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + { + if (!(bOnStartup && iStatus == ID_STATUS_OFFLINE) && GetCurrentStatus(accounts->pa[i]->szModuleName) != iStatus && iStatus != iInitialStatus) + { + CallProtoService(accounts->pa[i]->szModuleName, PS_SETSTATUS, (WPARAM)iStatus, 0); +#ifdef _DEBUG + log2file("SetStatusMessage(): Set %s status for %s.", StatusModeToDbSetting(iStatus, ""), accounts->pa[i]->szModuleName); +#endif + } + continue; + } + + if (HasProtoStaticStatusMsg(accounts->pa[i]->szModuleName, iInitialStatus, iStatus)) + continue; + + if (message) + msg = InsertVarsIntoMsg(message, accounts->pa[i]->szModuleName, iStatus, NULL); + + SaveMessageToDB(accounts->pa[i]->szModuleName, message, TRUE); + SaveMessageToDB(accounts->pa[i]->szModuleName, msg, FALSE); + + Proto_SetStatus(accounts->pa[i]->szModuleName, iInitialStatus, iStatus, msg); + mir_free(msg); + } + + if (GetCurrentStatus(NULL) != iStatus && !bIsStatusCurrent && !iProfileStatus) + { + // not so nice... + UnhookEvent(h_statusmodechange); + CallService(MS_CLIST_SETSTATUSMODE, (WPARAM)iStatus, 0); + h_statusmodechange = HookEvent(ME_CLIST_STATUSMODECHANGE, ChangeStatusMessage); + } + } +} + +INT_PTR ShowStatusMessageDialogInternal(WPARAM wParam, LPARAM lParam) +{ + struct MsgBoxInitData *box_data; + BOOL idvstatusmsg = FALSE; + + if (Miranda_Terminated()) return 0; + + if (hTTBButton) + { + CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTTBButton, (LPARAM)TTBST_RELEASED); + CallService(MS_TTB_SETBUTTONOPTIONS, MAKEWPARAM((WORD)TTBO_TIPNAME, (WORD)hTTBButton), (LPARAM)Translate("Change Status Message")); + } + + box_data = (struct MsgBoxInitData *)mir_alloc(sizeof(struct MsgBoxInitData)); + + if (accounts->statusMsgCount == 1) + { + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + box_data->m_szProto = accounts->pa[i]->szModuleName; + box_data->m_iStatusModes = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0); + box_data->m_iStatusMsgModes = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + break; + } + } + else + { + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + if (!accounts->pa[i]->bIsVisible) + continue; + + if (hProtoStatusMenuItem[i] == (HANDLE)lParam) + { + box_data->m_szProto = accounts->pa[i]->szModuleName; + box_data->m_iStatusModes = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0); + box_data->m_iStatusMsgModes = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + + idvstatusmsg = TRUE; + break; + } + } + if (!idvstatusmsg) + { + box_data->m_szProto = NULL; + box_data->m_iStatusModes = accounts->statusFlags; + box_data->m_iStatusMsgModes = accounts->statusMsgFlags; + } + } + box_data->m_iStatus = ID_STATUS_CURRENT; + box_data->m_bOnEvent = FALSE; + box_data->m_bOnStartup = FALSE; + + if (hwndSAMsgDialog) + DestroyWindow(hwndSAMsgDialog); + hwndSAMsgDialog = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AWAYMSGBOX), NULL, AwayMsgBoxDlgProc, (LPARAM)box_data); + return 0; +} + +INT_PTR ShowStatusMessageDialog(WPARAM wParam, LPARAM lParam) +{ + struct MsgBoxInitData *box_data; + BOOL idvstatusmsg = FALSE; + + if (Miranda_Terminated()) return 0; + + box_data = (struct MsgBoxInitData *)mir_alloc(sizeof(struct MsgBoxInitData)); + + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + if (!accounts->pa[i]->bIsVisible) + continue; + + if (!strcmp(accounts->pa[i]->szModuleName, (char *)lParam)) + { + box_data->m_szProto = accounts->pa[i]->szModuleName; + box_data->m_iStatusModes = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0); + box_data->m_iStatusMsgModes = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + + idvstatusmsg = TRUE; + break; + } + } + if (!idvstatusmsg) + { + box_data->m_szProto = NULL; + box_data->m_iStatusModes = accounts->statusFlags; + box_data->m_iStatusMsgModes = accounts->statusMsgFlags; + } + box_data->m_iStatus = ID_STATUS_CURRENT; + box_data->m_bOnEvent = FALSE; + box_data->m_bOnStartup = FALSE; + + if (hwndSAMsgDialog) + DestroyWindow(hwndSAMsgDialog); + hwndSAMsgDialog = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AWAYMSGBOX), NULL, AwayMsgBoxDlgProc, (LPARAM)box_data); + + return 0; +} + +static int ChangeStatusMessage(WPARAM wParam, LPARAM lParam) +{ + int iStatus = (int)wParam; + char *szProto = (char*)lParam; + int iDlgFlags; + BOOL bShowDlg, bOnStartup = FALSE, bGlobalStartupStatus = TRUE, bScreenSaverRunning = FALSE; + char szSetting[80]; + + if (Miranda_Terminated()) return 0; + + // TODO this could be done better + if (szProto && !strcmp(szProto, "SimpleStatusMsgGlobalStartupStatus")) + { + szProto = NULL; + bOnStartup = TRUE; + } + + if (accounts->statusMsgCount == 1 && !szProto) + { + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + szProto = accounts->pa[i]->szModuleName; + if (bOnStartup && iStatus == ID_STATUS_CURRENT) + { + iStatus = GetStartupStatus(accounts->pa[i]->szModuleName); + bGlobalStartupStatus = FALSE; + } + break; + } + } + + mir_snprintf(szSetting, SIZEOF(szSetting), "%sFlags", szProto ? szProto : ""); + iDlgFlags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", (char *)StatusModeToDbSetting(iStatus, szSetting), STATUS_DEFAULT); + bShowDlg = iDlgFlags & STATUS_SHOW_DLG || bOnStartup; + SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &bScreenSaverRunning, 0); + + if (szProto) + { + struct MsgBoxInitData *box_data; + int status_modes = 0, status_modes_msg = 0, iProtoFlags; + + status_modes = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_5, 0); + if (!(Proto_Status2Flag(iStatus) & status_modes) && iStatus != ID_STATUS_OFFLINE) + return 0; + + status_modes_msg = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0); + if (!(Proto_Status2Flag(iStatus) & status_modes_msg) || !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + { + if (bOnStartup && GetCurrentStatus(szProto) != iStatus) + { + CallProtoService(szProto, PS_SETSTATUS, iStatus, 0); +#ifdef _DEBUG + log2file("ChangeStatusMessage(): Set %s status for %s.", StatusModeToDbSetting(iStatus, ""), szProto); +#endif + } + return 0; + } + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sFlags", szProto); + iProtoFlags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", szSetting, PROTO_DEFAULT); + if (iProtoFlags & PROTO_NO_MSG || iProtoFlags & PROTO_THIS_MSG) + { + if (HasProtoStaticStatusMsg(szProto, iStatus, iStatus)) + return 1; + } + else if (iProtoFlags & PROTO_NOCHANGE && !bOnStartup) + { + DBVARIANT dbv; + TCHAR *msg = NULL; + + mir_snprintf(szSetting, SIZEOF(szSetting), "FCur%sMsg", szProto); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + msg = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + //else + // msg = mir_tstrdup(_T("")); +#ifdef _DEBUG + log2file("ChangeStatusMessage(): Set %s status and \"" TCHAR_STR_PARAM "\" status message for %s.", StatusModeToDbSetting(iStatus, ""), msg, szProto); +#endif + SetStatusMessage(szProto, iStatus, iStatus, msg, FALSE); + if (msg) mir_free(msg); + return 1; + } + + if (!bShowDlg || bScreenSaverRunning) + { + TCHAR *msg = GetAwayMessageFormat(iStatus, szProto); +#ifdef _DEBUG + log2file("ChangeStatusMessage(): Set %s status and \"" TCHAR_STR_PARAM "\" status message for %s.", StatusModeToDbSetting(iStatus, ""), msg, szProto); +#endif + SetStatusMessage(szProto, iStatus, iStatus, msg, FALSE); + if (msg) mir_free(msg); + return 1; + } + + box_data = (struct MsgBoxInitData *) mir_alloc(sizeof(struct MsgBoxInitData)); + box_data->m_szProto = szProto; + + if (!bOnStartup) + SaveStatusAsCurrent(szProto, iStatus); + + if (GetCurrentStatus(szProto) == iStatus || (bOnStartup && !bGlobalStartupStatus)) + box_data->m_iStatus = ID_STATUS_CURRENT; + else + box_data->m_iStatus = iStatus; + + box_data->m_iStatusModes = status_modes; + box_data->m_iStatusMsgModes = status_modes_msg; + box_data->m_bOnEvent = TRUE; + box_data->m_bOnStartup = bOnStartup; + + if (hwndSAMsgDialog) + DestroyWindow(hwndSAMsgDialog); + hwndSAMsgDialog = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AWAYMSGBOX), NULL, AwayMsgBoxDlgProc, (LPARAM)box_data); + } + else + { + struct MsgBoxInitData *box_data; + int iProtoFlags; + + // iStatus == ID_STATUS_CURRENT only when bOnStartup == TRUE + if (iStatus == ID_STATUS_OFFLINE || (!(accounts->statusMsgFlags & Proto_Status2Flag(iStatus)) && iStatus != ID_STATUS_CURRENT)) + return 0; + + iProtoFlags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ProtoFlags", PROTO_DEFAULT); + if (!bShowDlg || bScreenSaverRunning || (iProtoFlags & PROTO_NOCHANGE && !bOnStartup)) + { + TCHAR *msg = NULL; + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + if (DBGetContactSettingByte(NULL, accounts->pa[i]->szModuleName, "LockMainStatus", 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(iStatus)) || + !(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + if (iProtoFlags & PROTO_NOCHANGE) + { + DBVARIANT dbv; + mir_snprintf(szSetting, SIZEOF(szSetting), "FCur%sMsg", accounts->pa[i]->szModuleName); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + msg = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + //else + // msg = mir_tstrdup(_T("")); + } + else + msg = GetAwayMessageFormat(iStatus, NULL); +#ifdef _DEBUG + log2file("ChangeStatusMessage(): Set %s status and \"" TCHAR_STR_PARAM "\" status message for %s.", StatusModeToDbSetting(iStatus, ""), msg, accounts->pa[i]->szModuleName); +#endif + SetStatusMessage(accounts->pa[i]->szModuleName, iStatus, iStatus, msg, FALSE); + if (msg) { mir_free(msg); msg = NULL; } + } + return 1; + } + + box_data = (struct MsgBoxInitData *)mir_alloc(sizeof(struct MsgBoxInitData)); + box_data->m_szProto = NULL; + box_data->m_iStatus = iStatus; + box_data->m_iStatusModes = accounts->statusFlags; + box_data->m_iStatusMsgModes = accounts->statusMsgFlags; + box_data->m_bOnEvent = TRUE; + box_data->m_bOnStartup = bOnStartup; + + if (hwndSAMsgDialog) + DestroyWindow(hwndSAMsgDialog); + hwndSAMsgDialog = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AWAYMSGBOX), NULL, AwayMsgBoxDlgProc, (LPARAM)box_data); + } + return 0; +} + +static INT_PTR ChangeStatusMsg(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage(wParam, lParam); + return 0; +} + +static INT_PTR SetOfflineStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_OFFLINE, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetOnlineStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_ONLINE, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetAwayStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_AWAY, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetDNDStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_DND, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetNAStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_NA, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetOccupiedStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_OCCUPIED, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetFreeChatStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_FREECHAT, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetInvisibleStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_INVISIBLE, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetOnThePhoneStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_ONTHEPHONE, (LPARAM)NULL); + return 0; +} + +static INT_PTR SetOutToLunchStatus(WPARAM wParam, LPARAM lParam) +{ + ChangeStatusMessage((WPARAM)ID_STATUS_OUTTOLUNCH, (LPARAM)NULL); + return 0; +} + +static int ProcessProtoAck(WPARAM wParam,LPARAM lParam) +{ + ACKDATA *ack = (ACKDATA *)lParam; + + if (!ack || !ack->szModule) + return 0; + + if (ack->type == ACKTYPE_AWAYMSG && ack->result == ACKRESULT_SENTREQUEST && !ack->lParam) + { + TCHAR *tszMsg = GetAwayMessage(CallProtoService((char *)ack->szModule, PS_GETSTATUS, 0, 0), (char *)ack->szModule, TRUE, NULL); + + { + char *szMsg = mir_u2a(tszMsg); + CallContactService(ack->hContact, PSS_AWAYMSG, (WPARAM)(HANDLE)ack->hProcess, (LPARAM)szMsg); + if (szMsg) mir_free(szMsg); + } + +#ifdef _DEBUG + log2file("ProcessProtoAck(): Send away message \"" TCHAR_STR_PARAM "\" reply.", tszMsg); +#endif + if (tszMsg) mir_free(tszMsg); + return 0; + } + + if (ack->type != ACKTYPE_STATUS || ack->result != ACKRESULT_SUCCESS || ack->hContact != NULL) + return 0; + + if (ack->lParam >= ID_STATUS_CONNECTING && ack->lParam < ID_STATUS_CONNECTING + MAX_CONNECT_RETRIES) + ack->lParam = ID_STATUS_OFFLINE; + + SaveStatusAsCurrent(ack->szModule, (int)ack->lParam); +#ifdef _DEBUG + log2file("ProcessProtoAck(): Set %s (%d) status for %s.", StatusModeToDbSetting((int)ack->lParam, ""), (int)ack->lParam, (char *)ack->szModule); +#endif + + return 0; +} + +int SetStartupStatus(int i) +{ + int flags; + char szSetting[80]; + TCHAR *fmsg = NULL, *msg = NULL; + int iStatus = GetStartupStatus(accounts->pa[i]->szModuleName); + + if (iStatus == ID_STATUS_OFFLINE) + return -1; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) || + !(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + { + CallProtoService(accounts->pa[i]->szModuleName, PS_SETSTATUS, (WPARAM)iStatus, 0); + return -1; + } + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sFlags", accounts->pa[i]->szModuleName); + flags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", szSetting, PROTO_DEFAULT); + if (flags & PROTO_NO_MSG || flags & PROTO_THIS_MSG) + { + if (HasProtoStaticStatusMsg(accounts->pa[i]->szModuleName, ID_STATUS_OFFLINE, iStatus)) + return 0; + } + else if (flags & PROTO_NOCHANGE) + { + DBVARIANT dbv; + mir_snprintf(szSetting, SIZEOF(szSetting), "FCur%sMsg", accounts->pa[i]->szModuleName); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + fmsg = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + //else + // fmsg = mir_tstrdup(_T("")); + } + else + fmsg = GetAwayMessageFormat(iStatus, accounts->pa[i]->szModuleName); + +#ifdef _DEBUG + log2file("SetStartupStatus(): Set %s status and \"" TCHAR_STR_PARAM "\" status message for %s.", StatusModeToDbSetting(iStatus, ""), fmsg, accounts->pa[i]->szModuleName); +#endif + + if (fmsg) + msg = InsertVarsIntoMsg(fmsg, accounts->pa[i]->szModuleName, iStatus, NULL); + + SaveMessageToDB(accounts->pa[i]->szModuleName, fmsg, TRUE); + SaveMessageToDB(accounts->pa[i]->szModuleName, msg, FALSE); + + if (fmsg) + mir_free(fmsg); + + Proto_SetStatus(accounts->pa[i]->szModuleName, ID_STATUS_OFFLINE, iStatus, msg /*? msg : _T("")*/); + mir_free(msg); + + return 0; +} + +VOID CALLBACK SetStartupStatusGlobal(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + int prev_status_mode = -1, status_mode, temp_status_mode = ID_STATUS_OFFLINE, i; + BOOL globalstatus = TRUE; + + KillTimer(hwnd, idEvent); + + // is global status mode going to be set? + for (i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + status_mode = GetStartupStatus(accounts->pa[i]->szModuleName); + + if (status_mode != ID_STATUS_OFFLINE) + temp_status_mode = status_mode; + + if (status_mode != prev_status_mode && prev_status_mode != -1) + { + globalstatus = FALSE; + break; + } + + prev_status_mode = status_mode; + } + + // popup status msg dialog at startup? + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "StartupPopupDlg", 1) && accounts->statusMsgFlags) + { + if (globalstatus) + { + ChangeStatusMessage((WPARAM)status_mode, (LPARAM)"SimpleStatusMsgGlobalStartupStatus"); + } + else + { + // pseudo-currentDesiredStatusMode ;-) + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "StartupStatus", (WORD)temp_status_mode); + ChangeStatusMessage((WPARAM)ID_STATUS_CURRENT, (LPARAM)"SimpleStatusMsgGlobalStartupStatus"); + } + return; + } + + for (i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + +// if (DBGetContactSettingByte(NULL, accounts->pa[i]->szModuleName, "LockMainStatus", 0)) +// continue; + + SetStartupStatus(i); + } +} + +VOID CALLBACK SetStartupStatusProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + BOOL found = FALSE; + int i; + + for (i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + if (g_uSetStatusTimer[i] == idEvent) + { + KillTimer(NULL, g_uSetStatusTimer[i]); + found = TRUE; + break; + } + } + + if (!found) + { + KillTimer(hwnd, idEvent); + return; + } + + SetStartupStatus(i); +} + +VOID CALLBACK UpdateMsgTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + MIRANDA_IDLE_INFO mii = {0}; + mii.cbSize = sizeof(mii); + CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii); + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "NoUpdateOnIdle", 1) && mii.idleType) + return; + + if (!hwndSAMsgDialog) + { + char szBuffer[64]; + DBVARIANT dbv; + TCHAR *tszMsg; + int iCurrentStatus; + + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + iCurrentStatus = CallProtoService(accounts->pa[i]->szModuleName, PS_GETSTATUS, 0, 0); + if (iCurrentStatus < ID_STATUS_ONLINE) + continue; + + mir_snprintf(szBuffer, SIZEOF(szBuffer), "FCur%sMsg", accounts->pa[i]->szModuleName); + if (DBGetContactSettingTString(NULL, "SimpleStatusMsg", szBuffer, &dbv)) + continue; + + tszMsg = InsertVarsIntoMsg(dbv.ptszVal, accounts->pa[i]->szModuleName, iCurrentStatus, NULL); + DBFreeVariant(&dbv); + + mir_snprintf(szBuffer, SIZEOF(szBuffer), "Cur%sMsg", accounts->pa[i]->szModuleName); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szBuffer, &dbv)) + { + if (tszMsg && dbv.ptszVal && !lstrcmp(tszMsg, dbv.ptszVal) || !tszMsg && !dbv.ptszVal) + { + DBFreeVariant(&dbv); + mir_free(tszMsg); + continue; + } + DBFreeVariant(&dbv); + } + + if (tszMsg && lstrlen(tszMsg)) + { +#ifdef _DEBUG + log2file("UpdateMsgTimerProc(): Set %s status and \"" TCHAR_STR_PARAM "\" status message for %s.", StatusModeToDbSetting(iCurrentStatus, ""), tszMsg, accounts->pa[i]->szModuleName); +#endif + Proto_SetStatus(accounts->pa[i]->szModuleName, iCurrentStatus, iCurrentStatus, tszMsg); + SaveMessageToDB(accounts->pa[i]->szModuleName, tszMsg, FALSE); + } + mir_free(tszMsg); + } + } +} + +static int AddTopToolbarButton(WPARAM wParam, LPARAM lParam) +{ + TTBButton ttbb = {0}; + ttbb.cbSize = sizeof(ttbb); + ttbb.hIconHandleUp = GetIconHandle(IDI_CSMSG); + ttbb.pszService = MS_SIMPLESTATUSMSG_SHOWDIALOGINT; + ttbb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP; + ttbb.name = ttbb.pszTooltipUp = LPGEN("Change Status Message"); + hTTBButton = TopToolbar_AddButton(&ttbb); + + ReleaseIconEx("csmsg"); + return 0; +} + +void RegisterHotkey(void) +{ + HOTKEYDESC hkd = {0}; + + hkd.cbSize = sizeof(hkd); + hkd.dwFlags = HKD_TCHAR; + hkd.pszName = "SimpleStatusMsg_OpenDialog"; + hkd.ptszDescription = _T("Open Status Message Dialog"); + hkd.ptszSection = _T("Status Message"); + hkd.pszService = MS_SIMPLESTATUSMSG_SHOWDIALOGINT; + hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, VK_OEM_3); + Hotkey_Register(&hkd); +} + +static int ChangeStatusMsgPrebuild(WPARAM wParam, LPARAM lParam) +{ +#ifdef _DEBUG + log2file("ChangeStatusMsgPrebuild()"); +#endif + PROTOACCOUNT **pa; + int iStatusMenuItemCount = 0, count, i; + DWORD iStatusMsgFlags = 0; + + ProtoEnumAccounts(&count, &pa); + hProtoStatusMenuItem = (HANDLE *)mir_realloc(hProtoStatusMenuItem, sizeof(HANDLE) * count); + for (i = 0; i < count; ++i) + { + if (!IsAccountEnabled(pa[i])) + continue; + + if (CallProtoService(pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) + iStatusMsgFlags |= CallProtoService(pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3,0); + + if (!pa[i]->bIsVisible) + continue; + + iStatusMenuItemCount++; + } + + if (!iStatusMsgFlags || !iStatusMenuItemCount) + return 0; + + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(mi); + mi.flags = CMIF_ICONFROMICOLIB | CMIF_TCHAR; + if (!DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowStatusMenuItem", 1)) + mi.flags |= CMIF_HIDDEN; + mi.icolibItem = GetIconHandle(IDI_CSMSG); + mi.pszService = MS_SIMPLESTATUSMSG_SHOWDIALOGINT; + mi.ptszName = LPGENT("Status Message..."); + mi.position = 2000200000; + Menu_AddStatusMenuItem(&mi); + + mi.popupPosition = 500084000; + mi.position = 2000040000; + + for (i = 0; i < count; ++i) + { + char szSetting[80]; + TCHAR szBuffer[256]; + int iProtoFlags; + + if (!IsAccountEnabled(pa[i])) + continue; + + if (!CallProtoService(pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + if (!pa[i]->bIsVisible) + continue; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sFlags", pa[i]->szModuleName); + iProtoFlags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", szSetting, PROTO_DEFAULT); + if (iProtoFlags & PROTO_NO_MSG || iProtoFlags & PROTO_THIS_MSG) + continue; + + if (DBGetContactSettingByte(NULL, pa[i]->szModuleName, "LockMainStatus", 0) && + CallService(MS_SYSTEM_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(0, 9, 0, 10)) + { + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s (locked)"), pa[i]->tszAccountName); + mi.ptszPopupName = szBuffer; + } + else mi.ptszPopupName = pa[i]->tszAccountName; + hProtoStatusMenuItem[i] = Menu_AddStatusMenuItem(&mi); + } + + return 0; +} + +static int OnIdleChanged(WPARAM, LPARAM lParam) +{ +#ifdef _DEBUG + log2file("OnIdleChanged()"); +#endif + if (!(lParam & IDF_ISIDLE)) + g_iIdleTime = -1; + + MIRANDA_IDLE_INFO mii = {0}; + mii.cbSize = sizeof(mii); + CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii); + if (mii.aaStatus == 0) + { +#ifdef _DEBUG + log2file("OnIdleChanged(): AutoAway disabled"); +#endif + return 0; + } + + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (DBGetContactSettingByte(NULL, accounts->pa[i]->szModuleName, "LockMainStatus", 0)) + continue; + + int iStatusBits = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + int iStatus = mii.aaStatus; + if (!(iStatusBits & Proto_Status2Flag(iStatus))) + { + if (iStatusBits & Proto_Status2Flag(ID_STATUS_AWAY)) + iStatus = ID_STATUS_AWAY; + else + continue; + } + + int iCurrentStatus = CallProtoService(accounts->pa[i]->szModuleName, PS_GETSTATUS, 0, 0); + if (iCurrentStatus < ID_STATUS_ONLINE || iCurrentStatus == ID_STATUS_INVISIBLE) + continue; + + if ((lParam & IDF_ISIDLE && (DBGetContactSettingByte(NULL, "AutoAway", accounts->pa[i]->szModuleName, 0) || + iCurrentStatus == ID_STATUS_ONLINE || iCurrentStatus == ID_STATUS_FREECHAT)) || + (!(lParam & IDF_ISIDLE) && !mii.aaLock)) + { + if (!(lParam & IDF_ISIDLE)) + iStatus = ID_STATUS_ONLINE; + TCHAR *tszMsg = GetAwayMessage(iStatus, accounts->pa[i]->szModuleName, FALSE, NULL); + TCHAR *tszVarsMsg = InsertVarsIntoMsg(tszMsg, accounts->pa[i]->szModuleName, iStatus, NULL); + SaveMessageToDB(accounts->pa[i]->szModuleName, tszMsg, TRUE); + SaveMessageToDB(accounts->pa[i]->szModuleName, tszVarsMsg, FALSE); + mir_free(tszMsg); + mir_free(tszVarsMsg); + } + } + + return 0; +} + +static int CSStatusChange(WPARAM wParam, LPARAM lParam) +{ + PROTOCOLSETTINGEX** ps = *(PROTOCOLSETTINGEX***)wParam; + int status_mode, CSProtoCount; + char szSetting[80]; + TCHAR *msg = NULL; + + if (ps == NULL) return -1; + + CSProtoCount = CallService(MS_CS_GETPROTOCOUNT, 0, 0); + for (int i = 0; i < CSProtoCount; ++i) + { + if (ps[i]->szName == NULL || !*ps[i]->szName) continue; + if (ps[i]->status == ID_STATUS_IDLE) + status_mode = ps[i]->lastStatus; + else if (ps[i]->status == ID_STATUS_CURRENT) + status_mode = CallProtoService(ps[i]->szName, PS_GETSTATUS, 0, 0); + else + status_mode = ps[i]->status; + + SaveStatusAsCurrent(ps[i]->szName, status_mode); +#ifdef _DEBUG + log2file("CSStatusChange(): Set %s status for %s.", StatusModeToDbSetting(status_mode, ""), ps[i]->szName); +#endif + + // TODO SaveMessageToDB also when NULL? + if (ps[i]->szMsg) + { + int max_hist_msgs, j; + DBVARIANT dbv; + char buff[80]; + BOOL found = FALSE; + + wchar_t *szMsgW = mir_t2u(ps[i]->szMsg); + + +#ifdef _DEBUG + log2file("CSStatusChange(): Set \"%s\" status message for %s.", ps[i]->szMsg, ps[i]->szName); +#endif + max_hist_msgs = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "MaxHist", 10); + for (j = 1; j <= max_hist_msgs; j++) + { + mir_snprintf(buff, SIZEOF(buff), "SMsg%d", j); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", buff, &dbv)) + { + + if (!lstrcmp(dbv.ptszVal, szMsgW)) + + { + found = TRUE; + mir_snprintf(szSetting, SIZEOF(szSetting), "Last%sMsg", ps[i]->szName); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", szSetting, buff); + DBFreeVariant(&dbv); + break; + } + } + } + + if (!found) + { + mir_snprintf(buff, SIZEOF(buff), "FCur%sMsg", ps[i]->szName); + mir_snprintf(szSetting, SIZEOF(szSetting), "Last%sMsg", ps[i]->szName); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", szSetting, buff); + } + + mir_snprintf(szSetting, SIZEOF(szSetting), "%sMsg", ps[i]->szName); + + DBWriteContactSettingWString(NULL, "SRAway", StatusModeToDbSetting(status_mode, szSetting), szMsgW); + msg = InsertVarsIntoMsg(szMsgW, ps[i]->szName, status_mode, NULL); + SaveMessageToDB(ps[i]->szName, szMsgW, TRUE); + mir_free(szMsgW); + + SaveMessageToDB(ps[i]->szName, msg, FALSE); + mir_free(msg); + } + } + + return 0; +} + +static TCHAR *ParseWinampSong(ARGUMENTSINFO *ai) +{ + TCHAR *ptszWinampTitle; + + if (ai->argc != 1) + return NULL; + + ai->flags |= AIF_DONTPARSE; + ptszWinampTitle = GetWinampSong(); + + if (ptszWinampTitle != NULL) + { + mir_free(g_ptszWinampSong); + g_ptszWinampSong = mir_tstrdup(ptszWinampTitle); + } + else if (g_ptszWinampSong && lstrcmp(g_ptszWinampSong, _T("SimpleStatusMsg")) && DBGetContactSettingByte(NULL, "SimpleStatusMsg", "AmpLeaveTitle", 1)) + ptszWinampTitle = mir_tstrdup(g_ptszWinampSong); + + return ptszWinampTitle; +} + +static TCHAR *ParseDate(ARGUMENTSINFO *ai) +{ + TCHAR szStr[128] = {0}; + + if (ai->argc != 1) + return NULL; + + ai->flags |= AIF_DONTPARSE; + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, szStr, SIZEOF(szStr)); + + return mir_tstrdup(szStr); +} + +int ICQMsgTypeToStatus(int iMsgType) +{ + switch (iMsgType) + { + case MTYPE_AUTOONLINE: return ID_STATUS_ONLINE; + case MTYPE_AUTOAWAY: return ID_STATUS_AWAY; + case MTYPE_AUTOBUSY: return ID_STATUS_OCCUPIED; + case MTYPE_AUTONA: return ID_STATUS_NA; + case MTYPE_AUTODND: return ID_STATUS_DND; + case MTYPE_AUTOFFC: return ID_STATUS_FREECHAT; + default: return ID_STATUS_OFFLINE; + } +} + +static int OnICQStatusMsgRequest(WPARAM wParam, LPARAM lParam, LPARAM lMirParam) +{ +#ifdef _DEBUG + log2file("OnICQStatusMsgRequest(): UIN: %d on %s", (int)lParam, (char *)lMirParam); +#endif + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "NoUpdateOnICQReq", 1)) + return 0; + + HANDLE hContact; + char *szProto; + BOOL bContactFound = FALSE; + + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL && !strcmp(szProto, (char *)lMirParam) && DBGetContactSettingDword(hContact, szProto, "UIN", 0) == (DWORD)lParam) + { + bContactFound = TRUE; + break; + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + if (!bContactFound) + return 0; + + int iStatus = ICQMsgTypeToStatus(wParam); + TCHAR *tszMsg = GetAwayMessage(iStatus, szProto, TRUE, hContact); + Proto_SetAwayMsgT(szProto, iStatus, tszMsg); + mir_free(tszMsg); + + return 0; +} + +static int OnAccListChanged(WPARAM wParam, LPARAM lParam) +{ +#ifdef _DEBUG + log2file("OnAccListChanged()"); +#endif + accounts->statusFlags = 0; + accounts->statusCount = 0; + accounts->statusMsgFlags = 0; + accounts->statusMsgCount = 0; + UnhookProtoEvents(); + + ProtoEnumAccounts(&accounts->count, &accounts->pa); + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!strcmp(accounts->pa[i]->szProtoName, "ICQ")) + HookProtoEvent(accounts->pa[i]->szModuleName, ME_ICQ_STATUSMSGREQ, OnICQStatusMsgRequest); + + accounts->statusFlags |= (CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) &~ CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0)); + + if (CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) &~ CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0)) + accounts->statusCount++; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + accounts->statusMsgFlags |= CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3,0); + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + accounts->statusMsgCount++; + } + + return 0; +} + +static int OnModulesLoaded(WPARAM wParam, LPARAM lParam) +{ +#ifdef _DEBUG + log2file("### Session started ###"); +#endif + // known modules list + if (ServiceExists("DBEditorpp/RegisterSingleModule")) + CallService("DBEditorpp/RegisterSingleModule", (WPARAM)"SimpleStatusMsg", 0); + + IconsInit(); + OnAccListChanged(0, 0); + + LoadAwayMsgModule(); + + HookEventEx(ME_TTB_MODULELOADED, AddTopToolbarButton); + + RegisterHotkey(); + + HookEventEx(ME_OPT_INITIALISE, InitOptions); + h_statusmodechange = HookEvent(ME_CLIST_STATUSMODECHANGE, ChangeStatusMessage); + HookEventEx(ME_PROTO_ACK, ProcessProtoAck); + HookEventEx(ME_IDLE_CHANGED, OnIdleChanged); + + HookEventEx(ME_CLIST_PREBUILDSTATUSMENU, ChangeStatusMsgPrebuild); + ChangeStatusMsgPrebuild(0, 0); + + if (ServiceExists(MS_VARS_REGISTERTOKEN)) + { + TOKENREGISTER tr = {0}; + tr.cbSize = sizeof(TOKENREGISTER); + tr.memType = TR_MEM_MIRANDA; + tr.flags = TRF_FREEMEM | TRF_FIELD | TRF_TCHAR | TRF_PARSEFUNC; + tr.tszTokenString = _T("winampsong"); + tr.parseFunctionT = ParseWinampSong; + tr.szHelpText = LPGEN("External Applications\tretrieves song name of the song currently playing in Winamp (Simple Status Message compatible)"); + CallService(MS_VARS_REGISTERTOKEN, 0, (LPARAM)&tr); + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ExclDateToken", 0) != 0) + { + tr.tszTokenString = _T("date"); + tr.parseFunctionT = ParseDate; + tr.szHelpText = LPGEN("Miranda Related\tget the date (Simple Status Message compatible)"); + CallService(MS_VARS_REGISTERTOKEN, 0, (LPARAM)&tr); + } + } + +/* if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "AmpLeaveTitle", 1))*/ { + DBVARIANT dbv; + + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", "AmpLastTitle", &dbv)) + { + g_ptszWinampSong = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + g_ptszWinampSong = mir_tstrdup(_T("SimpleStatusMsg")); + } +/* else + g_ptszWinampSong = mir_tstrdup(_T("SimpleStatusMsg"));*/ + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "UpdateMsgOn", 1)) + g_uUpdateMsgTimer = SetTimer(NULL, 0, DBGetContactSettingWord(NULL, "SimpleStatusMsg", "UpdateMsgInt", 10) * 1000, (TIMERPROC)UpdateMsgTimerProc); + + if (ServiceExists(MS_CS_SETSTATUSEX)) + HookEventEx(ME_CS_STATUSCHANGEEX, CSStatusChange); + + if (accounts->statusCount == 0) + return 0; + + if (!ServiceExists(MS_SS_GETPROFILECOUNT)) + { + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "GlobalStatusDelay", 1)) + { + SetTimer(NULL, 0, DBGetContactSettingWord(NULL, "SimpleStatusMsg", "SetStatusDelay", 300), (TIMERPROC)SetStartupStatusGlobal); + } + else + { + char szSetting[80]; + + g_uSetStatusTimer = (UINT_PTR*)mir_alloc(sizeof(UINT_PTR) * accounts->count); + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) &~ CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Set%sStatusDelay", accounts->pa[i]->szModuleName); + g_uSetStatusTimer[i] = SetTimer(NULL, 0, DBGetContactSettingWord(NULL, "SimpleStatusMsg", szSetting, 300), (TIMERPROC)SetStartupStatusProc); + } + } + } + + return 0; +} + +static int OnOkToExit(WPARAM wParam, LPARAM lParam) +{ + if (accounts->statusCount) + { + char szSetting[80]; + + for (int i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) &~ CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Last%sStatus", accounts->pa[i]->szModuleName); + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", szSetting, (WORD)CallProtoService(accounts->pa[i]->szModuleName, PS_GETSTATUS, 0, 0)); + } + + if (g_ptszWinampSong && lstrcmp(g_ptszWinampSong, _T("SimpleStatusMsg")) /*&& DBGetContactSettingByte(NULL, "SimpleStatusMsg", "AmpLeaveTitle", 1)*/) + DBWriteMessage("AmpLastTitle", g_ptszWinampSong); + } + + return 0; +} + +static int OnPreShutdown(WPARAM wParam, LPARAM lParam) +{ + if (!accounts->statusMsgFlags) + return 0; + + AwayMsgPreShutdown(); + if (hwndSAMsgDialog) DestroyWindow(hwndSAMsgDialog); + if (hProtoStatusMenuItem) mir_free(hProtoStatusMenuItem); + if (g_uSetStatusTimer) mir_free(g_uSetStatusTimer); + if (g_ptszWinampSong) mir_free(g_ptszWinampSong); + if (g_uUpdateMsgTimer) KillTimer(NULL, g_uUpdateMsgTimer); + + return 0; +} + +static INT_PTR IsSARunning(WPARAM wParam, LPARAM lParam) +{ + return 1; +} + +//remember to mir_free() the return value +static INT_PTR sttGetAwayMessageT(WPARAM wParam, LPARAM lParam) +{ + return (INT_PTR)GetAwayMessage((int)wParam, (char*)lParam, TRUE, NULL); +} + + +static INT_PTR sttGetAwayMessage(WPARAM wParam, LPARAM lParam) +{ + TCHAR* msg = GetAwayMessage((int)wParam, (char*)lParam, TRUE, NULL); + char* res = mir_t2a(msg); + mir_free(msg); + return (INT_PTR)res; +} + + +extern "C" int __declspec(dllexport) Load(void) +{ + + mir_getLP(&pluginInfo); + hwndSAMsgDialog = NULL; + accounts = (PROTOACCOUNTS *)mir_alloc(sizeof(PROTOACCOUNTS)); + + DBWriteContactSettingWord(NULL, "CList", "Status", (WORD)ID_STATUS_OFFLINE); + HookEventEx(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + HookEventEx(ME_PROTO_ACCLISTCHANGED, OnAccListChanged); + + + CreateServiceFunctionEx(MS_AWAYMSG_GETSTATUSMSG, sttGetAwayMessage); + CreateServiceFunctionEx(MS_AWAYMSG_GETSTATUSMSGW, sttGetAwayMessageT); + + CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_SETSTATUS, SetStatusModeFromExtern); + CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_SHOWDIALOG, ShowStatusMessageDialog); + CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_CHANGESTATUSMSG, ChangeStatusMsg); + CreateServiceFunctionEx(MS_SIMPLESTATUSMSG_SHOWDIALOGINT, ShowStatusMessageDialogInternal); // internal use ONLY + + // Deprecated SimpleAway services + CreateServiceFunctionEx(MS_SA_ISSARUNNING, IsSARunning); + CreateServiceFunctionEx(MS_SA_CHANGESTATUSMSG, ChangeStatusMsg); + CreateServiceFunctionEx(MS_SA_TTCHANGESTATUSMSG, ShowStatusMessageDialogInternal); + CreateServiceFunctionEx(MS_SA_SHOWSTATUSMSGDIALOG, ShowStatusMessageDialog); + CreateServiceFunctionEx(MS_SA_SETSTATUSMODE, SetStatusModeFromExtern); + + CreateServiceFunctionEx(MS_SA_SETOFFLINESTATUS, SetOfflineStatus); + CreateServiceFunctionEx(MS_SA_SETONLINESTATUS, SetOnlineStatus); + CreateServiceFunctionEx(MS_SA_SETAWAYSTATUS, SetAwayStatus); + CreateServiceFunctionEx(MS_SA_SETDNDSTATUS, SetDNDStatus); + CreateServiceFunctionEx(MS_SA_SETNASTATUS, SetNAStatus); + CreateServiceFunctionEx(MS_SA_SETOCCUPIEDSTATUS, SetOccupiedStatus); + CreateServiceFunctionEx(MS_SA_SETFREECHATSTATUS, SetFreeChatStatus); + CreateServiceFunctionEx(MS_SA_SETINVISIBLESTATUS, SetInvisibleStatus); + CreateServiceFunctionEx(MS_SA_SETONTHEPHONESTATUS, SetOnThePhoneStatus); + CreateServiceFunctionEx(MS_SA_SETOUTTOLUNCHSTATUS, SetOutToLunchStatus); + + HookEventEx(ME_SYSTEM_OKTOEXIT, OnOkToExit); + HookEventEx(ME_SYSTEM_PRESHUTDOWN, OnPreShutdown); + + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + UnhookEvents(); + UnhookEvent(h_statusmodechange); + UnhookProtoEvents(); + DestroyServiceFunctionsEx(); + mir_free(accounts); + +#ifdef _DEBUG + log2file("### Session ended ###"); +#endif + + return 0; +} diff --git a/plugins/SimpleStatusMsg/src/msgbox.cpp b/plugins/SimpleStatusMsg/src/msgbox.cpp new file mode 100644 index 0000000000..924307ea04 --- /dev/null +++ b/plugins/SimpleStatusMsg/src/msgbox.cpp @@ -0,0 +1,1798 @@ +/* + +Simple Status Message plugin for Miranda IM +Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "commonheaders.h" +#include "simplestatusmsg.h" + +#define I_ICON_DEL 0 +#define I_ICON_HIST 1 +#define I_ICON_MSG 2 +#define I_ICON_ADD 3 +#define I_ICON_CLEAR 4 + +struct MsgBoxData +{ + char *m_szProto; + int m_iStatus; + int m_iInitialStatus; + int m_iStatusModes; + int m_iStatusMsgModes; + HWND status_cbex; + HWND recent_cbex; + HICON icon[5]; + HIMAGELIST status_icons; + HIMAGELIST other_icons; + int m_iCountdown; + int curr_sel_msg; + int m_iDlgFlags; + int max_hist_msgs; + int num_def_msgs; + BOOL m_bPredefChanged; + BOOL m_bIsMsgHistory; + BOOL m_bOnStartup; +}; + +typedef struct +{ + clock_t ctLastDblClk; + UINT uClocksPerDblClk; +} +MsgEditCtrl; + +HIMAGELIST AddOtherIconsToImageList(struct MsgBoxData *data) +{ + HIMAGELIST himlIcons = ImageList_Create(16, 16, (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16) | ILC_MASK, 4, 0); + + for (int i = 0; i < 5; ++i) + ImageList_AddIcon(himlIcons, data->icon[i]); + + return himlIcons; +} + +int statusicon_nr[9]; + +HIMAGELIST AddStatusIconsToImageList(const char *szProto, int status_flags) +{ + int num_icons = 1; + int i; + + for (i = 0; i < 9; ++i) + if (Proto_Status2Flag(ID_STATUS_ONLINE + i) & status_flags) num_icons++; + + HIMAGELIST himlIcons = ImageList_Create(16, 16, (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16) | ILC_MASK, num_icons, 0); + HICON hicon = LoadSkinnedProtoIcon(szProto, ID_STATUS_OFFLINE); + ImageList_AddIcon(himlIcons, hicon); + CallService(MS_SKIN2_RELEASEICON, (LPARAM)hicon, (WPARAM)0); + statusicon_nr[0] = 0; + + int j = 1; + for (i = 0; i < 9; ++i) + { + if (Proto_Status2Flag(ID_STATUS_ONLINE + i) & status_flags) + { + hicon = LoadSkinnedProtoIcon(szProto, ID_STATUS_ONLINE + i); + ImageList_AddIcon(himlIcons, hicon); + CallService(MS_SKIN2_RELEASEICON, (LPARAM)hicon, (WPARAM)0); + statusicon_nr[i + 1] = j; + j++; + } + else + statusicon_nr[i + 1] = 0; + } + + return himlIcons; +} + +HWND WINAPI CreateStatusComboBoxEx(HWND hwndDlg, struct MsgBoxData *data) +{ + int j = 0, cur_sel = 0; + TCHAR *status_desc; + + if (!(data->m_iDlgFlags & DLG_SHOW_STATUS)) + return NULL; + + HWND handle = CreateWindowEx(0, WC_COMBOBOXEX, NULL, + WS_TABSTOP | CBS_NOINTEGRALHEIGHT | WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST, + 0, 0, 0, 240, hwndDlg, NULL, g_hInst, NULL); + + COMBOBOXEXITEM cbei = {0}; + if (!(data->m_iDlgFlags & DLG_SHOW_STATUS_ICONS)) + cbei.mask = CBEIF_LPARAM | CBEIF_TEXT; + else + cbei.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE; + + if (data->m_bOnStartup) + status_desc = (TCHAR*)TranslateT(""); + else + status_desc = (TCHAR*)TranslateT(""); + cbei.iItem = j; + cbei.pszText = (LPTSTR)status_desc; + cbei.cchTextMax = sizeof(status_desc); + + if (data->m_szProto || data->m_iStatus == ID_STATUS_CURRENT) + { + if (data->m_bOnStartup) + j = GetStartupStatus(data->m_szProto) - ID_STATUS_OFFLINE; + else + j = GetCurrentStatus(data->m_szProto) - ID_STATUS_OFFLINE; + } + else + j = data->m_iStatus - ID_STATUS_OFFLINE; + + if (j < 0 || j > 9) j = 0; // valid status modes only + + if (data->m_iDlgFlags & DLG_SHOW_STATUS_ICONS) + { + cbei.iImage = statusicon_nr[j]; + cbei.iSelectedImage = statusicon_nr[j]; + } + j = 0; + cbei.lParam = (LPARAM)ID_STATUS_CURRENT; + + if (ID_STATUS_CURRENT == data->m_iInitialStatus) + cur_sel = j; + + SendMessage(handle, CBEM_INSERTITEM, 0, (LPARAM)&cbei); + j++; + + for (int i = 0; i < 10; ++i) + { + if ((Proto_Status2Flag(ID_STATUS_OFFLINE + i) & data->m_iStatusModes) || i == 0) + { + status_desc = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, ID_STATUS_OFFLINE + i, GSMDF_TCHAR); + cbei.iItem = j; + cbei.pszText = (LPTSTR)status_desc; + cbei.cchTextMax = sizeof(status_desc); + if (data->m_iDlgFlags & DLG_SHOW_STATUS_ICONS) + { + cbei.iImage = j - 1; + cbei.iSelectedImage = j - 1; + } + cbei.lParam = (LPARAM)ID_STATUS_OFFLINE + i; + + if (ID_STATUS_OFFLINE + i == data->m_iInitialStatus) + cur_sel = j; + + if (SendMessage(handle, CBEM_INSERTITEM, 0, (LPARAM)&cbei) == -1) + break; + j++; + } + } + + if (!data->m_szProto && (data->m_iDlgFlags & DLG_SHOW_STATUS_PROFILES) && ServiceExists(MS_SS_GETPROFILECOUNT)) + { + int defaultProfile; + int profileCount = (int)CallService(MS_SS_GETPROFILECOUNT, (WPARAM)&defaultProfile, 0); + char buff1[128]; + + for (int i = 0; i < profileCount; ++i) + { + CallService(MS_SS_GETPROFILENAME, (WPARAM)i, (LPARAM)buff1); + + status_desc = mir_a2u(buff1); + + cbei.iItem = j; + cbei.pszText = (LPTSTR)status_desc; + cbei.cchTextMax = sizeof(status_desc); + if (data->m_iDlgFlags & DLG_SHOW_STATUS_ICONS) + { + int k = GetCurrentStatus(NULL) - ID_STATUS_OFFLINE; + if (k < 0 || k > 9) k = 0; // valid status modes only + cbei.iImage = statusicon_nr[k]; + cbei.iSelectedImage = statusicon_nr[k]; + } + cbei.lParam = (LPARAM)40083+i; + + mir_free(status_desc); + + if (SendMessage(handle, CBEM_INSERTITEM, 0, (LPARAM)&cbei) == -1) + break; + j++; + } + } + + if (!(data->m_iDlgFlags & DLG_SHOW_STATUS_ICONS)) + SendMessage(handle, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)16); + else + { + SendMessage(handle, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)18); + SendMessage(handle, CBEM_SETIMAGELIST, 0, (LPARAM)data->status_icons); + } + SetWindowPos(handle, NULL, 11, 11, 112, 20, SWP_NOACTIVATE); + SendMessage(handle, CB_SETCURSEL, (WPARAM)cur_sel, 0); + SendMessage(handle, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)16); + + return handle; +} + +#define HISTORY_MSG 1 +#define CLEAR_HISTORY 2 +#define PREDEFINED_MSG 3 +#define ADD_MSG 4 +#define DELETE_SELECTED 5 +#define DEFAULT_MSG 6 + +HWND WINAPI CreateRecentComboBoxEx(HWND hwndDlg, struct MsgBoxData *data) +{ + int i, j; + char buff[16]; + BOOL found = FALSE; + DBVARIANT dbv; + TCHAR text[128]; + + HWND handle = CreateWindowEx(0, WC_COMBOBOXEX, NULL, + WS_TABSTOP | CBS_NOINTEGRALHEIGHT | WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST, + 0, 0, 0, 300, hwndDlg, NULL, g_hInst, NULL); + + COMBOBOXEXITEM cbei = {0}; + if (!(data->m_iDlgFlags & DLG_SHOW_LIST_ICONS)) + cbei.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_INDENT; + else + cbei.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE; + + j = DBGetContactSettingWord(NULL, "SimpleStatusMsg", "LMMsg", 1); + + for (i = 1; i <= data->max_hist_msgs; ++i) + { + // history messages + if (j < 1) j = data->max_hist_msgs; + mir_snprintf(buff, SIZEOF(buff), "SMsg%d", j); + j--; + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", buff, &dbv)) + { + if (dbv.ptszVal != NULL && dbv.ptszVal != '\0') + { + found = TRUE; + cbei.iItem = -1; + cbei.pszText = (LPTSTR)dbv.ptszVal; + cbei.cchTextMax = sizeof(dbv.ptszVal); + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + cbei.iImage = I_ICON_HIST; + cbei.iSelectedImage = I_ICON_HIST; + } + else + cbei.iIndent = 0; + cbei.lParam = MAKELPARAM(HISTORY_MSG, j + 1); + + if (SendMessage(handle, CBEM_INSERTITEM, 0, (LPARAM)&cbei) == -1) + { + DBFreeVariant(&dbv); + break; + } + } + DBFreeVariant(&dbv); + } + } + + data->m_bIsMsgHistory = found; + + if ((data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + if (found) + { + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BCLEAR))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), TRUE); + } + else if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BCLEAR))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), FALSE); + } + else if (data->m_iDlgFlags & DLG_SHOW_BUTTONS_INLIST) + { + if (found) + { + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + mir_sntprintf(text, SIZEOF(text), TranslateT("Clear History")); + cbei.iImage = I_ICON_CLEAR; + cbei.iSelectedImage = I_ICON_CLEAR; + } + else + { + mir_sntprintf(text, SIZEOF(text), _T("## %s ##"), TranslateT("Clear History")); + cbei.iIndent = 1; + } + cbei.iItem = -1; + cbei.pszText = (LPTSTR)text; + cbei.cchTextMax = SIZEOF(text); + cbei.lParam = MAKELPARAM(CLEAR_HISTORY, 0); + SendMessage(handle, CBEM_INSERTITEM, 0, (LPARAM)&cbei); + } + + cbei.iItem = -1; + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + mir_sntprintf(text, SIZEOF(text), TranslateT("Add to Predefined")); + cbei.iImage = I_ICON_ADD; + cbei.iSelectedImage = I_ICON_ADD; + } + else + { + mir_sntprintf(text, SIZEOF(text), _T("## %s ##"), TranslateT("Add to Predefined")); + cbei.iIndent = 1; + } + cbei.pszText = (LPTSTR)text; + cbei.cchTextMax = SIZEOF(text); + cbei.lParam = MAKELPARAM(ADD_MSG, 0); + SendMessage(handle, CBEM_INSERTITEM, 0, (LPARAM)&cbei); + + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + mir_sntprintf(text, SIZEOF(text), TranslateT("Delete Selected")); + cbei.iImage = I_ICON_DEL; + cbei.iSelectedImage = I_ICON_DEL; + } + else + { + cbei.iIndent = 1; + mir_sntprintf(text, SIZEOF(text), _T("## %s ##"), TranslateT("Delete Selected")); + } + cbei.iItem = -1; + cbei.pszText = (LPTSTR)text; + cbei.cchTextMax = SIZEOF(text); + cbei.lParam = MAKELPARAM(DELETE_SELECTED, 0); + SendMessage(handle, CBEM_INSERTITEM, 0, (LPARAM)&cbei); + } + + if ((data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + if (data->num_def_msgs || found) + { + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), TRUE); + } + else if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + } + + for (i = 1; i <= data->num_def_msgs; ++i) + { + // predefined messages + mir_snprintf(buff, SIZEOF(buff), "DefMsg%d", i); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", buff, &dbv)) + { + if (dbv.ptszVal) + { + if (!lstrlen(dbv.ptszVal)) + { + DBFreeVariant(&dbv); + continue; + } + + cbei.iItem = -1; + cbei.pszText = (LPTSTR)dbv.ptszVal; + cbei.cchTextMax = sizeof(dbv.ptszVal); + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + cbei.iImage = I_ICON_MSG; + cbei.iSelectedImage = I_ICON_MSG; + } + else + cbei.iIndent = 0; + cbei.lParam = MAKELPARAM(PREDEFINED_MSG, i); + + if (SendMessage(handle,CBEM_INSERTITEM,0,(LPARAM)&cbei) == -1) + break; + } + DBFreeVariant(&dbv); + } + } + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "PutDefInList", 0)) + { + cbei.iItem = -1; + cbei.pszText = (LPTSTR)GetDefaultMessage(data->m_iStatus); + cbei.cchTextMax = sizeof(GetDefaultMessage(data->m_iStatus)); + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + cbei.iImage = I_ICON_MSG; + cbei.iSelectedImage = I_ICON_MSG; + } + else + cbei.iIndent = 0; + cbei.lParam = MAKELPARAM(DEFAULT_MSG, 0); + + SendMessage(handle,CBEM_INSERTITEM,0,(LPARAM)&cbei); + } + + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + SendMessage(handle, CBEM_SETIMAGELIST, 0, (LPARAM)data->other_icons); + if (!(data->m_iDlgFlags & DLG_SHOW_STATUS)) + { + SetWindowPos(handle, NULL, 11, 11, 290, 20, SWP_NOACTIVATE); + SendMessage(handle, CB_SETDROPPEDWIDTH, (WPARAM)290, 0); + } + else + { + SetWindowPos(handle, NULL, 127, 11, 174, 20, SWP_NOACTIVATE); + SendMessage(handle, CB_SETDROPPEDWIDTH, (WPARAM)250, 0); + } + SendMessage(handle, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)16); + SendMessage(handle, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)16); + + if (((data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) && !found && !data->num_def_msgs) + EnableWindow(handle, FALSE); + + if (((!(data->m_iDlgFlags & DLG_SHOW_BUTTONS)) && (!(data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) && (!(data->m_iDlgFlags & DLG_SHOW_BUTTONS_INLIST))) && !found && !data->num_def_msgs) + EnableWindow(handle, FALSE); + + return handle; +} + +VOID APIENTRY HandlePopupMenu(HWND hwnd, POINT pt, HWND edit_control) +{ + HMENU hmenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_EDITMENU)); + if (hmenu == NULL) + return; + + HMENU hmenuTrackPopup = GetSubMenu(hmenu, 0); + + TranslateMenu(hmenuTrackPopup); + + ClientToScreen(hwnd, (LPPOINT) &pt); + + LPDWORD sel_s = NULL, sel_e = NULL; + SendMessage(edit_control, EM_GETSEL, (WPARAM)&sel_s, (LPARAM)&sel_e); + if (sel_s == sel_e) + { + EnableMenuItem(hmenuTrackPopup, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(hmenuTrackPopup, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); + } + if (SendMessage(edit_control, WM_GETTEXTLENGTH, 0, 0) == 0) + EnableMenuItem(hmenuTrackPopup, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED); + + if (ServiceExists(MS_VARS_FORMATSTRING)) + DeleteMenu(hmenuTrackPopup, ID__VARIABLES, MF_BYCOMMAND); + else + DeleteMenu(hmenuTrackPopup, 8, MF_BYPOSITION); + + if (ServiceExists(MS_FORTUNEMSG_GETSTATUSMSG)) + DeleteMenu(hmenuTrackPopup, ID__FORTUNEAWAYMSG, MF_BYCOMMAND); + else + DeleteMenu(hmenuTrackPopup, 7, MF_BYPOSITION); + + int m_selection = TrackPopupMenu(hmenuTrackPopup, TPM_LEFTALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL); + switch (m_selection) + { + case IDM_COPY: + SendMessage(edit_control, WM_COPY, 0, 0); + break; + + case IDM_CUT: + SendMessage(edit_control, WM_CUT, 0, 0); + break; + + case IDM_PASTE: + SendMessage(edit_control, WM_PASTE, 0, 0); + break; + + case IDM_SELECTALL: + SendMessage(edit_control, EM_SETSEL, 0, -1); + break; + + case IDM_DELETE: + SendMessage(edit_control, WM_SETTEXT, 0, (LPARAM)""); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_EDIT1, EN_CHANGE), (LPARAM)edit_control); + break; + + case ID__FORTUNEAWAYMSG: + CallService(MS_UTILS_OPENURL,1,(LPARAM)"http://nightly.miranda.im/"); + break; + + case ID__VARIABLES: + + CallService(MS_UTILS_OPENURL,1,(LPARAM)"http://nightly.miranda.im/"); + + break; + + case ID__VARIABLES_MOREVARIABLES: + { + VARHELPINFO vhi = {0}; + vhi.cbSize = sizeof(vhi); + vhi.flags = VHF_FULLDLG | VHF_SETLASTSUBJECT; + vhi.hwndCtrl = edit_control; + vhi.szSubjectDesc = NULL; + vhi.szExtraTextDesc = NULL; + CallService(MS_VARS_SHOWHELPEX, (WPARAM)hwnd, (LPARAM)&vhi); + break; + } + + default: + if (!OpenClipboard(GetParent(hwnd))) break; + if (EmptyClipboard()) + { + TCHAR item_string[128]; + int len; + + GetMenuString(hmenu, m_selection, (LPTSTR)&item_string, 128, MF_BYCOMMAND); + len = lstrlen(item_string); + if (len) + { + LPTSTR lptstrCopy; + HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(TCHAR)); + if (hglbCopy == NULL) + { + CloseClipboard(); + break; + } + lptstrCopy = (LPTSTR)GlobalLock(hglbCopy); + memcpy(lptstrCopy, item_string, len * sizeof(TCHAR)); + lptstrCopy[len] = (TCHAR)0; + GlobalUnlock(hglbCopy); + + SetClipboardData(CF_UNICODETEXT, hglbCopy); + + } + } + CloseClipboard(); + SendMessage(edit_control, WM_PASTE, 0, 0); + break; + } + DestroyMenu(hmenu); +} + +static WNDPROC MainDlgProc; + +static LRESULT CALLBACK EditBoxSubProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_CONTEXTMENU: + { + POINT pt = {(LONG)LOWORD(lParam), (LONG)HIWORD(lParam)}; + RECT rc; + GetClientRect(hwndDlg, &rc); + + if (pt.x == -1 && pt.y == -1) + { + GetCursorPos(&pt); + if (!PtInRect(&rc, pt)) + { + pt.x = rc.left + (rc.right - rc.left) / 2; + pt.y = rc.top + (rc.bottom - rc.top) / 2; + } + } + else + ScreenToClient(hwndDlg, &pt); + + if (PtInRect(&rc, pt)) + HandlePopupMenu(hwndDlg, pt, GetDlgItem(GetParent(hwndDlg), IDC_EDIT1)); + + return 0; + } + + case WM_CHAR: + if (wParam=='\n' && GetKeyState(VK_CONTROL) & 0x8000) + { + PostMessage(GetParent(hwndDlg), WM_COMMAND, IDC_OK, 0); + return 0; + } + if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) // Ctrl + A + { + SendMessage(hwndDlg, EM_SETSEL, 0, -1); + return 0; + } + if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) // Ctrl + W + { + SendMessage(GetParent(hwndDlg), WM_COMMAND, IDC_CANCEL, 0); + return 0; + } + if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000) // Ctrl + Backspace + { + DWORD start, end; + TCHAR *text; + int textLen; + SendMessage(hwndDlg, EM_GETSEL, (WPARAM)&end, (LPARAM)(PDWORD)NULL); + SendMessage(hwndDlg, WM_KEYDOWN, VK_LEFT, 0); + SendMessage(hwndDlg, EM_GETSEL, (WPARAM)&start, (LPARAM)(PDWORD)NULL); + textLen = GetWindowTextLength(hwndDlg); + text = (TCHAR *)mir_alloc(sizeof(TCHAR) * (textLen + 1)); + GetWindowText(hwndDlg, text, textLen + 1); + MoveMemory(text + start, text + end, sizeof(TCHAR) * (textLen + 1 - end)); + SetWindowText(hwndDlg, text); + mir_free(text); + SendMessage(hwndDlg, EM_SETSEL, start, start); + SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwndDlg), EN_CHANGE), (LPARAM)hwndDlg); + return 0; + } + break; + + case WM_LBUTTONDBLCLK: + { + MsgEditCtrl* mec = (MsgEditCtrl*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if (mec != NULL) + { + mec->ctLastDblClk = clock(); + mec->uClocksPerDblClk = GetDoubleClickTime() * CLOCKS_PER_SEC / 1000; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)mec); + } + break; + } + + case WM_LBUTTONDOWN: + { + MsgEditCtrl* mec = (MsgEditCtrl*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if (mec != NULL && UINT(clock() - mec->ctLastDblClk) < mec->uClocksPerDblClk) + { + SendMessage(hwndDlg, EM_SETSEL, 0, -1); + return 0; + } + break; + } + + case WM_SETFOCUS: + { + MsgEditCtrl* mec = (MsgEditCtrl*)mir_calloc(sizeof(MsgEditCtrl)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)mec); + break; + } + + case WM_KILLFOCUS: + { + MsgEditCtrl* mec = (MsgEditCtrl*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + mir_free(mec); + mec = NULL; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)mec); + break; + } + } + + return CallWindowProc(MainDlgProc, hwndDlg, uMsg, wParam, lParam); +} + +int AddToPredefined(HWND hwndDlg, struct MsgBoxData *data) +{ + COMBOBOXEXITEM newitem = {0}; + int len = 0, num_items; + TCHAR msg[1024], text[1024]; + + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + len = GetDlgItemText(hwndDlg, IDC_EDIT1, msg, SIZEOF(msg)); + + if (!len) + return -1; + + num_items = SendMessage(data->recent_cbex, CB_GETCOUNT, 0, 0) - 1; + for (int i = 1; i <= data->num_def_msgs; i++, num_items--) + { + newitem.mask = CBEIF_LPARAM | CBEIF_TEXT; + newitem.iItem = num_items; + newitem.cchTextMax = SIZEOF(text); + newitem.pszText = text; + + SendMessage(data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&newitem); + if (LOWORD(newitem.lParam) == PREDEFINED_MSG && !lstrcmp(text, msg)) + return num_items; + } + + data->num_def_msgs++; + data->m_bPredefChanged = TRUE; + + newitem.iItem = -1; + newitem.pszText = (LPTSTR)msg; + newitem.cchTextMax = SIZEOF(msg); + if (data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + newitem.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE; + newitem.iImage = I_ICON_MSG; + newitem.iSelectedImage = I_ICON_MSG; + } + else + { + newitem.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_INDENT; + newitem.iIndent = 0; + } + newitem.lParam = MAKELPARAM(PREDEFINED_MSG, 0); + return SendMessage(data->recent_cbex, CBEM_INSERTITEM, 0, (LPARAM)&newitem); +} + +void ClearHistory(struct MsgBoxData *data, int cur_sel) +{ + COMBOBOXEXITEM histitem = {0}; + int i, num_items; + char text[16], buff2[80]; + + for (i = 1; i <= data->max_hist_msgs; i++) + { + mir_snprintf(text, SIZEOF(text), "SMsg%d", i); + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", text, _T("")); + } + DBWriteContactSettingString(NULL, "SimpleStatusMsg", "LastMsg", ""); + for (i = 0; i < accounts->count; i++) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(buff2, SIZEOF(buff2), "Last%sMsg", accounts->pa[i]->szModuleName); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", buff2, ""); + } + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "LMMsg", (WORD)data->max_hist_msgs); + SendMessage(data->recent_cbex, CB_SETCURSEL, -1, 0); + num_items = SendMessage(data->recent_cbex, CB_GETCOUNT, 0, 0); + if (num_items == CB_ERR) + return; + + if ((!(data->m_iDlgFlags & DLG_SHOW_BUTTONS)) && (!(data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT))) + SendMessage(data->recent_cbex, CBEM_DELETEITEM, (WPARAM)cur_sel, 0); + + for (i = num_items; i >= 0; i--) + { + histitem.mask = CBEIF_LPARAM; + histitem.iItem = i; + SendMessage(data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&histitem); + if (LOWORD(histitem.lParam) == HISTORY_MSG) + SendMessage(data->recent_cbex, CBEM_DELETEITEM, (WPARAM)i, 0); + } +} + +void DisplayCharsCount(struct MsgBoxData *dlg_data, HWND hwndDlg) +{ + TCHAR msg[1024]; + TCHAR status_text[128]; + int len, lines = 1; + + if (dlg_data->m_iCountdown != -2) + return; + + len = GetDlgItemText(hwndDlg, IDC_EDIT1, msg, SIZEOF(msg)); + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "RemoveCR", 0)) + { + int index, num_lines = SendMessage(GetDlgItem(hwndDlg, IDC_EDIT1), EM_GETLINECOUNT, 0, 0); + for (int i = 1; i < num_lines; ++i) + { + index = SendMessage(GetDlgItem(hwndDlg, IDC_EDIT1), EM_LINEINDEX, (WPARAM)i, 0); + if (msg[index - 1] == '\n') lines++; + } + } + mir_sntprintf(status_text, SIZEOF(status_text), TranslateT("OK (%d)"), len - (lines - 1)); + SendMessage(GetDlgItem(hwndDlg, IDC_OK), WM_SETTEXT, 0, (LPARAM)status_text); +} + +void SetEditControlText(struct MsgBoxData *data, HWND hwndDlg, int iStatus) +{ + int flags, fcursel = CB_ERR, num_start; + DBVARIANT dbv, dbv2; + char setting[80]; + + num_start = SendMessage(data->recent_cbex, CB_GETCOUNT, 0, 0); + num_start -= data->num_def_msgs + 1; + + mir_snprintf(setting, SIZEOF(setting), "%sFlags", data->m_szProto ? data->m_szProto : ""); + flags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", (char *)StatusModeToDbSetting(iStatus, setting), STATUS_DEFAULT); + + if (flags & STATUS_LAST_MSG) + { + if (data->m_szProto) + mir_snprintf(setting, SIZEOF(setting), "Last%sMsg", data->m_szProto); + else + mir_snprintf(setting, SIZEOF(setting), "LastMsg"); + + if (!DBGetContactSetting(NULL, "SimpleStatusMsg", setting, &dbv)) + { + if (dbv.pszVal) + { + if (strlen(dbv.pszVal) && !DBGetContactSettingTString(NULL, "SimpleStatusMsg", dbv.pszVal, &dbv2)) + { + if (dbv2.ptszVal && lstrlen(dbv2.ptszVal)) + { + SetDlgItemText(hwndDlg, IDC_EDIT1, dbv2.ptszVal); + fcursel = SendMessage(data->recent_cbex, CB_FINDSTRINGEXACT, num_start, (LPARAM)dbv2.ptszVal); + if (fcursel != CB_ERR) + SendMessage(data->recent_cbex, CB_SETCURSEL, (WPARAM)fcursel, 0); + } + DBFreeVariant(&dbv2); + } + } + DBFreeVariant(&dbv); + } + } + else if (flags & STATUS_DEFAULT_MSG) + { + SetDlgItemText(hwndDlg, IDC_EDIT1, GetDefaultMessage(iStatus)); + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "PutDefInList", 0)) + { + fcursel = SendMessage(data->recent_cbex, CB_FINDSTRINGEXACT, num_start, (LPARAM)GetDefaultMessage(iStatus)); + if (fcursel != CB_ERR) + SendMessage(data->recent_cbex, CB_SETCURSEL, (WPARAM)fcursel, 0); + } + } + else if (flags & STATUS_THIS_MSG) + { + if (data->m_szProto) + mir_snprintf(setting, SIZEOF(setting), "%sDefault", data->m_szProto); + else + mir_snprintf(setting, SIZEOF(setting), "Default"); + + if (!DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(iStatus, setting), &dbv)) + { + SetDlgItemText(hwndDlg, IDC_EDIT1, dbv.ptszVal); + fcursel = SendMessage(data->recent_cbex, CB_FINDSTRINGEXACT, num_start, (LPARAM)dbv.ptszVal); + if (fcursel != CB_ERR) + SendMessage(data->recent_cbex, CB_SETCURSEL, (WPARAM)fcursel, 0); + DBFreeVariant(&dbv); + } + } + else if (flags & STATUS_LAST_STATUS_MSG) + { + if (data->m_szProto) + mir_snprintf(setting, SIZEOF(setting), "%sMsg", data->m_szProto); + else + mir_snprintf(setting, SIZEOF(setting), "Msg"); + + if (!DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(iStatus, setting), &dbv)) + { + SetDlgItemText(hwndDlg, IDC_EDIT1, dbv.ptszVal); + fcursel = SendMessage(data->recent_cbex, CB_FINDSTRINGEXACT, num_start, (LPARAM)dbv.ptszVal); + if (fcursel != CB_ERR) + SendMessage(data->recent_cbex, CB_SETCURSEL, (WPARAM)fcursel, 0); + DBFreeVariant(&dbv); + } + } + + if (fcursel != CB_ERR) + data->curr_sel_msg = fcursel; +} + +void ChangeDlgStatus(HWND hwndDlg, struct MsgBoxData *msgbox_data, int iStatus) +{ + TCHAR szTitle[256], szProtoName[128]; + BOOL bDisabled = msgbox_data->m_szProto && !(CallProtoService(msgbox_data->m_szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND); + + mir_sntprintf(szProtoName, SIZEOF(szProtoName), msgbox_data->m_szProto ? ProtoGetAccount(msgbox_data->m_szProto)->tszAccountName : TranslateT("Global")); + if (iStatus == ID_STATUS_CURRENT) + { + if (msgbox_data->m_bOnStartup) + mir_sntprintf(szTitle, SIZEOF(szTitle), TranslateT("%s Message (%s)"), TranslateT(""), szProtoName); + else + mir_sntprintf(szTitle, SIZEOF(szTitle), TranslateT("%s Message (%s)"), TranslateT(""), szProtoName); + } + else if (iStatus > ID_STATUS_CURRENT) + { + TCHAR buff[128]; + + char buff1[128]; + CallService(MS_SS_GETPROFILENAME, iStatus - 40083, (LPARAM)buff1); + MultiByteToWideChar(CallService(MS_LANGPACK_GETCODEPAGE, 0, 0), 0, buff1, -1, buff, 128); + + mir_sntprintf(szTitle, SIZEOF(szTitle), TranslateT("%s Message (%s)"), (TCHAR*)buff, szProtoName); + } + else + mir_sntprintf(szTitle, SIZEOF(szTitle), TranslateT("%s Message (%s)"), (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, GSMDF_TCHAR), szProtoName); + SetWindowText(hwndDlg, szTitle); + + if (iStatus == ID_STATUS_CURRENT) + iStatus = msgbox_data->m_bOnStartup ? GetStartupStatus(msgbox_data->m_szProto) : GetCurrentStatus(msgbox_data->m_szProto); + else if (iStatus > ID_STATUS_CURRENT) + iStatus = GetCurrentStatus(NULL); + + CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIcon(msgbox_data->m_szProto, iStatus)), 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedProtoIcon(msgbox_data->m_szProto, iStatus)) , 0); + + if (!bDisabled && ((Proto_Status2Flag(iStatus) & msgbox_data->m_iStatusMsgModes) + || (iStatus == ID_STATUS_OFFLINE && (Proto_Status2Flag(ID_STATUS_INVISIBLE) & msgbox_data->m_iStatusMsgModes)))) + { + int num_items = SendMessage(msgbox_data->recent_cbex, CB_GETCOUNT, 0, 0); + int fcursel = CB_ERR, num_start = num_items - msgbox_data->num_def_msgs - 1; + TCHAR msg[1024]; + + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT1), TRUE); + + if (!IsWindowEnabled(msgbox_data->recent_cbex) && num_items) + EnableWindow(msgbox_data->recent_cbex, TRUE); + + // TODO what if num_start <= 0 ? + if (GetDlgItemText(hwndDlg, IDC_EDIT1, msg, SIZEOF(msg))) + fcursel = SendMessage(msgbox_data->recent_cbex, CB_FINDSTRINGEXACT, num_start, (LPARAM)msg); + if (fcursel != CB_ERR) + { + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, fcursel, 0); + msgbox_data->curr_sel_msg = fcursel; + } + + if ((msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + if (!GetDlgItemText(hwndDlg, IDC_EDIT1, msg, SIZEOF(msg))) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + } + else if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), TRUE); + if (num_items) + { + if (msgbox_data->curr_sel_msg == -1) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + } + else + { + COMBOBOXEXITEM cbitem = {0}; + cbitem.mask = CBEIF_LPARAM | CBEIF_TEXT; + cbitem.iItem = msgbox_data->curr_sel_msg; + cbitem.cchTextMax = SIZEOF(msg); + cbitem.pszText = msg; + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&cbitem); + if (LOWORD(cbitem.lParam) == PREDEFINED_MSG) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + } + else if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), TRUE); + + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), TRUE); + } + + if (msgbox_data->m_bIsMsgHistory && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BCLEAR))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), TRUE); + } + } + } + else + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT1), FALSE); + if (IsWindowEnabled(msgbox_data->recent_cbex)) + EnableWindow(msgbox_data->recent_cbex, FALSE); + + if ((msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BCLEAR))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), FALSE); + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + } + } +} + +#define DM_SIMPAWAY_SHUTDOWN (WM_USER + 10) +#define DM_SIMPAWAY_CHANGEICONS (WM_USER + 11) + +INT_PTR CALLBACK AwayMsgBoxDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + struct MsgBoxData *msgbox_data = (struct MsgBoxData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (uMsg) + { + case WM_INITDIALOG: + { + TCHAR szTitle[256], szFormat[256], szProtoName[128]; + struct MsgBoxInitData *init_data; + struct MsgBoxData *copy_init_data; + INITCOMMONCONTROLSEX icex = {0}; + BOOL bCurrentStatus = FALSE, bDisabled = FALSE; + + InitCommonControls(); + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_USEREX_CLASSES; + InitCommonControlsEx(&icex); + + TranslateDialogDefault(hwndDlg); + init_data = (struct MsgBoxInitData*)lParam; + GetWindowText(hwndDlg, szFormat, SIZEOF(szFormat)); + mir_sntprintf(szProtoName, SIZEOF(szProtoName), init_data->m_szProto ? ProtoGetAccount(init_data->m_szProto)->tszAccountName : TranslateT("Global")); + + if (init_data->m_iStatus == ID_STATUS_CURRENT) + { + if (init_data->m_bOnStartup) + mir_sntprintf(szTitle, SIZEOF(szTitle), szFormat, TranslateT(""), szProtoName); + else + mir_sntprintf(szTitle, SIZEOF(szTitle), szFormat, TranslateT(""), szProtoName); + } + else + mir_sntprintf(szTitle, SIZEOF(szTitle), szFormat, (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, init_data->m_iStatus, GSMDF_TCHAR), szProtoName); + SetWindowText(hwndDlg, szTitle); + + int icoStatus = ID_STATUS_OFFLINE; + if (init_data->m_iStatus == ID_STATUS_CURRENT) + icoStatus = init_data->m_bOnStartup ? GetStartupStatus(init_data->m_szProto) : GetCurrentStatus(init_data->m_szProto); + else + icoStatus = init_data->m_iStatus; + if (icoStatus < ID_STATUS_OFFLINE) + icoStatus = ID_STATUS_OFFLINE; + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIcon(init_data->m_szProto, icoStatus)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedProtoIcon(init_data->m_szProto, icoStatus)); + + copy_init_data = (struct MsgBoxData *)mir_alloc(sizeof(struct MsgBoxData)); + + SendDlgItemMessage(hwndDlg, IDC_EDIT1, EM_LIMITTEXT, 1024, 0); + + HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, DM_SIMPAWAY_SHUTDOWN); + HookEventMessage(ME_SKIN2_ICONSCHANGED, hwndDlg, DM_SIMPAWAY_CHANGEICONS); + + copy_init_data->num_def_msgs = DBGetContactSettingWord(NULL, "SimpleStatusMsg", "DefMsgCount", 0); + copy_init_data->max_hist_msgs = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "MaxHist", 10); + copy_init_data->m_iDlgFlags = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "DlgFlags", DLG_SHOW_DEFAULT); + copy_init_data->m_szProto = init_data->m_szProto; + copy_init_data->m_iStatus = init_data->m_iStatus; + copy_init_data->m_iStatusModes = init_data->m_iStatusModes; + copy_init_data->m_iStatusMsgModes = init_data->m_iStatusMsgModes; + copy_init_data->m_iInitialStatus = init_data->m_iStatus; + copy_init_data->m_bOnStartup = init_data->m_bOnStartup; + + //Load Icons + copy_init_data->icon[I_ICON_DEL] = LoadIconEx("cross"); + copy_init_data->icon[I_ICON_HIST] = LoadIconEx("recent"); + copy_init_data->icon[I_ICON_MSG] = LoadIconEx("predef"); + copy_init_data->icon[I_ICON_ADD] = LoadIconEx("add"); + copy_init_data->icon[I_ICON_CLEAR] = LoadIconEx("clear"); + if (copy_init_data->m_iDlgFlags & DLG_SHOW_STATUS_ICONS) + copy_init_data->status_icons = AddStatusIconsToImageList(init_data->m_szProto, copy_init_data->m_iStatusModes); + if (copy_init_data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + copy_init_data->other_icons = AddOtherIconsToImageList(copy_init_data); + + if ((copy_init_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (copy_init_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + SendMessage(GetDlgItem(hwndDlg, IDC_BADD), BUTTONADDTOOLTIP, (WPARAM)Translate("Add to Predefined"), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_BADD), BM_SETIMAGE, IMAGE_ICON, (LPARAM)copy_init_data->icon[I_ICON_ADD]); + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), TRUE); + ShowWindow(GetDlgItem(hwndDlg, IDC_BADD), TRUE); + + SendMessage(GetDlgItem(hwndDlg, IDC_BDEL), BUTTONADDTOOLTIP, (WPARAM)Translate("Delete Selected"), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_BDEL), BM_SETIMAGE, IMAGE_ICON, (LPARAM)copy_init_data->icon[I_ICON_DEL]); + ShowWindow(GetDlgItem(hwndDlg, IDC_BDEL), TRUE); + + SendMessage(GetDlgItem(hwndDlg, IDC_BCLEAR), BUTTONADDTOOLTIP, (WPARAM)Translate("Clear History"), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_BCLEAR), BM_SETIMAGE, IMAGE_ICON, (LPARAM)copy_init_data->icon[I_ICON_CLEAR]); + ShowWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), TRUE); + + if (copy_init_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT) + { + SendMessage(GetDlgItem(hwndDlg, IDC_BADD), BUTTONSETASFLATBTN, TRUE, 0); + SendMessage(GetDlgItem(hwndDlg, IDC_BDEL), BUTTONSETASFLATBTN, TRUE, 0); + SendMessage(GetDlgItem(hwndDlg, IDC_BCLEAR), BUTTONSETASFLATBTN, TRUE, 0); + } + } + else + { + SetWindowPos(GetDlgItem(hwndDlg, IDC_OK), NULL, 52, 115, 0, 0, SWP_NOSIZE|SWP_NOZORDER); + SetWindowPos(GetDlgItem(hwndDlg, IDC_CANCEL), NULL, 160, 115, 0, 0, SWP_NOSIZE|SWP_NOZORDER); + ShowWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + ShowWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + ShowWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), FALSE); + } + copy_init_data->status_cbex = CreateStatusComboBoxEx(hwndDlg, copy_init_data); + + if (copy_init_data->m_iStatus == ID_STATUS_CURRENT) + { + if (copy_init_data->m_bOnStartup) + copy_init_data->m_iStatus = GetStartupStatus(copy_init_data->m_szProto); + else + copy_init_data->m_iStatus = GetCurrentStatus(copy_init_data->m_szProto); + if (copy_init_data->m_szProto == NULL) + bCurrentStatus = TRUE; + } + + copy_init_data->recent_cbex = CreateRecentComboBoxEx(hwndDlg, copy_init_data); + copy_init_data->curr_sel_msg = -1; + copy_init_data->m_bPredefChanged = FALSE; + + SetEditControlText(copy_init_data, hwndDlg, copy_init_data->m_iStatus); + if ((copy_init_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (copy_init_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + TCHAR msg[1024]; + + if (!GetDlgItemText(hwndDlg, IDC_EDIT1, msg, SIZEOF(msg))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + + if (copy_init_data->curr_sel_msg == -1) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + } + else + { + COMBOBOXEXITEM cbitem = {0}; + cbitem.mask = CBEIF_LPARAM|CBEIF_TEXT; + cbitem.iItem = copy_init_data->curr_sel_msg; + cbitem.cchTextMax = SIZEOF(msg); + cbitem.pszText = msg; + + SendMessage(copy_init_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&cbitem); + if (LOWORD(cbitem.lParam) == PREDEFINED_MSG) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + } + else if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), TRUE); + } + } + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)copy_init_data); + + if (copy_init_data->m_szProto && !(CallProtoService(copy_init_data->m_szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + bDisabled = TRUE; + + if (!(((Proto_Status2Flag(copy_init_data->m_iStatus) & copy_init_data->m_iStatusMsgModes) || + (copy_init_data->m_iStatus == ID_STATUS_OFFLINE && (Proto_Status2Flag(ID_STATUS_INVISIBLE) & copy_init_data->m_iStatusMsgModes))) && !bDisabled)) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT1), FALSE); + if (IsWindowEnabled(copy_init_data->recent_cbex)) + EnableWindow(copy_init_data->recent_cbex, FALSE); + + if ((copy_init_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (copy_init_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BCLEAR))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), FALSE); + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + } + } + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "AutoClose", 1) && init_data->m_bOnEvent) + { + copy_init_data->m_iCountdown = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "DlgTime", 5); + SendMessage(hwndDlg, WM_TIMER, 0, 0); + SetTimer(hwndDlg, 1, 1000, 0); + } + else + { + copy_init_data->m_iCountdown = -2; + DisplayCharsCount(copy_init_data, hwndDlg); + } + + if (bCurrentStatus) + copy_init_data->m_iStatus = ID_STATUS_CURRENT; + + mir_free(init_data); + + MainDlgProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT1), GWLP_WNDPROC, (LONG_PTR)EditBoxSubProc); + if (!init_data->m_bOnEvent && IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + { + SetFocus(GetDlgItem(hwndDlg, IDC_EDIT1)); + SendMessage(GetDlgItem(hwndDlg, IDC_EDIT1), EM_SETSEL, 0, -1); + } + else + SetFocus(GetDlgItem(hwndDlg, IDC_OK)); + + if (!DBGetContactSettingByte(NULL, "SimpleStatusMsg", "WinCentered", 1)) + { + WINDOWPLACEMENT wp; + int x, y; + + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + + x = (int)DBGetContactSettingDword(NULL, "SimpleStatusMsg", "Winx", -1); + y = (int)DBGetContactSettingDword(NULL, "SimpleStatusMsg", "Winy", -1); + + if (x !=- 1) + { + OffsetRect(&wp.rcNormalPosition, x - wp.rcNormalPosition.left, y - wp.rcNormalPosition.top); + wp.flags = 0; + SetWindowPlacement(hwndDlg, &wp); + } + } + return FALSE; + } + + case WM_TIMER: + if (msgbox_data->m_iCountdown == -1) + { + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_OK, 0); + msgbox_data->m_iCountdown = -2; + DisplayCharsCount(msgbox_data, hwndDlg); + break; + } + else + { + TCHAR str[64]; + mir_sntprintf(str, SIZEOF(str), TranslateT("Closing in %d"), msgbox_data->m_iCountdown); + SetDlgItemText(hwndDlg, IDC_OK, str); + } + msgbox_data->m_iCountdown--; + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_OK: + { + TCHAR tszMsg[1024]; + int iStatus, iMsgLen = 0, iProfileStatus = 0; + BOOL bCurrentStatus = FALSE; + + if (msgbox_data->m_iStatus == ID_STATUS_CURRENT) + { + msgbox_data->m_iStatus = msgbox_data->m_bOnStartup ? GetStartupStatus(msgbox_data->m_szProto) : GetCurrentStatus(msgbox_data->m_szProto); + if (msgbox_data->m_szProto == NULL) + bCurrentStatus = TRUE; + } + else if (msgbox_data->m_iStatus >= ID_STATUS_CURRENT) + { + iProfileStatus = msgbox_data->m_iStatus; + msgbox_data->m_iStatus = GetCurrentStatus(NULL); + } + + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + iMsgLen = GetDlgItemText(hwndDlg, IDC_EDIT1, tszMsg, SIZEOF(tszMsg)); + + if (iMsgLen == 0) + { + char szSetting[80]; + if (msgbox_data->m_szProto) + { + mir_snprintf(szSetting, SIZEOF(szSetting), "Last%sMsg", msgbox_data->m_szProto); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", szSetting, ""); + + mir_snprintf(szSetting, SIZEOF(szSetting), "%sMsg", msgbox_data->m_szProto); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(msgbox_data->m_iStatus, szSetting), _T("")); + } + else + { + DBWriteContactSettingString(NULL, "SimpleStatusMsg", "LastMsg", ""); + for (int j = 0; j < accounts->count; j++) + { + if (!IsAccountEnabled(accounts->pa[j])) + continue; + + if (!CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (DBGetContactSettingByte(NULL, accounts->pa[j]->szModuleName, "LockMainStatus", 0)) + continue; + + if (!(CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Last%sMsg", accounts->pa[j]->szModuleName); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", szSetting, ""); + + mir_snprintf(szSetting, SIZEOF(szSetting), "%sMsg", accounts->pa[j]->szModuleName); + iStatus = msgbox_data->m_bOnStartup ? GetStartupStatus(accounts->pa[j]->szModuleName) : GetCurrentStatus(accounts->pa[j]->szModuleName); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(iStatus, szSetting), _T("")); + } + + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(msgbox_data->m_iStatus, "Msg"), _T("")); // for compatibility with some plugins + } + + if (bCurrentStatus) + SetStatusMessage(msgbox_data->m_szProto, msgbox_data->m_iInitialStatus, ID_STATUS_CURRENT, 0, msgbox_data->m_bOnStartup); + else if (iProfileStatus != 0) + SetStatusMessage(msgbox_data->m_szProto, msgbox_data->m_iInitialStatus, iProfileStatus, 0, FALSE); + else + SetStatusMessage(msgbox_data->m_szProto, msgbox_data->m_iInitialStatus, msgbox_data->m_iStatus, 0, msgbox_data->m_bOnStartup); + } + else + { + char buff[64], buff2[80]; + DBVARIANT dbv; + BOOL found = FALSE; + + for (int i = 1; i <= msgbox_data->max_hist_msgs; i++) + { + mir_snprintf(buff, SIZEOF(buff), "SMsg%d", i); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", buff, &dbv)) + { + if (!lstrcmp(dbv.ptszVal, tszMsg)) + { + found = TRUE; + if (msgbox_data->m_szProto) + { + mir_snprintf(buff2, SIZEOF(buff2), "Last%sMsg", msgbox_data->m_szProto); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", buff2, buff); + + mir_snprintf(buff2, SIZEOF(buff2), "%sMsg", msgbox_data->m_szProto); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(msgbox_data->m_iStatus, buff2), tszMsg); + } + else + { + DBWriteContactSettingString(NULL, "SimpleStatusMsg", "LastMsg", buff); + for (int j = 0; j < accounts->count; j++) + { + if (!IsAccountEnabled(accounts->pa[j])) + continue; + + if (!CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (DBGetContactSettingByte(NULL, accounts->pa[j]->szModuleName, "LockMainStatus", 0)) + continue; + + if (!(CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(buff2, SIZEOF(buff2), "Last%sMsg", accounts->pa[j]->szModuleName); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", buff2, buff); + + mir_snprintf(buff2, SIZEOF(buff2), "%sMsg", accounts->pa[j]->szModuleName); + iStatus = msgbox_data->m_bOnStartup ? GetStartupStatus(accounts->pa[j]->szModuleName) : GetCurrentStatus(accounts->pa[j]->szModuleName); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(iStatus, buff2), tszMsg); + } + } + DBFreeVariant(&dbv); + break; + } + } + } + + if (!found) + { + int last_modified_msg = DBGetContactSettingWord(NULL, "SimpleStatusMsg", "LMMsg", msgbox_data->max_hist_msgs); + + if (last_modified_msg == msgbox_data->max_hist_msgs) + last_modified_msg = 1; + else + last_modified_msg++; + + mir_snprintf(buff, SIZEOF(buff), "SMsg%d", last_modified_msg); + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", buff, tszMsg); + + if (msgbox_data->m_szProto) + { + mir_snprintf(buff2, SIZEOF(buff2), "Last%sMsg", msgbox_data->m_szProto); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", buff2, buff); + + mir_snprintf(buff2, SIZEOF(buff2), "%sMsg", msgbox_data->m_szProto); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(msgbox_data->m_iStatus, buff2), tszMsg); + } + else + { + DBWriteContactSettingString(NULL, "SimpleStatusMsg", "LastMsg", buff); + for (int j = 0; j < accounts->count; j++) + { + if (!IsAccountEnabled(accounts->pa[j])) + continue; + + if (!CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (DBGetContactSettingByte(NULL, accounts->pa[j]->szModuleName, "LockMainStatus", 0)) + continue; + + if (!(CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(buff2, SIZEOF(buff2), "Last%sMsg", accounts->pa[j]->szModuleName); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", buff2, buff); + + mir_snprintf(buff2, SIZEOF(buff2), "%sMsg", accounts->pa[j]->szModuleName); + iStatus = msgbox_data->m_bOnStartup ? GetStartupStatus(accounts->pa[j]->szModuleName) : GetCurrentStatus(accounts->pa[j]->szModuleName); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(iStatus, buff2), tszMsg); + } + } + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "LMMsg", (WORD)last_modified_msg); + } + + if (!msgbox_data->m_szProto) + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(msgbox_data->m_iStatus, "Msg"), tszMsg); // for compatibility with some plugins + + if (bCurrentStatus) + SetStatusMessage(msgbox_data->m_szProto, msgbox_data->m_iInitialStatus, ID_STATUS_CURRENT, tszMsg, msgbox_data->m_bOnStartup); + else if (iProfileStatus != 0) + SetStatusMessage(msgbox_data->m_szProto, msgbox_data->m_iInitialStatus, iProfileStatus, tszMsg, FALSE); + else + SetStatusMessage(msgbox_data->m_szProto, msgbox_data->m_iInitialStatus, msgbox_data->m_iStatus, tszMsg, msgbox_data->m_bOnStartup); + } + } + + case IDCANCEL: + case IDC_CANCEL: + DestroyWindow(hwndDlg); + return TRUE; + + case IDC_EDIT1: // Notification from the edit control + if (msgbox_data->m_iCountdown > -2) + { + KillTimer(hwndDlg, 1); + msgbox_data->m_iCountdown = -2; + DisplayCharsCount(msgbox_data, hwndDlg); + } + switch (HIWORD(wParam)) + { + case EN_CHANGE: + DisplayCharsCount(msgbox_data, hwndDlg); + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, -1, 0); + if ((msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + TCHAR msg[1024]; + + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + + if (!GetDlgItemText(hwndDlg, IDC_EDIT1, msg, SIZEOF(msg))) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + } + else if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), TRUE); + } + break; + } + break; + } + + if ((HWND)lParam == msgbox_data->status_cbex) + { + if (msgbox_data->m_iCountdown > -2) + { + KillTimer(hwndDlg, 1); + msgbox_data->m_iCountdown = -2; + DisplayCharsCount(msgbox_data, hwndDlg); + } + switch (HIWORD(wParam)) + { + case CBN_SELENDOK: + case CBN_SELCHANGE: + { + COMBOBOXEXITEM cbitem = {0}; + + cbitem.mask = CBEIF_LPARAM; + cbitem.iItem = SendMessage(msgbox_data->status_cbex, CB_GETCURSEL, 0, 0); + SendMessage(msgbox_data->status_cbex, CBEM_GETITEM, 0, (LPARAM)&cbitem); + + msgbox_data->m_iStatus = cbitem.lParam; + ChangeDlgStatus(hwndDlg, msgbox_data, (int)cbitem.lParam); + + if (HIWORD(wParam) == CBN_SELENDOK && IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + SetFocus(GetDlgItem(hwndDlg, IDC_EDIT1)); + break; + } + } + } + + if ((HWND)lParam == msgbox_data->recent_cbex) + { + if (msgbox_data->m_iCountdown > -2) + { + KillTimer(hwndDlg, 1); + msgbox_data->m_iCountdown = -2; + DisplayCharsCount(msgbox_data, hwndDlg); + } + switch (HIWORD(wParam)) + { + case CBN_SELENDOK: + { + TCHAR text[1024]; + int cur_sel = SendMessage(msgbox_data->recent_cbex, CB_GETCURSEL, 0, 0); + COMBOBOXEXITEM cbitem = {0}; + + cbitem.mask = CBEIF_LPARAM | CBEIF_TEXT; + cbitem.iItem = cur_sel; + cbitem.cchTextMax = SIZEOF(text); + cbitem.pszText = text; + + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&cbitem); + if (LOWORD(cbitem.lParam) == HISTORY_MSG || LOWORD(cbitem.lParam) == PREDEFINED_MSG || LOWORD(cbitem.lParam) == DEFAULT_MSG) + { + SetDlgItemText(hwndDlg, IDC_EDIT1, text); + DisplayCharsCount(msgbox_data, hwndDlg); + if ((msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), TRUE); + if (LOWORD(cbitem.lParam) == PREDEFINED_MSG) + { + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + } + else if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), TRUE); + } + } + else if (LOWORD(cbitem.lParam) == CLEAR_HISTORY) + { + if (MessageBox(NULL, TranslateT("Are you sure you want to clear status message history?"), TranslateT("Confirm clearing history"), MB_ICONQUESTION | MB_YESNO) == IDYES) + { + ClearHistory(msgbox_data, cur_sel); + } + else if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + { + TCHAR msg[1024]; + int fcursel = CB_ERR, num_start; + num_start = SendMessage(msgbox_data->recent_cbex, CB_GETCOUNT, 0, 0); + num_start -= msgbox_data->num_def_msgs + 1; + GetDlgItemText(hwndDlg, IDC_EDIT1, msg, SIZEOF(msg)); + fcursel = SendMessage(msgbox_data->recent_cbex, CB_FINDSTRINGEXACT, num_start, (LPARAM)msg); + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, fcursel, 0); + } + } + else if (LOWORD(cbitem.lParam) == DELETE_SELECTED) + { + COMBOBOXEXITEM histitem = {0}; + BOOL scursel = FALSE; + + histitem.mask = CBEIF_LPARAM; + histitem.iItem = msgbox_data->curr_sel_msg; + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&histitem); + + if (LOWORD(histitem.lParam) == HISTORY_MSG) + { + char szSetting[16]; + mir_snprintf(szSetting, SIZEOF(szSetting), "SMsg%d", (int)HIWORD(histitem.lParam)); + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", szSetting, _T("")); + SendMessage(msgbox_data->recent_cbex, CBEM_DELETEITEM, (WPARAM)msgbox_data->curr_sel_msg, 0); + } + if (LOWORD(histitem.lParam) == PREDEFINED_MSG) + { + msgbox_data->m_bPredefChanged = TRUE; + SendMessage(msgbox_data->recent_cbex, CBEM_DELETEITEM, (WPARAM)msgbox_data->curr_sel_msg, 0); + } + + cur_sel = msgbox_data->curr_sel_msg; + while (!scursel) + { + if (cur_sel - 1 >= 0) + cur_sel--; + else + { + scursel = TRUE; + break; + } + histitem.mask = CBEIF_LPARAM; + histitem.iItem = cur_sel; + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&histitem); + + if ((LOWORD(histitem.lParam) != CLEAR_HISTORY) && (LOWORD(histitem.lParam) != DELETE_SELECTED) && (LOWORD(histitem.lParam) != ADD_MSG)) + scursel = TRUE; + } + msgbox_data->curr_sel_msg = cur_sel; + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, (WPARAM)cur_sel, 0); + + histitem.mask = CBEIF_LPARAM | CBEIF_TEXT; + histitem.iItem = cur_sel; + histitem.cchTextMax = SIZEOF(text); + histitem.pszText = text; + + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&histitem); + if (LOWORD(histitem.lParam) == HISTORY_MSG || LOWORD(histitem.lParam) == PREDEFINED_MSG || LOWORD(histitem.lParam) == DEFAULT_MSG) + { + SetDlgItemText(hwndDlg, IDC_EDIT1, text); + DisplayCharsCount(msgbox_data, hwndDlg); + } + } + else if (LOWORD(cbitem.lParam) == ADD_MSG) + { + int sel = AddToPredefined(hwndDlg, msgbox_data); + if (sel != -1) + { + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, (WPARAM)sel, 0); + msgbox_data->curr_sel_msg = sel; + } + else + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, (WPARAM)msgbox_data->curr_sel_msg, 0); + break; + } + msgbox_data->curr_sel_msg = cur_sel; + + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_EDIT1))) + { + SetFocus(GetDlgItem(hwndDlg, IDC_EDIT1)); + SendMessage(GetDlgItem(hwndDlg, IDC_EDIT1), EM_SETSEL, 0, -1); + } + break; + } + } + } + + if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_BADD)) + { + switch (HIWORD(wParam)) + { + case BN_CLICKED: + { + int sel = AddToPredefined(hwndDlg, msgbox_data); + if (sel != -1) + { + if (!IsWindowEnabled(msgbox_data->recent_cbex)) + EnableWindow(msgbox_data->recent_cbex, TRUE); + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BDEL))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), TRUE); + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BADD))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), FALSE); + + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, (WPARAM)sel, 0); + msgbox_data->curr_sel_msg = sel; + } + break; + } + } + } + + if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_BCLEAR)) + { + switch (HIWORD(wParam)) + { + case BN_CLICKED: + if (MessageBox(NULL, TranslateT("Are you sure you want to clear status message history?"), TranslateT("Confirm clearing history"), MB_ICONQUESTION | MB_YESNO) == IDYES) + { + ClearHistory(msgbox_data, 0); + + int num_items = SendMessage(msgbox_data->recent_cbex, CB_GETCOUNT, 0, 0); + if (!num_items) + { + if (IsWindowEnabled(msgbox_data->recent_cbex)) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + EnableWindow(msgbox_data->recent_cbex, FALSE); + } + } + EnableWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), FALSE); + } + break; + } + } + + if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_BDEL)) + { + switch (HIWORD(wParam)) + { + case BN_CLICKED: + { + int cur_sel; + char buff[16]; + int left_items = 0; + COMBOBOXEXITEM histitem = {0}; + + cur_sel = SendMessage(msgbox_data->recent_cbex, CB_GETCURSEL, 0, 0); + + histitem.mask = CBEIF_LPARAM; + histitem.iItem = msgbox_data->curr_sel_msg; + + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&histitem); + + if (LOWORD(histitem.lParam) == HISTORY_MSG) + { + mir_snprintf(buff, SIZEOF(buff), "SMsg%d", (int)HIWORD(histitem.lParam)); + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", buff, _T("")); + } + else if (LOWORD(histitem.lParam) == PREDEFINED_MSG) + { + msgbox_data->m_bPredefChanged = TRUE; + } + left_items = SendMessage(msgbox_data->recent_cbex, CBEM_DELETEITEM, (WPARAM)msgbox_data->curr_sel_msg, 0); + + if (!left_items) + { + if (IsWindowEnabled(msgbox_data->recent_cbex)) + EnableWindow(msgbox_data->recent_cbex, FALSE); + if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BCLEAR))) + EnableWindow(GetDlgItem(hwndDlg, IDC_BCLEAR), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BDEL), FALSE); + } + else + { + TCHAR text[1024]; + + if (cur_sel - 1 >= 0) + cur_sel--; + msgbox_data->curr_sel_msg = cur_sel; + SendMessage(msgbox_data->recent_cbex, CB_SETCURSEL, (WPARAM)cur_sel, 0); + + histitem.mask = CBEIF_LPARAM | CBEIF_TEXT; + histitem.iItem = cur_sel; + histitem.cchTextMax = SIZEOF(text); + histitem.pszText = text; + + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&histitem); + if (LOWORD(histitem.lParam) == HISTORY_MSG || LOWORD(histitem.lParam) == PREDEFINED_MSG || LOWORD(histitem.lParam) == DEFAULT_MSG) + { + SetDlgItemText(hwndDlg, IDC_EDIT1, text); + DisplayCharsCount(msgbox_data, hwndDlg); + EnableWindow(GetDlgItem(hwndDlg, IDC_BADD), LOWORD(histitem.lParam) == PREDEFINED_MSG ? FALSE : TRUE); + } + } + break; + } + } + } + break; + + case DM_SIMPAWAY_SHUTDOWN: + DestroyWindow(hwndDlg); + break; + + case DM_SIMPAWAY_CHANGEICONS: + ReleaseIconEx("cross"); + ReleaseIconEx("recent"); + ReleaseIconEx("predef"); + ReleaseIconEx("add"); + ReleaseIconEx("clear"); + msgbox_data->icon[I_ICON_DEL] = LoadIconEx("cross"); + msgbox_data->icon[I_ICON_HIST] = LoadIconEx("recent"); + msgbox_data->icon[I_ICON_MSG] = LoadIconEx("predef"); + msgbox_data->icon[I_ICON_ADD] = LoadIconEx("add"); + msgbox_data->icon[I_ICON_CLEAR] = LoadIconEx("clear"); + if (msgbox_data->m_iDlgFlags & DLG_SHOW_LIST_ICONS) + { + for (int i = 0; i < 5; ++i) + ImageList_ReplaceIcon(msgbox_data->other_icons, i, msgbox_data->icon[i]); + } + if ((msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS) || (msgbox_data->m_iDlgFlags & DLG_SHOW_BUTTONS_FLAT)) + { + SendMessage(GetDlgItem(hwndDlg, IDC_BADD), BM_SETIMAGE, IMAGE_ICON, (LPARAM)msgbox_data->icon[I_ICON_ADD]); + SendMessage(GetDlgItem(hwndDlg, IDC_BCLEAR), BM_SETIMAGE, IMAGE_ICON, (LPARAM)msgbox_data->icon[I_ICON_CLEAR]); + SendMessage(GetDlgItem(hwndDlg, IDC_BDEL), BM_SETIMAGE, IMAGE_ICON, (LPARAM)msgbox_data->icon[I_ICON_DEL]); + } + break; + + case WM_DESTROY: + { + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + DBWriteContactSettingDword(NULL, "SimpleStatusMsg", "Winx", wp.rcNormalPosition.left); + DBWriteContactSettingDword(NULL, "SimpleStatusMsg", "Winy", wp.rcNormalPosition.top); + + if (msgbox_data->m_bPredefChanged) + { + int i, num_items, new_num_def_msgs = 0; + COMBOBOXEXITEM cbitem = {0}; + TCHAR text[1024]; + char buff[64]; + + num_items = SendMessage(msgbox_data->recent_cbex, CB_GETCOUNT, 0, 0); + num_items--; + for (i = 1; i <= msgbox_data->num_def_msgs; i++) + { + cbitem.mask = CBEIF_LPARAM|CBEIF_TEXT; + cbitem.iItem = num_items; + cbitem.cchTextMax = SIZEOF(text); + cbitem.pszText = text; + + SendMessage(msgbox_data->recent_cbex, CBEM_GETITEM, 0, (LPARAM)&cbitem); + mir_snprintf(buff, SIZEOF(buff), "DefMsg%d", i); + if (LOWORD(cbitem.lParam) == PREDEFINED_MSG) + { + new_num_def_msgs++; + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", buff, text); + } + else + DBDeleteContactSetting(NULL, "SimpleStatusMsg", buff); + num_items--; + } + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "DefMsgCount", (WORD)new_num_def_msgs); + } + + ImageList_Destroy(msgbox_data->status_icons); + ImageList_Destroy(msgbox_data->other_icons); + ReleaseIconEx("cross"); + ReleaseIconEx("recent"); + ReleaseIconEx("predef"); + ReleaseIconEx("add"); + ReleaseIconEx("clear"); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)NULL), 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)NULL), 0); + + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_EDIT1), GWLP_WNDPROC, (LONG_PTR)MainDlgProc); + if (msgbox_data) + mir_free(msgbox_data); + hwndSAMsgDialog = NULL; + break; + } + } + return FALSE; +} diff --git a/plugins/SimpleStatusMsg/src/options.cpp b/plugins/SimpleStatusMsg/src/options.cpp new file mode 100644 index 0000000000..cc450c12e4 --- /dev/null +++ b/plugins/SimpleStatusMsg/src/options.cpp @@ -0,0 +1,1750 @@ +/* + +Simple Status Message plugin for Miranda IM +Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "commonheaders.h" +#include "simplestatusmsg.h" + +extern UINT_PTR g_uUpdateMsgTimer; +extern VOID CALLBACK UpdateMsgTimerProc(HWND, UINT, UINT_PTR, DWORD); +extern VOID APIENTRY HandlePopupMenu(HWND hwnd, POINT pt, HWND edit_control); + +static WNDPROC OldDlgProc; + +static void RebuildStatusMenu(void) +{ + CLIST_INTERFACE* pcli = (CLIST_INTERFACE*)CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, 0); + if (pcli && pcli->version > 4) + pcli->pfnReloadProtoMenus(); +} + +static LRESULT CALLBACK OptEditBoxSubProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_CONTEXTMENU: + { + POINT pt = {(LONG)LOWORD(lParam), (LONG)HIWORD(lParam)}; + RECT rc; + GetClientRect(hwndDlg, &rc); + + if (pt.x == -1 && pt.y == -1) + { + GetCursorPos(&pt); + if (!PtInRect(&rc, pt)) + { + pt.x = rc.left + (rc.right - rc.left) / 2; + pt.y = rc.top + (rc.bottom - rc.top) / 2; + } + } + else + ScreenToClient(hwndDlg, &pt); + + if (PtInRect(&rc, pt)) + HandlePopupMenu(hwndDlg, pt, GetDlgItem(GetParent(hwndDlg), IDC_OPTEDIT1)); + + return 0; + } + + case WM_CHAR: + if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) // Ctrl + A + { + SendMessage(hwndDlg, EM_SETSEL, 0, -1); + return 0; + } + if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000) // Ctrl + Backspace + { + DWORD start, end; + TCHAR *text; + int textLen; + SendMessage(hwndDlg, EM_GETSEL, (WPARAM)&end, (LPARAM)(PDWORD)NULL); + SendMessage(hwndDlg, WM_KEYDOWN, VK_LEFT, 0); + SendMessage(hwndDlg, EM_GETSEL, (WPARAM)&start, (LPARAM)(PDWORD)NULL); + textLen = GetWindowTextLength(hwndDlg); + text = (TCHAR *)mir_alloc(sizeof(TCHAR) * (textLen + 1)); + GetWindowText(hwndDlg, text, textLen + 1); + MoveMemory(text + start, text + end, sizeof(TCHAR) * (textLen + 1 - end)); + SetWindowText(hwndDlg, text); + mir_free(text); + SendMessage(hwndDlg, EM_SETSEL, start, start); + SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwndDlg), EN_CHANGE), (LPARAM)hwndDlg); + return 0; + } + break; + } + + return CallWindowProc(OldDlgProc, hwndDlg, uMsg, wParam, lParam); +} + +struct SingleProtoMsg +{ + int flags; + TCHAR *msg; + int max_length; +}; + +struct SingleStatusMsg +{ + int flags[9]; + TCHAR msg[9][1024]; +}; + +struct OptDlgData +{ + BOOL proto_ok; + struct SingleProtoMsg *proto_msg; + struct SingleStatusMsg *status_msg; +}; + +static INT_PTR CALLBACK DlgOptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + struct OptDlgData *data = (struct OptDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (uMsg) + { + case WM_INITDIALOG: + { + int val, i, index; + DBVARIANT dbv; + + TranslateDialogDefault(hwndDlg); + + data = (struct OptDlgData *)mir_alloc(sizeof(struct OptDlgData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)data); + + SendDlgItemMessage(hwndDlg, IDC_OPTEDIT1, EM_LIMITTEXT, 1024, 0); + SendMessage(GetDlgItem(hwndDlg, IDC_SMAXLENGTH), UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_EMAXLENGTH), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_SMAXLENGTH), UDM_SETRANGE32, 1, 1024); + SendMessage(GetDlgItem(hwndDlg, IDC_EMAXLENGTH), EM_LIMITTEXT, 4, 0); + + data->status_msg = (struct SingleStatusMsg *)mir_alloc(sizeof(struct SingleStatusMsg)*(accounts->count + 1)); + + for (i = ID_STATUS_ONLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + { + if (accounts->statusMsgFlags & Proto_Status2Flag(i)) + { + index = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_INSERTSTRING, -1, (LPARAM)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, i, GSMDF_TCHAR)); + if (index != CB_ERR && index != CB_ERRSPACE) + { + int j; + char setting[80]; + + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_SETITEMDATA, (WPARAM)index, (LPARAM)i - ID_STATUS_ONLINE); + + val = DBGetContactSettingByte(NULL, "SimpleStatusMsg", (char *)StatusModeToDbSetting(i, "Flags"), STATUS_DEFAULT); + data->status_msg[0].flags[i - ID_STATUS_ONLINE] = val; + if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(i, "Default"), &dbv)) + dbv.ptszVal = mir_tstrdup(GetDefaultMessage(i)); + lstrcpy(data->status_msg[0].msg[i - ID_STATUS_ONLINE], dbv.ptszVal); + mir_free(dbv.ptszVal); + DBFreeVariant(&dbv); + + for (j = 0; j < accounts->count; j++) + { + if (!IsAccountEnabled(accounts->pa[j]) || !CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) || !(CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(setting, SIZEOF(setting), "%sFlags", accounts->pa[j]->szModuleName); + val = DBGetContactSettingByte(NULL, "SimpleStatusMsg", (char *)StatusModeToDbSetting(i, setting), STATUS_DEFAULT); + data->status_msg[j+1].flags[i-ID_STATUS_ONLINE] = val; + mir_snprintf(setting, SIZEOF(setting), "%sDefault", accounts->pa[j]->szModuleName); + if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(i, setting), &dbv)) + dbv.ptszVal = mir_tstrdup(GetDefaultMessage(i)); + lstrcpy(data->status_msg[j + 1].msg[i - ID_STATUS_ONLINE], dbv.ptszVal); + mir_free(dbv.ptszVal); + DBFreeVariant(&dbv); + } + } + } + } + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_SETCURSEL, 0, 0); + + data->proto_msg = (struct SingleProtoMsg *)mir_alloc(sizeof(struct SingleProtoMsg)*(accounts->count + 1)); + if (!data->proto_msg) + { + // TODO not really needed? + EnableWindow(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTPROTO), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO2), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO3), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO4), FALSE); + data->proto_ok = FALSE; + } + else + { + char setting[64]; + + data->proto_ok = TRUE; + + index = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_ADDSTRING, 0, (LPARAM)TranslateT("Global status change")); +// SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_SETITEMDATA, index, 0); + if (index != CB_ERR && index != CB_ERRSPACE) + { + data->proto_msg[0].msg = NULL; + + val = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ProtoFlags", PROTO_DEFAULT); + data->proto_msg[0].flags = val; + data->proto_msg[0].max_length = 0; + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_SETITEMDATA, (WPARAM)index, 0); + } + + for (i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i]) + || !CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) + || !(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + { + data->proto_msg[i+1].msg = NULL; + continue; + } + + index = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_ADDSTRING, 0, (LPARAM)accounts->pa[i]->tszAccountName); +// SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_SETITEMDATA, index, (LPARAM)i + 1); + if (index != CB_ERR && index != CB_ERRSPACE) + { + mir_snprintf(setting, SIZEOF(setting), "Proto%sDefault", accounts->pa[i]->szModuleName); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", setting, &dbv)) + { + data->proto_msg[i+1].msg = mir_tstrdup(dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + data->proto_msg[i+1].msg = NULL; + + mir_snprintf(setting, SIZEOF(setting), "Proto%sFlags", accounts->pa[i]->szModuleName); + val = DBGetContactSettingByte(NULL, "SimpleStatusMsg", setting, PROTO_DEFAULT); + data->proto_msg[i+1].flags = val; + mir_snprintf(setting, SIZEOF(setting), "Proto%sMaxLen", accounts->pa[i]->szModuleName); + val = DBGetContactSettingWord(NULL, "SimpleStatusMsg", setting, 1024); + data->proto_msg[i+1].max_length = val; + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_SETITEMDATA, (WPARAM)index, (LPARAM)i + 1); + } + } + + if (accounts->statusMsgCount == 1) + { +// ShowWindow(GetDlgItem(hwndDlg, IDC_BOPTPROTO), SW_HIDE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTPROTO), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), FALSE); + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_SETCURSEL, 1, 0); + } + else + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_SETCURSEL, 0, 0); + + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CBOPTPROTO, CBN_SELCHANGE), (LPARAM)GetDlgItem(hwndDlg, IDC_CBOPTPROTO)); + } + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "PutDefInList", 0)) + CheckDlgButton(hwndDlg, IDC_COPTMSG2, BST_CHECKED); + + if (ServiceExists(MS_VARS_FORMATSTRING)) + { + HICON hIcon=NULL; + char *szTipInfo=NULL; + + if (ServiceExists(MS_VARS_GETSKINITEM)) + { + hIcon = (HICON)CallService(MS_VARS_GETSKINITEM, 0, VSI_HELPICON); + szTipInfo = (char *)CallService(MS_VARS_GETSKINITEM, 0, VSI_HELPTIPTEXT); + } + + if (hIcon != NULL) + SendMessage(GetDlgItem(hwndDlg, IDC_VARSHELP), BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + else + SetDlgItemText(hwndDlg, IDC_VARSHELP, _T("V")); + + if (szTipInfo == NULL) + SendMessage(GetDlgItem(hwndDlg, IDC_VARSHELP), BUTTONADDTOOLTIP, (WPARAM)TranslateT("Open String Formatting Help"), 0); + else + SendMessage(GetDlgItem(hwndDlg, IDC_VARSHELP), BUTTONADDTOOLTIP, (WPARAM)szTipInfo, 0); + + SendDlgItemMessage(hwndDlg, IDC_VARSHELP, BUTTONSETASFLATBTN, TRUE, 0); + } + ShowWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), ServiceExists(MS_VARS_FORMATSTRING)); + + OldDlgProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_OPTEDIT1), GWLP_WNDPROC, (LONG_PTR)OptEditBoxSubProc); + + return TRUE; + } + + case WM_COMMAND: + if ( ( (HIWORD(wParam) == BN_CLICKED) || /*(HIWORD(wParam) == EN_KILLFOCUS) ||*/ (HIWORD(wParam) == EN_CHANGE) + || ( (HIWORD(wParam) == CBN_SELCHANGE) && (LOWORD(wParam) != IDC_CBOPTPROTO) && (LOWORD(wParam) != IDC_CBOPTSTATUS)) + ) && (HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + switch (LOWORD(wParam)) + { + case IDC_EMAXLENGTH: + switch (HIWORD(wParam)) + { + case EN_KILLFOCUS: + { + BOOL translated; + int val, i; + + val = GetDlgItemInt(hwndDlg, IDC_EMAXLENGTH, &translated, FALSE); + if (translated && val > 1024) + SetDlgItemInt(hwndDlg, IDC_EMAXLENGTH, 1024, FALSE); + if (translated && val < 1) + SetDlgItemInt(hwndDlg, IDC_EMAXLENGTH, 1, FALSE); + val = GetDlgItemInt(hwndDlg, IDC_EMAXLENGTH, &translated, FALSE); + + i = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + data->proto_msg[i].max_length = val; + break; + } + } + break; + + case IDC_CBOPTPROTO: + switch (HIWORD(wParam)) + { + case CBN_SELCHANGE: + case CBN_SELENDOK: + { + int i, j, l, k, status_modes = 0, newindex = 0; + + i = SendMessage((HWND)lParam, CB_GETITEMDATA, (WPARAM)SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0), 0); + + if (i == 0) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXLENGTH), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_EMAXLENGTH), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SMAXLENGTH), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO3), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO4), FALSE); + SetDlgItemInt(hwndDlg, IDC_EMAXLENGTH, 1024, FALSE); + + if (data->proto_msg[i].flags & PROTO_POPUPDLG) + CheckRadioButton(hwndDlg, IDC_ROPTPROTO1, IDC_ROPTPROTO4, IDC_ROPTPROTO1); + else if (data->proto_msg[i].flags & PROTO_NOCHANGE) + CheckRadioButton(hwndDlg, IDC_ROPTPROTO1, IDC_ROPTPROTO4, IDC_ROPTPROTO2); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXLENGTH), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_EMAXLENGTH), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_SMAXLENGTH), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO3), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTPROTO4), TRUE); + SetDlgItemInt(hwndDlg, IDC_EMAXLENGTH, data->proto_msg[i].max_length, FALSE); + + if (data->proto_msg[i].flags & PROTO_POPUPDLG) + CheckRadioButton(hwndDlg, IDC_ROPTPROTO1, IDC_ROPTPROTO4, IDC_ROPTPROTO1); + else if (data->proto_msg[i].flags & PROTO_NOCHANGE) + CheckRadioButton(hwndDlg, IDC_ROPTPROTO1, IDC_ROPTPROTO4, IDC_ROPTPROTO2); + else if (data->proto_msg[i].flags & PROTO_THIS_MSG) + CheckRadioButton(hwndDlg, IDC_ROPTPROTO1, IDC_ROPTPROTO4, IDC_ROPTPROTO3); + else if (data->proto_msg[i].flags & PROTO_NO_MSG) + CheckRadioButton(hwndDlg, IDC_ROPTPROTO1, IDC_ROPTPROTO4, IDC_ROPTPROTO4); + } + + if (data->proto_msg[i].flags & PROTO_NO_MSG || data->proto_msg[i].flags & PROTO_THIS_MSG + || data->proto_msg[i].flags & PROTO_NOCHANGE) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG1), FALSE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG2), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG3), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG5), FALSE); + + if (data->proto_msg[i].flags & PROTO_NO_MSG || data->proto_msg[i].flags & PROTO_NOCHANGE) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG4), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG4), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), TRUE); + } + + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG2), FALSE); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTSTATUS), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG1), TRUE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG2), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG3), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG4), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG5), TRUE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG2), TRUE); + } + + if (i) + { + k = i - 1; + status_modes = CallProtoService(accounts->pa[k]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + } + else + status_modes = accounts->statusMsgFlags; + + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETCURSEL, 0, 0), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_RESETCONTENT, 0, 0); + + for (l=ID_STATUS_ONLINE; l<=ID_STATUS_OUTTOLUNCH; l++) + { + int index; + if (status_modes & Proto_Status2Flag(l)) + { + index = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_INSERTSTRING, -1, (LPARAM)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, l, GSMDF_TCHAR)); + + if (index != CB_ERR && index != CB_ERRSPACE) + { + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_SETITEMDATA, (WPARAM)index, (LPARAM)l - ID_STATUS_ONLINE); + if (j == l-ID_STATUS_ONLINE) + newindex=index; + } + } + } + + if (!newindex) + { + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_SETCURSEL, 0, 0); + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETCURSEL, 0, 0), 0); + } + else + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_SETCURSEL, (WPARAM)newindex, 0); + + if (data->status_msg[i].flags[j] & STATUS_SHOW_DLG) + CheckDlgButton(hwndDlg, IDC_COPTMSG1, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_COPTMSG1, BST_UNCHECKED); + + if (data->proto_msg[i].flags & PROTO_THIS_MSG) + { + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG4); + if (data->proto_msg[i].msg) + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, data->proto_msg[i].msg); + else + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + } + else + { + if (data->status_msg[i].flags[j] & STATUS_EMPTY_MSG) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG1); + } + else if (data->status_msg[i].flags[j] & STATUS_DEFAULT_MSG) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, GetDefaultMessage(j+ID_STATUS_ONLINE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG2); + } + else if (data->status_msg[i].flags[j] & STATUS_LAST_MSG) + { + char setting[80]; + DBVARIANT dbv, dbv2; + + if (i) + mir_snprintf(setting, SIZEOF(setting), "Last%sMsg", accounts->pa[k]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "LastMsg"); + + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + if (!DBGetContactSetting(NULL, "SimpleStatusMsg", setting, &dbv)) + { + if (dbv.pszVal) + { + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", dbv.pszVal, &dbv2) && strlen(dbv.pszVal)) + { + if ((dbv2.ptszVal) && (lstrlen(dbv2.ptszVal))) + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv2.ptszVal); + + DBFreeVariant(&dbv2); + } + } + DBFreeVariant(&dbv); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG3); + } + else if (data->status_msg[i].flags[j] & STATUS_THIS_MSG) + { + if (data->proto_msg[i].flags & PROTO_NO_MSG || data->proto_msg[i].flags & PROTO_NOCHANGE) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), TRUE); + } + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG4); + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, data->status_msg[i].msg[j]); + } + else if (data->status_msg[i].flags[j] & STATUS_LAST_STATUS_MSG) + { + char setting[80]; + DBVARIANT dbv; + + if (i) + mir_snprintf(setting, SIZEOF(setting), "%sMsg", accounts->pa[k]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "Msg"); + + if (!DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(j + ID_STATUS_ONLINE, setting), &dbv)) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG5); + } + } + break; + } + } + break; + + case IDC_ROPTPROTO1: + case IDC_ROPTPROTO2: + case IDC_ROPTPROTO3: + case IDC_ROPTPROTO4: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + { + int i, j; + + i = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETCURSEL, 0, 0), 0); + + data->proto_msg[i].flags = 0; + + if ((LOWORD(wParam) == IDC_ROPTPROTO2) || (LOWORD(wParam) == IDC_ROPTPROTO4)) + { + data->proto_msg[i].flags |= (LOWORD(wParam) == IDC_ROPTPROTO4) ? PROTO_NO_MSG : PROTO_NOCHANGE; + EnableWindow(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG1), FALSE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG2), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG3), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG4), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG5), FALSE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG2), FALSE); + } + else if (LOWORD(wParam) == IDC_ROPTPROTO3) + { + data->proto_msg[i].flags |= PROTO_THIS_MSG; + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), TRUE); + if (data->proto_msg[i].msg) + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, data->proto_msg[i].msg); + else + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + EnableWindow(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTSTATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG1), FALSE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG2), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG3), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG4), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG5), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG4); + + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG2), FALSE); + } + else if (LOWORD(wParam) == IDC_ROPTPROTO1) + { + data->proto_msg[i].flags |= PROTO_POPUPDLG; + EnableWindow(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTSTATUS), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG1), TRUE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG2), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG3), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG4), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ROPTMSG5), TRUE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_COPTMSG2), TRUE); + } + + if (LOWORD(wParam) != IDC_ROPTPROTO3) + { + if (data->status_msg[i].flags[j] & STATUS_EMPTY_MSG) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG1); + } + else if (data->status_msg[i].flags[j] & STATUS_DEFAULT_MSG) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, GetDefaultMessage(j+ID_STATUS_ONLINE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG2); + } + else if (data->status_msg[i].flags[j] & STATUS_LAST_MSG) + { + char setting[80]; + DBVARIANT dbv, dbv2; + + if (i) + mir_snprintf(setting, SIZEOF(setting), "Last%sMsg", accounts->pa[i-1]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "LastMsg"); + + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + if (!DBGetContactSetting(NULL, "SimpleStatusMsg", setting, &dbv)) + { + if (dbv.pszVal) + { + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", dbv.pszVal, &dbv2) && strlen(dbv.pszVal)) + { + if (dbv2.ptszVal && lstrlen(dbv2.ptszVal)) + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv2.ptszVal); + DBFreeVariant(&dbv2); + } + } + DBFreeVariant(&dbv); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG3); + } + else if (data->status_msg[i].flags[j] & STATUS_THIS_MSG) + { + if ((LOWORD(wParam) == IDC_ROPTPROTO2) || (LOWORD(wParam) == IDC_ROPTPROTO4)) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), TRUE); + } + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG4); + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, data->status_msg[i].msg[j]); + } + else if (data->status_msg[i].flags[j] & STATUS_LAST_STATUS_MSG) + { + char setting[80]; + DBVARIANT dbv; + + if (i) + mir_snprintf(setting, SIZEOF(setting), "%sMsg", accounts->pa[i-1]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "Msg"); + + if (!DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(j + ID_STATUS_ONLINE, setting), &dbv)) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG5); + } + } + break; + } + } + break; + + case IDC_CBOPTSTATUS: + switch (HIWORD(wParam)) + { + case CBN_SELCHANGE: + case CBN_SELENDOK: + { + int i, j; + + i = SendMessage((HWND)lParam, CB_GETITEMDATA, (WPARAM)SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0), 0); + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + + if (data->status_msg[j].flags[i] & STATUS_SHOW_DLG) + CheckDlgButton(hwndDlg, IDC_COPTMSG1, BST_CHECKED); + else + CheckDlgButton(hwndDlg, IDC_COPTMSG1, BST_UNCHECKED); + + if (data->status_msg[j].flags[i] & STATUS_EMPTY_MSG) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG1); + } + else if (data->status_msg[j].flags[i] & STATUS_DEFAULT_MSG) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, GetDefaultMessage(i+ID_STATUS_ONLINE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG2); + } + else if (data->status_msg[j].flags[i] & STATUS_LAST_MSG) + { + char setting[80]; + DBVARIANT dbv,dbv2; + + if (j) + mir_snprintf(setting, SIZEOF(setting), "Last%sMsg", accounts->pa[j-1]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "LastMsg"); + + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + if (!DBGetContactSetting(NULL, "SimpleStatusMsg", setting, &dbv)) + { + if (dbv.pszVal) + { + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", dbv.pszVal, &dbv2) && strlen(dbv.pszVal)) + { + if (dbv2.ptszVal && lstrlen(dbv2.ptszVal)) + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv2.ptszVal); + DBFreeVariant(&dbv2); + } + } + DBFreeVariant(&dbv); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG3); + } + else if (data->status_msg[j].flags[i] & STATUS_THIS_MSG) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), TRUE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG4); + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, data->status_msg[j].msg[i]); + } + else if (data->status_msg[j].flags[i] & STATUS_LAST_STATUS_MSG) + { + char setting[80]; + DBVARIANT dbv; + + if (j) + mir_snprintf(setting, SIZEOF(setting), "%sMsg", accounts->pa[j-1]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "Msg"); + + if (!DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(i + ID_STATUS_ONLINE, setting), &dbv)) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + CheckRadioButton(hwndDlg, IDC_ROPTMSG1, IDC_ROPTMSG5, IDC_ROPTMSG5); + } + break; + } + } + break; + + case IDC_COPTMSG1: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + { + int i, j; + + i = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETCURSEL, 0, 0), 0); + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + if (IsDlgButtonChecked(hwndDlg, IDC_COPTMSG1) == BST_CHECKED) + data->status_msg[j].flags[i] |= STATUS_SHOW_DLG; + else + data->status_msg[j].flags[i] &= ~STATUS_SHOW_DLG; + break; + } + } + break; + + case IDC_ROPTMSG1: + case IDC_ROPTMSG2: + case IDC_ROPTMSG3: + case IDC_ROPTMSG4: + case IDC_ROPTMSG5: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + { + int i, j; + + i = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETCURSEL, 0, 0), 0); + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + + if (LOWORD(wParam) == IDC_ROPTMSG4 && data->proto_msg[j].flags & PROTO_THIS_MSG) + break; + + data->status_msg[j].flags[i] = 0; + + if (IsDlgButtonChecked(hwndDlg, IDC_COPTMSG1) == BST_CHECKED) + data->status_msg[j].flags[i] |= STATUS_SHOW_DLG; + + if (LOWORD(wParam) == IDC_ROPTMSG1) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + data->status_msg[j].flags[i] |= STATUS_EMPTY_MSG; + } + else if (LOWORD(wParam) == IDC_ROPTMSG2) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, GetDefaultMessage(i+ID_STATUS_ONLINE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + data->status_msg[j].flags[i] |= STATUS_DEFAULT_MSG; + } + else if (LOWORD(wParam) == IDC_ROPTMSG3) + { + char setting[80]; + DBVARIANT dbv, dbv2; + + if (j) + mir_snprintf(setting, SIZEOF(setting), "Last%sMsg", accounts->pa[j-1]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "LastMsg"); + + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + if (!DBGetContactSetting(NULL, "SimpleStatusMsg", setting, &dbv)) + { + if (dbv.pszVal) + { + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", dbv.pszVal, &dbv2) && strlen(dbv.pszVal)) + { + if (dbv2.ptszVal && lstrlen(dbv2.ptszVal)) + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv2.ptszVal); + DBFreeVariant(&dbv2); + } + } + DBFreeVariant(&dbv); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + data->status_msg[j].flags[i] |= STATUS_LAST_MSG; + } + else if (LOWORD(wParam) == IDC_ROPTMSG4) + { + data->status_msg[j].flags[i] |= STATUS_THIS_MSG; + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), TRUE); + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, data->status_msg[j].msg[i]); + } + else if (LOWORD(wParam) == IDC_ROPTMSG5) + { + char setting[80]; + DBVARIANT dbv; + + if (j) + mir_snprintf(setting, SIZEOF(setting), "%sMsg", accounts->pa[j-1]->szModuleName); + else + mir_snprintf(setting, SIZEOF(setting), "Msg"); + + if (!DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(i+ID_STATUS_ONLINE, setting), &dbv)) + { + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + SetDlgItemText(hwndDlg, IDC_OPTEDIT1, _T("")); + + EnableWindow(GetDlgItem(hwndDlg, IDC_OPTEDIT1), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARSHELP), FALSE); + data->status_msg[j].flags[i] |= STATUS_LAST_STATUS_MSG; + } + break; + } + } + break; + + case IDC_OPTEDIT1: + { + int i = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETCURSEL, 0, 0), 0); + int j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + + if (HIWORD(wParam) == EN_KILLFOCUS) + { + TCHAR msg[1024]; + + if (data->proto_msg[j].flags & PROTO_THIS_MSG) + { + int len = GetDlgItemText(hwndDlg, IDC_OPTEDIT1, msg, SIZEOF(msg)); + if (len > 0) + { + if (data->proto_msg[j].msg == NULL) + data->proto_msg[j].msg = mir_tstrdup(msg); + else + { + mir_free(data->proto_msg[j].msg); + data->proto_msg[j].msg = mir_tstrdup(msg); + } + } + else + { + if (data->proto_msg[j].msg != NULL) + { + mir_free(data->proto_msg[j].msg); + data->proto_msg[j].msg = NULL; + } + } + } + else + { + GetDlgItemText(hwndDlg, IDC_OPTEDIT1, msg, SIZEOF(msg)); + lstrcpy(data->status_msg[j].msg[i], msg); + } + } + break; + } + + case IDC_VARSHELP: + variables_showhelp(hwndDlg, IDC_OPTEDIT1, VHF_FULLDLG|VHF_SETLASTSUBJECT, NULL, NULL); + break; + + case IDC_BOPTPROTO: + { + int i, j, k; + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + + if (j) + { + for (i = ID_STATUS_ONLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + { + if (accounts->statusMsgFlags & Proto_Status2Flag(i)) + { + data->status_msg[0].flags[i-ID_STATUS_ONLINE] = data->status_msg[j].flags[i-ID_STATUS_ONLINE]; + if (data->status_msg[j].flags[i-ID_STATUS_ONLINE] & STATUS_THIS_MSG) + lstrcpy(data->status_msg[0].msg[i-ID_STATUS_ONLINE], data->status_msg[j].msg[i-ID_STATUS_ONLINE]); + } + } + } + + for (k = 0; k < accounts->count; k++) + { + if (!IsAccountEnabled(accounts->pa[k]) || !CallProtoService(accounts->pa[k]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) || !(CallProtoService(accounts->pa[k]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + if (k != j - 1) + { + data->proto_msg[k+1].flags = data->proto_msg[j].flags; + if (j) + data->proto_msg[k+1].max_length = data->proto_msg[j].max_length; + + if (data->proto_msg[j].flags & PROTO_THIS_MSG) + { + int len = lstrlen(data->proto_msg[j].msg); + if (len > 0) + { + if (data->proto_msg[k+1].msg == NULL) + data->proto_msg[k+1].msg = mir_tstrdup(data->proto_msg[j].msg); + else + { + mir_free(data->proto_msg[k+1].msg); + data->proto_msg[k+1].msg = mir_tstrdup(data->proto_msg[j].msg); + } + } + else + { + if (data->proto_msg[k+1].msg != NULL) + { + mir_free(data->proto_msg[k+1].msg); + data->proto_msg[k+1].msg = NULL; + } + } + } + else if (data->proto_msg[j].flags & PROTO_POPUPDLG) + { + for (i = ID_STATUS_ONLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + { + if (CallProtoService(accounts->pa[k]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(i)) + { + data->status_msg[k + 1].flags[i - ID_STATUS_ONLINE] = data->status_msg[j].flags[i - ID_STATUS_ONLINE]; + if (data->status_msg[j].flags[i - ID_STATUS_ONLINE] & STATUS_THIS_MSG) + lstrcpy(data->status_msg[k + 1].msg[i - ID_STATUS_ONLINE], data->status_msg[j].msg[i - ID_STATUS_ONLINE]); + } + } + } + } + } + break; + } // case IDC_BOPTPROTO + + case IDC_BOPTSTATUS: + { + int status_modes, i, j, k; + + i = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTSTATUS), CB_GETCURSEL, 0, 0), 0); + j = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTPROTO), CB_GETCURSEL, 0, 0), 0); + + if (j) + status_modes = CallProtoService(accounts->pa[j-1]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + else + status_modes = accounts->statusMsgFlags; + + for (k = ID_STATUS_ONLINE; k <= ID_STATUS_OUTTOLUNCH; k++) + { + if (k - ID_STATUS_ONLINE != i && status_modes & Proto_Status2Flag(k)) + { + data->status_msg[j].flags[k - ID_STATUS_ONLINE] = data->status_msg[j].flags[i]; + if (data->status_msg[j].flags[i] & STATUS_THIS_MSG) + lstrcpy(data->status_msg[j].msg[k - ID_STATUS_ONLINE], data->status_msg[j].msg[i]); + } + } + break; + } //case IDC_BOPTSTATUS + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) + { + char szSetting[80]; + int i; + + for (i = ID_STATUS_ONLINE; i <= ID_STATUS_OUTTOLUNCH; i++) + { + if (accounts->statusMsgFlags & Proto_Status2Flag(i)) + { + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(i, "Default"), data->status_msg[0].msg[i - ID_STATUS_ONLINE]); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", StatusModeToDbSetting(i, "Flags"), (BYTE)data->status_msg[0].flags[i - ID_STATUS_ONLINE]); + + for (int j = 0; j < accounts->count; j++) + { + if (!IsAccountEnabled(accounts->pa[j])) + continue; + + if (!(CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + if (CallProtoService(accounts->pa[j]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(i)) + { + mir_snprintf(szSetting, SIZEOF(szSetting), "%sDefault", accounts->pa[j]->szModuleName); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(i, szSetting), data->status_msg[j + 1].msg[i - ID_STATUS_ONLINE]); + + mir_snprintf(szSetting, SIZEOF(szSetting), "%sFlags", accounts->pa[j]->szModuleName); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", StatusModeToDbSetting(i, szSetting), (BYTE)data->status_msg[j + 1].flags[i - ID_STATUS_ONLINE]); + } + } + } + } + + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "PutDefInList", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_COPTMSG2) == BST_CHECKED)); + + if (data->proto_ok) + { + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "ProtoFlags", (BYTE)data->proto_msg[0].flags); + + for (i = 0; i < accounts->count; i++) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sDefault", accounts->pa[i]->szModuleName); + if (data->proto_msg[i+1].msg && (data->proto_msg[i+1].flags & PROTO_THIS_MSG)) + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", szSetting, data->proto_msg[i+1].msg); +// else +// DBDeleteContactSetting(NULL, "SimpleStatusMsg", szSetting); + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sMaxLen", accounts->pa[i]->szModuleName); + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", szSetting, (WORD)data->proto_msg[i+1].max_length); + + mir_snprintf(szSetting, SIZEOF(szSetting), "Proto%sFlags", accounts->pa[i]->szModuleName); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", szSetting, (BYTE)data->proto_msg[i+1].flags); + } + } + RebuildStatusMenu(); + return TRUE; + } + break; + + case WM_DESTROY: + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_OPTEDIT1), GWLP_WNDPROC, (LONG_PTR)OldDlgProc); + if (data->proto_ok) + { + for (int i = 0; i < accounts->count + 1; ++i) + { + if (data->proto_msg[i].msg) // they want to be free, do they? + mir_free(data->proto_msg[i].msg); + } + mir_free(data->proto_msg); + } + mir_free(data->status_msg); + mir_free(data); + break; + } + return FALSE; +} + +static INT_PTR CALLBACK DlgVariablesOptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_SSECUPDTMSG, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_ESECUPDTMSG), 0); + SendDlgItemMessage(hwndDlg, IDC_SSECUPDTMSG, UDM_SETRANGE32, 1, 999); + SendDlgItemMessage(hwndDlg, IDC_SSECUPDTMSG, UDM_SETPOS, 0, MAKELONG((short)DBGetContactSettingWord(NULL, "SimpleStatusMsg", "UpdateMsgInt", 10), 0)); + SendDlgItemMessage(hwndDlg, IDC_ESECUPDTMSG, EM_LIMITTEXT, 3, 0); + + CheckDlgButton(hwndDlg, IDC_CUPDATEMSG, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "UpdateMsgOn", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CNOIDLE, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "NoUpdateOnIdle", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CNOICQREQ, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "NoUpdateOnICQReq", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CLEAVEWINAMP, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "AmpLeaveTitle", 1) ? BST_CHECKED : BST_UNCHECKED); + if (ServiceExists(MS_VARS_FORMATSTRING)) + { + CheckDlgButton(hwndDlg, IDC_CVARIABLES, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "EnableVariables", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CDATEPARSING, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ExclDateToken", 0) ? BST_CHECKED : BST_UNCHECKED); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CVARIABLES), FALSE); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_CDATEPARSING), IsDlgButtonChecked(hwndDlg, IDC_CVARIABLES) == BST_CHECKED); + + SendMessage(hwndDlg, WM_USER + 2, 0, 0); + return TRUE; + } + + case WM_USER + 2: + { + BOOL bChecked = IsDlgButtonChecked(hwndDlg, IDC_CUPDATEMSG) == BST_CHECKED; + EnableWindow(GetDlgItem(hwndDlg, IDC_ESECUPDTMSG), bChecked); + EnableWindow(GetDlgItem(hwndDlg, IDC_SSECUPDTMSG), bChecked); + EnableWindow(GetDlgItem(hwndDlg, IDC_CNOIDLE), bChecked); + EnableWindow(GetDlgItem(hwndDlg, IDC_CNOICQREQ), bChecked); + EnableWindow(GetDlgItem(hwndDlg, IDC_CLEAVEWINAMP), bChecked); + break; + } + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_ESECUPDTMSG: + { + if ((HWND)lParam != GetFocus() || HIWORD(wParam) != EN_CHANGE) return 0; + int val = GetDlgItemInt(hwndDlg, IDC_ESECUPDTMSG, NULL, FALSE); + if (val == 0 && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ESECUPDTMSG))) + SendDlgItemMessage(hwndDlg, IDC_SSECUPDTMSG, UDM_SETPOS, 0, MAKELONG((short)1, 0)); + break; + } + + case IDC_CUPDATEMSG: + SendMessage(hwndDlg, WM_USER + 2, 0, 0); + break; + + case IDC_CVARIABLES: + EnableWindow(GetDlgItem(hwndDlg, IDC_CDATEPARSING), IsDlgButtonChecked(hwndDlg, IDC_CVARIABLES) == BST_CHECKED); + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) + { + if (g_uUpdateMsgTimer) + KillTimer(NULL, g_uUpdateMsgTimer); + + int val = SendDlgItemMessage(hwndDlg, IDC_SSECUPDTMSG, UDM_GETPOS, 0, 0); + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "UpdateMsgInt", (WORD)val); + + if (IsDlgButtonChecked(hwndDlg, IDC_CUPDATEMSG) == BST_CHECKED && val) + { + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "UpdateMsgOn", (BYTE)1); + g_uUpdateMsgTimer = SetTimer(NULL, 0, val * 1000, (TIMERPROC)UpdateMsgTimerProc); + } + else + { + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "UpdateMsgOn", (BYTE)0); + } + + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "NoUpdateOnIdle", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CNOIDLE) == BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "NoUpdateOnICQReq", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CNOICQREQ) == BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "AmpLeaveTitle", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CLEAVEWINAMP) == BST_CHECKED)); + if (ServiceExists(MS_VARS_FORMATSTRING)) + { + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "EnableVariables", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CVARIABLES) == BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "ExclDateToken", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CDATEPARSING) == BST_CHECKED)); + } + return TRUE; + } + break; + } + return FALSE; +} + +static BOOL IsHistoryMsgsFound(HWND hwndDlg, int histMax) +{ + char szSetting[16]; + DBVARIANT dbv; + int j = DBGetContactSettingWord(NULL, "SimpleStatusMsg", "LMMsg", 1); + for (int i = 1; i <= histMax; ++i, --j) + { + if (j < 1) j = histMax; + mir_snprintf(szSetting, SIZEOF(szSetting), "SMsg%d", j); + if (!DBGetContactSettingTString(NULL, "SimpleStatusMsg", szSetting, &dbv)) + { + if (dbv.ptszVal != NULL && *dbv.ptszVal != '\0') + { + DBFreeVariant(&dbv); + return TRUE; + } + DBFreeVariant(&dbv); + } + } + return FALSE; +} + +static INT_PTR CALLBACK DlgAdvancedOptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + int settingValue; + + TranslateDialogDefault(hwndDlg); + + // Layout + int i_btnhide = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_ADDSTRING, 0, (LPARAM)TranslateT("Hide")); + int i_btndown = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_ADDSTRING, 0, (LPARAM)TranslateT("Show next to cancel button")); + int i_btndownflat = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_ADDSTRING, 0, (LPARAM)TranslateT("Flat, next to cancel button")); + int i_btnlist = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_ADDSTRING, 0, (LPARAM)TranslateT("Show in message list")); + + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETITEMDATA, (WPARAM)i_btnhide, 0); + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETITEMDATA, (WPARAM)i_btndown, DLG_SHOW_BUTTONS); + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETITEMDATA, (WPARAM)i_btndownflat, DLG_SHOW_BUTTONS_FLAT); + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETITEMDATA, (WPARAM)i_btnlist, DLG_SHOW_BUTTONS_INLIST); + + settingValue = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "DlgFlags", DLG_SHOW_DEFAULT); + CheckDlgButton(hwndDlg, IDC_CSTATUSLIST, settingValue & DLG_SHOW_STATUS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CPROFILES, settingValue & DLG_SHOW_STATUS_PROFILES ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CICONS1, settingValue & DLG_SHOW_STATUS_ICONS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CICONS2, settingValue & DLG_SHOW_LIST_ICONS ? BST_CHECKED : BST_UNCHECKED); + + if (!(settingValue & DLG_SHOW_STATUS)) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CPROFILES), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CICONS1), FALSE); + } + + if (settingValue & DLG_SHOW_BUTTONS) + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETCURSEL, (WPARAM)i_btndown, 0); + else if (settingValue & DLG_SHOW_BUTTONS_FLAT) + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETCURSEL, (WPARAM)i_btndownflat, 0); + else if (settingValue & DLG_SHOW_BUTTONS_INLIST) + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETCURSEL, (WPARAM)i_btnlist, 0); + else + SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_SETCURSEL, (WPARAM)i_btnhide, 0); + + if (!ServiceExists(MS_SS_GETPROFILECOUNT)) + { + TCHAR szText[100]; + mir_sntprintf(szText, SIZEOF(szText), _T("%s *"), TranslateT("Show status profiles in status list")); + SetDlgItemText(hwndDlg, IDC_CPROFILES, szText); + EnableWindow(GetDlgItem(hwndDlg, IDC_CPROFILES), FALSE); + ShowWindow(GetDlgItem(hwndDlg, IDC_NOTE1), SW_SHOW); + } + + // Misc. + settingValue = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "MaxHist", 10); + + SendDlgItemMessage(hwndDlg, IDC_SMAXHIST, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_EMAXHIST), 0); + SendDlgItemMessage(hwndDlg, IDC_SMAXHIST, UDM_SETRANGE32, 0, 25); + SendDlgItemMessage(hwndDlg, IDC_SMAXHIST, UDM_SETPOS, 0, MAKELONG((short)settingValue, 0)); + SendDlgItemMessage(hwndDlg, IDC_EMAXHIST, EM_LIMITTEXT, 2, 0); + + if (settingValue == 0) + EnableWindow(GetDlgItem(hwndDlg, IDC_CICONS2), FALSE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTHIST), IsHistoryMsgsFound(hwndDlg, settingValue)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTDEF), DBGetContactSettingWord(NULL, "SimpleStatusMsg", "DefMsgCount", 0) != 0); + + SendDlgItemMessage(hwndDlg, IDC_STIMEOUT, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_ETIMEOUT), 0); + SendDlgItemMessage(hwndDlg, IDC_STIMEOUT, UDM_SETRANGE32, 1, 60); + SendDlgItemMessage(hwndDlg, IDC_STIMEOUT, UDM_SETPOS, 0, MAKELONG((short)DBGetContactSettingByte(NULL, "SimpleStatusMsg", "DlgTime", 5), 0)); + SendDlgItemMessage(hwndDlg, IDC_ETIMEOUT, EM_LIMITTEXT, 2, 0); + + CheckDlgButton(hwndDlg, IDC_CCLOSEWND, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "AutoClose", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CRPOSWND, !DBGetContactSettingByte(NULL, "SimpleStatusMsg", "WinCentered", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CREMOVECR, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "RemoveCR", 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CSHOWCOPY, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowCopy", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CSHOWGURL, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowGoToURL", 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CSHOWSMSG, DBGetContactSettingByte(NULL, "SimpleStatusMsg", "ShowStatusMenuItem", 1) ? BST_CHECKED : BST_UNCHECKED); + + SendMessage(hwndDlg, WM_USER + 2, 0, 0); + return TRUE; + } + + case WM_USER + 2: + { + BOOL bChecked = IsDlgButtonChecked(hwndDlg, IDC_CCLOSEWND) == BST_CHECKED; + EnableWindow(GetDlgItem(hwndDlg, IDC_ETIMEOUT), bChecked); + EnableWindow(GetDlgItem(hwndDlg, IDC_STIMEOUT), bChecked); + break; + } + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_CSTATUSLIST: + { + BOOL bChecked = IsDlgButtonChecked(hwndDlg, IDC_CSTATUSLIST) == BST_CHECKED; + EnableWindow(GetDlgItem(hwndDlg, IDC_CPROFILES), bChecked && ServiceExists(MS_SS_GETPROFILECOUNT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CICONS1), bChecked); + break; + } + + case IDC_CBOPTBUTTONS: + if ((HWND)lParam != GetFocus() || HIWORD(wParam) != CBN_SELCHANGE) return 0; + break; + + case IDC_EMAXHIST: + { + if ((HWND)lParam != GetFocus() || HIWORD(wParam) != EN_CHANGE) return 0; + int val = GetDlgItemInt(hwndDlg, IDC_EMAXHIST, NULL, FALSE); + if (val > 25) + SendDlgItemMessage(hwndDlg, IDC_SMAXHIST, UDM_SETPOS, 0, MAKELONG((short)25, 0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CICONS2), val != 0); + break; + } + + case IDC_CCLOSEWND: + SendMessage(hwndDlg, WM_USER + 2, 0, 0); + break; + + case IDC_ETIMEOUT: + { + if ((HWND)lParam != GetFocus() || HIWORD(wParam) != EN_CHANGE) return 0; + int val = GetDlgItemInt(hwndDlg, IDC_ETIMEOUT, NULL, FALSE); + if (val == 0 && GetWindowTextLength(GetDlgItem(hwndDlg, IDC_ETIMEOUT))) + SendDlgItemMessage(hwndDlg, IDC_STIMEOUT, UDM_SETPOS, 0, MAKELONG((short)1, 0)); + else if (val > 60) + SendDlgItemMessage(hwndDlg, IDC_STIMEOUT, UDM_SETPOS, 0, MAKELONG((short)60, 0)); + break; + } + + case IDC_BOPTHIST: + if (MessageBox(NULL, TranslateT("Are you sure you want to clear status message history?"), TranslateT("Confirm clearing history"), MB_ICONQUESTION | MB_YESNO) == IDYES) + { + int i, max_hist_msgs; + char text[8], setting[80]; + + if (hwndSAMsgDialog) DestroyWindow(hwndSAMsgDialog); + + max_hist_msgs = DBGetContactSettingByte(NULL, "SimpleStatusMsg", "MaxHist", 10); + for (i = 1; i <= max_hist_msgs; i++) + { + mir_snprintf(text, SIZEOF(text), "SMsg%d", i); + DBWriteContactSettingTString(NULL, "SimpleStatusMsg", text, _T("")); + } + DBWriteContactSettingString(NULL, "SimpleStatusMsg", "LastMsg", ""); + for (i = 0; i < accounts->count; i++) + { + if (!IsAccountEnabled(accounts->pa[i])) + continue; + + if (!CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0)) + continue; + + if (!(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND)) + continue; + + mir_snprintf(setting, SIZEOF(setting), "Last%sMsg", accounts->pa[i]->szModuleName); + DBWriteContactSettingString(NULL, "SimpleStatusMsg", setting, ""); + } + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "LMMsg", (WORD)max_hist_msgs); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTHIST), FALSE); + } + return 0; + + case IDC_BOPTDEF: + if (MessageBox(NULL, TranslateT("Are you sure you want to clear predefined status messages?"), TranslateT("Confirm clearing predefined"), MB_ICONQUESTION | MB_YESNO) == IDYES) + { + char szSetting[16]; + int nDefMSgCount; + + if (hwndSAMsgDialog) DestroyWindow(hwndSAMsgDialog); + + nDefMSgCount = DBGetContactSettingWord(NULL, "SimpleStatusMsg", "DefMsgCount", 0); + for (int i = 1; i <= nDefMSgCount; i++) + { + mir_snprintf(szSetting, SIZEOF(szSetting), "DefMsg%d", i); + DBDeleteContactSetting(NULL, "SimpleStatusMsg", szSetting); + } + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "DefMsgCount", 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_BOPTDEF), FALSE); + } + return 0; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) + { + // Layout + int flags = 0, curSel; + + if (IsDlgButtonChecked(hwndDlg, IDC_CSTATUSLIST) == BST_CHECKED) flags |= DLG_SHOW_STATUS; + if (IsDlgButtonChecked(hwndDlg, IDC_CICONS1) == BST_CHECKED) flags |= DLG_SHOW_STATUS_ICONS; + if (IsDlgButtonChecked(hwndDlg, IDC_CICONS2) == BST_CHECKED) flags |= DLG_SHOW_LIST_ICONS; + if (IsDlgButtonChecked(hwndDlg, IDC_CPROFILES) == BST_CHECKED) flags |= DLG_SHOW_STATUS_PROFILES; + + curSel = SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_GETCURSEL, 0, 0); + if (curSel != CB_ERR) + flags |= SendMessage(GetDlgItem(hwndDlg, IDC_CBOPTBUTTONS), CB_GETITEMDATA, (WPARAM)curSel, 0); + + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "DlgFlags", (BYTE)flags); + + // Misc. + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "MaxHist", (BYTE)GetDlgItemInt(hwndDlg, IDC_EMAXHIST, NULL, FALSE)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "AutoClose", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CCLOSEWND) == BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "DlgTime", (BYTE)GetDlgItemInt(hwndDlg, IDC_ETIMEOUT, NULL, FALSE)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "WinCentered", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CRPOSWND) != BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "RemoveCR", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CREMOVECR) == BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "ShowCopy", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CSHOWCOPY) == BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "ShowGoToURL", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CSHOWGURL) == BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "ShowStatusMenuItem", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_CSHOWSMSG) == BST_CHECKED)); + RebuildStatusMenu(); + + return TRUE; + } + break; + } + return FALSE; +} + +struct StatusOptDlgData +{ + int *status; + int *setdelay; + int setglobaldelay; +}; + +static INT_PTR CALLBACK DlgStatusOptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + struct StatusOptDlgData *data = (struct StatusOptDlgData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (uMsg) + { + case WM_INITDIALOG: + { + int index, i; + + TranslateDialogDefault(hwndDlg); + + data = (struct StatusOptDlgData *)mir_alloc(sizeof(struct StatusOptDlgData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)data); + + data->status = (int *)mir_alloc(sizeof(int) * accounts->count); + data->setdelay = (int *)mir_alloc(sizeof(int) * accounts->count); + for (i = 0; i < accounts->count; ++i) + { + if (!IsAccountEnabled(accounts->pa[i]) || !(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) &~ CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + index = SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_ADDSTRING, 0, (LPARAM)accounts->pa[i]->tszAccountName); + if (index != LB_ERR && index != LB_ERRSPACE) + { + char setting[80]; + mir_snprintf(setting, SIZEOF(setting), "Startup%sStatus", accounts->pa[i]->szModuleName); + data->status[i] = DBGetContactSettingWord(NULL, "SimpleStatusMsg", setting, ID_STATUS_OFFLINE); + mir_snprintf(setting, SIZEOF(setting), "Set%sStatusDelay", accounts->pa[i]->szModuleName); + data->setdelay[i] = DBGetContactSettingWord(NULL, "SimpleStatusMsg", setting, 300); + SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_SETITEMDATA, (WPARAM)index, (LPARAM)i); + } + } + SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_SETCURSEL, 0, 0); + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_LISTPROTO, LBN_SELCHANGE), (LPARAM)GetDlgItem(hwndDlg, IDC_LISTPROTO)); + + data->setglobaldelay = DBGetContactSettingWord(NULL, "SimpleStatusMsg", "SetStatusDelay", 300); + + SendMessage(GetDlgItem(hwndDlg, IDC_SSETSTATUS), UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_ESETSTATUS), 0); + SendMessage(GetDlgItem(hwndDlg, IDC_SSETSTATUS), UDM_SETRANGE32, 0, 9000); + SendMessage(GetDlgItem(hwndDlg, IDC_ESETSTATUS), EM_LIMITTEXT, 4, 0); + + if (!DBGetContactSettingByte(NULL, "SimpleStatusMsg", "GlobalStatusDelay", 1)) + { + CheckDlgButton(hwndDlg, IDC_SPECSET, BST_CHECKED); + i = SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETCURSEL, 0, 0), 0); + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setdelay[i], FALSE); + } + else + { + CheckDlgButton(hwndDlg, IDC_SPECSET, BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setglobaldelay, FALSE); + } + + if (DBGetContactSettingByte(NULL, "SimpleStatusMsg", "StartupPopupDlg", 1)) + { + CheckDlgButton(hwndDlg, IDC_POPUPDLG, BST_CHECKED); + if (IsDlgButtonChecked(hwndDlg, IDC_SPECSET) == BST_CHECKED) + { + CheckDlgButton(hwndDlg, IDC_SPECSET, BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setglobaldelay, FALSE); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_SPECSET), FALSE); + } + else + CheckDlgButton(hwndDlg, IDC_POPUPDLG, BST_UNCHECKED); + + if (accounts->statusCount == 1 && accounts->statusMsgCount == 1) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_SPECSET), FALSE); + CheckDlgButton(hwndDlg, IDC_SPECSET, BST_UNCHECKED); //should work like when checked, but should not be checked + i = SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETCURSEL, 0, 0), 0); + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setdelay[i], FALSE); + } + + return TRUE; + } + + case WM_COMMAND: + if ( ( (HIWORD(wParam) == BN_CLICKED) || /*(HIWORD(wParam) == EN_KILLFOCUS) ||*/ (HIWORD(wParam) == EN_CHANGE) + || ( (HIWORD(wParam) == LBN_SELCHANGE) && (LOWORD(wParam) != IDC_LISTPROTO)) + ) && (HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + switch (LOWORD(wParam)) + { + case IDC_ESETSTATUS: + switch (HIWORD(wParam)) + { + case EN_KILLFOCUS: + { + BOOL translated; + int val = GetDlgItemInt(hwndDlg, IDC_ESETSTATUS, &translated, FALSE); + if (translated && val > 9000) + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, 9000, FALSE); + if (translated && val < 0) + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, 0, FALSE); + val = GetDlgItemInt(hwndDlg, IDC_ESETSTATUS, &translated, FALSE); + + if (IsDlgButtonChecked(hwndDlg, IDC_SPECSET) == BST_CHECKED || (accounts->statusCount == 1 && accounts->statusMsgCount == 1)) + { + int i = SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETCURSEL, 0, 0), 0); + data->setdelay[i] = val; + } + else + data->setglobaldelay = val; + break; + } + } + break; + + case IDC_SPECSET: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + if (SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED || (accounts->statusCount == 1 && accounts->statusMsgCount == 1)) + { + int i = SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETCURSEL, 0, 0), 0); + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setdelay[i], FALSE); + } + else + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setglobaldelay, FALSE); + break; + } + break; + + case IDC_POPUPDLG: + switch (HIWORD(wParam)) + { + case BN_CLICKED: + if (accounts->statusCount == 1 && accounts->statusMsgCount == 1) + break; + + if (SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED) + { + if (IsDlgButtonChecked(hwndDlg, IDC_SPECSET) == BST_CHECKED) + { + CheckDlgButton(hwndDlg, IDC_SPECSET, BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setglobaldelay, FALSE); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_SPECSET), FALSE); + } + else + EnableWindow(GetDlgItem(hwndDlg, IDC_SPECSET), TRUE); + break; + } + break; + + case IDC_LISTPROTO: + switch (HIWORD(wParam)) + { + case LBN_SELCHANGE: + { + int status_modes, i, l, index, newindex = 0; + + i = SendMessage((HWND)lParam, LB_GETITEMDATA, (WPARAM)SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0), 0); + status_modes = CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0) & ~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0); + + SendMessage(GetDlgItem(hwndDlg, IDC_LISTSTATUS), LB_RESETCONTENT, 0, 0); + for (l = ID_STATUS_OFFLINE; l <= ID_STATUS_OUTTOLUNCH; l++) + { + if (status_modes & Proto_Status2Flag(l) || l == ID_STATUS_OFFLINE) + { + index = SendMessage(GetDlgItem(hwndDlg, IDC_LISTSTATUS), LB_INSERTSTRING, -1, (LPARAM)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, l, GSMDF_TCHAR)); + if (index != LB_ERR && index != LB_ERRSPACE) + { + SendMessage(GetDlgItem(hwndDlg, IDC_LISTSTATUS), LB_SETITEMDATA, (WPARAM)index, (LPARAM)l - ID_STATUS_OFFLINE); + if (data->status[i] == l) + newindex = index; + } + } + } + + index = SendMessage(GetDlgItem(hwndDlg, IDC_LISTSTATUS), LB_INSERTSTRING, -1, (LPARAM)TranslateT("")); + if (index != LB_ERR && index != LB_ERRSPACE) + { + SendMessage(GetDlgItem(hwndDlg, IDC_LISTSTATUS), LB_SETITEMDATA, (WPARAM)index, (LPARAM)ID_STATUS_CURRENT-ID_STATUS_OFFLINE); + if (data->status[i] == ID_STATUS_CURRENT) + newindex = index; + } + + SendMessage(GetDlgItem(hwndDlg, IDC_LISTSTATUS), LB_SETCURSEL, (WPARAM)newindex, 0); + + if (IsDlgButtonChecked(hwndDlg, IDC_SPECSET) == BST_CHECKED || (accounts->statusCount == 1 && accounts->statusMsgCount == 1)) + SetDlgItemInt(hwndDlg, IDC_ESETSTATUS, data->setdelay[i], FALSE); + break; + } + } + break; + + case IDC_LISTSTATUS: + switch (HIWORD(wParam)) + { + case LBN_SELCHANGE: + { + int i = SendMessage((HWND)lParam, LB_GETITEMDATA, (WPARAM)SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0), 0); + int j = SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETITEMDATA, (WPARAM)SendMessage(GetDlgItem(hwndDlg, IDC_LISTPROTO), LB_GETCURSEL, 0, 0), 0); + data->status[j] = i + ID_STATUS_OFFLINE; + break; + } + } + break; + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) + { + char szSetting[80]; + for (int i = 0; i < accounts->count; i++) + { + if (!IsAccountEnabled(accounts->pa[i]) || !(CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(accounts->pa[i]->szModuleName, PS_GETCAPS, PFLAGNUM_5, 0))) + continue; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Startup%sStatus", accounts->pa[i]->szModuleName); + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", szSetting, (WORD)data->status[i]); + + mir_snprintf(szSetting, SIZEOF(szSetting), "Set%sStatusDelay", accounts->pa[i]->szModuleName); + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", szSetting, (WORD)data->setdelay[i]); + } + DBWriteContactSettingWord(NULL, "SimpleStatusMsg", "SetStatusDelay", (WORD)data->setglobaldelay); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "GlobalStatusDelay", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_SPECSET) != BST_CHECKED)); + DBWriteContactSettingByte(NULL, "SimpleStatusMsg", "StartupPopupDlg", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_POPUPDLG) == BST_CHECKED)); + return TRUE; + } + break; + + case WM_DESTROY: + mir_free(data->status); + mir_free(data->setdelay); + mir_free(data); + break; + } + return FALSE; +} + +int InitOptions(WPARAM wParam, LPARAM lParam) +{ + if (accounts->statusCount == 0) + return 0; + + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.hInstance = g_hInst; + odp.flags = ODPF_BOLDGROUPS; + + if (!ServiceExists(MS_SS_GETPROFILECOUNT)) { + odp.pszTitle = LPGEN("Status"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_STATUS); + odp.pfnDlgProc = DlgStatusOptionsProc; + Options_AddPage(wParam, &odp); + } + + if (accounts->statusMsgCount == 0) + return 0; + + odp.position = 870000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENERAL); + odp.pszTitle = LPGEN("Status Messages"); + odp.pszGroup = LPGEN("Status"); + odp.pszTab = LPGEN("General"); + odp.pfnDlgProc = DlgOptionsProc; + Options_AddPage(wParam, &odp); + + odp.pszTab = LPGEN("Variables"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_VARIABLES); + odp.pfnDlgProc = DlgVariablesOptionsProc; + Options_AddPage(wParam, &odp); + + odp.pszTab = LPGEN("Advanced"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ADVANCED); + odp.pfnDlgProc = DlgAdvancedOptionsProc; + odp.flags |= ODPF_EXPERTONLY; + Options_AddPage(wParam, &odp); + + return 0; +} diff --git a/plugins/SimpleStatusMsg/src/resource.h b/plugins/SimpleStatusMsg/src/resource.h new file mode 100644 index 0000000000..137327acac --- /dev/null +++ b/plugins/SimpleStatusMsg/src/resource.h @@ -0,0 +1,126 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDD_COPY 101 +#define IDD_AWAYMSGBOX 102 +#define IDD_OPT_GENERAL 103 +#define IDD_READAWAYMSG 104 +#define IDI_CROSS 105 +#define IDI_HISTORY 106 +#define IDI_MESSAGE 107 +#define IDI_PLUS 108 +#define IDI_CHIST 109 +#define IDI_COPY 110 +#define IDI_CSMSG 111 +#define IDR_EDITMENU 112 +#define IDD_OPT_ADVANCED 113 +#define IDD_OPT_STATUS 114 +#define IDI_GOTOURL 115 +#define IDD_OPT_VARIABLES 116 +#define IDC_BOPTDEF 1000 +#define IDC_BOPTHIST 1001 +#define IDC_OK 1002 +#define IDC_EDIT1 1003 +#define IDC_CANCEL 1004 +#define IDC_ROPTMSG1 1005 +#define IDC_ROPTMSG2 1006 +#define IDC_ROPTMSG3 1007 +#define IDC_ROPTMSG4 1008 +#define IDC_ROPTMSG5 1009 +#define IDC_SPECSET 1010 +#define IDC_MSG 1011 +#define IDC_RETRIEVING 1012 +#define IDC_CLEAVEWINAMP 1013 +#define IDC_COPY 1014 +#define IDC_CSTATUSLIST 1015 +#define IDC_CICONS2 1016 +#define IDC_CICONS1 1017 +#define IDC_CPROFILES 1018 +#define IDC_EMAXHIST 1019 +#define IDC_ETIMEOUT 1020 +#define IDC_CSHOWGURL 1021 +#define IDC_SMAXHIST 1022 +#define IDC_CCLOSEWND 1023 +#define IDC_STIMEOUT 1024 +#define IDC_CBOPTSTATUS 1025 +#define IDC_COPTMSG1 1026 +#define IDC_OPTEDIT1 1027 +#define IDC_CBOPTPROTO 1028 +#define IDC_ROPTPROTO1 1029 +#define IDC_ROPTPROTO2 1030 +#define IDC_ROPTPROTO3 1031 +#define IDC_CREMOVECR 1032 +#define IDC_CSHOWCOPY 1033 +#define IDC_EMAXLENGTH 1034 +#define IDC_SMAXLENGTH 1035 +#define IDC_COPTMSG2 1036 +#define IDC_VARSHELP 1037 +#define IDC_CBOPTBUTTONS 1038 +#define IDC_CSHOWSMSG 1039 +#define IDC_CRPOSWND 1040 +#define IDC_ESECUPDTMSG 1041 +#define IDC_CUPDATEMSG 1042 +#define IDC_SSECUPDTMSG 1043 +#define IDC_BOPTPROTO 1044 +#define IDC_BOPTSTATUS 1045 +#define IDC_LISTPROTO 1046 +#define IDC_LISTSTATUS 1047 +#define IDC_ESETSTATUS 1048 +#define IDC_SSETSTATUS 1049 +#define IDC_NOTE1 1050 +#define IDC_POPUPDLG 1051 +#define IDC_ROPTPROTO4 1052 +#define IDC_BADD 1053 +#define IDC_BDEL 1054 +#define IDC_BCLEAR 1055 +#define IDC_CNOIDLE 1056 +#define IDC_CNOICQREQ 1057 +#define IDC_CVARIABLES 1058 +#define IDC_CDATEPARSING 1059 +#define IDC_MAXLENGTH 1060 +#define IDM_VDATE 40002 +#define IDM_VWINAMPSONG 40003 +#define IDM_VRANDXY 40004 +#define IDM_VTIME 40006 +#define IDM_CUT 40007 +#define IDM_COPY 40008 +#define IDM_PASTE 40009 +#define IDM_DELETE 40010 +#define IDM_SELECTALL 40011 +#define ID__FORTUNE 40012 +#define ID__FORTUNEAWAYMSG_PROTOFORTUNEMSG 40013 +#define ID__FORTUNEAWAYMSG_STATUSFORTUNEMSG 40014 +#define ID__VARIABLES_LSSTATUSCONTACT 40015 +#define ID__VARIABLES_LSDATECONTACTFORMAT 40016 +#define ID__VARIABLES_CINFOCONTACTPROPERTY 40017 +#define ID__VARIABLES_MSTATUSPROTOCOL 40018 +#define ID__VARIABLES_LSTIMECONTACTFORMAT 40019 +#define ID__VARIABLES_DBSETTINGCONTACTMODULESETTING 40020 +#define ID__VARIABLES_TXTFILEFILELINE 40021 +#define ID__VARIABLES_IFCONDITIONTRUEFALSE 40022 +#define ID__VARIABLES_STRCMPSTRING1STRING2 40023 +#define ID__VARIABLES_STRICMPSTRING1STRING2 40024 +#define ID__VARIABLES_CDATEFORMAT 40025 +#define ID__VARIABLES_CTIMEFORMAT 40026 +#define ID__VARIABLES_REPLACESUBSTRING1STRING2 40027 +#define ID__VARIABLES_LOWERSTRING 40028 +#define ID__VARIABLES_UPPERSTRING 40029 +#define ID__VARIABLES_CONTACTSTRINGPROPERTY 40030 +#define ID__VARIABLES_SCROLLSTRINGNUMCHARSNUMCHARS 40031 +#define ID__VARIABLES_MOREVARIABLES 40032 +#define ID__VARIABLES 40033 +#define ID__FORTUNEAWAYMSG 40034 +#define IDM_VRANDMSG 40035 +#define IDM_VRANDDEFMSG 40036 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 117 +#define _APS_NEXT_COMMAND_VALUE 40037 +#define _APS_NEXT_CONTROL_VALUE 1061 +#define _APS_NEXT_SYMED_VALUE 100 +#endif +#endif diff --git a/plugins/SimpleStatusMsg/src/simplestatusmsg.h b/plugins/SimpleStatusMsg/src/simplestatusmsg.h new file mode 100644 index 0000000000..d66aba197c --- /dev/null +++ b/plugins/SimpleStatusMsg/src/simplestatusmsg.h @@ -0,0 +1,105 @@ +/* + +Simple Status Message plugin for Miranda IM +Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#ifndef SIMPLESTATUSMSG_H__ +#define SIMPLESTATUSMSG_H__ 1 + +typedef struct tagACCOUNTS +{ + PROTOACCOUNT **pa; + int count; + int statusCount; + DWORD statusFlags; + int statusMsgCount; + DWORD statusMsgFlags; +} +PROTOACCOUNTS; + +extern PROTOACCOUNTS *accounts; + +#define DLG_SHOW_STATUS 1 +#define DLG_SHOW_STATUS_ICONS 2 +#define DLG_SHOW_LIST_ICONS 4 +#define DLG_SHOW_BUTTONS 8 +#define DLG_SHOW_BUTTONS_INLIST 16 +#define DLG_SHOW_BUTTONS_FLAT 32 +#define DLG_SHOW_STATUS_PROFILES 64 +//NOTE: MAX 128 +#define DLG_SHOW_DEFAULT DLG_SHOW_STATUS | DLG_SHOW_STATUS_ICONS | DLG_SHOW_LIST_ICONS | DLG_SHOW_BUTTONS + +#define STATUS_SHOW_DLG 1 +#define STATUS_EMPTY_MSG 2 +#define STATUS_DEFAULT_MSG 4 +#define STATUS_LAST_MSG 8 +#define STATUS_THIS_MSG 16 +#define STATUS_LAST_STATUS_MSG 32 +#define STATUS_DEFAULT STATUS_SHOW_DLG | STATUS_LAST_MSG + +#define PROTO_NO_MSG 1 +#define PROTO_THIS_MSG 2 +#define PROTO_POPUPDLG 4 +#define PROTO_NOCHANGE 8 +#define PROTO_DEFAULT PROTO_NOCHANGE + +struct MsgBoxInitData +{ + char *m_szProto; + int m_iStatus; + int m_iStatusModes; + int m_iStatusMsgModes; + BOOL m_bOnEvent; + BOOL m_bOnStartup; +}; + +extern HINSTANCE g_hInst; +extern HWND hwndSAMsgDialog; + +#define MS_SIMPLESTATUSMSG_SHOWDIALOGINT "SimpleStatusMsg/ShowDialogInternal" // internal use ONLY + +/* awaymsg.cpp */ +int LoadAwayMsgModule(void); +int AwayMsgPreShutdown(void); + +/* main.cpp */ +void SetStatusMessage(const char *szProto, int initial_status_mode, int status_mode, TCHAR *message, BOOL on_startup); + +/* msgbox.cpp */ +INT_PTR CALLBACK AwayMsgBoxDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +/* options.cpp */ +int InitOptions(WPARAM wParam, LPARAM lParam); + +/* utils.cpp */ +void IconsInit(void); +HICON LoadIconEx(const char* name); +HANDLE GetIconHandle(int iconId); +void ReleaseIconEx(const char* name); +HANDLE HookEventEx(const char *szEvent, MIRANDAHOOK hookProc); +void UnhookEvents(void); +HANDLE HookProtoEvent(const char *szModule, const char *szEvent, MIRANDAHOOKPARAM hookProc); +void UnhookProtoEvents(void); +HANDLE CreateServiceFunctionEx(const char *name, MIRANDASERVICE serviceProc); +void DestroyServiceFunctionsEx(void); +int GetRandom(int from, int to); +const TCHAR *GetDefaultMessage(int status); +const char *StatusModeToDbSetting(int status, const char *suffix); +int GetCurrentStatus(const char *szProto); +int GetStartupStatus(const char *szProto); + +#endif // SIMPLESTATUSMSG_H__ diff --git a/plugins/SimpleStatusMsg/src/utils.cpp b/plugins/SimpleStatusMsg/src/utils.cpp new file mode 100644 index 0000000000..549dd957bc --- /dev/null +++ b/plugins/SimpleStatusMsg/src/utils.cpp @@ -0,0 +1,226 @@ +/* + +Simple Status Message plugin for Miranda IM +Copyright (C) 2006-2011 Bartosz 'Dezeath' Białek, (C) 2005 Harven + +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., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "commonheaders.h" +#include "simplestatusmsg.h" + +static HANDLE *hHookList = NULL; +static HANDLE *hProtoHookList = NULL; +static HANDLE *hServiceList = NULL; +static int HookCount = 0; +static int ProtoHookCount = 0; +static int ServiceCount = 0; + +struct tagiconList +{ + const TCHAR *szDescr; + const char *szName; + int defIconID; +} +static const iconList[] = +{ + { LPGENT("Delete Selected"), "cross", IDI_CROSS }, + { LPGENT("Recent Message"), "recent", IDI_HISTORY }, + { LPGENT("Predefined Message"), "predef", IDI_MESSAGE }, + { LPGENT("Add to Predefined"), "add", IDI_PLUS }, + { LPGENT("Clear History"), "clear", IDI_CHIST }, + { LPGENT("Copy Away Message"), "copy", IDI_COPY }, + { LPGENT("Change Status Message"), "csmsg", IDI_CSMSG, }, + { LPGENT("Go to URL in Away Message"), "gotourl", IDI_GOTOURL } +}; + +HANDLE hIconLibItem[SIZEOF(iconList)]; + +void IconsInit(void) +{ + SKINICONDESC sid = {0}; + char szFile[MAX_PATH]; + char szSettingName[100]; + + GetModuleFileNameA(g_hInst, szFile, MAX_PATH); + sid.cbSize = sizeof(SKINICONDESC); + sid.flags = SIDF_TCHAR; + sid.pszDefaultFile = szFile; + sid.ptszSection = _T("Simple Status Message"); + for (int i = 0; i < SIZEOF(iconList); i++) + { + mir_snprintf(szSettingName, SIZEOF(szSettingName), "SimpleStatusMsg_%s", iconList[i].szName); + sid.pszName = szSettingName; + sid.ptszDescription = (TCHAR*)iconList[i].szDescr; + sid.iDefaultIndex = -iconList[i].defIconID; + hIconLibItem[i] = Skin_AddIcon(&sid); + } +} + +HICON LoadIconEx(const char* name) +{ + char szSettingName[100]; + mir_snprintf(szSettingName, sizeof(szSettingName), "SimpleStatusMsg_%s", name); + return (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szSettingName); +} + +HANDLE GetIconHandle(int iconId) +{ + for(int i = 0; i < SIZEOF(iconList); i++) + if (iconList[i].defIconID == iconId) return hIconLibItem[i]; + return NULL; +} + +void ReleaseIconEx(const char* name) +{ + char szSettingName[100]; + mir_snprintf(szSettingName, sizeof(szSettingName), "SimpleStatusMsg_%s", name); + CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)szSettingName); +} + +HANDLE HookEventEx(const char *szEvent, MIRANDAHOOK hookProc) +{ + HookCount++; + hHookList = (HANDLE *)mir_realloc(hHookList, sizeof(HANDLE) * HookCount); + return hHookList[HookCount - 1] = HookEvent(szEvent, hookProc); +} + +void UnhookEvents(void) +{ + if (hHookList == NULL) return; + for (int i = 0; i < HookCount; ++i) + if (hHookList[i] != NULL) UnhookEvent(hHookList[i]); + mir_free(hHookList); + hHookList = NULL; + HookCount = 0; +} + +HANDLE HookProtoEvent(const char *szModule, const char *szEvent, MIRANDAHOOKPARAM hookProc) +{ + char szProtoEvent[MAXMODULELABELLENGTH]; + mir_snprintf(szProtoEvent, sizeof(szProtoEvent), "%s%s", szModule, szEvent); + ProtoHookCount++; + hProtoHookList = (HANDLE *)mir_realloc(hProtoHookList, sizeof(HANDLE) * ProtoHookCount); + return hProtoHookList[ProtoHookCount - 1] = HookEventParam(szProtoEvent, hookProc, (LPARAM)szModule); +} + +void UnhookProtoEvents(void) +{ + if (hProtoHookList == NULL) return; + for (int i = 0; i < ProtoHookCount; ++i) + if (hProtoHookList[i] != NULL) UnhookEvent(hProtoHookList[i]); + mir_free(hProtoHookList); + hProtoHookList = NULL; + ProtoHookCount = 0; +} + +HANDLE CreateServiceFunctionEx(const char *name, MIRANDASERVICE serviceProc) +{ + ServiceCount++; + hServiceList = (HANDLE *)mir_realloc(hServiceList, sizeof(HANDLE) * ServiceCount); + return hServiceList[ServiceCount - 1] = CreateServiceFunction(name, serviceProc); +} + +void DestroyServiceFunctionsEx(void) +{ + for (int i = 0; i < ServiceCount; ++i) + if (hServiceList[i] != NULL) DestroyServiceFunction(hServiceList[i]); + mir_free(hServiceList); + ServiceCount = 0; +} + +// Generate random number in a specified range +int GetRandom(int from, int to) +{ + if ((to - from) < 1) return from; + unsigned randnum; + CallService(MS_UTILS_GETRANDOM, sizeof(randnum), (LPARAM)&randnum); + return ((randnum % (to - from + 1)) + from); +} + +// From SRAway module +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; +} + +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; +} + +int GetCurrentStatus(const char *szProto) +{ + if (szProto) + { + char szSetting[80]; + mir_snprintf(szSetting, SIZEOF(szSetting), "Cur%sStatus", szProto); + return (int)DBGetContactSettingWord(NULL, "SimpleStatusMsg", szSetting, ID_STATUS_OFFLINE); + + } + return CallService(MS_CLIST_GETSTATUSMODE, 0, 0); +} + +int GetStartupStatus(const char *szProto) +{ + if (szProto) + { + int status_mode; + char szSetting[80]; + + mir_snprintf(szSetting, SIZEOF(szSetting), "Startup%sStatus", szProto); + status_mode = DBGetContactSettingWord(NULL, "SimpleStatusMsg", szSetting, ID_STATUS_OFFLINE); + if (status_mode == ID_STATUS_CURRENT) + { + // load status used for this proto last time + mir_snprintf(szSetting, SIZEOF(szSetting), "Last%sStatus", szProto); + status_mode = DBGetContactSettingWord(NULL, "SimpleStatusMsg", szSetting, ID_STATUS_OFFLINE); + } + return status_mode; + } + return (int)DBGetContactSettingWord(NULL, "SimpleStatusMsg", "StartupStatus", ID_STATUS_OFFLINE); +} -- cgit v1.2.3