From 0fb39531240a0a23e92c0456fe72e26027740696 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 19 Jun 2018 12:43:27 +0300 Subject: StatusManager: - project structure linearized; - AAA flag "Use same settings wasn't saved across Miranda starts; - perversion with declaring static arrays in commonstatus.h removed --- .../src/AdvancedAutoAway/aaa_msgoptions.cpp | 188 ---- .../src/AdvancedAutoAway/aaa_options.cpp | 461 -------- .../src/AdvancedAutoAway/advancedautoaway.cpp | 553 ---------- .../src/AdvancedAutoAway/advancedautoaway.h | 46 - .../StatusManager/src/KeepStatus/keepstatus.cpp | 1102 -------------------- plugins/StatusManager/src/KeepStatus/keepstatus.h | 112 -- .../StatusManager/src/KeepStatus/ks_options.cpp | 487 --------- .../StatusManager/src/StartupStatus/ss_options.cpp | 879 ---------------- .../src/StartupStatus/ss_profiles.cpp | 332 ------ .../src/StartupStatus/ss_toolbars.cpp | 72 -- .../src/StartupStatus/startupstatus.cpp | 461 -------- .../src/StartupStatus/startupstatus.h | 138 --- plugins/StatusManager/src/aaa_options.cpp | 627 +++++++++++ plugins/StatusManager/src/advancedautoaway.cpp | 555 ++++++++++ plugins/StatusManager/src/advancedautoaway.h | 48 + plugins/StatusManager/src/commonstatus.cpp | 14 + plugins/StatusManager/src/commonstatus.h | 16 +- plugins/StatusManager/src/confirmdialog.cpp | 13 +- plugins/StatusManager/src/keepstatus.cpp | 1102 ++++++++++++++++++++ plugins/StatusManager/src/keepstatus.h | 112 ++ plugins/StatusManager/src/ks_options.cpp | 487 +++++++++ plugins/StatusManager/src/ss_options.cpp | 879 ++++++++++++++++ plugins/StatusManager/src/ss_profiles.cpp | 332 ++++++ plugins/StatusManager/src/ss_toolbars.cpp | 72 ++ plugins/StatusManager/src/startupstatus.cpp | 461 ++++++++ plugins/StatusManager/src/startupstatus.h | 138 +++ plugins/StatusManager/src/stdafx.h | 6 +- 27 files changed, 4848 insertions(+), 4845 deletions(-) delete mode 100644 plugins/StatusManager/src/AdvancedAutoAway/aaa_msgoptions.cpp delete mode 100644 plugins/StatusManager/src/AdvancedAutoAway/aaa_options.cpp delete mode 100644 plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp delete mode 100644 plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.h delete mode 100644 plugins/StatusManager/src/KeepStatus/keepstatus.cpp delete mode 100644 plugins/StatusManager/src/KeepStatus/keepstatus.h delete mode 100644 plugins/StatusManager/src/KeepStatus/ks_options.cpp delete mode 100644 plugins/StatusManager/src/StartupStatus/ss_options.cpp delete mode 100644 plugins/StatusManager/src/StartupStatus/ss_profiles.cpp delete mode 100644 plugins/StatusManager/src/StartupStatus/ss_toolbars.cpp delete mode 100644 plugins/StatusManager/src/StartupStatus/startupstatus.cpp delete mode 100644 plugins/StatusManager/src/StartupStatus/startupstatus.h create mode 100644 plugins/StatusManager/src/aaa_options.cpp create mode 100644 plugins/StatusManager/src/advancedautoaway.cpp create mode 100644 plugins/StatusManager/src/advancedautoaway.h create mode 100644 plugins/StatusManager/src/keepstatus.cpp create mode 100644 plugins/StatusManager/src/keepstatus.h create mode 100644 plugins/StatusManager/src/ks_options.cpp create mode 100644 plugins/StatusManager/src/ss_options.cpp create mode 100644 plugins/StatusManager/src/ss_profiles.cpp create mode 100644 plugins/StatusManager/src/ss_toolbars.cpp create mode 100644 plugins/StatusManager/src/startupstatus.cpp create mode 100644 plugins/StatusManager/src/startupstatus.h (limited to 'plugins/StatusManager/src') diff --git a/plugins/StatusManager/src/AdvancedAutoAway/aaa_msgoptions.cpp b/plugins/StatusManager/src/AdvancedAutoAway/aaa_msgoptions.cpp deleted file mode 100644 index 2f4228af74..0000000000 --- a/plugins/StatusManager/src/AdvancedAutoAway/aaa_msgoptions.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "..\stdafx.h" - -struct AAMSGSETTING -{ - short useCustom; - int status; - char* msg; -}; - -char *StatusModeToDbSetting(int status, const char *suffix); - -void DisableDialog(HWND hwndDlg) -{ - EnableWindow(GetDlgItem(hwndDlg, IDC_STATUS), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADUSECUSTOM), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RADUSEMIRANDA), FALSE); -} - -INT_PTR CALLBACK DlgProcAutoAwayMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static AAMSGSETTING** settings; - static int last, count; - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - ShowWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), ServiceExists(MS_VARS_SHOWHELP) ? SW_SHOW : SW_HIDE); - count = 0; - last = -1; - - PROTOACCOUNT** proto; - int protoCount = 0; - Proto_EnumAccounts(&protoCount, &proto); - if (protoCount <= 0) { - DisableDialog(hwndDlg); - break; - } - - DWORD protoModeMsgFlags = 0; - for (int i = 0; i < protoCount; i++) - if (CallProtoService(proto[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND & ~PF1_INDIVMODEMSG) - protoModeMsgFlags |= CallProtoService(proto[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); - - if (protoModeMsgFlags == 0) { - DisableDialog(hwndDlg); - break; - } - - settings = (AAMSGSETTING**)mir_alloc(sizeof(AAMSGSETTING*)); - count = 0; - for (int i = 0; i < _countof(statusModeList); i++) { - if (!(protoModeMsgFlags & Proto_Status2Flag(statusModeList[i]))) - continue; - - int j = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)Clist_GetStatusModeDescription(statusModeList[i], 0)); - SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, j, statusModeList[i]); - settings = (AAMSGSETTING**)mir_realloc(settings, (count + 1) * sizeof(AAMSGSETTING*)); - settings[count] = (AAMSGSETTING*)mir_alloc(sizeof(AAMSGSETTING)); - settings[count]->status = statusModeList[i]; - - DBVARIANT dbv; - if (!db_get(0, AAAMODULENAME, StatusModeToDbSetting(statusModeList[i], SETTING_STATUSMSG), &dbv)) { - settings[count]->msg = (char*)mir_alloc(mir_strlen(dbv.pszVal) + 1); - mir_strcpy(settings[count]->msg, dbv.pszVal); - db_free(&dbv); - } - else settings[count]->msg = nullptr; - - settings[count]->useCustom = db_get_b(0, AAAMODULENAME, StatusModeToDbSetting(statusModeList[i], SETTING_MSGCUSTOM), FALSE); - count += 1; - } - SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETCURSEL, 0, 0); - SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); - } - break; - - case WM_COMMAND: - if (((HIWORD(wParam) == EN_CHANGE) || (HIWORD(wParam) == BN_CLICKED)) && ((HWND)lParam == GetFocus())) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - switch (LOWORD(wParam)) { - case IDC_RADUSEMIRANDA: - CheckDlgButton(hwndDlg, IDC_RADUSECUSTOM, BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADUSEMIRANDA) ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); - EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); - settings[SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0)]->useCustom = IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM); - break; - - case IDC_RADUSECUSTOM: - CheckDlgButton(hwndDlg, IDC_RADUSEMIRANDA, BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM) ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); - EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); - settings[SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0)]->useCustom = IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM); - break; - - case IDC_STATUS: - if (HIWORD(wParam) == CBN_SELCHANGE) { - int i = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0); - int len = SendDlgItemMessage(hwndDlg, IDC_STATUSMSG, WM_GETTEXTLENGTH, 0, 0); - if (last != -1) { - if (settings[last]->msg == nullptr) - settings[last]->msg = (char*)mir_alloc(len + 1); - else - settings[last]->msg = (char*)mir_realloc(settings[last]->msg, len + 1); - GetDlgItemTextA(hwndDlg, IDC_STATUSMSG, settings[last]->msg, (len + 1)); - } - - if (i != -1) { - if (settings[i]->msg != nullptr) - SetDlgItemTextA(hwndDlg, IDC_STATUSMSG, settings[i]->msg); - else { - ptrW msgw((wchar_t*)CallService(MS_AWAYMSG_GETSTATUSMSGW, settings[i]->status, 0)); - SetDlgItemText(hwndDlg, IDC_STATUSMSG, (msgw != nullptr) ? msgw : L""); - } - - if (settings[i]->useCustom) { - EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), TRUE); - CheckDlgButton(hwndDlg, IDC_RADUSECUSTOM, BST_CHECKED); - CheckDlgButton(hwndDlg, IDC_RADUSEMIRANDA, BST_UNCHECKED); - } - else { - EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), FALSE); - CheckDlgButton(hwndDlg, IDC_RADUSEMIRANDA, BST_CHECKED); - CheckDlgButton(hwndDlg, IDC_RADUSECUSTOM, BST_UNCHECKED); - } - } - last = i; - } - break; - - case IDC_VARIABLESHELP: - CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_STATUSMSG), 0); - break; - } - break; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case PSN_WIZFINISH: - AAALoadOptions(); - break; - - case PSN_APPLY: - SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); - for (int i = 0; i < count; i++) { - db_set_b(0, AAAMODULENAME, StatusModeToDbSetting(settings[i]->status, SETTING_MSGCUSTOM), (BYTE)settings[i]->useCustom); - if ((settings[i]->useCustom) && (settings[i]->msg != nullptr) && (settings[i]->msg[0] != '\0')) - db_set_s(0, AAAMODULENAME, StatusModeToDbSetting(settings[i]->status, SETTING_STATUSMSG), settings[i]->msg); - } - break; - } - break; - - case WM_DESTROY: - for (int i = 0; i < count; i++) { - mir_free(settings[i]->msg); - mir_free(settings[i]); - } - mir_free(settings); - break; - } - - return FALSE; -} diff --git a/plugins/StatusManager/src/AdvancedAutoAway/aaa_options.cpp b/plugins/StatusManager/src/AdvancedAutoAway/aaa_options.cpp deleted file mode 100644 index 2176847926..0000000000 --- a/plugins/StatusManager/src/AdvancedAutoAway/aaa_options.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* -AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) -Copyright 2003-2006 P. Boon - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "..\stdafx.h" - -int LoadAutoAwaySetting(SMProto &autoAwaySetting, char* protoName); - -INT_PTR CALLBACK DlgProcAutoAwayMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); - -static BOOL bSettingSame = FALSE; - -///////////////////////////////////////////////////////////////////////////////////////// -// Dialog service functions - -static int WriteAutoAwaySetting(SMProto &autoAwaySetting, char *protoName) -{ - char setting[128]; - mir_snprintf(setting, "%s_OptionFlags", protoName); - db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.optionFlags); - mir_snprintf(setting, "%s_AwayTime", protoName); - db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.awayTime); - mir_snprintf(setting, "%s_NATime", protoName); - db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.naTime); - mir_snprintf(setting, "%s_StatusFlags", protoName); - db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.statusFlags); - mir_snprintf(setting, "%s_Lv1Status", protoName); - db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.lv1Status); - mir_snprintf(setting, "%s_Lv2Status", protoName); - db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.lv2Status); - - return 0; -} - -static void SetDialogItems(HWND hwndDlg, SMProto *setting) -{ - bool bSetNA = (setting->optionFlags & FLAG_SETNA) != 0; - - bool bIsTimed = (setting->optionFlags & FLAG_ONMOUSE) != 0; - bool bSaver = (setting->optionFlags & FLAG_ONSAVER) != 0; - bool bFullScr = (setting->optionFlags & FLAG_FULLSCREEN) != 0; - bool bOnLock = (setting->optionFlags & FLAG_ONLOCK) != 0; - bool bOnTS = (setting->optionFlags & FLAG_ONTS) != 0; - bool bAnyOption = bIsTimed | bSaver | bFullScr | bOnLock | bOnTS; - - CheckDlgButton(hwndDlg, IDC_FULLSCREEN, bFullScr ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SCREENSAVE, bSaver ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_ONLOCK, (setting->optionFlags & FLAG_ONLOCK) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_ONTSDISCONNECT, bOnTS ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_TIMED, bIsTimed ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SETNA, bSetNA ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CONFIRM, (setting->optionFlags & FLAG_CONFIRM) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_RESETSTATUS, (setting->optionFlags & FLAG_RESET) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_ENTERIDLE, (setting->optionFlags & FLAG_ENTERIDLE) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_MONITORMIRANDA, (setting->optionFlags & FLAG_MONITORMIRANDA) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_LV2ONINACTIVE, (setting->optionFlags & FLAG_LV2ONINACTIVE) != 0 ? BST_CHECKED : BST_UNCHECKED); - - SetDlgItemInt(hwndDlg, IDC_AWAYTIME, setting->awayTime, FALSE); - SetDlgItemInt(hwndDlg, IDC_NATIME, setting->naTime, FALSE); - - EnableWindow(GetDlgItem(hwndDlg, IDC_SETNA), bIsTimed); - EnableWindow(GetDlgItem(hwndDlg, IDC_LV2ONINACTIVE), bIsTimed && bSetNA); - EnableWindow(GetDlgItem(hwndDlg, IDC_MONITORMIRANDA), bIsTimed); - EnableWindow(GetDlgItem(hwndDlg, IDC_AWAYTIME), bIsTimed); - EnableWindow(GetDlgItem(hwndDlg, IDC_LV1AFTERSTR), bIsTimed); - - EnableWindow(GetDlgItem(hwndDlg, IDC_LV1STATUS), bAnyOption); - EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSLIST), bAnyOption); - EnableWindow(GetDlgItem(hwndDlg, IDC_RESETSTATUS), bAnyOption && IsDlgButtonChecked(hwndDlg, IDC_LV2ONINACTIVE)); - EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIRM), bAnyOption && IsDlgButtonChecked(hwndDlg, IDC_LV2ONINACTIVE) && IsDlgButtonChecked(hwndDlg, IDC_RESETSTATUS)); - - EnableWindow(GetDlgItem(hwndDlg, IDC_NATIME), bSetNA && bIsTimed); - EnableWindow(GetDlgItem(hwndDlg, IDC_SETNASTR), bSetNA && bIsTimed); - EnableWindow(GetDlgItem(hwndDlg, IDC_SETNASTR), bSetNA && bIsTimed); - EnableWindow(GetDlgItem(hwndDlg, IDC_LV2STATUS), bSetNA && bIsTimed); - - EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOL), !bSettingSame); -} - -static SMProto* GetSetting(HWND hwndDlg, SMProto *sameSetting) -{ - if (bSettingSame) - return sameSetting; - - int iItem = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_GETCURSEL, 0, 0); - if (iItem == -1) - return nullptr; - - INT_PTR iData = (INT_PTR)SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_GETITEMDATA, iItem, 0); - return (iData == -1) ? nullptr : (SMProto*)iData; -} - -static void SetDialogStatus(HWND hwndDlg, SMProto *sameSetting) -{ - SMProto *setting = GetSetting(hwndDlg, sameSetting); - if (setting == nullptr) - return; - - // create columns - HWND hList = GetDlgItem(hwndDlg, IDC_STATUSLIST); - ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); - - LVCOLUMN lvCol = { 0 }; - lvCol.mask = LVCF_WIDTH | LVCF_TEXT; - lvCol.pszText = TranslateT("Status"); - lvCol.cx = 118; - ListView_InsertColumn(hList, 0, &lvCol); - - // get pointer to settings - SetDialogItems(hwndDlg, setting); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Rules dialog window procedure - -static TProtoSettings optionSettings; - -static INT_PTR CALLBACK DlgProcAutoAwayRulesOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static SMProto* sameSetting; - SMProto *setting; - static int init; - - switch (msg) { - case WM_INITDIALOG: - init = TRUE; - TranslateDialogDefault(hwndDlg); - - // copy the settings - optionSettings = protoList; - - sameSetting = (SMProto*)mir_alloc(sizeof(SMProto)); - LoadAutoAwaySetting(*sameSetting, SETTING_ALL); - - // fill list from currentProtoSettings - { - for (auto &p : optionSettings) { - int item = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_ADDSTRING, 0, (LPARAM)p->m_tszAccName); - SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_SETITEMDATA, item, (LPARAM)p); - } - } - // set cursor to first protocol - SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_SETCURSEL, 0, 0); - - // status list - SetDialogStatus(hwndDlg, sameSetting); - - SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_PROTOCOL, (LPARAM)0x11111111); - init = FALSE; - break; - - case WM_COMMAND: - if ((HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == BN_CLICKED) && (HWND)lParam == GetFocus()) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - setting = GetSetting(hwndDlg, sameSetting); - if (!setting) - break; - - switch (LOWORD(wParam)) { - case IDC_PROTOCOL: - // status listview - init = TRUE; - { - HWND hList = GetDlgItem(hwndDlg, IDC_STATUSLIST); - ListView_DeleteAllItems(hList); - - int flags = 0; - if (!bSettingSame) - flags = CallProtoService(setting->m_szName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(setting->m_szName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0); - - LVITEM lvItem = { 0 }; - lvItem.mask = LVIF_TEXT | LVIF_PARAM; - lvItem.iItem = 0; - lvItem.iSubItem = 0; - for (int i = 0; i < _countof(statusModeList); i++) { - if ((flags & statusModePf2List[i]) || (statusModePf2List[i] == PF2_OFFLINE) || (bSettingSame)) { - lvItem.pszText = Clist_GetStatusModeDescription(statusModeList[i], 0); - lvItem.lParam = (LPARAM)statusModePf2List[i]; - ListView_InsertItem(hList, &lvItem); - ListView_SetCheckState(hList, lvItem.iItem, setting->statusFlags & statusModePf2List[i] ? TRUE : FALSE); - lvItem.iItem++; - } - } - } - init = FALSE; - // status dropdown boxes - { - int flags = 0; - if (!bSettingSame) - flags = CallProtoService(setting->m_szName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(setting->m_szName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0); - - // clear box and add new status, loop status and check if compatible with proto - SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_RESETCONTENT, 0, 0); - SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_RESETCONTENT, 0, 0); - for (int i = 0; i < _countof(statusModeList); i++) { - if ((flags & statusModePf2List[i]) || statusModePf2List[i] == PF2_OFFLINE || bSettingSame) { - wchar_t *statusMode = Clist_GetStatusModeDescription(statusModeList[i], 0); - int item = SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_ADDSTRING, 0, (LPARAM)statusMode); - SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_SETITEMDATA, item, (LPARAM)statusModeList[i]); - item = SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_ADDSTRING, 0, (LPARAM)statusMode); - SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_SETITEMDATA, item, (LPARAM)statusModeList[i]); - if (statusModeList[i] == setting->lv1Status) { - SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_SETCURSEL, (WPARAM)item, 0); - SetDlgItemText(hwndDlg, IDC_SETNASTR, CMStringW(FORMAT, TranslateT("minutes of %s mode"), statusMode)); - } - if (statusModeList[i] == setting->lv2Status) - SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_SETCURSEL, (WPARAM)item, 0); - } - } - } - SetDialogItems(hwndDlg, setting); - break; - - case IDC_LV1STATUS: - if (HIWORD(wParam) == CBN_SELCHANGE) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - setting->lv1Status = (int)SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_GETCURSEL, 0, 0), 0); - SetDlgItemText(hwndDlg, IDC_SETNASTR, CMStringW(FORMAT, TranslateT("minutes of %s mode"), Clist_GetStatusModeDescription(setting->lv1Status, 0))); - break; - - case IDC_LV2STATUS: - if (HIWORD(wParam) == CBN_SELCHANGE) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - setting->lv2Status = (int)SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_GETCURSEL, 0, 0), 0); - break; - - case IDC_FULLSCREEN: - setting->optionFlags ^= FLAG_FULLSCREEN; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_SCREENSAVE: - setting->optionFlags ^= FLAG_ONSAVER; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_ONLOCK: - setting->optionFlags ^= FLAG_ONLOCK; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_ONTSDISCONNECT: - setting->optionFlags ^= FLAG_ONTS; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_TIMED: - setting->optionFlags ^= FLAG_ONMOUSE; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_SETNA: - setting->optionFlags ^= FLAG_SETNA; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_AWAYTIME: - setting->awayTime = GetDlgItemInt(hwndDlg, IDC_AWAYTIME, nullptr, FALSE); - break; - - case IDC_NATIME: - setting->naTime = GetDlgItemInt(hwndDlg, IDC_NATIME, nullptr, FALSE); - break; - - case IDC_LV2ONINACTIVE: - setting->optionFlags ^= FLAG_LV2ONINACTIVE; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_CONFIRM: - setting->optionFlags ^= FLAG_CONFIRM; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_RESETSTATUS: - setting->optionFlags ^= FLAG_RESET; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_MONITORMIRANDA: - setting->optionFlags ^= FLAG_MONITORMIRANDA; - SetDialogItems(hwndDlg, setting); - break; - - case IDC_ENTERIDLE: - setting->optionFlags ^= FLAG_ENTERIDLE; - SetDialogItems(hwndDlg, setting); - break; - } - break; - - case WM_SHOWWINDOW: - init = TRUE; - - if (setting = GetSetting(hwndDlg, sameSetting)) - SetDialogItems(hwndDlg, setting); - - SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_PROTOCOL, (LPARAM)0x11111111); - init = FALSE; - break; - - case WM_NOTIFY: - switch (((NMHDR*)lParam)->idFrom) { - case IDC_STATUSLIST: - if (init) - break; - - switch (((NMHDR*)lParam)->code) { - case LVN_ITEMCHANGED: - NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; - if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_STATUSLIST)) && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK)) { - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - if (setting = GetSetting(hwndDlg, sameSetting)) { - HWND hList = GetDlgItem(hwndDlg, IDC_STATUSLIST); - LVITEM lvItem = { 0 }; - lvItem.mask = LVIF_PARAM; - lvItem.iItem = nmlv->iItem; - ListView_GetItem(hList, &lvItem); - int pf2Status = lvItem.lParam; - if (ListView_GetCheckState(hList, lvItem.iItem)) - setting->statusFlags |= pf2Status; - else - setting->statusFlags &= ~pf2Status; - } - } - break; - } - break; - } - - switch (((LPNMHDR)lParam)->code) { - case PSN_WIZFINISH: - AAALoadOptions(); - break; - - case PSN_APPLY: - if (bSettingSame) - WriteAutoAwaySetting(*sameSetting, SETTING_ALL); - else { - for (auto &it : optionSettings) - WriteAutoAwaySetting(*it, it->m_szName); - } - } - break; - - case WM_DESTROY: - optionSettings.destroy(); - mir_free(sameSetting); - break; - } - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// General options window procedure - -static INT_PTR CALLBACK DlgProcAutoAwayGeneralOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - CheckDlgButton(hwndDlg, IDC_IGNLOCK, db_get_b(0, AAAMODULENAME, SETTING_IGNLOCK, FALSE) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_IGNSYSKEYS, db_get_b(0, AAAMODULENAME, SETTING_IGNSYSKEYS, FALSE) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_IGNALTCOMBO, db_get_b(0, AAAMODULENAME, SETTING_IGNALTCOMBO, FALSE) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_MONITORMOUSE, db_get_b(0, AAAMODULENAME, SETTING_MONITORMOUSE, BST_CHECKED) != 0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_MONITORKEYBOARD, db_get_b(0, AAAMODULENAME, SETTING_MONITORKEYBOARD, BST_CHECKED) != 0 ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemInt(hwndDlg, IDC_AWAYCHECKTIMEINSECS, db_get_w(0, AAAMODULENAME, SETTING_AWAYCHECKTIMEINSECS, 5), FALSE); - SetDlgItemInt(hwndDlg, IDC_CONFIRMDELAY, db_get_w(0, AAAMODULENAME, SETTING_CONFIRMDELAY, 5), FALSE); - CheckDlgButton(hwndDlg, bSettingSame ? IDC_SAMESETTINGS : IDC_PERPROTOCOLSETTINGS, BST_CHECKED); - break; - - case WM_COMMAND: - if ((HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == BN_CLICKED) && (HWND)lParam == GetFocus()) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - switch (LOWORD(wParam)) { - case IDC_MONITORMOUSE: - CheckDlgButton(hwndDlg, IDC_MONITORMOUSE, (((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD))) || (IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)) ? BST_CHECKED : BST_UNCHECKED)); - break; - - case IDC_MONITORKEYBOARD: - CheckDlgButton(hwndDlg, IDC_MONITORKEYBOARD, (((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD))) || (IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD)) ? BST_CHECKED : BST_UNCHECKED)); - break; - - case IDC_SAMESETTINGS: - case IDC_PERPROTOCOLSETTINGS: - bSettingSame = IsDlgButtonChecked(hwndDlg, IDC_SAMESETTINGS); - break; - } - break; - - case WM_NOTIFY: - if (((LPNMHDR)lParam)->idFrom == 0) { - switch (((LPNMHDR)lParam)->code) { - case PSN_WIZFINISH: - AAALoadOptions(); - break; - - case PSN_APPLY: - db_set_b(0, AAAMODULENAME, SETTING_IGNLOCK, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_IGNLOCK)); - db_set_b(0, AAAMODULENAME, SETTING_IGNSYSKEYS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_IGNSYSKEYS)); - db_set_b(0, AAAMODULENAME, SETTING_IGNALTCOMBO, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_IGNALTCOMBO)); - db_set_b(0, AAAMODULENAME, SETTING_SAMESETTINGS, (BYTE)bSettingSame); - db_set_w(0, AAAMODULENAME, SETTING_AWAYCHECKTIMEINSECS, (WORD)GetDlgItemInt(hwndDlg, IDC_AWAYCHECKTIMEINSECS, nullptr, FALSE)); - db_set_w(0, AAAMODULENAME, SETTING_CONFIRMDELAY, (WORD)GetDlgItemInt(hwndDlg, IDC_CONFIRMDELAY, nullptr, FALSE)); - db_set_b(0, AAAMODULENAME, SETTING_MONITORMOUSE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)); - db_set_b(0, AAAMODULENAME, SETTING_MONITORKEYBOARD, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD)); - } - } - break; - } - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Options initialization procedure - -int AutoAwayOptInitialise(WPARAM wParam, LPARAM) -{ - OPTIONSDIALOGPAGE odp = { 0 }; - odp.position = 1000000000; - odp.hInstance = g_plugin.getInst(); - odp.flags = ODPF_BOLDGROUPS; - odp.szGroup.a = LPGEN("Status"); - odp.szTitle.a = LPGEN("Auto away"); - - odp.szTab.a = LPGEN("General"); - odp.pfnDlgProc = DlgProcAutoAwayGeneralOpts; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENAUTOAWAY); - Options_AddPage(wParam, &odp, AAALangPack); - - odp.szTab.a = LPGEN("Rules"); - odp.pfnDlgProc = DlgProcAutoAwayRulesOpts; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AUTOAWAY); - Options_AddPage(wParam, &odp, AAALangPack); - - odp.szTab.a = LPGEN("Status messages"); - odp.pfnDlgProc = DlgProcAutoAwayMsgOpts; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AUTOAWAYMSG); - Options_AddPage(wParam, &odp, AAALangPack); - return 0; -} diff --git a/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp b/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp deleted file mode 100644 index 7981175e5f..0000000000 --- a/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* - AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - Some code is copied from Miranda's AutoAway module -*/ - -#include "..\stdafx.h" - -#ifdef _DEBUG -#define SECS_PER_MINUTE 20 /* speedup */ -#else -#define SECS_PER_MINUTE 60 /* default I believe */ -#endif - -///////////////////////////////////////////////////////////////////////////////////////// - -int AAALangPack; - -static HANDLE hEvents[3]; - -static BOOL ignoreLockKeys = FALSE; -static BOOL ignoreSysKeys = FALSE; -static BOOL ignoreAltCombo = FALSE; -static BOOL monitorMouse = TRUE; -static BOOL monitorKeyboard = TRUE; -static HWND confirmDialog; -static int mouseStationaryTimer; -HHOOK hMirandaMouseHook = nullptr; -HHOOK hMirandaKeyBoardHook = nullptr; -#pragma data_seg("Shared") -DWORD lastInput = 0; -POINT lastMousePos = { 0 }; -HHOOK hMouseHook = nullptr; -HHOOK hKeyBoardHook = nullptr; -#pragma data_seg() -#pragma comment(linker, "/section:Shared,rws") -DWORD lastMirandaInput = 0; -static UINT_PTR hAutoAwayTimer; -// prototypes -extern DWORD StatusModeToProtoFlag(int status); -static int HookWindowsHooks(int hookMiranda, int hookAll); -static int UnhookWindowsHooks(); -static LRESULT CALLBACK MouseHookFunction(int code, WPARAM wParam, LPARAM lParam); -static LRESULT CALLBACK KeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam); -static LRESULT CALLBACK MirandaMouseHookFunction(int code, WPARAM wParam, LPARAM lParam); -static LRESULT CALLBACK MirandaKeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam); -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); - -static VOID CALLBACK AutoAwayTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); -extern int AutoAwayOptInitialise(WPARAM wParam, LPARAM lParam); -extern char *StatusModeToDbSetting(int status, const char *suffix); - -///////////////////////////////////////////////////////////////////////////////////////// -// Load from DB - -void AAAUnloadOptions() -{ - UnhookWindowsHooks(); - if (hAutoAwayTimer != 0) - KillTimer(nullptr, hAutoAwayTimer); -} - -void AAALoadOptions() -{ - // if bOverride is enabled, samesettings will be ignored (for options loading) - int monitorMiranda = FALSE; // use windows hooks? - int monitorAll = FALSE; // use windows hooks? - - AAAUnloadOptions(); - - ignoreLockKeys = db_get_b(0, AAAMODULENAME, SETTING_IGNLOCK, FALSE); - ignoreSysKeys = db_get_b(0, AAAMODULENAME, SETTING_IGNSYSKEYS, FALSE); - ignoreAltCombo = db_get_b(0, AAAMODULENAME, SETTING_IGNALTCOMBO, FALSE); - monitorMouse = db_get_b(0, AAAMODULENAME, SETTING_MONITORMOUSE, TRUE); - monitorKeyboard = db_get_b(0, AAAMODULENAME, SETTING_MONITORKEYBOARD, TRUE); - lastInput = lastMirandaInput = GetTickCount(); - - for (auto &it : protoList) { - char* protoName; - if ((db_get_b(0, AAAMODULENAME, SETTING_SAMESETTINGS, 0))) - protoName = SETTING_ALL; - else - protoName = it->m_szName; - LoadAutoAwaySetting(*it, protoName); - - if (it->optionFlags & FLAG_MONITORMIRANDA) - monitorMiranda = TRUE; - else if (ignoreLockKeys || ignoreSysKeys || ignoreAltCombo || (monitorMouse != monitorKeyboard)) - monitorAll = TRUE; - } - - HookWindowsHooks(monitorMiranda, monitorAll); - hAutoAwayTimer = SetTimer(nullptr, 0, db_get_w(0, AAAMODULENAME, SETTING_AWAYCHECKTIMEINSECS, 5) * 1000, AutoAwayTimer); -} - -int LoadAutoAwaySetting(SMProto &autoAwaySetting, char* protoName) -{ - char setting[128]; - mir_snprintf(setting, "%s_OptionFlags", protoName); - autoAwaySetting.optionFlags = db_get_w(0, AAAMODULENAME, setting, FLAG_LV2ONINACTIVE | FLAG_RESET | FLAG_ENTERIDLE); - mir_snprintf(setting, "%s_AwayTime", protoName); - autoAwaySetting.awayTime = db_get_w(0, AAAMODULENAME, setting, SETTING_AWAYTIME_DEFAULT); - mir_snprintf(setting, "%s_NATime", protoName); - autoAwaySetting.naTime = db_get_w(0, AAAMODULENAME, setting, SETTING_NATIME_DEFAULT); - mir_snprintf(setting, "%s_StatusFlags", protoName); - autoAwaySetting.statusFlags = db_get_w(0, AAAMODULENAME, setting, StatusModeToProtoFlag(ID_STATUS_ONLINE) | StatusModeToProtoFlag(ID_STATUS_FREECHAT)); - - int flags; - if (db_get_b(0, AAAMODULENAME, SETTING_SAMESETTINGS, 0)) - flags = 0xFFFFFF; - else - flags = CallProtoService(protoName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(protoName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0); - mir_snprintf(setting, "%s_Lv1Status", protoName); - autoAwaySetting.lv1Status = db_get_w(0, AAAMODULENAME, setting, (flags&StatusModeToProtoFlag(ID_STATUS_AWAY)) ? ID_STATUS_AWAY : ID_STATUS_OFFLINE); - mir_snprintf(setting, "%s_Lv2Status", protoName); - autoAwaySetting.lv2Status = db_get_w(0, AAAMODULENAME, setting, (flags&StatusModeToProtoFlag(ID_STATUS_NA)) ? ID_STATUS_NA : ID_STATUS_OFFLINE); - - return 0; -} - -static int ProcessProtoAck(WPARAM, LPARAM lParam) -{ - ACKDATA *ack = (ACKDATA*)lParam; - if (ack->type != ACKTYPE_STATUS || ack->result != ACKRESULT_SUCCESS) - return 0; - - log_debugA("ProcessProtoAck: ack->szModule: %s", ack->szModule); - for (auto &it : protoList) { - log_debugA("chk: %s", it->m_szName); - if (!mir_strcmp(it->m_szName, ack->szModule)) { - log_debugA("ack->szModule: %s p.statusChanged: %d", ack->szModule, it->bStatusChanged); - if (!it->bStatusChanged) - it->bManualStatus = true; - - it->bStatusChanged = false; - } - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Account control event - -static char* status2descr(int status) -{ - switch (status) { - case ACTIVE: return "ACTIVE"; - case STATUS1_SET: return "STATUS1_SET"; - case STATUS2_SET: return "STATUS2_SET"; - case SET_ORGSTATUS: return "SET_ORGSTATUS"; - case HIDDEN_ACTIVE: return "HIDDEN_ACTIVE"; - } - return "ERROR"; -} - -static int changeState(SMProto &setting, int mode, STATES newState) -{ - if (setting.curState == newState) - return 0; - - setting.oldState = setting.curState; - setting.curState = newState; - - log_debugA("%s state change: %s -> %s", setting.m_szName, status2descr(setting.oldState), status2descr(setting.curState)); - - if (setting.curState != SET_ORGSTATUS && setting.curState != ACTIVE && setting.bStatusChanged) { - /* change the awaymessage */ - if (setting.m_szMsg != nullptr) { - mir_free(setting.m_szMsg); - setting.m_szMsg = nullptr; - } - - if (db_get_b(0, AAAMODULENAME, StatusModeToDbSetting(setting.aaaStatus, SETTING_MSGCUSTOM), FALSE)) - setting.m_szMsg = db_get_wsa(0, AAAMODULENAME, StatusModeToDbSetting(setting.aaaStatus, SETTING_STATUSMSG)); - } - else if (setting.m_szMsg != nullptr) { - mir_free(setting.m_szMsg); - setting.m_szMsg = nullptr; - } - - if (setting.optionFlags & FLAG_ENTERIDLE) { - if (newState == ACTIVE) // we're returning back - Idle_Enter(-1); - else - Idle_Enter(mode); - } - - return 0; -} - -static int getIdleMode(int options) -{ - if ((options & FLAG_ONSAVER) && IsScreenSaverRunning()) - return 1; - - if ((options & FLAG_ONLOCK) && IsWorkstationLocked()) - return 2; - - if ((options & FLAG_ONTS) && IsTerminalDisconnected()) - return 3; - - if ((options & FLAG_FULLSCREEN) && IsFullScreen()) - return 4; - - return 0; -} - -static VOID CALLBACK AutoAwayTimer(HWND, UINT, UINT_PTR, DWORD) -{ - int statusChanged = FALSE; - int confirm = FALSE; - - for (auto &it : protoList) { - it->aaaStatus = ID_STATUS_DISABLED; - - if (it->optionFlags & FLAG_MONITORMIRANDA) - mouseStationaryTimer = (GetTickCount() - lastMirandaInput) / 1000; - else { - LASTINPUTINFO ii = { sizeof(ii) }; - GetLastInputInfo(&ii); - mouseStationaryTimer = (GetTickCount() - ii.dwTime) / 1000; - } - - int sts1Time = it->awayTime * SECS_PER_MINUTE; - int sts2Time = it->naTime * SECS_PER_MINUTE; - int sts1setTime = it->sts1setTimer == 0 ? 0 : (GetTickCount() - it->sts1setTimer) / 1000; - int currentMode = Proto_GetStatus(it->m_szName); - - int mode = getIdleMode(it->optionFlags); - - /* check states */ - if (it->curState == ACTIVE) { - if (((mouseStationaryTimer >= sts1Time && (it->optionFlags & FLAG_ONMOUSE)) || mode) && currentMode != it->lv1Status && it->statusFlags & StatusModeToProtoFlag(currentMode)) { - if (it->optionFlags & FLAG_ONMOUSE) - mode = 5; - - /* from ACTIVE to STATUS1_SET */ - it->m_lastStatus = it->originalStatusMode = Proto_GetStatus(it->m_szName); - it->aaaStatus = it->lv1Status; - it->sts1setTimer = GetTickCount(); - sts1setTime = 0; - it->bStatusChanged = statusChanged = true; - changeState(*it, mode, STATUS1_SET); - } - else if (mouseStationaryTimer >= sts2Time && currentMode == it->lv1Status && currentMode != it->lv2Status && (it->optionFlags & FLAG_SETNA) && (it->statusFlags & StatusModeToProtoFlag(currentMode))) { - /* from ACTIVE to STATUS2_SET */ - it->m_lastStatus = it->originalStatusMode = Proto_GetStatus(it->m_szName); - it->aaaStatus = it->lv2Status; - it->bStatusChanged = statusChanged = true; - changeState(*it, mode, STATUS2_SET); - } - } - - if (it->curState == STATUS1_SET) { - if ((mouseStationaryTimer < sts1Time && !mode) && !(it->optionFlags & FLAG_RESET)) { - /* from STATUS1_SET to HIDDEN_ACTIVE */ - changeState(*it, mode, HIDDEN_ACTIVE); - it->m_lastStatus = Proto_GetStatus(it->m_szName); - } - else if (((mouseStationaryTimer < sts1Time) && !mode) && - ((it->optionFlags & FLAG_LV2ONINACTIVE) || (!(it->optionFlags & FLAG_SETNA))) && - (it->optionFlags & FLAG_RESET)) { - /* from STATUS1_SET to SET_ORGSTATUS */ - changeState(*it, mode, SET_ORGSTATUS); - } - else if ((it->optionFlags & FLAG_SETNA) && sts1setTime >= sts2Time) { - /* when set STATUS2, currentMode doesn't have to be in the selected status list (statusFlags) */ - /* from STATUS1_SET to STATUS2_SET */ - it->m_lastStatus = Proto_GetStatus(it->m_szName); - it->aaaStatus = it->lv2Status; - it->bStatusChanged = statusChanged = true; - changeState(*it, mode, STATUS2_SET); - } - } - - if (it->curState == STATUS2_SET) { - if (mouseStationaryTimer < sts2Time && !mode && (it->optionFlags & FLAG_RESET)) { - /* from STATUS2_SET to SET_ORGSTATUS */ - changeState(*it, mode, SET_ORGSTATUS); - } - else if (mouseStationaryTimer < sts2Time && !mode && !(it->optionFlags & FLAG_RESET)) { - /* from STATUS2_SET to HIDDEN_ACTIVE */ - /* Remember: after status1 is set, and "only on inactive" is NOT set, it implies !reset. */ - changeState(*it, mode, HIDDEN_ACTIVE); - it->m_lastStatus = Proto_GetStatus(it->m_szName); - } - } - - if (it->curState == HIDDEN_ACTIVE) { - if (it->bManualStatus) { - /* HIDDEN_ACTIVE to ACTIVE */ - // it->bStatusChanged = false; - changeState(*it, mode, ACTIVE); - it->sts1setTimer = 0; - it->bManualStatus = false; - } - else if ((it->optionFlags & FLAG_SETNA) && currentMode == it->lv1Status && - currentMode != it->lv2Status && (it->statusFlags & StatusModeToProtoFlag(currentMode)) && - (mouseStationaryTimer >= sts2Time || (sts1setTime >= sts2Time && !(it->optionFlags & FLAG_LV2ONINACTIVE)))) { - /* HIDDEN_ACTIVE to STATUS2_SET */ - it->m_lastStatus = it->originalStatusMode = Proto_GetStatus(it->m_szName); - it->aaaStatus = it->lv2Status; - it->bStatusChanged = statusChanged = true; - changeState(*it, mode, STATUS2_SET); - } - } - if (it->curState == SET_ORGSTATUS) { - /* SET_ORGSTATUS to ACTIVE */ - it->m_lastStatus = Proto_GetStatus(it->m_szName); - it->aaaStatus = it->originalStatusMode; - confirm = (it->optionFlags & FLAG_CONFIRM) ? TRUE : confirm; - it->bStatusChanged = statusChanged = true; - changeState(*it, mode, ACTIVE); - it->sts1setTimer = 0; - } - it->bManualStatus = false; - } - - if (confirm || statusChanged) { - TProtoSettings ps(protoList); // make a copy of data not to pollute main array - for (auto &it : ps) - it->m_status = it->aaaStatus; - - if (confirm) - confirmDialog = ShowConfirmDialogEx(&ps, db_get_w(0, AAAMODULENAME, SETTING_CONFIRMDELAY, 5)); - else if (statusChanged) - SetStatusEx(ps); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Windows hooks - -static int HookWindowsHooks(int hookMiranda, int hookAll) -{ - if (hookMiranda) { - if (monitorKeyboard && hMirandaKeyBoardHook == nullptr) - hMirandaKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, MirandaKeyBoardHookFunction, nullptr, GetCurrentThreadId()); - if (monitorMouse && hMirandaMouseHook == nullptr) - hMirandaMouseHook = SetWindowsHookEx(WH_MOUSE, MirandaMouseHookFunction, nullptr, GetCurrentThreadId()); - } - if (hookAll) { - if (monitorKeyboard && hKeyBoardHook == nullptr) - hKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, KeyBoardHookFunction, nullptr, GetCurrentThreadId()); - if (monitorMouse && hMouseHook == nullptr) - hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseHookFunction, nullptr, GetCurrentThreadId()); - } - - return 0; -} - -static int UnhookWindowsHooks() -{ - UnhookWindowsHookEx(hMouseHook); - UnhookWindowsHookEx(hKeyBoardHook); - UnhookWindowsHookEx(hMirandaMouseHook); - UnhookWindowsHookEx(hMirandaKeyBoardHook); - - hMouseHook = hKeyBoardHook = hMirandaMouseHook = hMirandaKeyBoardHook = nullptr; - return 0; -} - -static LRESULT CALLBACK MirandaMouseHookFunction(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - PMOUSEHOOKSTRUCT mouseInfo = (PMOUSEHOOKSTRUCT)lParam; - POINT pt = mouseInfo->pt; - - /* TioDuke's KeyBoardNotifyExt: only update if a Miranda window is focused */ - DWORD pid; - GetWindowThreadProcessId(GetForegroundWindow(), &pid); - if (pid != GetCurrentProcessId()) - return CallNextHookEx(hMirandaMouseHook, code, wParam, lParam); - - if (pt.x != lastMousePos.x || pt.y != lastMousePos.y) { - lastMousePos = pt; - lastMirandaInput = GetTickCount(); - } - } - - return CallNextHookEx(hMirandaMouseHook, code, wParam, lParam); -} - -static LRESULT CALLBACK MirandaKeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - if (ignoreAltCombo) { - if (((GetKeyState(VK_MENU) < 0) || (wParam == VK_MENU)) || - ((GetKeyState(VK_TAB) < 0) || (wParam == VK_TAB)) || - ((GetKeyState(VK_SHIFT) < 0) || (wParam == VK_SHIFT)) || - ((GetKeyState(VK_CONTROL) < 0) || (wParam == VK_CONTROL)) || - ((GetKeyState(VK_ESCAPE) < 0) || (wParam == VK_ESCAPE)) || - ((GetKeyState(VK_LWIN) < 0) || (wParam == VK_LWIN)) || - ((GetKeyState(VK_RWIN) < 0) || (wParam == VK_RWIN))) { - return CallNextHookEx(hMirandaKeyBoardHook, code, wParam, lParam); - } - } - - switch (wParam) { - case VK_NUMLOCK: - case VK_CAPITAL: - case VK_SCROLL: - if (!ignoreLockKeys) - lastMirandaInput = GetTickCount(); - break; - - case VK_TAB: - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - case VK_ESCAPE: - case VK_LWIN: - case VK_RWIN: - if (!ignoreSysKeys) - lastMirandaInput = GetTickCount(); - break; - - default: - lastMirandaInput = GetTickCount(); - break; - } - } - - return CallNextHookEx(hMirandaKeyBoardHook, code, wParam, lParam); -} - -static LRESULT CALLBACK MouseHookFunction(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - PMOUSEHOOKSTRUCT mouseInfo = (PMOUSEHOOKSTRUCT)lParam; - POINT pt = mouseInfo->pt; - - /* TioDuke's KeyBoardNotifyExt: also grab clicks */ - if ((wParam >= WM_NCLBUTTONDOWN && wParam <= WM_NCXBUTTONDBLCLK && wParam != 0x00AA) || (wParam >= WM_LBUTTONDOWN && wParam <= WM_XBUTTONDBLCLK)) - lastInput = GetTickCount(); - - if (pt.x != lastMousePos.x || pt.y != lastMousePos.y) { - lastMousePos = pt; - lastInput = GetTickCount(); - } - } - - return CallNextHookEx(hMouseHook, code, wParam, lParam); -} - -static LRESULT CALLBACK KeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - if (ignoreAltCombo) { - if (((GetKeyState(VK_MENU) < 0) || (wParam == VK_MENU)) || - ((GetKeyState(VK_TAB) < 0) || (wParam == VK_TAB)) || - ((GetKeyState(VK_SHIFT) < 0) || (wParam == VK_SHIFT)) || - ((GetKeyState(VK_CONTROL) < 0) || (wParam == VK_CONTROL)) || - ((GetKeyState(VK_ESCAPE) < 0) || (wParam == VK_ESCAPE)) || - ((GetKeyState(VK_LWIN) < 0) || (wParam == VK_LWIN)) || - ((GetKeyState(VK_RWIN) < 0) || (wParam == VK_RWIN))) { - return CallNextHookEx(hKeyBoardHook, code, wParam, lParam); - } - } - - switch (wParam) { - case VK_NUMLOCK: - case VK_CAPITAL: - case VK_SCROLL: - if (!ignoreLockKeys) - lastInput = GetTickCount(); - break; - - case VK_TAB: - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - case VK_ESCAPE: - case VK_LWIN: - case VK_RWIN: - if (!ignoreSysKeys) - lastInput = GetTickCount(); - break; - - default: - lastInput = GetTickCount(); - break; - } - } - - return CallNextHookEx(hKeyBoardHook, code, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Inits & stuff - -static int AutoAwayShutdown(WPARAM, LPARAM) -{ - AAAUnloadOptions(); - return 0; -} - -int AAAModuleLoaded(WPARAM, LPARAM) -{ - hEvents[0] = HookEvent(ME_OPT_INITIALISE, AutoAwayOptInitialise); - hEvents[1] = HookEvent(ME_SYSTEM_PRESHUTDOWN, AutoAwayShutdown); - hEvents[2] = HookEvent(ME_PROTO_ACK, ProcessProtoAck); - - mouseStationaryTimer = 0; - lastInput = lastMirandaInput = GetTickCount(); - - //////////////////////////////////////////////////////////////////////////////////////// - - AAALoadOptions(); - return 0; -} - -void AdvancedAutoAwayLoad() -{ - AAALangPack = GetPluginLangId(MIID_LAST, 0); - - if (g_bMirandaLoaded) - AAAModuleLoaded(0, 0); - else - HookEvent(ME_SYSTEM_MODULESLOADED, AAAModuleLoaded); -} - -void AdvancedAutoAwayUnload() -{ - if (g_bMirandaLoaded) - AutoAwayShutdown(0, 0); - - KillModuleOptions(AAALangPack); - - for (auto &it : hEvents) { - UnhookEvent(it); - it = nullptr; - } - - protoList.destroy(); -} diff --git a/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.h b/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.h deleted file mode 100644 index e2d6b4ec61..0000000000 --- a/plugins/StatusManager/src/AdvancedAutoAway/advancedautoaway.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef __ADVANCED_AUTOAWAY_HEADER -#define __ADVANCED_AUTOAWAY_HEADER - -#define AAAMODULENAME "AdvancedAutoAway" -#define SETTING_IGNLOCK "IgnoreLockKeys" -#define SETTING_IGNSYSKEYS "IgnoreSysKeys" -#define SETTING_IGNALTCOMBO "IgnoreAltCombo" -#define SETTING_SAMESETTINGS "SameAutoAwaySettings" -#define SETTING_ALL "ALLPROTOS" -#define SETTING_MSGCUSTOM "Custom" -#define SETTING_STATUSMSG "Msg" -#define SETTING_CONFIRMDELAY "ConfirmTimeout" -#define SETTING_ENTERIDLE "EnterIdle" - -#define SETTING_AWAYTIME_DEFAULT 5 -#define SETTING_NATIME_DEFAULT 20 -#define SETTING_AWAYCHECKTIMEINSECS "CheckInterval" - -#define SETTING_MONITORMOUSE "MonitorMouse" -#define SETTING_MONITORKEYBOARD "MonitorKeyboard" - -void AdvancedAutoAwayLoad(); -void AdvancedAutoAwayUnload(); - -int LoadAutoAwaySetting(SMProto&, char *protoName); -void AAALoadOptions(); - -#endif diff --git a/plugins/StatusManager/src/KeepStatus/keepstatus.cpp b/plugins/StatusManager/src/KeepStatus/keepstatus.cpp deleted file mode 100644 index 5b130f024a..0000000000 --- a/plugins/StatusManager/src/KeepStatus/keepstatus.cpp +++ /dev/null @@ -1,1102 +0,0 @@ -/* - KeepStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "..\stdafx.h" - -int KSLangPack; - -static HANDLE hConnectionEvent = nullptr; -static HANDLE hServices[4], hEvents[2]; - -static mir_cs GenTimerCS, GenStatusCS, CheckContinueslyCS; - -static HANDLE hProtoAckHook = nullptr; -static HANDLE hStatusChangeHook = nullptr; -static HANDLE hCSStatusChangeHook = nullptr; -static HANDLE hCSStatusChangeExHook = nullptr; - -static HWND hMessageWindow = nullptr; - -static UINT_PTR checkConnectionTimerId = 0; -static UINT_PTR afterCheckTimerId = 0; -static UINT_PTR processAckTimerId = 0; -static UINT_PTR checkContinTimerId = 0; -static UINT_PTR checkConnectingTimerId = 0; -static int retryCount = 0; -static BOOL bLastPingResult = TRUE; -// variables (options) -static int maxRetries = 0; -static int initDelay = 0; -static int currentDelay = 0; -static int maxDelay = 0; -static int ackDelay = 500; -static int increaseExponential = 0; -static int showConnectionPopups = 0; -// prototypes -static int StartTimer(int timer, int timeout, BOOL restart); -static int StopTimer(int timer); -static int ProcessProtoAck(WPARAM wParam, LPARAM lParam); -static VOID CALLBACK CheckConnectingTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); -static VOID CALLBACK CheckAckStatusTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); -static int StatusChange(WPARAM wParam, LPARAM lParam); -static int CSStatusChange(WPARAM wParam, LPARAM lParam); -static int CSStatusChangeEx(WPARAM wParam, LPARAM lParam); -static VOID CALLBACK CheckConnectionTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); -static int StopChecking(); -static VOID CALLBACK AfterCheckTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); -static VOID CALLBACK CheckContinueslyTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); -INT_PTR IsProtocolEnabledService(WPARAM wParam, LPARAM lParam); - -static int ProcessPopup(int reason, LPARAM lParam); -LRESULT CALLBACK KSPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -static DWORD CALLBACK MessageWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - -// options.c -extern int KeepStatusOptionsInit(WPARAM wparam, LPARAM); - -///////////////////////////////////////////////////////////////////////////////////////// - -void KSUnloadOptions() -{ - UnhookEvent(hProtoAckHook); - UnhookEvent(hStatusChangeHook); - UnhookEvent(hCSStatusChangeHook); - UnhookEvent(hCSStatusChangeExHook); - hProtoAckHook = hStatusChangeHook = hCSStatusChangeHook = hCSStatusChangeExHook = nullptr; - - if (IsWindow(hMessageWindow)) - DestroyWindow(hMessageWindow); - - if (StartTimer(IDT_CHECKCONTIN, -1, FALSE)) - WSACleanup(); - - StopTimer(IDT_CHECKCONN | IDT_PROCESSACK | IDT_AFTERCHECK | IDT_CHECKCONTIN | IDT_CHECKCONNECTING); -} - -int KSLoadOptions() -{ - KSUnloadOptions(); - - if (db_get_b(0, KSMODULENAME, SETTING_CHECKCONNECTION, FALSE)) { - if (db_get_b(0, KSMODULENAME, SETTING_CONTCHECK, FALSE)) { - if (db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE)) { - WSADATA wsaData; - WSAStartup(MAKEWORD(2, 2), &wsaData); - } - StartTimer(IDT_CHECKCONTIN, 0, FALSE); - } - increaseExponential = db_get_b(0, KSMODULENAME, SETTING_INCREASEEXPONENTIAL, FALSE); - currentDelay = initDelay = 1000 * db_get_dw(0, KSMODULENAME, SETTING_INITDELAY, DEFAULT_INITDELAY); - maxDelay = 1000 * db_get_dw(0, KSMODULENAME, SETTING_MAXDELAY, DEFAULT_MAXDELAY); - maxRetries = db_get_b(0, KSMODULENAME, SETTING_MAXRETRIES, 0); - if (maxRetries == 0) - maxRetries = -1; - hProtoAckHook = HookEvent(ME_PROTO_ACK, ProcessProtoAck); - hStatusChangeHook = HookEvent(ME_CLIST_STATUSMODECHANGE, StatusChange); - if (ServiceExists(ME_CS_STATUSCHANGE)) - hCSStatusChangeHook = HookEvent(ME_CS_STATUSCHANGE, CSStatusChange); - hCSStatusChangeExHook = HookEvent(ME_CS_STATUSCHANGEEX, CSStatusChangeEx); - if (db_get_b(0, KSMODULENAME, SETTING_CHECKAPMRESUME, 0)) { - if (!IsWindow(hMessageWindow)) { - hMessageWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); - SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); - } - } - retryCount = 0; - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int SMProto::AssignStatus(int iStatus, int iLastStatus, wchar_t *pwszMsg) -{ - if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) - return -1; - if (iStatus != ID_STATUS_OFFLINE && m_status == ID_STATUS_DISABLED) - return -2; - if (!db_get_b(0, KSMODULENAME, SETTING_NOLOCKED, 0) && Proto_GetAccount(m_szName)->IsLocked()) - return -3; - - mir_cslock lck(GenStatusCS); - - char dbSetting[128]; - mir_snprintf(dbSetting, "%s_enabled", m_szName); - m_lastStatus = (iLastStatus == 0) ? m_status : iLastStatus; - if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) - m_status = ID_STATUS_DISABLED; - else if (iStatus == ID_STATUS_LAST) - m_status = m_lastStatus; - else - m_status = iStatus; - - log_infoA("KeepStatus: assigning status %d (%d, %d) to %s", m_status, m_lastStatus, iLastStatus, m_szName); - - if (pwszMsg != nullptr && mir_wstrcmp(pwszMsg, m_szMsg)) { - if (m_szMsg != nullptr) - mir_free(m_szMsg); - - m_szMsg = mir_wstrdup(pwszMsg); - } - else if (pwszMsg != m_szMsg) { - if (m_szMsg != nullptr) - mir_free(m_szMsg); - - m_szMsg = nullptr; - } - return 0; -} - -int SMProto::GetStatus() const -{ - switch (m_status) { - case ID_STATUS_CURRENT: - return Proto_GetStatus(m_szName); - case ID_STATUS_LAST: - return m_lastStatus; - default: - return m_status; - } -} - -static int SetCurrentStatus() -{ - TProtoSettings ps(protoList); - for (auto &p : ps) { - int realStatus = Proto_GetStatus(p->m_szName); - int curStatus = p->GetStatus(); - if (curStatus == ID_STATUS_DISABLED) - continue; - if (curStatus == realStatus) { - p->m_status = ID_STATUS_DISABLED; - continue; - } - - log_infoA("KeepStatus: status for %s differs: stored = %d, real = %d", p->m_szName, curStatus, realStatus); - - // force offline before reconnecting? - if (realStatus != ID_STATUS_OFFLINE && db_get_b(0, KSMODULENAME, SETTING_FIRSTOFFLINE, FALSE)) { - log_infoA("KeepStatus: Setting %s offline before making a new connection attempt", p->m_szName); - CallProtoService(p->m_szName, PS_SETSTATUS, (WPARAM)ID_STATUS_OFFLINE, 0); - } - } - ProcessPopup(KS_CONN_STATE_RETRY, (LPARAM)ps.getArray()); - return SetStatusEx(ps); -} - -static int StatusChange(WPARAM wParam, LPARAM lParam) -{ - char *szProto = (char *)lParam; - if (szProto == nullptr) { // global status change - for (auto &it : protoList) - it->AssignStatus(wParam, 0, it->m_szMsg); - } - else { - for (auto &it : protoList) - if (!mir_strcmp(it->m_szName, szProto)) - it->AssignStatus(wParam, 0, it->m_szMsg); - } - - return 0; -} - -static int CSStatusChange(WPARAM wParam, LPARAM) -{ - // the status was changed by commonstatus (old) - if (wParam != 0) { - PROTOCOLSETTING **protoSettings = *(PROTOCOLSETTING***)wParam; - if (protoSettings == nullptr) - return -1; - - for (int i = 0; i < protoList.getCount(); i++) { - auto psi = protoSettings[i]; - if (psi->szName == nullptr) - continue; - - for (auto &it : protoList) { - if (it->m_szName == nullptr) - continue; - - if (!mir_strcmp(psi->szName, it->m_szName)) - it->AssignStatus(psi->status, psi->lastStatus, it->m_szMsg); - } - } - } - - return 0; -} - -static int CSStatusChangeEx(WPARAM wParam, LPARAM pCount) -{ - // the status was changed by commonstatus (new) - if (wParam != 0) { - PROTOCOLSETTINGEX** protoSettings = *(PROTOCOLSETTINGEX***)wParam; - if (protoSettings == nullptr) - return -1; - - for (int i = 0; i < pCount; i++) { - auto psi = protoSettings[i]; - if (psi->m_szName == nullptr) - continue; - - for (auto &it : protoList) { - if (it->m_szName == nullptr) - continue; - - if (!mir_strcmp(psi->m_szName, it->m_szName)) - it->AssignStatus(psi->m_status, psi->m_lastStatus, psi->m_szMsg); - } - } - } - - return 0; -} - -struct TimerInfo -{ - int timer; - int timeout; - BOOL restart; -}; - -static INT_PTR CALLBACK StartTimerApcProc(void *param) -{ - TimerInfo *ti = (TimerInfo *)param; - int res = 0; - - mir_cslock lck(GenTimerCS); - log_debugA("StartTimer: %d, %d, %d", ti->timer, ti->timeout, ti->restart); - log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); - if (ti->timer & IDT_PROCESSACK) { - res = (processAckTimerId == 0) ? 0 : 1; - if (((processAckTimerId == 0) && (checkConnectionTimerId == 0)) || (ti->restart)) { - if (ti->timeout != -1) { - if (ti->restart) - KillTimer(nullptr, processAckTimerId); - if (ti->timeout == 0) - ti->timeout = ackDelay; - processAckTimerId = SetTimer(nullptr, 0, ti->timeout, CheckAckStatusTimer); - } - } - } - - if (ti->timer & IDT_CHECKCONN) { - res = (checkConnectionTimerId == 0 ? 0 : 1) || res; - if ((checkConnectionTimerId == 0) || (ti->restart)) { - if (ti->timeout != -1) { - if (ti->restart) - KillTimer(nullptr, checkConnectionTimerId); - - if (ti->timeout == 0) - ti->timeout = initDelay; - checkConnectionTimerId = SetTimer(nullptr, 0, ti->timeout, CheckConnectionTimer); - } - } - } - - if (ti->timer & IDT_AFTERCHECK) { - res = (afterCheckTimerId == 0 ? 0 : 1) || res; - if ((afterCheckTimerId == 0) || (ti->restart)) { - if (ti->timeout != -1) { - if (ti->restart) - KillTimer(nullptr, afterCheckTimerId); - - if (ti->timeout == 0) - ti->timeout = initDelay / 2; - afterCheckTimerId = SetTimer(nullptr, 0, ti->timeout, AfterCheckTimer); - } - } - } - - if (ti->timer & IDT_CHECKCONTIN) { - res = (checkContinTimerId == 0 ? 0 : 1) || res; - if ((checkContinTimerId == 0) || (ti->restart)) { - if (ti->timeout != -1) { - if (ti->restart) - KillTimer(nullptr, checkContinTimerId); - - if (ti->timeout == 0) - ti->timeout = 1000 * db_get_dw(0, KSMODULENAME, SETTING_CNTDELAY, CHECKCONTIN_DELAY); - checkContinTimerId = SetTimer(nullptr, 0, ti->timeout, CheckContinueslyTimer); - } - } - } - - if (ti->timer & IDT_CHECKCONNECTING) { - res = (checkConnectingTimerId == 0 ? 0 : 1) || res; - if ((checkConnectingTimerId == 0) || (ti->restart)) { - if (ti->timeout != -1) { - if (ti->restart) - KillTimer(nullptr, checkConnectingTimerId); - if (ti->timeout == 0) - ti->timeout = initDelay / 2; - checkConnectingTimerId = SetTimer(nullptr, 0, ti->timeout, CheckConnectingTimer); - } - } - } - - log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); - log_debugA("StartTimer done %d", res); - return res; -} - -static int StartTimer(int timer, int timeout, BOOL restart) -{ - TimerInfo ti = { timer, timeout, restart }; - return CallFunctionSync(&StartTimerApcProc, &ti); -} - -static int StopTimer(int timer) -{ - int res = 0; - - mir_cslock lck(GenTimerCS); - log_debugA("StopTimer %d", timer); - log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); - - if (timer & IDT_PROCESSACK) { - if (processAckTimerId == 0) - res = 0; - else { - KillTimer(nullptr, processAckTimerId); - processAckTimerId = 0; - res = 1; - } - } - - if (timer & IDT_CHECKCONN) { - if (checkConnectionTimerId == 0) - res = 0 || res; - else { - KillTimer(nullptr, checkConnectionTimerId); - checkConnectionTimerId = 0; - res = 1; - } - } - - if (timer & IDT_AFTERCHECK) { - if (afterCheckTimerId == 0) - res = 0 || res; - else { - KillTimer(nullptr, afterCheckTimerId); - afterCheckTimerId = 0; - res = 1; - } - } - - if (timer & IDT_CHECKCONTIN) { - if (checkContinTimerId == 0) - res = 0 || res; - else { - KillTimer(nullptr, checkContinTimerId); - checkContinTimerId = 0; - res = 1; - } - } - - if (timer & IDT_CHECKCONNECTING) { - if (checkConnectingTimerId == 0) - res = 0 || res; - else { - KillTimer(nullptr, checkConnectingTimerId); - checkConnectingTimerId = 0; - res = 1; - } - } - - log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); - log_debugA("StopTimer done %d", res); - return res; -} - -static int ProcessProtoAck(WPARAM, LPARAM lParam) -{ - ACKDATA *ack = (ACKDATA*)lParam; - if (ack->type != ACKTYPE_STATUS && ack->type != ACKTYPE_LOGIN) - return 0; - - char dbSetting[128]; - mir_snprintf(dbSetting, "%s_enabled", ack->szModule); - if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) - return 0; - - if (ack->type == ACKTYPE_STATUS && ack->result == ACKRESULT_SUCCESS) { - for (auto &it : protoList) - if (!mir_strcmp(it->m_szName, ack->szModule)) - it->lastStatusAckTime = GetTickCount(); - - StartTimer(IDT_PROCESSACK, 0, FALSE); - return 0; - } - - if (ack->type == ACKTYPE_LOGIN) { - if (ack->lParam == LOGINERR_OTHERLOCATION) { - for (auto &it : protoList) { - if (!mir_strcmp(ack->szModule, it->m_szName)) { - it->AssignStatus(ID_STATUS_OFFLINE); - if (db_get_b(0, KSMODULENAME, SETTING_CNCOTHERLOC, 0)) { - StopTimer(IDT_PROCESSACK); - for (auto &jt : protoList) - jt->AssignStatus(ID_STATUS_OFFLINE); - } - - NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_OTHERLOCATION, (LPARAM)it->m_szName); - ProcessPopup(KS_CONN_STATE_OTHERLOCATION, (LPARAM)ack->szModule); - } - } - } - else if (ack->result == ACKRESULT_FAILED) { - // login failed - NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_LOGINERROR, (LPARAM)ack->szModule); - - switch (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING)) { - case LOGINERR_CANCEL: - log_infoA("KeepStatus: cancel on login error (%s)", ack->szModule); - for (auto &it : protoList) - if (!mir_strcmp(ack->szModule, it->m_szName)) - it->AssignStatus(ID_STATUS_OFFLINE); - - ProcessPopup(KS_CONN_STATE_LOGINERROR, (LPARAM)ack->szModule); - StopChecking(); - break; - - case LOGINERR_SETDELAY: - { - int newDelay = 1000 * db_get_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, DEFAULT_MAXDELAY); - log_infoA("KeepStatus: set delay to %d ms on login error (%s)", newDelay, ack->szModule); - StartTimer(IDT_CHECKCONN, newDelay, TRUE); - } - ProcessPopup(KS_CONN_STATE_LOGINERROR, (LPARAM)ack->szModule); - break; - - default: - case LOGINERR_NOTHING: - StartTimer(IDT_PROCESSACK, 0, FALSE); - break; - } - } - } - - return 0; -} - -static VOID CALLBACK CheckConnectingTimer(HWND, UINT, UINT_PTR, DWORD) -{ - StopTimer(IDT_CHECKCONNECTING); - - for (auto &it : protoList) { - int curStatus = it->GetStatus(); - if (IsStatusConnecting(curStatus)) { // connecting - int maxConnectingTime = db_get_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, 0); - if (maxConnectingTime > 0) { - if ((unsigned int)maxConnectingTime <= ((GetTickCount() - it->lastStatusAckTime) / 1000)) { - // set offline - log_infoA("KeepStatus: %s is too long connecting; setting offline", it->m_szName); - CallProtoService(it->m_szName, PS_SETSTATUS, (WPARAM)ID_STATUS_OFFLINE, 0); - } - } - } - } -} - -static VOID CALLBACK CheckAckStatusTimer(HWND, UINT, UINT_PTR, DWORD) -{ - bool needChecking = false; - - StopTimer(IDT_PROCESSACK); - for (auto &it : protoList) { - int curStatus = it->GetStatus(); - int newStatus = Proto_GetStatus(it->m_szName); - // ok, np - if (curStatus == ID_STATUS_CURRENT || curStatus == ID_STATUS_DISABLED || curStatus == newStatus || newStatus > MAX_STATUS) - continue; - - if (IsStatusConnecting(newStatus)) { // connecting - int maxConnectingTime = db_get_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, 0); - if (maxConnectingTime > 0) - StartTimer(IDT_CHECKCONNECTING, (maxConnectingTime * 1000 - (GetTickCount() - it->lastStatusAckTime)), FALSE); - } - // keepstatus' administration was wrong! - else if (newStatus != ID_STATUS_OFFLINE) - it->AssignStatus(newStatus); - - // connection lost - else if (newStatus == ID_STATUS_OFFLINE) {// start checking connection - if (!StartTimer(IDT_CHECKCONN, -1, FALSE)) { /* check if not already checking */ - needChecking = true; - log_infoA("KeepStatus: connection lost! (%s)", it->m_szName); - NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_LOST, (LPARAM)it->m_szName); - ProcessPopup(KS_CONN_STATE_LOST, (LPARAM)it->m_szName); - } - } - } - - if (needChecking) - StartTimer(IDT_CHECKCONN, initDelay, FALSE); -} - -static VOID CALLBACK CheckConnectionTimer(HWND, UINT, UINT_PTR, DWORD) -{ - log_debugA("CheckConnectionTimer"); - bool setStatus = false; - - for (auto &it : protoList) { - int realStatus = Proto_GetStatus(it->m_szName); - int shouldBeStatus = it->GetStatus(); - if (shouldBeStatus == ID_STATUS_LAST) - shouldBeStatus = it->m_lastStatus; - if (shouldBeStatus == ID_STATUS_DISABLED) - continue; - if ((shouldBeStatus != realStatus) && (realStatus == ID_STATUS_OFFLINE) || (realStatus < MIN_STATUS)) { - setStatus = true; - break; - } - } - - // one of the status was wrong - if (setStatus && (maxRetries == -1 || retryCount < maxRetries)) { - if (increaseExponential) - currentDelay = min(2 * currentDelay, maxDelay); - - if (((db_get_b(0, KSMODULENAME, SETTING_CHKINET, 0)) && (!InternetGetConnectedState(nullptr, 0))) || ((db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE)) && (!bLastPingResult))) { - // no network - NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_RETRYNOCONN, (LPARAM)retryCount + 1); - ProcessPopup(KS_CONN_STATE_RETRYNOCONN, 0); - } - else { - NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_RETRY, (LPARAM)retryCount + 1); - SetCurrentStatus(); // set the status - } - retryCount += 1; - StartTimer(IDT_AFTERCHECK, min(currentDelay, AFTERCHECK_DELAY) / 2, FALSE); - StartTimer(IDT_CHECKCONN, currentDelay, TRUE); // restart this timer - } - else // all status set ok already, or stop checking - StopChecking(); - - log_debugA("CheckConnectionTimer done"); -} - -static int StopChecking() -{ - StopTimer(IDT_CHECKCONN | IDT_PROCESSACK | IDT_AFTERCHECK | IDT_CHECKCONNECTING); - - BOOL isOk = TRUE; - for (auto &it : protoList) { - int curStatus = it->GetStatus(); - int newStatus = Proto_GetStatus(it->m_szName); - if (newStatus != curStatus) { - it->AssignStatus(newStatus); - isOk = FALSE; - break; - } - } - - NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_STOPPEDCHECKING, (LPARAM)isOk); - ProcessPopup(KS_CONN_STATE_STOPPEDCHECKING, (LPARAM)isOk); - log_infoA("KeepStatus: stop checking (%s)", isOk ? "success" : "failure"); - retryCount = 0; - currentDelay = initDelay; - - return 0; -} - -static VOID CALLBACK AfterCheckTimer(HWND, UINT, UINT_PTR, DWORD) -{ - // after each connection check, this function is called to see if connection was recovered - StopTimer(IDT_AFTERCHECK); - - bool setStatus = false; - - for (auto &it : protoList) { - int realStatus = Proto_GetStatus(it->m_szName); - int shouldBeStatus = it->GetStatus(); - if (shouldBeStatus == ID_STATUS_LAST) // this should never happen - shouldBeStatus = it->m_lastStatus; - if (shouldBeStatus == ID_STATUS_DISABLED) // (on ignoring proto) - continue; - if ((shouldBeStatus != realStatus) && (realStatus == ID_STATUS_OFFLINE) || (realStatus < MIN_STATUS)) - setStatus = true; - } - - if (!setStatus || retryCount == maxRetries) - StopChecking(); -} - -static void CheckContinuouslyFunction(void *) -{ - Thread_SetName("KeepStatus: CheckContinuouslyFunction"); - - static int pingFailures = 0; - - // one at the time is enough, do it the 'easy' way - mir_cslock lck(CheckContinueslyCS); - - // do a ping, even if reconnecting - bool doPing = false; - for (auto &it : protoList) { - int shouldBeStatus = it->GetStatus(); - if (shouldBeStatus == ID_STATUS_LAST) - shouldBeStatus = it->m_lastStatus; - - if (shouldBeStatus == ID_STATUS_DISABLED) - continue; - - if (shouldBeStatus != ID_STATUS_OFFLINE) { - log_debugA("CheckContinuouslyFunction: %s should be %d", it->m_szName, shouldBeStatus); - doPing = true; - } - } - - if (!doPing) { - log_debugA("CheckContinuouslyFunction: All protocols should be offline, no need to check connection"); - return; - } - - BOOL ping = db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE); - if (ping) { - DBVARIANT dbv; - if (db_get(0, KSMODULENAME, SETTING_PINGHOST, &dbv)) - ping = FALSE; - else { - char *start, *end; - char host[MAX_PATH]; - DWORD *addr; - struct hostent *hostent; - char reply[sizeof(ICMP_ECHO_REPLY) + 8]; - - bLastPingResult = FALSE; - HANDLE hICMPFile = (HANDLE)IcmpCreateFile(); - if (hICMPFile == INVALID_HANDLE_VALUE) { - bLastPingResult = TRUE; - log_infoA("KeepStatus: icmp.dll error (2)"); - } - if (bLastPingResult == FALSE) { - start = dbv.pszVal; - while ((*start != '\0') && (!bLastPingResult)) { - end = start; - while ((*end != ' ') && (*end != '\0')) - end++; - memset(host, '\0', sizeof(host)); - strncpy(host, start, end - start); - hostent = gethostbyname(host); - if (hostent != nullptr) { - addr = (DWORD *)(*hostent->h_addr_list); - bLastPingResult = (IcmpSendEcho(hICMPFile, *addr, nullptr, 0, nullptr, reply, sizeof(ICMP_ECHO_REPLY) + 8, 5000) != 0); - - if (bLastPingResult) - pingFailures = 0; - else - pingFailures++; - - log_debugA("CheckContinuouslyFunction: pinging %s (result: %d/%d)", host, bLastPingResult, pingFailures); - } - else log_debugA("CheckContinuouslyFunction: unable to resolve %s", host); - - start = end; - while (*start == ' ') - start++; - } - } - IcmpCloseHandle(hICMPFile); - } - db_free(&dbv); - } - - if (StartTimer(IDT_CHECKCONN, -1, FALSE)) // already connecting, leave - return; - - if (((!ping) && (!InternetGetConnectedState(nullptr, 0))) || ((ping) && (!bLastPingResult) && (pingFailures >= db_get_w(0, KSMODULENAME, SETTING_PINGCOUNT, DEFAULT_PINGCOUNT)))) { - pingFailures = 0; - - for (auto &pa : Accounts()) { - if (!IsSuitableProto(pa)) - continue; - - if (IsStatusConnecting(pa->iRealStatus)) { - log_debugA("CheckContinuouslyFunction: %s is connecting", pa->szModuleName); - continue; // connecting, leave alone - } - if (IsProtocolEnabledService(0, (LPARAM)pa->szModuleName)) { - log_debugA("CheckContinuouslyFunction: forcing %s offline", pa->szModuleName); - CallProtoService(pa->szModuleName, PS_SETSTATUS, (WPARAM)ID_STATUS_OFFLINE, 0); - } - } - - if (StartTimer(IDT_CHECKCONN | IDT_PROCESSACK, -1, FALSE)) {// are our 'set offlines' noticed? - log_debugA("CheckContinuouslyFunction: currently checking"); - return; - } - - log_infoA("KeepStatus: connection lost! (continuesly check)"); - NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_LOST, 0); - ProcessPopup(KS_CONN_STATE_LOST, 0); - maxRetries = db_get_b(0, KSMODULENAME, SETTING_MAXRETRIES, 0); - if (maxRetries == 0) - maxRetries = -1; - StartTimer(IDT_CHECKCONN, initDelay, FALSE); - } -} - -static VOID CALLBACK CheckContinueslyTimer(HWND, UINT, UINT_PTR, DWORD) -{ - if (db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE)) - mir_forkthread(CheckContinuouslyFunction); - else - CheckContinuouslyFunction(nullptr); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// popup - -static INT_PTR ShowPopup(const wchar_t *msg, HICON hIcon) -{ - POPUPDATAT ppd = {}; - ppd.lchIcon = hIcon; - wcsncpy(ppd.lptzContactName, TranslateT("Keep status"), MAX_CONTACTNAME); - wcsncpy(ppd.lptzText, msg, MAX_SECONDLINE); - if (db_get_b(0, KSMODULENAME, SETTING_POPUP_USEWINCOLORS, 0)) { - ppd.colorBack = GetSysColor(COLOR_BTNFACE); - ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); - } - else if (!db_get_b(0, KSMODULENAME, SETTING_POPUP_USEDEFCOLORS, 0)) { - ppd.colorBack = db_get_dw(0, KSMODULENAME, SETTING_POPUP_BACKCOLOR, 0xAAAAAA); - ppd.colorText = db_get_dw(0, KSMODULENAME, SETTING_POPUP_TEXTCOLOR, 0x0000CC); - } - ppd.PluginWindowProc = KSPopupDlgProc; - - switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYFROMPU)) { - case POPUP_DELAYCUSTOM: - ppd.iSeconds = (int)db_get_dw(0, KSMODULENAME, SETTING_POPUP_TIMEOUT, 0); - if (ppd.iSeconds == 0) - ppd.iSeconds = currentDelay / 1000 - 1; - break; - - case POPUP_DELAYPERMANENT: - ppd.iSeconds = -1; - break; - - case POPUP_DELAYFROMPU: - default: - ppd.iSeconds = 0; - break; - } - return PUAddPopupT(&ppd); -} - -static wchar_t* GetHumanName(LPARAM lParam) -{ - PROTOACCOUNT *ProtoAccount = Proto_GetAccount((char*)lParam); - return (ProtoAccount != nullptr) ? ProtoAccount->tszAccountName : TranslateT("Protocol"); -} - -static int ProcessPopup(int reason, LPARAM lParam) -{ - if (!db_get_b(0, KSMODULENAME, SETTING_SHOWCONNECTIONPOPUPS, FALSE) || !ServiceExists(MS_POPUP_ADDPOPUPT)) - return -1; - - HICON hIcon = nullptr; - CMStringW wszText; - - switch (reason) { - case KS_CONN_STATE_OTHERLOCATION: // lParam = 1 proto - if (!db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE)) - return -1; - - hIcon = Skin_LoadProtoIcon((char*)lParam, SKINICON_STATUS_OFFLINE); - wszText.Format(TranslateT("%s connected from another location"), GetHumanName(lParam)); - break; - - case KS_CONN_STATE_LOGINERROR: // lParam = 1 proto - if (!db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE)) - return -1; - - hIcon = Skin_LoadProtoIcon((char*)lParam, SKINICON_STATUS_OFFLINE); - if (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING) == LOGINERR_CANCEL) - wszText.Format(TranslateT("%s login error, cancel reconnecting"), GetHumanName(lParam)); - else if (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING) == LOGINERR_SETDELAY) - wszText.Format(TranslateT("%s login error (next retry (%d) in %d s)"), GetHumanName(lParam), retryCount + 1, db_get_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, DEFAULT_MAXDELAY)); - else - return -1; - break; - - case KS_CONN_STATE_LOST: // lParam = 1 proto, or nullptr - if (!db_get_b(0, KSMODULENAME, SETTING_PUCONNLOST, TRUE)) - return -1; - - if (lParam) { // указатель на имя модуля. - hIcon = Skin_LoadProtoIcon((char*)lParam, SKINICON_STATUS_OFFLINE); - wszText.Format(TranslateT("%s status error (next retry (%d) in %d s)"), GetHumanName(lParam), retryCount + 1, currentDelay / 1000); - } - else wszText.Format(TranslateT("Status error (next retry (%d) in %d s)"), retryCount + 1, currentDelay / 1000); - break; - - case KS_CONN_STATE_RETRY: // lParam = PROTOCOLSETTINGEX** - if (!db_get_b(0, KSMODULENAME, SETTING_PUCONNRETRY, TRUE)) - return -1; - - if (lParam) { - PROTOCOLSETTINGEX **ps = (PROTOCOLSETTINGEX **)lParam; - - if (retryCount == maxRetries - 1) - wszText.Format(TranslateT("Resetting status... (last try (%d))"), retryCount + 1); - else - wszText.Format(TranslateT("Resetting status... (next retry (%d) in %d s)"), retryCount + 2, currentDelay / 1000); - wszText.Append(L"\r\n"); - for (int i = 0; i < protoList.getCount(); i++) { - PROTOCOLSETTINGEX *p = ps[i]; - if (p->m_status == ID_STATUS_DISABLED) - continue; - - if (mir_wstrlen(p->m_tszAccName) > 0) - if (db_get_b(0, KSMODULENAME, SETTING_PUSHOWEXTRA, TRUE)) - wszText.AppendFormat(TranslateT("%s\t(will be set to %s)\r\n"), p->m_tszAccName, Clist_GetStatusModeDescription(p->m_status, 0)); - } - - hIcon = Skin_LoadProtoIcon(ps[0]->m_szName, SKINICON_STATUS_OFFLINE); - wszText.TrimRight(); - } - break; - - case KS_CONN_STATE_RETRYNOCONN: // lParam = nullptr - if (!db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE)) - return -1; - - if (retryCount == maxRetries - 1) - wszText.Format(TranslateT("No internet connection seems available... (last try (%d))"), retryCount + 1); - else - wszText.Format(TranslateT("No internet connection seems available... (next retry (%d) in %d s)"), retryCount + 2, currentDelay / 1000); - break; - - case KS_CONN_STATE_STOPPEDCHECKING: // lParam == BOOL succes - if (!db_get_b(0, KSMODULENAME, SETTING_PURESULT, TRUE)) - return -1; - - if (lParam) { - hIcon = Skin_LoadIcon(SKINICON_STATUS_ONLINE); - wszText.Format(TranslateT("Status was set ok")); - } - else wszText.Format(TranslateT("Giving up")); - break; - } - if (hIcon == nullptr) - hIcon = Skin_LoadIcon(SKINICON_STATUS_OFFLINE); - - log_info(L"KeepStatus: %s", wszText.c_str()); - return ShowPopup(wszText, hIcon); -} - -LRESULT CALLBACK KSPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_CONTEXTMENU: // right - case WM_COMMAND: // left - switch (db_get_b(0, KSMODULENAME, - (message == WM_COMMAND) ? SETTING_POPUP_LEFTCLICK : SETTING_POPUP_RIGHTCLICK, - POPUP_ACT_CLOSEPOPUP)) { - case POPUP_ACT_CANCEL: - // cancel timer - StopChecking(); - PUDeletePopup(hWnd); - break; - - case POPUP_ACT_CLOSEPOPUP: - // close the popup - PUDeletePopup(hWnd); - break; - } - break; - } - - return DefWindowProc(hWnd, message, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// services - -INT_PTR StopReconnectingService(WPARAM, LPARAM) -{ - int ret = StartTimer(IDT_CHECKCONN | IDT_AFTERCHECK, -1, FALSE); - StopChecking(); - return ret; -} - -INT_PTR EnableProtocolService(WPARAM wParam, LPARAM lParam) -{ - char *szProto = (char *)lParam; - if (szProto == nullptr) - return -1; - - char dbSetting[128]; - mir_snprintf(dbSetting, "%s_enabled", szProto); - if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) // 'hard' disabled - return -1; - - int ret = -2; - for (auto &it : protoList) { - if (!mir_strcmp(szProto, it->m_szName)) { - if (wParam) - it->AssignStatus(Proto_GetStatus(it->m_szName)); - else - it->AssignStatus(ID_STATUS_DISABLED); - - ret = 0; - break; - } - } - return ret; -} - -INT_PTR IsProtocolEnabledService(WPARAM, LPARAM lParam) -{ - char *szProto = (char *)lParam; - - char dbSetting[128]; - mir_snprintf(dbSetting, "%s_enabled", szProto); - if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) - return FALSE; - - for (auto &it : protoList) - if (!mir_strcmp(szProto, it->m_szName)) - return it->GetStatus() != ID_STATUS_DISABLED; - - return FALSE; -} - -INT_PTR AnnounceStatusChangeService(WPARAM, LPARAM lParam) -{ - PROTOCOLSETTINGEX *newSituation = (PROTOCOLSETTINGEX *)lParam; - log_infoA("Another plugin announced a status change to %d for %s", newSituation->m_status, newSituation->m_szName == nullptr ? "all" : newSituation->m_szName); - - for (auto &it : protoList) - if (!mir_strcmp(it->m_szName, newSituation->m_szName)) - it->AssignStatus(newSituation->m_status, newSituation->m_lastStatus, newSituation->m_szMsg); - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// window for suspend - -static DWORD CALLBACK MessageWndProc(HWND, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static TProtoSettings *ps = nullptr; - - switch (msg) { - case WM_POWERBROADCAST: - switch (wParam) { - case PBT_APMSUSPEND: - log_infoA("KeepStatus: suspend state detected: %08X %08X", wParam, lParam); - if (ps == nullptr) { - ps = new TProtoSettings(protoList); - for (auto &it : *ps) - EnableProtocolService(0, (LPARAM)it->m_szName); - - // set proto's offline, the clist will not try to reconnect in that case - Clist_SetStatusMode(ID_STATUS_OFFLINE); - } - break; - - case PBT_APMRESUMESUSPEND: - case PBT_APMRESUMECRITICAL: - // case PBT_APMRESUMEAUTOMATIC: ? - log_infoA("KeepStatus: resume from suspend state"); - if (ps != nullptr) { - for (auto &it : *ps) { - SMProto *p = protoList.find(it); - if (p) - p->AssignStatus(it->m_status, it->m_lastStatus, it->m_szMsg); - } - delete ps; - ps = nullptr; - } - StartTimer(IDT_PROCESSACK, 0, FALSE); - break; - } - break; - - case WM_DESTROY: - if (ps != nullptr) { - delete ps; - ps = nullptr; - } - break; - } - - return TRUE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// init stuff - -static int onShutdown(WPARAM, LPARAM) -{ - KSUnloadOptions(); - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int KSModuleLoaded(WPARAM, LPARAM) -{ - hMessageWindow = nullptr; - KSLoadOptions(); - - hEvents[0] = HookEvent(ME_OPT_INITIALISE, KeepStatusOptionsInit); - hEvents[1] = HookEvent(ME_SYSTEM_PRESHUTDOWN, onShutdown); - return 0; -} - -void KeepStatusLoad() -{ - KSLangPack = GetPluginLangId(MIID_LAST, 0); - - if (g_bMirandaLoaded) - KSModuleLoaded(0, 0); - else - HookEvent(ME_SYSTEM_MODULESLOADED, KSModuleLoaded); - - hConnectionEvent = CreateHookableEvent(ME_KS_CONNECTIONEVENT); - - hServices[0] = CreateServiceFunction(MS_KS_STOPRECONNECTING, StopReconnectingService); - hServices[1] = CreateServiceFunction(MS_KS_ENABLEPROTOCOL, EnableProtocolService); - hServices[2] = CreateServiceFunction(MS_KS_ISPROTOCOLENABLED, IsProtocolEnabledService); - hServices[3] = CreateServiceFunction(MS_KS_ANNOUNCESTATUSCHANGE, AnnounceStatusChangeService); -} - -void KeepStatusUnload() -{ - if (g_bMirandaLoaded) - onShutdown(0, 0); - - KillModuleOptions(KSLangPack); - - for (auto &it : hServices) { - DestroyServiceFunction(it); - it = nullptr; - } - - for (auto &it : hEvents) { - UnhookEvent(it); - it = nullptr; - } - - DestroyHookableEvent(hConnectionEvent); hConnectionEvent = nullptr; -} diff --git a/plugins/StatusManager/src/KeepStatus/keepstatus.h b/plugins/StatusManager/src/KeepStatus/keepstatus.h deleted file mode 100644 index e4b1f5a7a4..0000000000 --- a/plugins/StatusManager/src/KeepStatus/keepstatus.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - KeepStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __KEEPSTATUS_HEADER -#define __KEEPSTATUS_HEADER - -#define KSMODULENAME "KeepStatus" -#define SETTING_CHECKCONNECTION "CheckConnection" -#define SETTING_MAXRETRIES "MaxRetries" -#define SETTING_INCREASEEXPONENTIAL "IncreaseExponential" -#define SETTING_INITDELAY "InitDelay" -#define SETTING_MAXDELAY "MaxDelay" -#define SETTING_SHOWCONNECTIONPOPUPS "ShowConnectionPopups" -#define SETTING_CHKINET "CheckInet" -#define SETTING_CNCOTHERLOC "CancelIfOtherLocation" -#define SETTING_LOGINERR "OnLoginErr" -#define SETTING_LOGINERR_DELAY "OnLoginErrDelay" -#define SETTING_CONTCHECK "ContinueslyCheck" -#define SETTING_BYPING "ByPingingHost" -#define SETTING_PINGHOST "HostToPing" -#define SETTING_CHECKAPMRESUME "CheckAPMResume" -#define SETTING_FIRSTOFFLINE "FirstOffline" -#define SETTING_NOLOCKED "NoLocked" -#define SETTING_MAXCONNECTINGTIME "MaxConnectingTime" -#define SETTING_PINGCOUNT "PingCount" -#define DEFAULT_PINGCOUNT 1 -#define SETTING_CNTDELAY "CntDelay" -#define STATUSCHANGEDELAY 500 // ms -#define DEFAULT_MAXRETRIES 0 -#define DEFAULT_INITDELAY 10 // s -#define DEFAULT_MAXDELAY 900 // s -#define AFTERCHECK_DELAY 10000 //ms (divided by 2) -#define CHECKCONTIN_DELAY 10 // s -#define SETTING_POPUP_DELAYTYPE "PopupDelayType" -#define SETTING_POPUP_USEWINCOLORS "PopupUseWinColors" -#define SETTING_POPUP_USEDEFCOLORS "PopupUseDefColors" -#define SETTING_POPUP_BACKCOLOR "PopupBackColor" -#define SETTING_POPUP_TEXTCOLOR "PopupTextColor" -#define SETTING_POPUP_TIMEOUT "PopupTimeout" -#define SETTING_POPUP_LEFTCLICK "PopupLeftClickAction" -#define SETTING_POPUP_RIGHTCLICK "PopupRightClickAction" -#define SETTING_PUOTHER "PopupShowOther" -#define SETTING_PUCONNLOST "PopupShowConnLost" -#define SETTING_PUCONNRETRY "PopupShowConnRetry" -#define SETTING_PURESULT "PopupShowResult" -#define SETTING_PUSHOWEXTRA "PopupShowExtra" -#define POPUP_ACT_NOTHING 0 -#define POPUP_ACT_CANCEL 1 -#define POPUP_ACT_CLOSEPOPUP 2 -#define POPUP_DELAYFROMPU 0 -#define POPUP_DELAYCUSTOM 1 -#define POPUP_DELAYPERMANENT 2 -#define LOGINERR_NOTHING 0 -#define LOGINERR_CANCEL 1 -#define LOGINERR_SETDELAY 2 - -#define IDT_PROCESSACK 0x01 -#define IDT_CHECKCONN 0x02 -#define IDT_AFTERCHECK 0x04 -#define IDT_CHECKCONTIN 0x08 -#define IDT_CHECKCONNECTING 0x10 - -// action -#define SETTING_ENABLECHECKING "EnableChecking" -// trigger -#define TRIGGERNAME "KeepStatus: Connection state change" -#define TRIGGER_CONNLOST 0x01 -#define TRIGGER_LOGINERROR 0x02 -#define TRIGGER_OTHERLOC 0x04 -#define TRIGGER_CONNRETRY 0x08 -#define TRIGGER_CONNSUCCESS 0x10 -#define TRIGGER_CONNGIVEUP 0x20 -#define SETTING_TRIGGERON "TriggerOn" - -/* old; replaced by PROTOCOLSETTINGEX see m_statusplugins.h */ -typedef struct { - char *szName; // pointer to protocol modulename - WORD status; // the status - WORD lastStatus;// last status -} PROTOCOLSETTING; - -/* old; replaced by ME_CS_STATUSCHANGE see m_statusplugins.h */ -// wParam = PROTOCOLSETTING** -// lParam = 0 -#define ME_CS_STATUSCHANGE "CommonStatus/StatusChange" - -///////////////////////////////////////////////////////////////////////////////////////// -// keepstatus.cpp - -void KeepStatusLoad(); -void KeepStatusUnload(); -int KSLoadOptions(); - -LRESULT CALLBACK KSPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - -#endif //__KEEPSTATUS_HEADER diff --git a/plugins/StatusManager/src/KeepStatus/ks_options.cpp b/plugins/StatusManager/src/KeepStatus/ks_options.cpp deleted file mode 100644 index fe96ea81b2..0000000000 --- a/plugins/StatusManager/src/KeepStatus/ks_options.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* - KeepStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "..\stdafx.h" - -///////////////////////////////////////////////////////////////////////////////////////// -// Basic options - -static INT_PTR CALLBACK DlgProcKSBasicOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - LVCOLUMN lvCol; - LVITEM lvItem; - DBVARIANT dbv; - - SetDlgItemInt(hwndDlg, IDC_MAXRETRIES, db_get_b(0, KSMODULENAME, SETTING_MAXRETRIES, DEFAULT_MAXRETRIES), FALSE); - SetDlgItemInt(hwndDlg, IDC_INITDELAY, db_get_dw(0, KSMODULENAME, SETTING_INITDELAY, DEFAULT_INITDELAY), FALSE); - CheckDlgButton(hwndDlg, IDC_CHECKCONNECTION, db_get_b(0, KSMODULENAME, SETTING_CHECKCONNECTION, FALSE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SHOWCONNECTIONPOPUPS, (db_get_b(0, KSMODULENAME, SETTING_SHOWCONNECTIONPOPUPS, FALSE) && ServiceExists(MS_POPUP_SHOWMESSAGE)) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CHKINET, db_get_b(0, KSMODULENAME, SETTING_CHKINET, FALSE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CONTCHECK, db_get_b(0, KSMODULENAME, SETTING_CONTCHECK, FALSE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_BYPING, db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE) ? BST_CHECKED : BST_UNCHECKED); - if (!db_get_s(0, KSMODULENAME, SETTING_PINGHOST, &dbv)) { - SetDlgItemTextA(hwndDlg, IDC_PINGHOST, dbv.pszVal); - db_free(&dbv); - } - - // proto list - HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST); - ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); - memset(&lvCol, 0, sizeof(lvCol)); - lvCol.mask = LVCF_WIDTH | LVCF_TEXT; - lvCol.pszText = TranslateT("Protocol"); - lvCol.cx = 118; - ListView_InsertColumn(hList, 0, &lvCol); - // fill the list - memset(&lvItem, 0, sizeof(lvItem)); - lvItem.mask = LVIF_TEXT | LVIF_PARAM; - lvItem.iItem = 0; - lvItem.iSubItem = 0; - - for (auto &pa : Accounts()) { - if (!IsSuitableProto(pa)) - continue; - - lvItem.pszText = pa->tszAccountName; - lvItem.lParam = (LPARAM)pa->szModuleName; - ListView_InsertItem(hList, &lvItem); - - char dbSetting[128]; - mir_snprintf(dbSetting, "%s_enabled", pa->szModuleName); - ListView_SetCheckState(hList, lvItem.iItem, db_get_b(0, KSMODULENAME, dbSetting, TRUE)); - lvItem.iItem++; - } - EnableWindow(GetDlgItem(hwndDlg, IDC_MAXRETRIES), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWCONNECTIONPOPUPS), ServiceExists(MS_POPUP_SHOWMESSAGE) && IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_INITDELAY), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOLLIST), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_CHKINET), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_CONTCHECK), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_BYPING), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK) && IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)) ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PINGHOST), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK)) && (IsDlgButtonChecked(hwndDlg, IDC_BYPING) && IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)) ? TRUE : FALSE); - } - break; - - case WM_COMMAND: - if (((HIWORD(wParam) == EN_CHANGE) || (HIWORD(wParam) == BN_CLICKED)) && ((HWND)lParam == GetFocus())) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - // something changed - switch (LOWORD(wParam)) { - case IDC_CHECKCONNECTION: - case IDC_CONTCHECK: - case IDC_BYPING: - BOOL bEnabled = IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION); - EnableWindow(GetDlgItem(hwndDlg, IDC_MAXRETRIES), bEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWCONNECTIONPOPUPS), ServiceExists(MS_POPUP_SHOWMESSAGE) && bEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_INITDELAY), bEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOLLIST), bEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_CHKINET), bEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_CONTCHECK), bEnabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BYPING), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK) && bEnabled) ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PINGHOST), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK)) && (IsDlgButtonChecked(hwndDlg, IDC_BYPING) && bEnabled) ? TRUE : FALSE); - break; - } - break; - - case WM_NOTIFY: - if (((NMHDR*)lParam)->idFrom == IDC_PROTOCOLLIST) { - switch (((NMHDR*)lParam)->code) { - case LVN_ITEMCHANGED: - NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; - if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_PROTOCOLLIST)) && ((nmlv->uNewState^nmlv->uOldState)&LVIS_STATEIMAGEMASK)) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - } - } - - switch (((LPNMHDR)lParam)->code) { - case PSN_WIZFINISH: - KSLoadOptions(); - break; - - case PSN_APPLY: - db_set_b(0, KSMODULENAME, SETTING_MAXRETRIES, (BYTE)GetDlgItemInt(hwndDlg, IDC_MAXRETRIES, nullptr, FALSE)); - db_set_b(0, KSMODULENAME, SETTING_CHECKCONNECTION, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); - db_set_b(0, KSMODULENAME, SETTING_SHOWCONNECTIONPOPUPS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWCONNECTIONPOPUPS)); - db_set_dw(0, KSMODULENAME, SETTING_INITDELAY, (DWORD)GetDlgItemInt(hwndDlg, IDC_INITDELAY, nullptr, FALSE)); - db_set_b(0, KSMODULENAME, SETTING_CHKINET, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CHKINET)); - db_set_b(0, KSMODULENAME, SETTING_CONTCHECK, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK)); - db_set_b(0, KSMODULENAME, SETTING_BYPING, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_BYPING)); - if (IsDlgButtonChecked(hwndDlg, IDC_BYPING)) { - int len = SendDlgItemMessage(hwndDlg, IDC_PINGHOST, WM_GETTEXTLENGTH, 0, 0); - if (len > 0) { - ptrA host((char*)mir_alloc(len + 1)); - GetDlgItemTextA(hwndDlg, IDC_PINGHOST, host, len + 1); - db_set_s(0, KSMODULENAME, SETTING_PINGHOST, host); - } - } - - HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST); - LVITEM lvItem; - lvItem.mask = LVIF_PARAM; - for (int i = 0; i < ListView_GetItemCount(hList); i++) { - lvItem.iItem = i; - lvItem.iSubItem = 0; - ListView_GetItem(hList, &lvItem); - - char dbSetting[128]; - mir_snprintf(dbSetting, "%s_enabled", (char *)lvItem.lParam); - db_set_b(0, KSMODULENAME, dbSetting, (BYTE)ListView_GetCheckState(hList, lvItem.iItem)); - } - } - break; - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Advanced options - -static INT_PTR CALLBACK DlgProcKSAdvOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - SetDlgItemInt(hwndDlg, IDC_MAXDELAY, db_get_dw(0, KSMODULENAME, SETTING_MAXDELAY, DEFAULT_MAXDELAY), FALSE); - SetDlgItemInt(hwndDlg, IDC_MAXCONNECTINGTIME, db_get_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, 0), FALSE); - CheckDlgButton(hwndDlg, IDC_INCREASEEXPONENTIAL, db_get_b(0, KSMODULENAME, SETTING_INCREASEEXPONENTIAL, FALSE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_CNCOTHERLOC, (db_get_b(0, KSMODULENAME, SETTING_CNCOTHERLOC, FALSE)) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_LOGINERR, db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING) == LOGINERR_NOTHING ? BST_UNCHECKED : BST_CHECKED); - CheckDlgButton(hwndDlg, IDC_CHECKAPMRESUME, (db_get_b(0, KSMODULENAME, SETTING_CHECKAPMRESUME, FALSE)) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_FIRSTOFFLINE, (db_get_b(0, KSMODULENAME, SETTING_FIRSTOFFLINE, FALSE)) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_NOLOCKED, (db_get_b(0, KSMODULENAME, SETTING_NOLOCKED, FALSE)) ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemInt(hwndDlg, IDC_LOGINERR_DELAY, db_get_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, DEFAULT_MAXDELAY), FALSE); - SetDlgItemInt(hwndDlg, IDC_PINGCOUNT, db_get_w(0, KSMODULENAME, SETTING_PINGCOUNT, DEFAULT_PINGCOUNT), FALSE); - SetDlgItemInt(hwndDlg, IDC_CNTDELAY, db_get_dw(0, KSMODULENAME, SETTING_CNTDELAY, CHECKCONTIN_DELAY), FALSE); - - switch (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_CANCEL)) { - case LOGINERR_SETDELAY: - CheckRadioButton(hwndDlg, IDC_LOGINERR_CANCEL, IDC_LOGINERR_SETDELAY, IDC_LOGINERR_SETDELAY); - break; - default: - case LOGINERR_CANCEL: - CheckRadioButton(hwndDlg, IDC_LOGINERR_CANCEL, IDC_LOGINERR_SETDELAY, IDC_LOGINERR_CANCEL); - break; - } - - EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_CANCEL), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_SETDELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_DELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY) && IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - break; - - case WM_COMMAND: - if (((HIWORD(wParam) == EN_CHANGE) || (HIWORD(wParam) == BN_CLICKED)) && ((HWND)lParam == GetFocus())) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - // something changed - switch (LOWORD(wParam)) { - case IDC_LOGINERR: - EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_CANCEL), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_SETDELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_DELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY) && IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - break; - - case IDC_LOGINERR_CANCEL: - case IDC_LOGINERR_SETDELAY: - CheckRadioButton(hwndDlg, IDC_LOGINERR_CANCEL, IDC_LOGINERR_SETDELAY, LOWORD(wParam)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_DELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY) && IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - break; - } - break; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case PSN_WIZFINISH: - KSLoadOptions(); - break; - - case PSN_APPLY: - db_set_b(0, KSMODULENAME, SETTING_INCREASEEXPONENTIAL, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_INCREASEEXPONENTIAL)); - db_set_dw(0, KSMODULENAME, SETTING_MAXDELAY, (DWORD)GetDlgItemInt(hwndDlg, IDC_MAXDELAY, nullptr, FALSE)); - db_set_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, (DWORD)GetDlgItemInt(hwndDlg, IDC_MAXCONNECTINGTIME, nullptr, FALSE)); - db_set_b(0, KSMODULENAME, SETTING_FIRSTOFFLINE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_FIRSTOFFLINE)); - db_set_b(0, KSMODULENAME, SETTING_NOLOCKED, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_NOLOCKED)); - db_set_b(0, KSMODULENAME, SETTING_CNCOTHERLOC, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CNCOTHERLOC)); - db_set_b(0, KSMODULENAME, SETTING_LOGINERR, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); - if (IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)) { - if (IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY)) { - db_set_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_SETDELAY); - db_set_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, GetDlgItemInt(hwndDlg, IDC_LOGINERR_DELAY, nullptr, FALSE)); - } - else db_set_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_CANCEL); - } - else db_set_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING); - - db_set_b(0, KSMODULENAME, SETTING_CHECKAPMRESUME, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CHECKAPMRESUME)); - db_set_w(0, KSMODULENAME, SETTING_PINGCOUNT, (WORD)GetDlgItemInt(hwndDlg, IDC_PINGCOUNT, nullptr, FALSE)); - db_set_dw(0, KSMODULENAME, SETTING_CNTDELAY, (DWORD)GetDlgItemInt(hwndDlg, IDC_CNTDELAY, nullptr, FALSE) == 0 ? CHECKCONTIN_DELAY : GetDlgItemInt(hwndDlg, IDC_CNTDELAY, nullptr, FALSE)); - } - break; - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Popup options - -static INT_PTR CALLBACK PopupOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static bool bFreeze = false; - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - - bFreeze = true; - - // left action - switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_CANCEL)) { - case POPUP_ACT_CLOSEPOPUP: - CheckDlgButton(hwndDlg, IDC_LCLOSE, BST_CHECKED); - break; - - case POPUP_ACT_CANCEL: - CheckDlgButton(hwndDlg, IDC_LCANCEL, BST_CHECKED); - break; - - case POPUP_ACT_NOTHING: - default: - CheckDlgButton(hwndDlg, IDC_LNOTHING, BST_CHECKED); - break; - } - - // right action - switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_CANCEL)) { - case POPUP_ACT_CLOSEPOPUP: - CheckDlgButton(hwndDlg, IDC_RCLOSE, BST_CHECKED); - break; - - case POPUP_ACT_CANCEL: - CheckDlgButton(hwndDlg, IDC_RCANCEL, BST_CHECKED); - break; - - case POPUP_ACT_NOTHING: - default: - CheckDlgButton(hwndDlg, IDC_RNOTHING, BST_CHECKED); - break; - } - - // delay - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYCUSTOM), ServiceExists(MS_POPUP_ADDPOPUPT)); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYFROMPU), ServiceExists(MS_POPUP_ADDPOPUPT)); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYPERMANENT), ServiceExists(MS_POPUP_ADDPOPUPT)); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), ServiceExists(MS_POPUP_ADDPOPUPT)); - switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYFROMPU)) { - case POPUP_DELAYCUSTOM: - CheckDlgButton(hwndDlg, IDC_DELAYCUSTOM, BST_CHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), ServiceExists(MS_POPUP_ADDPOPUPT)); - break; - - case POPUP_DELAYPERMANENT: - CheckDlgButton(hwndDlg, IDC_DELAYPERMANENT, BST_CHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), FALSE); - break; - - case POPUP_DELAYFROMPU: - default: - CheckDlgButton(hwndDlg, IDC_DELAYFROMPU, BST_CHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), FALSE); - break; - } - // delay - SetDlgItemInt(hwndDlg, IDC_DELAY, db_get_dw(0, KSMODULENAME, SETTING_POPUP_TIMEOUT, 0), FALSE); - // back color - SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_SETCOLOUR, 0, db_get_dw(0, KSMODULENAME, SETTING_POPUP_BACKCOLOR, 0xAAAAAA)); - // text - SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOR, CPM_SETCOLOUR, 0, db_get_dw(0, KSMODULENAME, SETTING_POPUP_TEXTCOLOR, 0x0000CC)); - // wincolors - CheckDlgButton(hwndDlg, IDC_WINCOLORS, db_get_b(0, KSMODULENAME, SETTING_POPUP_USEWINCOLORS, 0) ? BST_CHECKED : BST_UNCHECKED); - // defaultcolors - CheckDlgButton(hwndDlg, IDC_DEFAULTCOLORS, ((db_get_b(0, KSMODULENAME, SETTING_POPUP_USEDEFCOLORS, 0)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS))) ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); - EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); - EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULTCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS))); - EnableWindow(GetDlgItem(hwndDlg, IDC_WINCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS))); - // popup types - CheckDlgButton(hwndDlg, IDC_PUCONNLOST, db_get_b(0, KSMODULENAME, SETTING_PUCONNLOST, TRUE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PUOTHER, db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PUCONNRETRY, db_get_b(0, KSMODULENAME, SETTING_PUCONNRETRY, TRUE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PURESULT, db_get_b(0, KSMODULENAME, SETTING_PURESULT, TRUE) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PUSHOWEXTRA, db_get_b(0, KSMODULENAME, SETTING_PUSHOWEXTRA, TRUE) ? BST_CHECKED : BST_UNCHECKED); - bFreeze = false; - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_WINCOLORS: - case IDC_DEFAULTCOLORS: - EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); - EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); - EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULTCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS))); - EnableWindow(GetDlgItem(hwndDlg, IDC_WINCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS))); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case IDC_DELAYFROMPU: - case IDC_DELAYPERMANENT: - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), FALSE); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case IDC_DELAYCUSTOM: - EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), TRUE); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case IDC_BGCOLOR: - case IDC_TEXTCOLOR: - case IDC_DELAY: - case IDC_LNOTHING: - case IDC_LCLOSE: - case IDC_LCANCEL: - case IDC_RNOTHING: - case IDC_RCLOSE: - case IDC_RCANCEL: - case IDC_PUCONNLOST: - case IDC_PUOTHER: - case IDC_PUCONNRETRY: - case IDC_PURESULT: - case IDC_PUSHOWEXTRA: - if (!bFreeze) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case IDC_PREV: - { - POPUPDATAT ppd = {}; - ppd.lchIcon = Skin_LoadIcon(SKINICON_STATUS_OFFLINE); - wcsncpy(ppd.lptzContactName, TranslateT("Keep status"), MAX_CONTACTNAME); - wcsncpy(ppd.lptzText, TranslateT("You broke the Internet!"), MAX_SECONDLINE); - if (IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) { - ppd.colorBack = GetSysColor(COLOR_BTNFACE); - ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); - } - else if (IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)) { - ppd.colorBack = 0; - ppd.colorText = 0; - } - else { - ppd.colorBack = SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_GETCOLOUR, 0, 0); - ppd.colorText = SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOR, CPM_GETCOLOUR, 0, 0); - } - ppd.PluginWindowProc = KSPopupDlgProc; - ppd.PluginData = nullptr; - if (IsDlgButtonChecked(hwndDlg, IDC_DELAYFROMPU)) { - ppd.iSeconds = 0; - } - else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM)) { - ppd.iSeconds = GetDlgItemInt(hwndDlg, IDC_DELAY, nullptr, FALSE); - } - else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYPERMANENT)) { - ppd.iSeconds = -1; - } - PUAddPopupT(&ppd); - } - break; - } - break; - - case WM_NOTIFY: - if (((LPNMHDR)lParam)->code == PSN_APPLY) { - // left action - if (IsDlgButtonChecked(hwndDlg, IDC_LNOTHING)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_NOTHING); - else if (IsDlgButtonChecked(hwndDlg, IDC_LCLOSE)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_CLOSEPOPUP); - else if (IsDlgButtonChecked(hwndDlg, IDC_LCANCEL)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_CANCEL); - // right action - if (IsDlgButtonChecked(hwndDlg, IDC_RNOTHING)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_NOTHING); - else if (IsDlgButtonChecked(hwndDlg, IDC_RCLOSE)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_CLOSEPOPUP); - else if (IsDlgButtonChecked(hwndDlg, IDC_RCANCEL)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_CANCEL); - // delay - if (IsDlgButtonChecked(hwndDlg, IDC_DELAYFROMPU)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYFROMPU); - else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYCUSTOM); - else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYPERMANENT)) - db_set_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYPERMANENT); - // delay - db_set_dw(0, KSMODULENAME, SETTING_POPUP_TIMEOUT, GetDlgItemInt(hwndDlg, IDC_DELAY, nullptr, FALSE)); - // back color - db_set_dw(0, KSMODULENAME, SETTING_POPUP_BACKCOLOR, SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_GETCOLOUR, 0, 0)); - // text color - db_set_dw(0, KSMODULENAME, SETTING_POPUP_TEXTCOLOR, SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOR, CPM_GETCOLOUR, 0, 0)); - // use win - db_set_b(0, KSMODULENAME, SETTING_POPUP_USEWINCOLORS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)); - // use def - db_set_b(0, KSMODULENAME, SETTING_POPUP_USEDEFCOLORS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)); - // store types - db_set_b(0, KSMODULENAME, SETTING_PUCONNLOST, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUCONNLOST)); - db_set_b(0, KSMODULENAME, SETTING_PUOTHER, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUOTHER)); - db_set_b(0, KSMODULENAME, SETTING_PUCONNRETRY, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUCONNRETRY)); - db_set_b(0, KSMODULENAME, SETTING_PURESULT, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PURESULT)); - db_set_b(0, KSMODULENAME, SETTING_PUSHOWEXTRA, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUSHOWEXTRA)); - } - break; - } - - return 0; -} - -int KeepStatusOptionsInit(WPARAM wparam, LPARAM) -{ - OPTIONSDIALOGPAGE odp = {}; - odp.hInstance = g_plugin.getInst(); - odp.szGroup.a = LPGEN("Status"); - odp.szTitle.a = LPGEN("Keep status"); - odp.flags = ODPF_BOLDGROUPS; - - odp.szTab.a = LPGEN("Basic"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_KS_BASIC); - odp.pfnDlgProc = DlgProcKSBasicOpts; - Options_AddPage(wparam, &odp, KSLangPack); - - odp.szTab.a = LPGEN("Advanced"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_KS_ADV); - odp.pfnDlgProc = DlgProcKSAdvOpts; - Options_AddPage(wparam, &odp, KSLangPack); - - if (ServiceExists(MS_POPUP_ADDPOPUPT)) { - memset(&odp, 0, sizeof(odp)); - odp.position = 150000000; - odp.szGroup.a = LPGEN("Popups"); - odp.hInstance = g_plugin.getInst(); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_PUOPT_KEEPSTATUS); - odp.szTitle.a = LPGEN("Keep status"); - odp.pfnDlgProc = PopupOptDlgProc; - odp.flags = ODPF_BOLDGROUPS; - Options_AddPage(wparam, &odp, KSLangPack); - } - return 0; -} diff --git a/plugins/StatusManager/src/StartupStatus/ss_options.cpp b/plugins/StatusManager/src/StartupStatus/ss_options.cpp deleted file mode 100644 index dd6e877083..0000000000 --- a/plugins/StatusManager/src/StartupStatus/ss_options.cpp +++ /dev/null @@ -1,879 +0,0 @@ -/* - StartupStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "..\stdafx.h" - -char* OptName(int i, const char* setting) -{ - static char buf[100]; - mir_snprintf(buf, "%d_%s", i, setting); - return buf; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Command line processing - -static char* GetStatusDesc(int status) -{ - switch (status) { - case ID_STATUS_AWAY: return "away"; - case ID_STATUS_NA: return "na"; - case ID_STATUS_DND: return "dnd"; - case ID_STATUS_OCCUPIED: return "occupied"; - case ID_STATUS_FREECHAT: return "freechat"; - case ID_STATUS_ONLINE: return "online"; - case ID_STATUS_OFFLINE: return "offline"; - case ID_STATUS_INVISIBLE: return "invisible"; - case ID_STATUS_ONTHEPHONE: return "onthephone"; - case ID_STATUS_OUTTOLUNCH: return "outtolunch"; - case ID_STATUS_LAST: return "last"; - } - return "offline"; -} - -static char* GetCMDLArguments(TProtoSettings& protoSettings) -{ - if (protoSettings.getCount() == 0) - return nullptr; - - char *cmdl, *pnt; - pnt = cmdl = (char*)mir_alloc(mir_strlen(protoSettings[0].m_szName) + mir_strlen(GetStatusDesc(protoSettings[0].m_status)) + 4); - - for (int i = 0; i < protoSettings.getCount(); i++) { - *pnt++ = '/'; - mir_strcpy(pnt, protoSettings[i].m_szName); - pnt += mir_strlen(protoSettings[i].m_szName); - *pnt++ = '='; - mir_strcpy(pnt, GetStatusDesc(protoSettings[i].m_status)); - pnt += mir_strlen(GetStatusDesc(protoSettings[i].m_status)); - if (i != protoSettings.getCount() - 1) { - *pnt++ = ' '; - *pnt++ = '\0'; - cmdl = (char*)mir_realloc(cmdl, mir_strlen(cmdl) + mir_strlen(protoSettings[i + 1].m_szName) + mir_strlen(GetStatusDesc(protoSettings[i + 1].m_status)) + 4); - pnt = cmdl + mir_strlen(cmdl); - } - } - - if (db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, FALSE) == TRUE) { - *pnt++ = ' '; - *pnt++ = '\0'; - cmdl = (char*)mir_realloc(cmdl, mir_strlen(cmdl) + 12); - pnt = cmdl + mir_strlen(cmdl); - mir_strcpy(pnt, "/showdialog"); - pnt += 11; - *pnt = '\0'; - } - - return cmdl; -} - -static char* GetCMDL(TProtoSettings& protoSettings) -{ - char path[MAX_PATH]; - GetModuleFileNameA(nullptr, path, MAX_PATH); - - char* cmdl = (char*)mir_alloc(mir_strlen(path) + 4); - mir_snprintf(cmdl, mir_strlen(path) + 4, "\"%s\" ", path); - - char* args = GetCMDLArguments(protoSettings); - if (args) { - cmdl = (char*)mir_realloc(cmdl, mir_strlen(cmdl) + mir_strlen(args) + 1); - mir_strcat(cmdl, args); - mir_free(args); - } - return cmdl; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Link processing - -static wchar_t* GetLinkDescription(TProtoSettings& protoSettings) -{ - if (protoSettings.getCount() == 0) - return nullptr; - - CMStringW result(SHORTCUT_DESC); - for (auto &p : protoSettings) { - wchar_t *status; - if (p->m_status == ID_STATUS_LAST) - status = TranslateT(""); - else if (p->m_status == ID_STATUS_CURRENT) - status = TranslateT(""); - else if (p->m_status >= MIN_STATUS && p->m_status <= MAX_STATUS) - status = Clist_GetStatusModeDescription(p->m_status, 0); - else - status = nullptr; - if (status == nullptr) - status = TranslateT(""); - - result.AppendChar('\r'); - result.Append(p->m_tszAccName); - result.AppendChar(':'); - result.AppendChar(' '); - result.Append(status); - } - - return mir_wstrndup(result, result.GetLength()); -} - -class CCmdlDlg : public CDlgBase -{ - TProtoSettings ps; - - CCtrlButton btnLink, btnCopy; - -public: - CCmdlDlg(int iProfileNo) - : CDlgBase(g_plugin, IDD_CMDLOPTIONS), - btnCopy(this, IDC_COPY), - btnLink(this, IDC_SHORTCUT), - ps(protoList) - { - GetProfile(iProfileNo, ps); - } - - void OnInitDialog() override - { - char* cmdl = GetCMDL(ps); - SetDlgItemTextA(m_hwnd, IDC_CMDL, cmdl); - mir_free(cmdl); - } - - void onClick_Copy(CCtrlButton*) - { - if (OpenClipboard(m_hwnd)) { - EmptyClipboard(); - - char cmdl[2048]; - GetDlgItemTextA(m_hwnd, IDC_CMDL, cmdl, _countof(cmdl)); - HGLOBAL cmdlGlob = GlobalAlloc(GMEM_MOVEABLE, sizeof(cmdl)); - if (cmdlGlob != nullptr) { - LPTSTR cmdlStr = (LPTSTR)GlobalLock(cmdlGlob); - memcpy(cmdlStr, &cmdl, sizeof(cmdl)); - GlobalUnlock(cmdlGlob); - SetClipboardData(CF_TEXT, cmdlGlob); - } - CloseClipboard(); - } - } - - void onClick_Link(CCtrlButton*) - { - wchar_t savePath[MAX_PATH]; - if (SHGetSpecialFolderPath(nullptr, savePath, CSIDL_DESKTOPDIRECTORY, FALSE)) - wcsncat_s(savePath, SHORTCUT_FILENAME, _countof(savePath) - mir_wstrlen(savePath)); - else - mir_snwprintf(savePath, L".\\%s", SHORTCUT_FILENAME); - - // Get a pointer to the IShellLink interface. - IShellLink *psl; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); - if (SUCCEEDED(hres)) { - ptrA args(GetCMDLArguments(ps)); - ptrW desc(GetLinkDescription(ps)); - - // Set the path to the shortcut target, and add the - // description. - wchar_t path[MAX_PATH]; - GetModuleFileName(nullptr, path, _countof(path)); - psl->SetPath(path); - psl->SetDescription(desc); - psl->SetArguments(_A2T(args)); - - // Query IShellLink for the IPersistFile interface for saving the - // shortcut in persistent storage. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); - - if (SUCCEEDED(hres)) { - // Save the link by calling IPersistFile::Save. - hres = ppf->Save(savePath, TRUE); - ppf->Release(); - } - psl->Release(); - } - } -}; - -static INT_PTR CALLBACK StartupStatusOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static BOOL bInitDone = FALSE; - - switch (msg) { - case WM_INITDIALOG: - bInitDone = FALSE; - - TranslateDialogDefault(hwndDlg); - CheckDlgButton(hwndDlg, IDC_SETPROFILE, db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_OVERRIDE, db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SHOWDIALOG, db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, 0) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SETWINSTATE, db_get_b(0, SSMODULENAME, SETTING_SETWINSTATE, 0) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SETWINLOCATION, db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SETDOCKED, db_get_b(0, SSMODULENAME, SETTING_SETDOCKED, 0) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SETWINSIZE, db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_OFFLINECLOSE, db_get_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, 1) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_AUTODIAL, db_get_b(0, SSMODULENAME, SETTING_AUTODIAL, 0) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_AUTOHANGUP, db_get_b(0, SSMODULENAME, SETTING_AUTOHANGUP, 0) ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemInt(hwndDlg, IDC_SETPROFILEDELAY, db_get_dw(0, SSMODULENAME, SETTING_SETPROFILEDELAY, 500), FALSE); - SetDlgItemInt(hwndDlg, IDC_DLGTIMEOUT, db_get_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, 5), FALSE); - SetDlgItemInt(hwndDlg, IDC_XPOS, db_get_dw(0, SSMODULENAME, SETTING_XPOS, 0), TRUE); - SetDlgItemInt(hwndDlg, IDC_YPOS, db_get_dw(0, SSMODULENAME, SETTING_YPOS, 0), TRUE); - SetDlgItemInt(hwndDlg, IDC_WIDTH, db_get_dw(0, SSMODULENAME, SETTING_WIDTH, 0), FALSE); - SetDlgItemInt(hwndDlg, IDC_HEIGHT, db_get_dw(0, SSMODULENAME, SETTING_HEIGHT, 0), FALSE); - { - int val = db_get_b(0, SSMODULENAME, SETTING_DOCKED, DOCKED_NONE); - int item = SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_ADDSTRING, 0, (LPARAM)TranslateT("Left")); - SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETITEMDATA, (WPARAM)item, (LPARAM)DOCKED_LEFT); - if (val == DOCKED_LEFT) - SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETCURSEL, (WPARAM)item, 0); - - item = SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_ADDSTRING, 0, (LPARAM)TranslateT("Right")); - SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETITEMDATA, (WPARAM)item, (LPARAM)DOCKED_RIGHT); - if (val == DOCKED_RIGHT) - SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETCURSEL, (WPARAM)item, 0); - - item = SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_ADDSTRING, 0, (LPARAM)TranslateT("None")); - SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETITEMDATA, (WPARAM)item, (LPARAM)DOCKED_NONE); - if (val == DOCKED_NONE) - SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETCURSEL, (WPARAM)item, 0); - } - - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); - EnableWindow(GetDlgItem(hwndDlg, IDC_SETPROFILEDELAY), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); - EnableWindow(GetDlgItem(hwndDlg, IDC_OVERRIDE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); - EnableWindow(GetDlgItem(hwndDlg, IDC_DLGTIMEOUT), IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); - EnableWindow(GetDlgItem(hwndDlg, IDC_WINSTATE), IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)); - EnableWindow(GetDlgItem(hwndDlg, IDC_XPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_YPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); - SendMessage(hwndDlg, UM_REINITPROFILES, 0, 0); - SendMessage(hwndDlg, UM_REINITDOCKED, 0, 0); - SendMessage(hwndDlg, UM_REINITWINSTATE, 0, 0); - SendMessage(hwndDlg, UM_REINITWINSIZE, 0, 0); - SetTimer(hwndDlg, 0, 100, nullptr); - bInitDone = TRUE; - break; - - case WM_TIMER: - if (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION) && BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)) { - SetDlgItemTextA(hwndDlg, IDC_CURWINSIZE, ""); - SetDlgItemTextA(hwndDlg, IDC_CURWINLOC, ""); - break; - } - else { - wchar_t text[128]; - mir_snwprintf(text, TranslateT("size: %d x %d"), - db_get_dw(0, MODULE_CLIST, SETTING_WIDTH, 0), - db_get_dw(0, MODULE_CLIST, SETTING_HEIGHT, 0)); - SetDlgItemText(hwndDlg, IDC_CURWINSIZE, text); - - mir_snwprintf(text, TranslateT("loc: %d x %d"), - db_get_dw(0, MODULE_CLIST, SETTING_XPOS, 0), - db_get_dw(0, MODULE_CLIST, SETTING_YPOS, 0)); - SetDlgItemText(hwndDlg, IDC_CURWINLOC, text); - } - break; - - case UM_REINITPROFILES: - // creates profile combo box according to 'dat' - SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_RESETCONTENT, 0, 0); - { - int defProfile; - int profileCount = GetProfileCount((WPARAM)&defProfile, 0); - for (int i = 0; i < profileCount; i++) { - wchar_t profileName[128]; - if (GetProfileName(i, (LPARAM)profileName)) - continue; - - int item = SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_ADDSTRING, 0, (LPARAM)profileName); - SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETITEMDATA, item, i); - } - SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETCURSEL, defProfile, 0); - } - break; - - case UM_REINITDOCKED: - EnableWindow(GetDlgItem(hwndDlg, IDC_SETDOCKED), db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 1)); - if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_SETDOCKED))) - CheckDlgButton(hwndDlg, IDC_SETDOCKED, BST_UNCHECKED); - - EnableWindow(GetDlgItem(hwndDlg, IDC_DOCKED), IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)); - break; - - case UM_REINITWINSTATE: - { - int val = db_get_b(0, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); - SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_RESETCONTENT, 0, 0); - - int item = SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_ADDSTRING, 0, (LPARAM)TranslateT("Hidden")); - SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETITEMDATA, item, (LPARAM)SETTING_STATE_HIDDEN); - if (val == SETTING_STATE_HIDDEN) - SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETCURSEL, item, 0); - - if (!db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 0)) { - item = SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_ADDSTRING, 0, (LPARAM)TranslateT("Minimized")); - SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETITEMDATA, item, SETTING_STATE_MINIMIZED); - if (val == SETTING_STATE_MINIMIZED) - SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETCURSEL, item, 0); - } - item = SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_ADDSTRING, 0, (LPARAM)TranslateT("Normal")); - SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETITEMDATA, item, SETTING_STATE_NORMAL); - if (val == SETTING_STATE_NORMAL || (val == SETTING_STATE_MINIMIZED) && db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 0)) - SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETCURSEL, item, 0); - } - break; - - case UM_REINITWINSIZE: - EnableWindow(GetDlgItem(hwndDlg, IDC_WIDTH), IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)); - EnableWindow(GetDlgItem(hwndDlg, IDC_HEIGHT), !db_get_b(0, MODULE_CLUI, SETTING_AUTOSIZE, 0) && IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)); - - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == LBN_SELCHANGE || HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == EN_CHANGE) - if (bInitDone) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - - switch (LOWORD(wParam)) { - case IDC_SETPROFILE: - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); - EnableWindow(GetDlgItem(hwndDlg, IDC_SETPROFILEDELAY), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); - EnableWindow(GetDlgItem(hwndDlg, IDC_OVERRIDE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); - break; - case IDC_SHOWDIALOG: - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); - EnableWindow(GetDlgItem(hwndDlg, IDC_DLGTIMEOUT), IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); - break; - case IDC_SETWINSTATE: - EnableWindow(GetDlgItem(hwndDlg, IDC_WINSTATE), IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)); - break; - case IDC_SETDOCKED: - EnableWindow(GetDlgItem(hwndDlg, IDC_DOCKED), IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)); - break; - case IDC_SETWINLOCATION: - EnableWindow(GetDlgItem(hwndDlg, IDC_XPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); - EnableWindow(GetDlgItem(hwndDlg, IDC_YPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); - break; - case IDC_SETWINSIZE: - SendMessage(hwndDlg, UM_REINITWINSIZE, 0, 0); - break; - case IDC_SHOWCMDL: - { - int defProfile = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, - SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); - CCmdlDlg *pDlg = new CCmdlDlg(defProfile); - pDlg->Show(); - break; - } - } - break; - - case WM_SHOWWINDOW: - if (wParam == FALSE) - break; - - bInitDone = FALSE; - SendMessage(hwndDlg, UM_REINITPROFILES, 0, 0); - SendMessage(hwndDlg, UM_REINITDOCKED, 0, 0); - SendMessage(hwndDlg, UM_REINITWINSTATE, 0, 0); - SendMessage(hwndDlg, UM_REINITWINSIZE, 0, 0); - bInitDone = TRUE; - break; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case PSN_WIZFINISH: - SSLoadMainOptions(); - break; - - case PSN_APPLY: - db_set_b(0, SSMODULENAME, SETTING_SETPROFILE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); - if (IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)) - db_set_dw(0, SSMODULENAME, SETTING_SETPROFILEDELAY, GetDlgItemInt(hwndDlg, IDC_SETPROFILEDELAY, nullptr, FALSE)); - - if (IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)) { - int val = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); - db_set_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, (WORD)val); - } - db_set_b(0, SSMODULENAME, SETTING_OVERRIDE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_OVERRIDE)); - db_set_b(0, SSMODULENAME, SETTING_SHOWDIALOG, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); - if (IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)) - db_set_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, GetDlgItemInt(hwndDlg, IDC_DLGTIMEOUT, nullptr, FALSE)); - - db_set_b(0, SSMODULENAME, SETTING_SETWINSTATE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)); - if (IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)) { - int val = (int)SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_GETCURSEL, 0, 0), 0); - db_set_b(0, SSMODULENAME, SETTING_WINSTATE, (BYTE)val); - } - db_set_b(0, SSMODULENAME, SETTING_SETDOCKED, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)); - if (IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)) { - int val = (int)SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_GETCURSEL, 0, 0), 0); - db_set_b(0, SSMODULENAME, SETTING_DOCKED, (BYTE)val); - } - db_set_b(0, SSMODULENAME, SETTING_SETWINLOCATION, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); - if (IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)) { - db_set_dw(0, SSMODULENAME, SETTING_XPOS, GetDlgItemInt(hwndDlg, IDC_XPOS, nullptr, TRUE)); - db_set_dw(0, SSMODULENAME, SETTING_YPOS, GetDlgItemInt(hwndDlg, IDC_YPOS, nullptr, TRUE)); - } - db_set_b(0, SSMODULENAME, SETTING_SETWINSIZE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)); - if (IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)) { - db_set_dw(0, SSMODULENAME, SETTING_WIDTH, GetDlgItemInt(hwndDlg, IDC_WIDTH, nullptr, FALSE)); - db_set_dw(0, SSMODULENAME, SETTING_HEIGHT, GetDlgItemInt(hwndDlg, IDC_HEIGHT, nullptr, FALSE)); - } - db_set_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_OFFLINECLOSE)); - db_set_b(0, SSMODULENAME, SETTING_AUTODIAL, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_AUTODIAL)); - db_set_b(0, SSMODULENAME, SETTING_AUTOHANGUP, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_AUTOHANGUP)); - } - break; - } - - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// new profile dialog - -class CAddProfileDlg : public CDlgBase -{ - CCtrlEdit edtProfile; - CCtrlButton btnOk; - -public: - CAddProfileDlg() - : CDlgBase(g_plugin, IDD_ADDPROFILE), - btnOk(this, IDOK), - edtProfile(this, IDC_PROFILENAME) - { - edtProfile.OnChange = Callback(this, &CAddProfileDlg::onChange_Edit); - } - - void OnInitDialog() override - { - btnOk.Disable(); - } - - void OnApply() override - { - ptrW profileName(edtProfile.GetText()); - SendMessage(m_hwndParent, UM_ADDPROFILE, 0, (LPARAM)profileName.get()); - } - - void OnDestroy() override - { - EnableWindow(m_hwndParent, TRUE); - } - - void onChange_Edit(CCtrlEdit*) - { - btnOk.Enable(edtProfile.SendMsg(EM_LINELENGTH, 0, 0) > 0); - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// advanced options dialog - -static int DeleteSetting(const char *szSetting, void *lParam) -{ - LIST *p = (LIST *)lParam; - p->insert(mir_strdup(szSetting)); - return 0; -} - -class CSSAdvancedOptDlg : public CDlgBase -{ - bool bNeedRebuildMenu; - - OBJLIST arProfiles; - - void ReinitProfiles() - { - // creates profile combo box according to 'dat' - cmbProfile.ResetContent(); - for (auto &it : arProfiles) - cmbProfile.AddString(it->tszName, arProfiles.indexOf(&it)); - - cmbProfile.SetCurSel(0); - SetProfile(); - } - - void SetProfile() - { - int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); - chkCreateTTB.SetState(arProfiles[sel].createTtb); - chkShowDialog.SetState(arProfiles[sel].showDialog); - chkCreateMMI.SetState(arProfiles[sel].createMmi); - chkInSubmenu.SetState(arProfiles[sel].inSubMenu); - chkInSubmenu.Enable(arProfiles[sel].createMmi); - chkRegHotkey.SetState(arProfiles[sel].regHotkey); - edtHotkey.SendMsg(HKM_SETHOTKEY, arProfiles[sel].hotKey, 0); - edtHotkey.Enable(arProfiles[sel].regHotkey); - - // fill proto list - lstAccount.ResetContent(); - for (auto &it : arProfiles[sel].ps) - lstAccount.AddString(it->m_tszAccName, (LPARAM)it); - lstAccount.SetCurSel(0); - - SetProtocol(); - } - - void SetProtocol() - { - int idx = lstAccount.GetCurSel(); - if (idx != -1) { - // fill status box - SMProto* ps = (SMProto*)lstAccount.GetItemData(idx); - - int flags = (CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_2, 0))&~(CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_5, 0)); - lstStatus.ResetContent(); - for (int i = 0; i < _countof(statusModeList); i++) { - if ((flags & statusModePf2List[i]) || (statusModeList[i] == ID_STATUS_OFFLINE)) { - int item = lstStatus.AddString(Clist_GetStatusModeDescription(statusModeList[i], 0), statusModeList[i]); - if (ps->m_status == statusModeList[i]) - lstStatus.SetCurSel(item); - } - } - - int item = lstStatus.AddString(TranslateT(""), ID_STATUS_CURRENT); - if (ps->m_status == ID_STATUS_CURRENT) - lstStatus.SetCurSel(item); - - item = lstStatus.AddString(TranslateT(""), ID_STATUS_LAST); - if (ps->m_status == ID_STATUS_LAST) - lstStatus.SetCurSel(item); - } - - SetStatusMsg(); - } - - // set status message - void SetStatusMsg() - { - bool bStatusMsg = false; - int idx = lstAccount.GetCurSel(); - if (idx != -1) { - SMProto *ps = (SMProto*)lstAccount.GetItemData(idx); - - CheckRadioButton(m_hwnd, IDC_MIRANDAMSG, IDC_CUSTOMMSG, ps->m_szMsg != nullptr ? IDC_CUSTOMMSG : IDC_MIRANDAMSG); - if (ps->m_szMsg != nullptr) - edtStatusMsg.SetText(ps->m_szMsg); - - bStatusMsg = ((((CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND & ~PF1_INDIVMODEMSG)) && - (CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(ps->m_status))) || (ps->m_status == ID_STATUS_CURRENT) || (ps->m_status == ID_STATUS_LAST)); - } - chkMiranda.Enable(bStatusMsg); - chkCustom.Enable(bStatusMsg); - btnHelp.Enable(bStatusMsg && chkCustom.GetState()); - edtStatusMsg.Enable(bStatusMsg && chkCustom.GetState()); - } - - CCtrlEdit edtStatusMsg, edtHotkey; - CCtrlCombo cmbProfile; - CCtrlCheck chkMiranda, chkCustom, chkCreateMMI, chkInSubmenu, chkRegHotkey, chkCreateTTB, chkShowDialog; - CCtrlButton btnAdd, btnDelete, btnHelp; - CCtrlListBox lstStatus, lstAccount; - -public: - CSSAdvancedOptDlg() : - CDlgBase(g_plugin, IDD_OPT_STATUSPROFILES), - cmbProfile(this, IDC_PROFILE), - btnAdd(this, IDC_ADDPROFILE), - btnHelp(this, IDC_VARIABLESHELP), - btnDelete(this, IDC_DELPROFILE), - chkCustom(this, IDC_CUSTOMMSG), - chkMiranda(this, IDC_MIRANDAMSG), - chkCreateMMI(this, IDC_CREATEMMI), - chkInSubmenu(this, IDC_INSUBMENU), - chkRegHotkey(this, IDC_REGHOTKEY), - chkCreateTTB(this, IDC_CREATETTB), - chkShowDialog(this, IDC_SHOWDIALOG), - edtHotkey(this, IDC_HOTKEY), - edtStatusMsg(this, IDC_STATUSMSG), - lstStatus(this, IDC_STATUS), - lstAccount(this, IDC_PROTOCOL), - arProfiles(5), - bNeedRebuildMenu(false) - { - btnAdd.OnClick = Callback(this, &CSSAdvancedOptDlg::onClick_Add); - btnHelp.OnClick = Callback(this, &CSSAdvancedOptDlg::onClick_Help); - btnDelete.OnClick = Callback(this, &CSSAdvancedOptDlg::onClick_Delete); - - cmbProfile.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_Profile); - - chkCreateMMI.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_CreateMMI); - chkInSubmenu.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_InSubmenu); - chkCustom.OnChange = chkMiranda.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_StatusMsg); - chkRegHotkey.OnChange = chkCreateTTB.OnChange = chkShowDialog.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_Option); - - edtHotkey.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_Hotkey); - edtStatusMsg.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_EdtStatusMsg); - - lstStatus.OnSelChange = Callback(this, &CSSAdvancedOptDlg::onChange_Status); - lstAccount.OnSelChange = Callback(this, &CSSAdvancedOptDlg::onChange_Account); - - m_OnFinishWizard = Callback(this, &CSSAdvancedOptDlg::OnFinishWizard); - } - - void OnFinishWizard(void*) - { - SSLoadMainOptions(); - } - - virtual void OnInitDialog() override - { - chkCreateMMI.SetText(TranslateT("Create a status menu item")); - - int defProfile; - int profileCount = GetProfileCount((WPARAM)&defProfile, 0); - if (profileCount == 0) { - profileCount = 1; - defProfile = 0; - NotifyChange(); - } - - for (int i = 0; i < profileCount; i++) { - PROFILEOPTIONS *ppo = new PROFILEOPTIONS; - TProtoSettings &ar = ppo->ps; - - if (GetProfile(i, ar) == -1) { - /* create an empty profile */ - if (i == defProfile) - ppo->tszName = mir_wstrdup(TranslateT("default")); - else - ppo->tszName = mir_wstrdup(TranslateT("unknown")); - } - else { - ppo->tszName = db_get_wsa(0, SSMODULENAME, OptName(i, SETTING_PROFILENAME)); - if (ppo->tszName == nullptr) { - if (i == defProfile) - ppo->tszName = mir_wstrdup(TranslateT("default")); - else - ppo->tszName = mir_wstrdup(TranslateT("unknown")); - } - ppo->createTtb = db_get_b(0, SSMODULENAME, OptName(i, SETTING_CREATETTBBUTTON), 0); - ppo->showDialog = db_get_b(0, SSMODULENAME, OptName(i, SETTING_SHOWCONFIRMDIALOG), 0); - ppo->createMmi = db_get_b(0, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), 0); - ppo->inSubMenu = db_get_b(0, SSMODULENAME, OptName(i, SETTING_INSUBMENU), 1); - ppo->regHotkey = db_get_b(0, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), 0); - ppo->hotKey = db_get_w(0, SSMODULENAME, OptName(i, SETTING_HOTKEY), MAKEWORD((char)('0' + i), HOTKEYF_CONTROL | HOTKEYF_SHIFT)); - } - arProfiles.insert(ppo); - } - if (hTTBModuleLoadedHook == nullptr) - chkCreateTTB.Disable(); - - ReinitProfiles(); - ShowWindow(GetDlgItem(m_hwnd, IDC_VARIABLESHELP), ServiceExists(MS_VARS_SHOWHELPEX) ? SW_SHOW : SW_HIDE); - } - - virtual void OnApply() override - { - int oldCount = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); - for (int i = 0; i < oldCount; i++) { - LIST arSettings(10); - db_enum_settings(0, DeleteSetting, SSMODULENAME, &arSettings); - - char setting[128]; - int len = mir_snprintf(setting, "%d_", i); - for (auto &it : arSettings) { - if (!strncmp(setting, it, len)) - db_unset(0, SSMODULENAME, it); - mir_free(it); - } - } - - for (auto &it : arProfiles) { - int i = arProfiles.indexOf(&it); - db_set_b(0, SSMODULENAME, OptName(i, SETTING_SHOWCONFIRMDIALOG), it->showDialog); - db_set_b(0, SSMODULENAME, OptName(i, SETTING_CREATETTBBUTTON), it->createTtb); - db_set_b(0, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), it->createMmi); - db_set_b(0, SSMODULENAME, OptName(i, SETTING_INSUBMENU), it->inSubMenu); - db_set_b(0, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), it->regHotkey); - db_set_w(0, SSMODULENAME, OptName(i, SETTING_HOTKEY), it->hotKey); - db_set_ws(0, SSMODULENAME, OptName(i, SETTING_PROFILENAME), it->tszName); - - for (auto jt : it->ps) { - if (jt->m_szMsg != nullptr) { - char setting[128]; - mir_snprintf(setting, "%s_%s", jt->m_szName, SETTING_PROFILE_STSMSG); - db_set_ws(0, SSMODULENAME, OptName(i, setting), jt->m_szMsg); - } - db_set_w(0, SSMODULENAME, OptName(i, jt->m_szName), jt->m_status); - } - } - db_set_w(0, SSMODULENAME, SETTING_PROFILECOUNT, (WORD)arProfiles.getCount()); - - // Rebuild status menu - if (bNeedRebuildMenu) - Menu_ReloadProtoMenus(); - } - - // add a profile - void onClick_Add(CCtrlButton*) - { - CAddProfileDlg *pDlg = new CAddProfileDlg(); - pDlg->SetParent(m_hwnd); - pDlg->Show(); - EnableWindow(m_hwnd, FALSE); - } - - void onClick_Delete(CCtrlButton*) - { - // wparam == profile no - int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); - if (arProfiles.getCount() == 1) { - MessageBox(nullptr, TranslateT("At least one profile must exist"), TranslateT("Status manager"), MB_OK); - return; - } - - arProfiles.remove(sel); - - int defProfile; - GetProfileCount((WPARAM)&defProfile, 0); - if (sel == defProfile) { - MessageBox(nullptr, TranslateT("Your default profile will be changed"), TranslateT("Status manager"), MB_OK); - db_set_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); - } - ReinitProfiles();; - } - - void onClick_Help(CCtrlButton*) - { - variables_showhelp(m_hwnd, IDC_STATUSMSG, VHF_INPUT | VHF_EXTRATEXT | VHF_HELP | VHF_FULLFILLSTRUCT | VHF_HIDESUBJECTTOKEN, nullptr, "Protocol ID"); - } - - void onChange_Status(CCtrlListBox*) - { - int idx = lstAccount.GetCurSel(); - if (idx != -1) { - SMProto* ps = (SMProto*)lstAccount.GetItemData(idx); - ps->m_status = lstStatus.GetItemData(lstStatus.GetCurSel()); - NotifyChange(); - } - SetStatusMsg(); - } - - void onChange_Account(CCtrlListBox*) - { - SetProtocol(); - } - - void onChange_Profile(CCtrlCombo*) - { - SetProfile(); - } - - void onChange_StatusMsg(CCtrlCheck*) - { - int len; - SMProto* ps = (SMProto*)lstAccount.GetItemData(lstAccount.GetCurSel()); - if (ps->m_szMsg != nullptr) - mir_free(ps->m_szMsg); - - ps->m_szMsg = nullptr; - if (chkCustom.GetState()) { - len = edtStatusMsg.SendMsg(WM_GETTEXTLENGTH, 0, 0); - ps->m_szMsg = (wchar_t*)mir_calloc(sizeof(wchar_t) * (len + 1)); - GetDlgItemText(m_hwnd, IDC_STATUSMSG, ps->m_szMsg, (len + 1)); - } - SetStatusMsg(); - } - - void onChange_Hotkey(CCtrlEdit*) - { - int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); - arProfiles[sel].hotKey = edtHotkey.SendMsg(HKM_GETHOTKEY, 0, 0); - } - - void onChange_EdtStatusMsg(CCtrlEdit*) - { - // update the status message in memory, this is done on each character tick, not nice - // but it works - SMProto* ps = (SMProto*)lstAccount.GetItemData(lstAccount.GetCurSel()); - if (ps->m_szMsg != nullptr) { - if (*ps->m_szMsg) - mir_free(ps->m_szMsg); - ps->m_szMsg = nullptr; - } - int len = edtStatusMsg.SendMsg(WM_GETTEXTLENGTH, 0, 0); - ps->m_szMsg = (wchar_t*)mir_calloc(sizeof(wchar_t) * (len + 1)); - GetDlgItemText(m_hwnd, IDC_STATUSMSG, ps->m_szMsg, (len + 1)); - } - - void onChange_CreateMMI(CCtrlCheck*) - { - chkInSubmenu.Enable(chkCreateMMI.GetState()); - onChange_InSubmenu(nullptr); - } - - void onChange_InSubmenu(CCtrlCheck*) - { - bNeedRebuildMenu = TRUE; - onChange_Option(nullptr); - } - - void onChange_Option(CCtrlCheck*) - { - int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); - PROFILEOPTIONS &po = arProfiles[sel]; - po.createMmi = chkCreateMMI.GetState(); - po.inSubMenu = chkInSubmenu.GetState(); - po.createTtb = chkCreateTTB.GetState(); - po.regHotkey = chkRegHotkey.GetState(); - po.showDialog = chkShowDialog.GetState(); - edtHotkey.Enable(chkRegHotkey.GetState()); - } - - virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override - { - switch (msg) { - case UM_ADDPROFILE: - wchar_t *tszName = (wchar_t*)lParam; - if (tszName == nullptr) - break; - - PROFILEOPTIONS* ppo = new PROFILEOPTIONS; - ppo->tszName = mir_wstrdup(tszName); - arProfiles.insert(ppo); - - ReinitProfiles(); - break; - } - - return CDlgBase::DlgProc(msg, wParam, lParam); - } -}; - -int StartupStatusOptionsInit(WPARAM wparam, LPARAM) -{ - OPTIONSDIALOGPAGE odp = {}; - odp.hInstance = g_plugin.getInst(); - odp.szGroup.a = LPGEN("Status"); - odp.szTitle.a = LPGEN("Startup status"); - odp.flags = ODPF_BOLDGROUPS; - - odp.szTab.a = LPGEN("General"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_STARTUPSTATUS); - odp.pfnDlgProc = StartupStatusOptDlgProc; - Options_AddPage(wparam, &odp, SSLangPack); - - odp.szTab.a = LPGEN("Status profiles"); - odp.pszTemplate = nullptr; - odp.pfnDlgProc = nullptr; - odp.pDialog = new CSSAdvancedOptDlg(); - Options_AddPage(wparam, &odp, SSLangPack); - return 0; -} diff --git a/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp b/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp deleted file mode 100644 index c0345e7441..0000000000 --- a/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - StartupStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "..\stdafx.h" - -#define MAX_MMITEMS 6 - -struct PROFILECE -{ - int profile; - ptrA szProto; - ptrW msg; -}; - -static OBJLIST arProfiles(1); - -extern int protoCount; - -static int menuprofiles[MAX_MMITEMS]; -static int mcount = 0; - -static UINT_PTR releaseTtbTimerId = 0; - -static HANDLE hTBModuleLoadedHook; -static HANDLE hMessageHook = nullptr; - -static HWND hMessageWindow = nullptr; -static HKINFO *hkInfo = nullptr; -static int hkiCount = 0; - -static HANDLE* ttbButtons = nullptr; -static int ttbButtonCount = 0; - -HANDLE hTTBModuleLoadedHook; - -static INT_PTR profileService(WPARAM, LPARAM, LPARAM param) -{ - LoadAndSetProfile((WPARAM)menuprofiles[param], 0); - return 0; -} - -static int CreateMainMenuItems(WPARAM, LPARAM) -{ - CMenuItem mi(g_plugin); - mi.position = 2000100000; - mi.flags = CMIF_UNICODE; - mcount = 0; - int count = GetProfileCount(0, 0); - for (int i = 0; i < count && mcount < MAX_MMITEMS; i++) { - wchar_t profilename[128]; - if (!db_get_b(0, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), 0) || GetProfileName(i, (LPARAM)profilename)) - continue; - - if (db_get_b(0, SSMODULENAME, OptName(i, SETTING_INSUBMENU), 1) && !mi.root) { - mi.root = g_plugin.addRootMenu(MO_STATUS, LPGENW("Status profiles"), 2000100000); - Menu_ConfigureItem(mi.root, MCI_OPT_UID, "1AB30D51-BABA-4B27-9288-1A12278BAD8D"); - } - - char servicename[128]; - mir_snprintf(servicename, "%s%d", MS_SS_MENUSETPROFILEPREFIX, mcount); - CreateServiceFunctionParam(servicename, profileService, mcount); - - mi.name.w = profilename; - mi.position = 2000100000 + mcount; - mi.pszService = servicename; - if (Menu_AddStatusMenuItem(&mi)) - menuprofiles[mcount++] = i; - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -INT_PTR GetProfileName(WPARAM wParam, LPARAM lParam) -{ - int profile = (int)wParam; - if (profile < 0) // get default profile - profile = db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); - - int count = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); - if (profile >= count && count > 0) - return -1; - - wchar_t* buf = (wchar_t*)lParam; - if (count == 0) { - wcsncpy(buf, TranslateT("default"), 128 - 1); - return 0; - } - - DBVARIANT dbv; - char setting[80]; - mir_snprintf(setting, "%d_%s", profile, SETTING_PROFILENAME); - if (db_get_ws(0, SSMODULENAME, setting, &dbv)) - return -1; - - wcsncpy(buf, dbv.ptszVal, 128 - 1); buf[127] = 0; - db_free(&dbv); - return 0; -} - -INT_PTR GetProfileCount(WPARAM wParam, LPARAM) -{ - int *def = (int*)wParam; - int count = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); - if (def != nullptr) { - *def = db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); - if (*def >= count) - *def = 0; - } - - return count; -} - -wchar_t* GetStatusMessage(int profile, const char *szProto) -{ - char dbSetting[80]; - mir_snprintf(dbSetting, "%d_%s_%s", profile, szProto, SETTING_PROFILE_STSMSG); - - for (auto &p : arProfiles) { - if (p->profile == profile && !mir_strcmp(p->szProto, szProto)) { - p->msg = db_get_wsa(0, SSMODULENAME, dbSetting); - return p->msg; - } - } - - PROFILECE *pce = new PROFILECE; - pce->profile = profile; - pce->szProto = mir_strdup(szProto); - pce->msg = db_get_wsa(0, SSMODULENAME, dbSetting); - arProfiles.insert(pce); - - return pce->msg; -} - -void FillStatus(SMProto &ps, int profile) -{ - // load status - char setting[80]; - mir_snprintf(setting, "%d_%s", profile, ps.m_szName); - int iStatus = db_get_w(0, SSMODULENAME, setting, 0); - if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) - iStatus = DEFAULT_STATUS; - ps.m_status = iStatus; - - // load last status - mir_snprintf(setting, "%s%s", PREFIX_LAST, ps.m_szName); - iStatus = db_get_w(0, SSMODULENAME, setting, 0); - if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) - iStatus = DEFAULT_STATUS; - ps.m_lastStatus = iStatus; - - ps.m_szMsg = GetStatusMessage(profile, ps.m_szName); - if (ps.m_szMsg) - ps.m_szMsg = mir_wstrdup(ps.m_szMsg); -} - -int GetProfile(int profile, TProtoSettings &arSettings) -{ - if (profile < 0) // get default profile - profile = db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); - - int count = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); - if (profile >= count && count > 0) - return -1; - - for (auto &it : arSettings) - FillStatus(*it, profile); - - return (arSettings.getCount() == 0) ? -1 : 0; -} - -static void CALLBACK releaseTtbTimerFunction(HWND, UINT, UINT_PTR, DWORD) -{ - KillTimer(nullptr, releaseTtbTimerId); - for (int i = 0; i < ttbButtonCount; i++) - CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)ttbButtons[i], 0); -} - -INT_PTR LoadAndSetProfile(WPARAM iProfileNo, LPARAM) -{ - // wParam == profile no. - int profile = (int)iProfileNo; - TProtoSettings ps(protoList); - if (!GetProfile(profile, ps)) { - profile = (profile >= 0) ? profile : db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); - - char setting[64]; - mir_snprintf(setting, "%d_%s", profile, SETTING_SHOWCONFIRMDIALOG); - if (!db_get_b(0, SSMODULENAME, setting, 0)) - SetStatusEx(ps); - else - ShowConfirmDialogEx(&ps, db_get_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, 5)); - } - - // add timer here - if (hTTBModuleLoadedHook) - releaseTtbTimerId = SetTimer(nullptr, 0, 100, releaseTtbTimerFunction); - - return 0; -} - -static UINT GetFsModifiers(WORD wHotKey) -{ - UINT fsm = 0; - if (HIBYTE(wHotKey)&HOTKEYF_ALT) - fsm |= MOD_ALT; - if (HIBYTE(wHotKey)&HOTKEYF_CONTROL) - fsm |= MOD_CONTROL; - if (HIBYTE(wHotKey)&HOTKEYF_SHIFT) - fsm |= MOD_SHIFT; - if (HIBYTE(wHotKey)&HOTKEYF_EXT) - fsm |= MOD_WIN; - - return fsm; -} - -static DWORD CALLBACK MessageWndProc(HWND, UINT msg, WPARAM wParam, LPARAM) -{ - if (msg == WM_HOTKEY) { - for (int i = 0; i < hkiCount; i++) - if ((int)hkInfo[i].id == wParam) - LoadAndSetProfile((WPARAM)hkInfo[i].profile, 0); - } - - return TRUE; -} - -static int UnregisterHotKeys() -{ - if (hkInfo != nullptr) { - for (int i = 0; i < hkiCount; i++) { - UnregisterHotKey(hMessageWindow, (int)hkInfo[i].id); - GlobalDeleteAtom(hkInfo[i].id); - } - mir_free(hkInfo); - } - DestroyWindow(hMessageWindow); - - hkiCount = 0; - hkInfo = nullptr; - hMessageWindow = nullptr; - - return 0; -} - -// assumes UnregisterHotKeys was called before -static int RegisterHotKeys() -{ - hMessageWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); - SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); - - int count = GetProfileCount(0, 0); - for (int i = 0; i < count; i++) { - if (!db_get_b(0, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), 0)) - continue; - - WORD wHotKey = db_get_w(0, SSMODULENAME, OptName(i, SETTING_HOTKEY), 0); - hkInfo = (HKINFO*)mir_realloc(hkInfo, (hkiCount + 1)*sizeof(HKINFO)); - if (hkInfo == nullptr) - return -1; - - char atomname[255]; - mir_snprintf(atomname, "StatusProfile_%d", i); - hkInfo[hkiCount].id = GlobalAddAtomA(atomname); - if (hkInfo[hkiCount].id == 0) - continue; - - hkInfo[hkiCount].profile = i; - hkiCount++; - RegisterHotKey(hMessageWindow, (int)hkInfo[hkiCount - 1].id, GetFsModifiers(wHotKey), LOBYTE(wHotKey)); - } - - if (hkiCount == 0) - UnregisterHotKeys(); - - return 0; -} - -int SSLoadMainOptions() -{ - if (hTTBModuleLoadedHook) { - RemoveTopToolbarButtons(); - CreateTopToolbarButtons(0, 0); - } - - UnregisterHotKeys(); - RegisterHotKeys(); - return 0; -} - -int LoadProfileModule() -{ - CreateServiceFunction(MS_SS_LOADANDSETPROFILE, LoadAndSetProfile); - return 0; -} - -int InitProfileModule() -{ - hTTBModuleLoadedHook = HookEvent(ME_TTB_MODULELOADED, CreateTopToolbarButtons); - - HookEvent(ME_CLIST_PREBUILDSTATUSMENU, CreateMainMenuItems); - - CreateMainMenuItems(0, 0); - RegisterHotKeys(); - return 0; -} - -int DeinitProfilesModule() -{ - arProfiles.destroy(); - - UnregisterHotKeys(); - RemoveTopToolbarButtons(); - return 0; -} diff --git a/plugins/StatusManager/src/StartupStatus/ss_toolbars.cpp b/plugins/StatusManager/src/StartupStatus/ss_toolbars.cpp deleted file mode 100644 index af1091a023..0000000000 --- a/plugins/StatusManager/src/StartupStatus/ss_toolbars.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - StartupStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "..\stdafx.h" - -#define MAX_MMITEMS 6 - -static LIST ttbButtons(1); - -static IconItem iconList[] = -{ - { LPGEN("Pressed toolbar icon"), "StartupStatus/TtbDown", IDI_TTBDOWN }, - { LPGEN("Released toolbar icon"), "StartupStatus/TtbUp", IDI_TTBUP }, -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -void RemoveTopToolbarButtons() -{ - for (auto &it : ttbButtons.rev_iter()) - CallService(MS_TTB_REMOVEBUTTON, (WPARAM)it, 0); - ttbButtons.destroy(); -} - -int CreateTopToolbarButtons(WPARAM, LPARAM) -{ - if (iconList[0].hIcolib == nullptr) - g_plugin.registerIcon("Toolbar/StartupStatus", iconList); - - int profileCount = CallService(MS_SS_GETPROFILECOUNT, 0, 0); - - TTBButton ttb = {}; - ttb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP; - ttb.pszService = MS_SS_LOADANDSETPROFILE; - for (int i = 0; i < profileCount; i++) { - char setting[80]; - mir_snprintf(setting, "%d_%s", i, SETTING_CREATETTBBUTTON); - if (!db_get_b(0, SSMODULENAME, setting, FALSE)) - continue; - - DBVARIANT dbv; - mir_snprintf(setting, "%d_%s", i, SETTING_PROFILENAME); - if (db_get(0, SSMODULENAME, setting, &dbv)) - continue; - - ttb.hIconHandleDn = iconList[0].hIcolib; - ttb.hIconHandleUp = iconList[1].hIcolib; - ttb.wParamDown = ttb.wParamUp = i; - ttb.name = ttb.pszTooltipUp = dbv.pszVal; - HANDLE ttbAddResult = g_plugin.addTTB(&ttb); - if (ttbAddResult) - ttbButtons.insert(ttbAddResult); - db_free(&dbv); - } - return 0; -} diff --git a/plugins/StatusManager/src/StartupStatus/startupstatus.cpp b/plugins/StatusManager/src/StartupStatus/startupstatus.cpp deleted file mode 100644 index 4f3a487bb2..0000000000 --- a/plugins/StatusManager/src/StartupStatus/startupstatus.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* - StartupStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "..\stdafx.h" - -int SSLangPack; - -static HANDLE hServices[3], hEvents[3]; -static UINT_PTR setStatusTimerId = 0; - -///////////////////////////////////////////////////////////////////////////////////////// - -static HANDLE hProtoAckHook, hCSStatusChangeHook, hStatusChangeHook; - -static HWND hMessageWindow; - -static BYTE showDialogOnStartup = 0; - -///////////////////////////////////////////////////////////////////////////////////////// -// command line options - -static PROTOCOLSETTINGEX* IsValidProtocol(TProtoSettings &protoSettings, const char *protoName) -{ - for (auto &it : protoSettings) - if (!it->ssDisabled && !strncmp(it->m_szName, protoName, mir_strlen(it->m_szName))) - return it; - - return nullptr; -} - -static int IsValidStatusDesc(char* statusDesc) -{ - if (!strncmp("away", statusDesc, 4)) - return ID_STATUS_AWAY; - if (!strncmp("na", statusDesc, 2)) - return ID_STATUS_NA; - if (!strncmp("dnd", statusDesc, 3)) - return ID_STATUS_DND; - if (!strncmp("occupied", statusDesc, 8)) - return ID_STATUS_OCCUPIED; - if (!strncmp("freechat", statusDesc, 8)) - return ID_STATUS_FREECHAT; - if (!strncmp("online", statusDesc, 6)) - return ID_STATUS_ONLINE; - if (!strncmp("offline", statusDesc, 7)) - return ID_STATUS_OFFLINE; - if (!strncmp("invisible", statusDesc, 9)) - return ID_STATUS_INVISIBLE; - if (!strncmp("onthephone", statusDesc, 10)) - return ID_STATUS_ONTHEPHONE; - if (!strncmp("outtolunch", statusDesc, 10)) - return ID_STATUS_OUTTOLUNCH; - if (!strncmp("last", statusDesc, 4)) - return ID_STATUS_LAST; - - return 0; -} - -static void ProcessCommandLineOptions(TProtoSettings& protoSettings) -{ - if (protoSettings.getCount() == 0) - return; - - char *cmdl = GetCommandLineA(); - while (*cmdl != '\0') { - while (*cmdl != '/') { - if (*cmdl == '\0') - return; - - cmdl++; - } - if (*cmdl == '\0') - return; - - cmdl++; - if (!strncmp(cmdl, "showdialog", 10)) { - showDialogOnStartup = TRUE; - continue; - } - char *protoName = cmdl; // first protocol ? - PROTOCOLSETTINGEX* protoSetting = IsValidProtocol(protoSettings, protoName); - if (protoSetting != nullptr) { - while (*cmdl != '=') { - if (*cmdl == '\0') - return; - - cmdl++; // skip to status - } - - if (*cmdl == '\0') - return; - - cmdl++; - char *statusDesc = cmdl; - int status = IsValidStatusDesc(statusDesc); - if (status != 0) - protoSetting->m_status = status; - } - } -} - -static void SetLastStatusMessages(TProtoSettings &ps) -{ - for (auto &it : ps) { - if (it->m_status != ID_STATUS_LAST) - continue; - - char dbSetting[128]; - mir_snprintf(dbSetting, "%s%s", PREFIX_LASTMSG, it->m_szName); - it->m_szMsg = db_get_wsa(0, SSMODULENAME, dbSetting); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Account control event - -// 'allow override' -static int ProcessProtoAck(WPARAM, LPARAM lParam) -{ - // 'something' made a status change - ACKDATA *ack = (ACKDATA*)lParam; - if (ack->type != ACKTYPE_STATUS && ack->result != ACKRESULT_FAILED) - return 0; - - if (!db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) || protoList.getCount() == 0) - return 0; - - for (auto &it : protoList) { - if (!mir_strcmp(ack->szModule, it->m_szName)) { - it->ssDisabled = true; - log_debugA("StartupStatus: %s overridden by ME_PROTO_ACK, status will not be set", ack->szModule); - } - } - - return 0; -} - -static int StatusChange(WPARAM, LPARAM lParam) -{ - // change by menu - if (!db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) || protoList.getCount() == 0) - return 0; - - char *szProto = (char *)lParam; - if (szProto == nullptr) { // global status change - for (auto &it : protoList) { - it->ssDisabled = true; - log_debugA("StartupStatus: all protos overridden by ME_CLIST_STATUSMODECHANGE, status will not be set"); - } - } - else { - for (auto &it : protoList) { - if (!mir_strcmp(it->m_szName, szProto)) { - it->ssDisabled = true; - log_debugA("StartupStatus: %s overridden by ME_CLIST_STATUSMODECHANGE, status will not be set", szProto); - } - } - } - - return 0; -} - -static int CSStatusChangeEx(WPARAM wParam, LPARAM) -{ - // another status plugin made the change - if (!db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) || protoList.getCount() == 0) - return 0; - - if (wParam != 0) { - PROTOCOLSETTINGEX** ps = *(PROTOCOLSETTINGEX***)wParam; - if (ps == nullptr) - return -1; - - for (int i = 0; i < protoList.getCount(); i++) { - for (auto &it : protoList) { - if (ps[i]->m_szName == nullptr || it->m_szName == nullptr) - continue; - - if (!mir_strcmp(ps[i]->m_szName, it->m_szName)) { - log_debugA("StartupStatus: %s overridden by MS_CS_SETSTATUSEX, status will not be set", ps[i]->m_szName); - it->ssDisabled = true; - } - } - } - } - - return 0; -} - -static void CALLBACK SetStatusTimed(HWND, UINT, UINT_PTR, DWORD) -{ - KillTimer(nullptr, setStatusTimerId); - UnhookEvent(hProtoAckHook); - UnhookEvent(hCSStatusChangeHook); - UnhookEvent(hStatusChangeHook); - - TProtoSettings ps(protoList); - for (auto &it : ps) - if (it->ssDisabled) - it->m_status = ID_STATUS_DISABLED; - - SetStatusEx(ps); -} - -static int OnOkToExit(WPARAM, LPARAM) -{ - // save last protocolstatus - for (auto &pa : Accounts()) { - if (!IsSuitableProto(pa)) - continue; - - if (!Proto_GetAccount(pa->szModuleName)) - continue; - - char lastName[128], lastMsg[128]; - mir_snprintf(lastName, "%s%s", PREFIX_LAST, pa->szModuleName); - db_set_w(0, SSMODULENAME, lastName, pa->iRealStatus); - mir_snprintf(lastMsg, "%s%s", PREFIX_LASTMSG, pa->szModuleName); - db_unset(0, SSMODULENAME, lastMsg); - - if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND & ~PF1_INDIVMODEMSG)) - continue; - - if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(pa->iRealStatus))) - continue; - - // NewAwaySys - if (ServiceExists(MS_NAS_GETSTATE)) { - NAS_PROTOINFO npi = { sizeof(npi) }; - npi.szProto = pa->szModuleName; - CallService(MS_NAS_GETSTATE, (WPARAM)&npi, 1); - if (npi.szMsg == nullptr) { - npi.status = 0; - npi.szProto = nullptr; - CallService(MS_NAS_GETSTATE, (WPARAM)&npi, 1); - } - if (npi.szMsg != nullptr) { - db_set_ws(0, SSMODULENAME, lastMsg, npi.tszMsg); - mir_free(npi.tszMsg); - } - } - } - - if (db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1) || db_get_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, 0)) - Clist_SetStatusMode(ID_STATUS_OFFLINE); - - return 0; -} - -static int OnShutdown(WPARAM, LPARAM) -{ - // set windowstate and docked for next startup - if (db_get_b(0, SSMODULENAME, SETTING_SETWINSTATE, 0)) { - int state = db_get_b(0, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); - HWND hClist = g_clistApi.hwndContactList; - BOOL isHidden = !IsWindowVisible(hClist); - switch (state) { - case SETTING_STATE_HIDDEN: - // try to use services where possible - if (!isHidden) - g_clistApi.pfnShowHide(); - break; - - case SETTING_STATE_MINIMIZED: - if (!db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 0)) - ShowWindow(hClist, SW_SHOWMINIMIZED); - break; - - case SETTING_STATE_NORMAL: - // try to use services where possible (that's what they're for) - if (isHidden) - g_clistApi.pfnShowHide(); - break; - } - } - - // hangup - if (db_get_b(0, SSMODULENAME, SETTING_AUTOHANGUP, 0)) - InternetAutodialHangup(0); - - int state = db_get_b(0, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); - // set windowstate and docked for next startup - if (db_get_b(0, SSMODULENAME, SETTING_SETWINSTATE, 0)) - db_set_b(0, MODULE_CLIST, SETTING_WINSTATE, (BYTE)state); - - if (hMessageWindow) - DestroyWindow(hMessageWindow); - - protoList.destroy(); - return 0; -} - -/* Window proc for poweroff event */ -static DWORD CALLBACK MessageWndProc(HWND, UINT msg, WPARAM wParam, LPARAM) -{ - switch (msg) { - case WM_ENDSESSION: - log_debugA("WM_ENDSESSION"); - if (wParam) { - log_debugA("WM_ENDSESSION: calling exit"); - OnShutdown(0, 0); - log_debugA("WM_ENDSESSION: exit called"); - } - break; - } - - return TRUE; -} - -int SSModuleLoaded(WPARAM, LPARAM) -{ - InitProfileModule(); - - hEvents[0] = HookEvent(ME_OPT_INITIALISE, StartupStatusOptionsInit); - - /* shutdown hook for normal shutdown */ - hEvents[1] = HookEvent(ME_SYSTEM_OKTOEXIT, OnOkToExit); - hEvents[2] = HookEvent(ME_SYSTEM_PRESHUTDOWN, OnShutdown); - /* message window for poweroff */ - hMessageWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); - SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); - - GetProfile(-1, protoList); - - // override with cmdl - ProcessCommandLineOptions(protoList); - if (protoList.getCount() == 0) - return 0;// no protocols are loaded - - SetLastStatusMessages(protoList); - showDialogOnStartup = (showDialogOnStartup || db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, 0)); - - // dial - if (showDialogOnStartup || db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1)) - if (db_get_b(0, SSMODULENAME, SETTING_AUTODIAL, 0)) - InternetAutodial(0, nullptr); - - // set the status! - if (showDialogOnStartup || db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, 0)) - ShowConfirmDialogEx((TProtoSettings*)&protoList, db_get_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, 5)); - else if (db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1)) { - // set hooks for override - if (db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1)) { - hProtoAckHook = HookEvent(ME_PROTO_ACK, ProcessProtoAck); - hCSStatusChangeHook = HookEvent(ME_CS_STATUSCHANGEEX, CSStatusChangeEx); - hStatusChangeHook = HookEvent(ME_CLIST_STATUSMODECHANGE, StatusChange); - } - setStatusTimerId = SetTimer(nullptr, 0, db_get_dw(0, SSMODULENAME, SETTING_SETPROFILEDELAY, 500), SetStatusTimed); - } - - // win size and location - if (db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0) || db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0)) { - HWND hClist = g_clistApi.hwndContactList; - - // store in db - if (db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0)) { - db_set_dw(0, MODULE_CLIST, SETTING_XPOS, db_get_dw(0, SSMODULENAME, SETTING_XPOS, 0)); - db_set_dw(0, MODULE_CLIST, SETTING_YPOS, db_get_dw(0, SSMODULENAME, SETTING_YPOS, 0)); - } - if (db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0)) { - db_set_dw(0, MODULE_CLIST, SETTING_WIDTH, db_get_dw(0, SSMODULENAME, SETTING_WIDTH, 0)); - if (!db_get_b(0, MODULE_CLUI, SETTING_AUTOSIZE, 0)) - db_set_dw(0, MODULE_CLIST, SETTING_HEIGHT, db_get_dw(0, SSMODULENAME, SETTING_HEIGHT, 0)); - } - - WINDOWPLACEMENT wndpl = { sizeof(wndpl) }; - if (GetWindowPlacement(hClist, &wndpl)) { - if (wndpl.showCmd == SW_SHOWNORMAL && !Clist_IsDocked()) { - RECT rc; - if (GetWindowRect(hClist, &rc)) { - int x = rc.left; - int y = rc.top; - int width = rc.right - rc.left; - int height = rc.bottom - rc.top; - if (db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0)) { - x = db_get_dw(0, SSMODULENAME, SETTING_XPOS, x); - y = db_get_dw(0, SSMODULENAME, SETTING_YPOS, y); - } - if (db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0)) { - width = db_get_dw(0, SSMODULENAME, SETTING_WIDTH, width); - if (!db_get_b(0, MODULE_CLUI, SETTING_AUTOSIZE, 0)) - height = db_get_dw(0, SSMODULENAME, SETTING_HEIGHT, height); - } - MoveWindow(hClist, x, y, width, height, TRUE); - } - } - } - } - - return 0; -} - -static INT_PTR SrvGetProfile(WPARAM wParam, LPARAM lParam) -{ - return GetProfile((int)wParam, *(TProtoSettings*)lParam); -} - -void StartupStatusLoad() -{ - SSLangPack = GetPluginLangId(MIID_LAST, 0); - - if (g_bMirandaLoaded) - SSModuleLoaded(0, 0); - else - HookEvent(ME_SYSTEM_MODULESLOADED, SSModuleLoaded); - - if (db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1) || db_get_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, 0)) - db_set_w(0, "CList", "Status", (WORD)ID_STATUS_OFFLINE); - - // docking - if (db_get_b(0, SSMODULENAME, SETTING_SETDOCKED, 0)) { - int docked = db_get_b(0, SSMODULENAME, SETTING_DOCKED, DOCKED_NONE); - if (docked == DOCKED_LEFT || docked == DOCKED_RIGHT) - docked = -docked; - - db_set_b(0, MODULE_CLIST, SETTING_DOCKED, (BYTE)docked); - } - - // Create service functions; the get functions are created here; they don't rely on commonstatus - hServices[0] = CreateServiceFunction(MS_SS_GETPROFILE, SrvGetProfile); - hServices[1] = CreateServiceFunction(MS_SS_GETPROFILECOUNT, GetProfileCount); - hServices[2] = CreateServiceFunction(MS_SS_GETPROFILENAME, GetProfileName); - - LoadProfileModule(); -} - -void StartupStatusUnload() -{ - if (g_bMirandaLoaded) - OnShutdown(0, 0); - - KillModuleOptions(SSLangPack); - - for (auto &it : hServices) { - DestroyServiceFunction(it); - it = nullptr; - } - - for (auto &it : hEvents) { - UnhookEvent(it); - it = nullptr; - } - - DeinitProfilesModule(); -} diff --git a/plugins/StatusManager/src/StartupStatus/startupstatus.h b/plugins/StatusManager/src/StartupStatus/startupstatus.h deleted file mode 100644 index 5d16d50843..0000000000 --- a/plugins/StatusManager/src/StartupStatus/startupstatus.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - StartupStatus Plugin for Miranda-IM (www.miranda-im.org) - Copyright 2003-2006 P. Boon - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef __STARTUPSTATUSHEADER -#define __STARTUPSTATUSHEADER - -#define SSMODULENAME "StartupStatus" - -struct PROFILEOPTIONS : public MZeroedObject -{ - __inline PROFILEOPTIONS() : - ps(protoList) - {} - - __inline ~PROFILEOPTIONS() - { - mir_free(tszName); - } - - wchar_t *tszName; - TProtoSettings ps; - BOOL showDialog; - BOOL createTtb; - BOOL createMmi; - BOOL inSubMenu; - BOOL regHotkey; - WORD hotKey; -}; - -typedef struct { - ATOM id; - int profile; -} HKINFO; - -#define UM_REINITPROFILES WM_USER + 1 -#define UM_ADDPROFILE WM_USER + 5 -#define UM_REINITDOCKED WM_USER + 7 -#define UM_REINITWINSTATE WM_USER + 8 -#define UM_REINITWINSIZE WM_USER + 9 - -#define CLUIINTM_REDRAW (WM_USER+100) - -#define MODULE_CLIST "CList" -#define MODULE_CLUI "CLUI" -#define SETTING_STATUS "Status" - -#define SETTING_SETWINSTATE "SetState" -#define SETTING_WINSTATE "State" - -#define SETTING_SETDOCKED "SetDocked" -#define SETTING_DOCKED "Docked" - -#define SETTING_SHOWDIALOG "ShowDialog" -#define SETTING_OFFLINECLOSE "OfflineOnClose" -#define SETTING_SETPROFILE "SetStatusOnStartup" -#define SETTING_AUTODIAL "AutoDial" -#define SETTING_AUTOHANGUP "AutoHangup" - -#define SETTING_TOOLWINDOW "ToolWindow" - -#define SETTING_OVERRIDE "AllowOverride" - -#define SETTING_SETWINLOCATION "SetWinLoc" -#define SETTING_XPOS "x" -#define SETTING_YPOS "y" - -#define SETTING_SETWINSIZE "SetWinSize" -#define SETTING_WIDTH "Width" -#define SETTING_HEIGHT "Height" -#define SETTING_AUTOSIZE "AutoSize" - -#define SETTING_PROFILECOUNT "ProfileCount" -#define SETTING_DEFAULTPROFILE "DefaultProfile" -#define SETTING_PROFILENAME "ProfileName" -#define SETTING_CREATETTBBUTTON "CreateTTBButton" -#define SETTING_PROFILE_STSMSG "StatusMsg" -#define SETTING_SHOWCONFIRMDIALOG "profile_ShowDialog" -#define SETTING_CREATEMMITEM "CreateMMItem" -#define SETTING_INSUBMENU "InSubMenu" -#define SETTING_REGHOTKEY "RegHotKey" -#define SETTING_HOTKEY "HotKey" -#define SETTING_PROFILENO "ProfileNo" - -#define SETTING_SETPROFILEDELAY "SetStatusDelay" -#define SETTING_DLGTIMEOUT "DialogTimeout" - -#define SHORTCUT_DESC L"Miranda NG" -#define SHORTCUT_FILENAME L"\\Miranda NG.lnk" - -#define DOCKED_NONE 0 -#define DOCKED_LEFT 1 -#define DOCKED_RIGHT 2 - -#define MS_SS_MENUSETPROFILEPREFIX "StartupStatus/SetProfile_" - -// options -int StartupStatusOptionsInit(WPARAM wparam,LPARAM lparam); -char* OptName(int i, const char *setting); - -// startupstatus -void StartupStatusLoad(); -void StartupStatusUnload(); - -int SSLoadMainOptions(); - -// profile -void FillStatus(SMProto &ps, int profile); -int GetProfile(int profileID, TProtoSettings &arSettings); -wchar_t* GetStatusMessage(int profile, const char *szProto); - -INT_PTR LoadAndSetProfile(WPARAM wParam, LPARAM lParam); -INT_PTR GetProfileCount(WPARAM wParam, LPARAM lParam); -INT_PTR GetProfileName(WPARAM wParam, LPARAM lParam); - -extern HANDLE hTTBModuleLoadedHook; -void RemoveTopToolbarButtons(); -int CreateTopToolbarButtons(WPARAM wParam, LPARAM lParam); - -int LoadProfileModule(); -int InitProfileModule(); -int DeinitProfilesModule(); - -#endif //__STARTUPSTATUSHEADER diff --git a/plugins/StatusManager/src/aaa_options.cpp b/plugins/StatusManager/src/aaa_options.cpp new file mode 100644 index 0000000000..a8473936b1 --- /dev/null +++ b/plugins/StatusManager/src/aaa_options.cpp @@ -0,0 +1,627 @@ +/* +AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) +Copyright 2003-2006 P. Boon + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "stdafx.h" + +int LoadAutoAwaySetting(SMProto &autoAwaySetting, char* protoName); + +bool g_bAAASettingSame; + +struct AAMSGSETTING +{ + short useCustom; + int status; + char* msg; +}; + +char *StatusModeToDbSetting(int status, const char *suffix); + +void DisableDialog(HWND hwndDlg) +{ + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUS), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADUSECUSTOM), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_RADUSEMIRANDA), FALSE); +} + +INT_PTR CALLBACK DlgProcAutoAwayMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static AAMSGSETTING** settings; + static int last, count; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + ShowWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), ServiceExists(MS_VARS_SHOWHELP) ? SW_SHOW : SW_HIDE); + count = 0; + last = -1; + + PROTOACCOUNT** proto; + int protoCount = 0; + Proto_EnumAccounts(&protoCount, &proto); + if (protoCount <= 0) { + DisableDialog(hwndDlg); + break; + } + + DWORD protoModeMsgFlags = 0; + for (int i = 0; i < protoCount; i++) + if (CallProtoService(proto[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND & ~PF1_INDIVMODEMSG) + protoModeMsgFlags |= CallProtoService(proto[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + + if (protoModeMsgFlags == 0) { + DisableDialog(hwndDlg); + break; + } + + settings = (AAMSGSETTING**)mir_alloc(sizeof(AAMSGSETTING*)); + count = 0; + for (auto &it : statusModes) { + if (!(protoModeMsgFlags & Proto_Status2Flag(it.iStatus))) + continue; + + int j = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)Clist_GetStatusModeDescription(it.iStatus, 0)); + SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, j, it.iStatus); + settings = (AAMSGSETTING**)mir_realloc(settings, (count + 1) * sizeof(AAMSGSETTING*)); + settings[count] = (AAMSGSETTING*)mir_alloc(sizeof(AAMSGSETTING)); + settings[count]->status = it.iStatus; + + DBVARIANT dbv; + if (!db_get(0, AAAMODULENAME, StatusModeToDbSetting(it.iStatus, SETTING_STATUSMSG), &dbv)) { + settings[count]->msg = (char*)mir_alloc(mir_strlen(dbv.pszVal) + 1); + mir_strcpy(settings[count]->msg, dbv.pszVal); + db_free(&dbv); + } + else settings[count]->msg = nullptr; + + settings[count]->useCustom = db_get_b(0, AAAMODULENAME, StatusModeToDbSetting(it.iStatus, SETTING_MSGCUSTOM), FALSE); + count += 1; + } + SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETCURSEL, 0, 0); + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); + } + break; + + case WM_COMMAND: + if (((HIWORD(wParam) == EN_CHANGE) || (HIWORD(wParam) == BN_CLICKED)) && ((HWND)lParam == GetFocus())) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + switch (LOWORD(wParam)) { + case IDC_RADUSEMIRANDA: + CheckDlgButton(hwndDlg, IDC_RADUSECUSTOM, BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADUSEMIRANDA) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); + settings[SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0)]->useCustom = IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM); + break; + + case IDC_RADUSECUSTOM: + CheckDlgButton(hwndDlg, IDC_RADUSEMIRANDA, BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM)); + settings[SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0)]->useCustom = IsDlgButtonChecked(hwndDlg, IDC_RADUSECUSTOM); + break; + + case IDC_STATUS: + if (HIWORD(wParam) == CBN_SELCHANGE) { + int i = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0); + int len = SendDlgItemMessage(hwndDlg, IDC_STATUSMSG, WM_GETTEXTLENGTH, 0, 0); + if (last != -1) { + if (settings[last]->msg == nullptr) + settings[last]->msg = (char*)mir_alloc(len + 1); + else + settings[last]->msg = (char*)mir_realloc(settings[last]->msg, len + 1); + GetDlgItemTextA(hwndDlg, IDC_STATUSMSG, settings[last]->msg, (len + 1)); + } + + if (i != -1) { + if (settings[i]->msg != nullptr) + SetDlgItemTextA(hwndDlg, IDC_STATUSMSG, settings[i]->msg); + else { + ptrW msgw((wchar_t*)CallService(MS_AWAYMSG_GETSTATUSMSGW, settings[i]->status, 0)); + SetDlgItemText(hwndDlg, IDC_STATUSMSG, (msgw != nullptr) ? msgw : L""); + } + + if (settings[i]->useCustom) { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), TRUE); + CheckDlgButton(hwndDlg, IDC_RADUSECUSTOM, BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_RADUSEMIRANDA, BST_UNCHECKED); + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), FALSE); + CheckDlgButton(hwndDlg, IDC_RADUSEMIRANDA, BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_RADUSECUSTOM, BST_UNCHECKED); + } + } + last = i; + } + break; + + case IDC_VARIABLESHELP: + CallService(MS_VARS_SHOWHELP, (WPARAM)GetDlgItem(hwndDlg, IDC_STATUSMSG), 0); + break; + } + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case PSN_WIZFINISH: + AAALoadOptions(); + break; + + case PSN_APPLY: + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); + for (int i = 0; i < count; i++) { + db_set_b(0, AAAMODULENAME, StatusModeToDbSetting(settings[i]->status, SETTING_MSGCUSTOM), (BYTE)settings[i]->useCustom); + if ((settings[i]->useCustom) && (settings[i]->msg != nullptr) && (settings[i]->msg[0] != '\0')) + db_set_s(0, AAAMODULENAME, StatusModeToDbSetting(settings[i]->status, SETTING_STATUSMSG), settings[i]->msg); + } + break; + } + break; + + case WM_DESTROY: + for (int i = 0; i < count; i++) { + mir_free(settings[i]->msg); + mir_free(settings[i]); + } + mir_free(settings); + break; + } + + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Dialog service functions + +static int WriteAutoAwaySetting(SMProto &autoAwaySetting, char *protoName) +{ + char setting[128]; + mir_snprintf(setting, "%s_OptionFlags", protoName); + db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.optionFlags); + mir_snprintf(setting, "%s_AwayTime", protoName); + db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.awayTime); + mir_snprintf(setting, "%s_NATime", protoName); + db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.naTime); + mir_snprintf(setting, "%s_StatusFlags", protoName); + db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.statusFlags); + mir_snprintf(setting, "%s_Lv1Status", protoName); + db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.lv1Status); + mir_snprintf(setting, "%s_Lv2Status", protoName); + db_set_w(0, AAAMODULENAME, setting, (WORD)autoAwaySetting.lv2Status); + + return 0; +} + +static void SetDialogItems(HWND hwndDlg, SMProto *setting) +{ + bool bSetNA = (setting->optionFlags & FLAG_SETNA) != 0; + + bool bIsTimed = (setting->optionFlags & FLAG_ONMOUSE) != 0; + bool bSaver = (setting->optionFlags & FLAG_ONSAVER) != 0; + bool bFullScr = (setting->optionFlags & FLAG_FULLSCREEN) != 0; + bool bOnLock = (setting->optionFlags & FLAG_ONLOCK) != 0; + bool bOnTS = (setting->optionFlags & FLAG_ONTS) != 0; + bool bAnyOption = bIsTimed | bSaver | bFullScr | bOnLock | bOnTS; + + CheckDlgButton(hwndDlg, IDC_FULLSCREEN, bFullScr ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SCREENSAVE, bSaver ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONLOCK, (setting->optionFlags & FLAG_ONLOCK) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ONTSDISCONNECT, bOnTS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_TIMED, bIsTimed ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETNA, bSetNA ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CONFIRM, (setting->optionFlags & FLAG_CONFIRM) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_RESETSTATUS, (setting->optionFlags & FLAG_RESET) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ENTERIDLE, (setting->optionFlags & FLAG_ENTERIDLE) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MONITORMIRANDA, (setting->optionFlags & FLAG_MONITORMIRANDA) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_LV2ONINACTIVE, (setting->optionFlags & FLAG_LV2ONINACTIVE) != 0 ? BST_CHECKED : BST_UNCHECKED); + + SetDlgItemInt(hwndDlg, IDC_AWAYTIME, setting->awayTime, FALSE); + SetDlgItemInt(hwndDlg, IDC_NATIME, setting->naTime, FALSE); + + EnableWindow(GetDlgItem(hwndDlg, IDC_SETNA), bIsTimed); + EnableWindow(GetDlgItem(hwndDlg, IDC_LV2ONINACTIVE), bIsTimed && bSetNA); + EnableWindow(GetDlgItem(hwndDlg, IDC_MONITORMIRANDA), bIsTimed); + EnableWindow(GetDlgItem(hwndDlg, IDC_AWAYTIME), bIsTimed); + EnableWindow(GetDlgItem(hwndDlg, IDC_LV1AFTERSTR), bIsTimed); + + EnableWindow(GetDlgItem(hwndDlg, IDC_LV1STATUS), bAnyOption); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSLIST), bAnyOption); + EnableWindow(GetDlgItem(hwndDlg, IDC_RESETSTATUS), bAnyOption && IsDlgButtonChecked(hwndDlg, IDC_LV2ONINACTIVE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CONFIRM), bAnyOption && IsDlgButtonChecked(hwndDlg, IDC_LV2ONINACTIVE) && IsDlgButtonChecked(hwndDlg, IDC_RESETSTATUS)); + + EnableWindow(GetDlgItem(hwndDlg, IDC_NATIME), bSetNA && bIsTimed); + EnableWindow(GetDlgItem(hwndDlg, IDC_SETNASTR), bSetNA && bIsTimed); + EnableWindow(GetDlgItem(hwndDlg, IDC_SETNASTR), bSetNA && bIsTimed); + EnableWindow(GetDlgItem(hwndDlg, IDC_LV2STATUS), bSetNA && bIsTimed); + + EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOL), !g_bAAASettingSame); +} + +static SMProto* GetSetting(HWND hwndDlg, SMProto *sameSetting) +{ + if (g_bAAASettingSame) + return sameSetting; + + int iItem = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_GETCURSEL, 0, 0); + if (iItem == -1) + return nullptr; + + INT_PTR iData = (INT_PTR)SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_GETITEMDATA, iItem, 0); + return (iData == -1) ? nullptr : (SMProto*)iData; +} + +static void SetDialogStatus(HWND hwndDlg, SMProto *sameSetting) +{ + SMProto *setting = GetSetting(hwndDlg, sameSetting); + if (setting == nullptr) + return; + + // create columns + HWND hList = GetDlgItem(hwndDlg, IDC_STATUSLIST); + ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); + + LVCOLUMN lvCol = { 0 }; + lvCol.mask = LVCF_WIDTH | LVCF_TEXT; + lvCol.pszText = TranslateT("Status"); + lvCol.cx = 118; + ListView_InsertColumn(hList, 0, &lvCol); + + // get pointer to settings + SetDialogItems(hwndDlg, setting); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Rules dialog window procedure + +static TProtoSettings optionSettings; + +static INT_PTR CALLBACK DlgProcAutoAwayRulesOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static SMProto* sameSetting; + SMProto *setting; + static int init; + + switch (msg) { + case WM_INITDIALOG: + init = TRUE; + TranslateDialogDefault(hwndDlg); + + // copy the settings + optionSettings = protoList; + + sameSetting = (SMProto*)mir_alloc(sizeof(SMProto)); + LoadAutoAwaySetting(*sameSetting, SETTING_ALL); + + // fill list from currentProtoSettings + { + for (auto &p : optionSettings) { + int item = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_ADDSTRING, 0, (LPARAM)p->m_tszAccName); + SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_SETITEMDATA, item, (LPARAM)p); + } + } + // set cursor to first protocol + SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_SETCURSEL, 0, 0); + + // status list + SetDialogStatus(hwndDlg, sameSetting); + + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_PROTOCOL, (LPARAM)0x11111111); + init = FALSE; + break; + + case WM_COMMAND: + if ((HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == BN_CLICKED) && (HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + setting = GetSetting(hwndDlg, sameSetting); + if (!setting) + break; + + switch (LOWORD(wParam)) { + case IDC_PROTOCOL: + // status listview + init = TRUE; + { + HWND hList = GetDlgItem(hwndDlg, IDC_STATUSLIST); + ListView_DeleteAllItems(hList); + + int flags = 0; + if (!g_bAAASettingSame) + flags = CallProtoService(setting->m_szName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(setting->m_szName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0); + + LVITEM lvItem = { 0 }; + lvItem.mask = LVIF_TEXT | LVIF_PARAM; + lvItem.iItem = 0; + lvItem.iSubItem = 0; + for (auto &it : statusModes) { + if ((flags & it.iFlag) || (it.iFlag == PF2_OFFLINE) || (g_bAAASettingSame)) { + lvItem.pszText = Clist_GetStatusModeDescription(it.iStatus, 0); + lvItem.lParam = (LPARAM)it.iFlag; + ListView_InsertItem(hList, &lvItem); + ListView_SetCheckState(hList, lvItem.iItem, setting->statusFlags & it.iFlag ? TRUE : FALSE); + lvItem.iItem++; + } + } + } + init = FALSE; + // status dropdown boxes + { + int flags = 0; + if (!g_bAAASettingSame) + flags = CallProtoService(setting->m_szName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(setting->m_szName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0); + + // clear box and add new status, loop status and check if compatible with proto + SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_RESETCONTENT, 0, 0); + for (auto &it : statusModes) { + if ((flags & it.iFlag) || it.iFlag == PF2_OFFLINE || g_bAAASettingSame) { + wchar_t *statusMode = Clist_GetStatusModeDescription(it.iStatus, 0); + int item = SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_ADDSTRING, 0, (LPARAM)statusMode); + SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_SETITEMDATA, item, it.iStatus); + item = SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_ADDSTRING, 0, (LPARAM)statusMode); + SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_SETITEMDATA, item, it.iStatus); + if (it.iStatus == setting->lv1Status) { + SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_SETCURSEL, (WPARAM)item, 0); + SetDlgItemText(hwndDlg, IDC_SETNASTR, CMStringW(FORMAT, TranslateT("minutes of %s mode"), statusMode)); + } + if (it.iStatus == setting->lv2Status) + SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_SETCURSEL, (WPARAM)item, 0); + } + } + } + SetDialogItems(hwndDlg, setting); + break; + + case IDC_LV1STATUS: + if (HIWORD(wParam) == CBN_SELCHANGE) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + setting->lv1Status = (int)SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_LV1STATUS, CB_GETCURSEL, 0, 0), 0); + SetDlgItemText(hwndDlg, IDC_SETNASTR, CMStringW(FORMAT, TranslateT("minutes of %s mode"), Clist_GetStatusModeDescription(setting->lv1Status, 0))); + break; + + case IDC_LV2STATUS: + if (HIWORD(wParam) == CBN_SELCHANGE) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + setting->lv2Status = (int)SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_LV2STATUS, CB_GETCURSEL, 0, 0), 0); + break; + + case IDC_FULLSCREEN: + setting->optionFlags ^= FLAG_FULLSCREEN; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_SCREENSAVE: + setting->optionFlags ^= FLAG_ONSAVER; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_ONLOCK: + setting->optionFlags ^= FLAG_ONLOCK; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_ONTSDISCONNECT: + setting->optionFlags ^= FLAG_ONTS; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_TIMED: + setting->optionFlags ^= FLAG_ONMOUSE; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_SETNA: + setting->optionFlags ^= FLAG_SETNA; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_AWAYTIME: + setting->awayTime = GetDlgItemInt(hwndDlg, IDC_AWAYTIME, nullptr, FALSE); + break; + + case IDC_NATIME: + setting->naTime = GetDlgItemInt(hwndDlg, IDC_NATIME, nullptr, FALSE); + break; + + case IDC_LV2ONINACTIVE: + setting->optionFlags ^= FLAG_LV2ONINACTIVE; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_CONFIRM: + setting->optionFlags ^= FLAG_CONFIRM; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_RESETSTATUS: + setting->optionFlags ^= FLAG_RESET; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_MONITORMIRANDA: + setting->optionFlags ^= FLAG_MONITORMIRANDA; + SetDialogItems(hwndDlg, setting); + break; + + case IDC_ENTERIDLE: + setting->optionFlags ^= FLAG_ENTERIDLE; + SetDialogItems(hwndDlg, setting); + break; + } + break; + + case WM_SHOWWINDOW: + init = TRUE; + + if (setting = GetSetting(hwndDlg, sameSetting)) + SetDialogItems(hwndDlg, setting); + + SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDC_PROTOCOL, (LPARAM)0x11111111); + init = FALSE; + break; + + case WM_NOTIFY: + switch (((NMHDR*)lParam)->idFrom) { + case IDC_STATUSLIST: + if (init) + break; + + switch (((NMHDR*)lParam)->code) { + case LVN_ITEMCHANGED: + NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; + if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_STATUSLIST)) && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK)) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + if (setting = GetSetting(hwndDlg, sameSetting)) { + HWND hList = GetDlgItem(hwndDlg, IDC_STATUSLIST); + LVITEM lvItem = { 0 }; + lvItem.mask = LVIF_PARAM; + lvItem.iItem = nmlv->iItem; + ListView_GetItem(hList, &lvItem); + int pf2Status = lvItem.lParam; + if (ListView_GetCheckState(hList, lvItem.iItem)) + setting->statusFlags |= pf2Status; + else + setting->statusFlags &= ~pf2Status; + } + } + break; + } + break; + } + + switch (((LPNMHDR)lParam)->code) { + case PSN_WIZFINISH: + AAALoadOptions(); + break; + + case PSN_APPLY: + if (g_bAAASettingSame) + WriteAutoAwaySetting(*sameSetting, SETTING_ALL); + else { + for (auto &it : optionSettings) + WriteAutoAwaySetting(*it, it->m_szName); + } + } + break; + + case WM_DESTROY: + optionSettings.destroy(); + mir_free(sameSetting); + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// General options window procedure + +static INT_PTR CALLBACK DlgProcAutoAwayGeneralOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_IGNLOCK, db_get_b(0, AAAMODULENAME, SETTING_IGNLOCK, FALSE) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_IGNSYSKEYS, db_get_b(0, AAAMODULENAME, SETTING_IGNSYSKEYS, FALSE) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_IGNALTCOMBO, db_get_b(0, AAAMODULENAME, SETTING_IGNALTCOMBO, FALSE) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MONITORMOUSE, db_get_b(0, AAAMODULENAME, SETTING_MONITORMOUSE, BST_CHECKED) != 0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MONITORKEYBOARD, db_get_b(0, AAAMODULENAME, SETTING_MONITORKEYBOARD, BST_CHECKED) != 0 ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_AWAYCHECKTIMEINSECS, db_get_w(0, AAAMODULENAME, SETTING_AWAYCHECKTIMEINSECS, 5), FALSE); + SetDlgItemInt(hwndDlg, IDC_CONFIRMDELAY, db_get_w(0, AAAMODULENAME, SETTING_CONFIRMDELAY, 5), FALSE); + CheckDlgButton(hwndDlg, g_bAAASettingSame ? IDC_SAMESETTINGS : IDC_PERPROTOCOLSETTINGS, BST_CHECKED); + break; + + case WM_COMMAND: + if ((HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == BN_CLICKED) && (HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + switch (LOWORD(wParam)) { + case IDC_MONITORMOUSE: + CheckDlgButton(hwndDlg, IDC_MONITORMOUSE, (((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD))) || (IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)) ? BST_CHECKED : BST_UNCHECKED)); + break; + + case IDC_MONITORKEYBOARD: + CheckDlgButton(hwndDlg, IDC_MONITORKEYBOARD, (((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD))) || (IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD)) ? BST_CHECKED : BST_UNCHECKED)); + break; + + case IDC_SAMESETTINGS: + case IDC_PERPROTOCOLSETTINGS: + g_bAAASettingSame = IsDlgButtonChecked(hwndDlg, IDC_SAMESETTINGS); + break; + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0) { + switch (((LPNMHDR)lParam)->code) { + case PSN_WIZFINISH: + AAALoadOptions(); + break; + + case PSN_APPLY: + db_set_b(0, AAAMODULENAME, SETTING_IGNLOCK, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_IGNLOCK)); + db_set_b(0, AAAMODULENAME, SETTING_IGNSYSKEYS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_IGNSYSKEYS)); + db_set_b(0, AAAMODULENAME, SETTING_IGNALTCOMBO, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_IGNALTCOMBO)); + db_set_b(0, AAAMODULENAME, SETTING_SAMESETTINGS, (BYTE)g_bAAASettingSame); + db_set_w(0, AAAMODULENAME, SETTING_AWAYCHECKTIMEINSECS, (WORD)GetDlgItemInt(hwndDlg, IDC_AWAYCHECKTIMEINSECS, nullptr, FALSE)); + db_set_w(0, AAAMODULENAME, SETTING_CONFIRMDELAY, (WORD)GetDlgItemInt(hwndDlg, IDC_CONFIRMDELAY, nullptr, FALSE)); + db_set_b(0, AAAMODULENAME, SETTING_MONITORMOUSE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_MONITORMOUSE)); + db_set_b(0, AAAMODULENAME, SETTING_MONITORKEYBOARD, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_MONITORKEYBOARD)); + } + } + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Options initialization procedure + +int AutoAwayOptInitialise(WPARAM wParam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.position = 1000000000; + odp.hInstance = g_plugin.getInst(); + odp.flags = ODPF_BOLDGROUPS; + odp.szGroup.a = LPGEN("Status"); + odp.szTitle.a = LPGEN("Auto away"); + + odp.szTab.a = LPGEN("General"); + odp.pfnDlgProc = DlgProcAutoAwayGeneralOpts; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_GENAUTOAWAY); + Options_AddPage(wParam, &odp, AAALangPack); + + odp.szTab.a = LPGEN("Rules"); + odp.pfnDlgProc = DlgProcAutoAwayRulesOpts; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AUTOAWAY); + Options_AddPage(wParam, &odp, AAALangPack); + + odp.szTab.a = LPGEN("Status messages"); + odp.pfnDlgProc = DlgProcAutoAwayMsgOpts; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AUTOAWAYMSG); + Options_AddPage(wParam, &odp, AAALangPack); + return 0; +} diff --git a/plugins/StatusManager/src/advancedautoaway.cpp b/plugins/StatusManager/src/advancedautoaway.cpp new file mode 100644 index 0000000000..649f61353f --- /dev/null +++ b/plugins/StatusManager/src/advancedautoaway.cpp @@ -0,0 +1,555 @@ +/* + AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Some code is copied from Miranda's AutoAway module +*/ + +#include "stdafx.h" + +#ifdef _DEBUG +#define SECS_PER_MINUTE 20 /* speedup */ +#else +#define SECS_PER_MINUTE 60 /* default I believe */ +#endif + +///////////////////////////////////////////////////////////////////////////////////////// + +int AAALangPack; + +static HANDLE hEvents[3]; + +static BOOL ignoreLockKeys = FALSE; +static BOOL ignoreSysKeys = FALSE; +static BOOL ignoreAltCombo = FALSE; +static BOOL monitorMouse = TRUE; +static BOOL monitorKeyboard = TRUE; +static HWND confirmDialog; +static int mouseStationaryTimer; +HHOOK hMirandaMouseHook = nullptr; +HHOOK hMirandaKeyBoardHook = nullptr; +#pragma data_seg("Shared") +DWORD lastInput = 0; +POINT lastMousePos = { 0 }; +HHOOK hMouseHook = nullptr; +HHOOK hKeyBoardHook = nullptr; +#pragma data_seg() +#pragma comment(linker, "/section:Shared,rws") +DWORD lastMirandaInput = 0; +static UINT_PTR hAutoAwayTimer; +// prototypes +extern DWORD StatusModeToProtoFlag(int status); +static int HookWindowsHooks(int hookMiranda, int hookAll); +static int UnhookWindowsHooks(); +static LRESULT CALLBACK MouseHookFunction(int code, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK KeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK MirandaMouseHookFunction(int code, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK MirandaKeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam); +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); + +static VOID CALLBACK AutoAwayTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); +extern int AutoAwayOptInitialise(WPARAM wParam, LPARAM lParam); +extern char *StatusModeToDbSetting(int status, const char *suffix); + +///////////////////////////////////////////////////////////////////////////////////////// +// Load from DB + +void AAAUnloadOptions() +{ + UnhookWindowsHooks(); + if (hAutoAwayTimer != 0) + KillTimer(nullptr, hAutoAwayTimer); +} + +void AAALoadOptions() +{ + // if bOverride is enabled, samesettings will be ignored (for options loading) + int monitorMiranda = FALSE; // use windows hooks? + int monitorAll = FALSE; // use windows hooks? + + AAAUnloadOptions(); + + ignoreLockKeys = db_get_b(0, AAAMODULENAME, SETTING_IGNLOCK, FALSE); + ignoreSysKeys = db_get_b(0, AAAMODULENAME, SETTING_IGNSYSKEYS, FALSE); + ignoreAltCombo = db_get_b(0, AAAMODULENAME, SETTING_IGNALTCOMBO, FALSE); + monitorMouse = db_get_b(0, AAAMODULENAME, SETTING_MONITORMOUSE, TRUE); + monitorKeyboard = db_get_b(0, AAAMODULENAME, SETTING_MONITORKEYBOARD, TRUE); + lastInput = lastMirandaInput = GetTickCount(); + + for (auto &it : protoList) { + char* protoName; + if (g_bAAASettingSame) + protoName = SETTING_ALL; + else + protoName = it->m_szName; + LoadAutoAwaySetting(*it, protoName); + + if (it->optionFlags & FLAG_MONITORMIRANDA) + monitorMiranda = TRUE; + else if (ignoreLockKeys || ignoreSysKeys || ignoreAltCombo || (monitorMouse != monitorKeyboard)) + monitorAll = TRUE; + } + + HookWindowsHooks(monitorMiranda, monitorAll); + hAutoAwayTimer = SetTimer(nullptr, 0, db_get_w(0, AAAMODULENAME, SETTING_AWAYCHECKTIMEINSECS, 5) * 1000, AutoAwayTimer); +} + +int LoadAutoAwaySetting(SMProto &autoAwaySetting, char* protoName) +{ + char setting[128]; + mir_snprintf(setting, "%s_OptionFlags", protoName); + autoAwaySetting.optionFlags = db_get_w(0, AAAMODULENAME, setting, FLAG_LV2ONINACTIVE | FLAG_RESET | FLAG_ENTERIDLE); + mir_snprintf(setting, "%s_AwayTime", protoName); + autoAwaySetting.awayTime = db_get_w(0, AAAMODULENAME, setting, SETTING_AWAYTIME_DEFAULT); + mir_snprintf(setting, "%s_NATime", protoName); + autoAwaySetting.naTime = db_get_w(0, AAAMODULENAME, setting, SETTING_NATIME_DEFAULT); + mir_snprintf(setting, "%s_StatusFlags", protoName); + autoAwaySetting.statusFlags = db_get_w(0, AAAMODULENAME, setting, StatusModeToProtoFlag(ID_STATUS_ONLINE) | StatusModeToProtoFlag(ID_STATUS_FREECHAT)); + + int flags; + if (g_bAAASettingSame) + flags = 0xFFFFFF; + else + flags = CallProtoService(protoName, PS_GETCAPS, PFLAGNUM_2, 0)&~CallProtoService(protoName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0); + mir_snprintf(setting, "%s_Lv1Status", protoName); + autoAwaySetting.lv1Status = db_get_w(0, AAAMODULENAME, setting, (flags&StatusModeToProtoFlag(ID_STATUS_AWAY)) ? ID_STATUS_AWAY : ID_STATUS_OFFLINE); + mir_snprintf(setting, "%s_Lv2Status", protoName); + autoAwaySetting.lv2Status = db_get_w(0, AAAMODULENAME, setting, (flags&StatusModeToProtoFlag(ID_STATUS_NA)) ? ID_STATUS_NA : ID_STATUS_OFFLINE); + + return 0; +} + +static int ProcessProtoAck(WPARAM, LPARAM lParam) +{ + ACKDATA *ack = (ACKDATA*)lParam; + if (ack->type != ACKTYPE_STATUS || ack->result != ACKRESULT_SUCCESS) + return 0; + + log_debugA("ProcessProtoAck: ack->szModule: %s", ack->szModule); + for (auto &it : protoList) { + log_debugA("chk: %s", it->m_szName); + if (!mir_strcmp(it->m_szName, ack->szModule)) { + log_debugA("ack->szModule: %s p.statusChanged: %d", ack->szModule, it->bStatusChanged); + if (!it->bStatusChanged) + it->bManualStatus = true; + + it->bStatusChanged = false; + } + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Account control event + +static char* status2descr(int status) +{ + switch (status) { + case ACTIVE: return "ACTIVE"; + case STATUS1_SET: return "STATUS1_SET"; + case STATUS2_SET: return "STATUS2_SET"; + case SET_ORGSTATUS: return "SET_ORGSTATUS"; + case HIDDEN_ACTIVE: return "HIDDEN_ACTIVE"; + } + return "ERROR"; +} + +static int changeState(SMProto &setting, int mode, STATES newState) +{ + if (setting.curState == newState) + return 0; + + setting.oldState = setting.curState; + setting.curState = newState; + + log_debugA("%s state change: %s -> %s", setting.m_szName, status2descr(setting.oldState), status2descr(setting.curState)); + + if (setting.curState != SET_ORGSTATUS && setting.curState != ACTIVE && setting.bStatusChanged) { + /* change the awaymessage */ + if (setting.m_szMsg != nullptr) { + mir_free(setting.m_szMsg); + setting.m_szMsg = nullptr; + } + + if (db_get_b(0, AAAMODULENAME, StatusModeToDbSetting(setting.aaaStatus, SETTING_MSGCUSTOM), FALSE)) + setting.m_szMsg = db_get_wsa(0, AAAMODULENAME, StatusModeToDbSetting(setting.aaaStatus, SETTING_STATUSMSG)); + } + else if (setting.m_szMsg != nullptr) { + mir_free(setting.m_szMsg); + setting.m_szMsg = nullptr; + } + + if (setting.optionFlags & FLAG_ENTERIDLE) { + if (newState == ACTIVE) // we're returning back + Idle_Enter(-1); + else + Idle_Enter(mode); + } + + return 0; +} + +static int getIdleMode(int options) +{ + if ((options & FLAG_ONSAVER) && IsScreenSaverRunning()) + return 1; + + if ((options & FLAG_ONLOCK) && IsWorkstationLocked()) + return 2; + + if ((options & FLAG_ONTS) && IsTerminalDisconnected()) + return 3; + + if ((options & FLAG_FULLSCREEN) && IsFullScreen()) + return 4; + + return 0; +} + +static VOID CALLBACK AutoAwayTimer(HWND, UINT, UINT_PTR, DWORD) +{ + int statusChanged = FALSE; + int confirm = FALSE; + + for (auto &it : protoList) { + it->aaaStatus = ID_STATUS_DISABLED; + + if (it->optionFlags & FLAG_MONITORMIRANDA) + mouseStationaryTimer = (GetTickCount() - lastMirandaInput) / 1000; + else { + LASTINPUTINFO ii = { sizeof(ii) }; + GetLastInputInfo(&ii); + mouseStationaryTimer = (GetTickCount() - ii.dwTime) / 1000; + } + + int sts1Time = it->awayTime * SECS_PER_MINUTE; + int sts2Time = it->naTime * SECS_PER_MINUTE; + int sts1setTime = it->sts1setTimer == 0 ? 0 : (GetTickCount() - it->sts1setTimer) / 1000; + int currentMode = Proto_GetStatus(it->m_szName); + + int mode = getIdleMode(it->optionFlags); + + /* check states */ + if (it->curState == ACTIVE) { + if (((mouseStationaryTimer >= sts1Time && (it->optionFlags & FLAG_ONMOUSE)) || mode) && currentMode != it->lv1Status && it->statusFlags & StatusModeToProtoFlag(currentMode)) { + if (it->optionFlags & FLAG_ONMOUSE) + mode = 5; + + /* from ACTIVE to STATUS1_SET */ + it->m_lastStatus = it->originalStatusMode = Proto_GetStatus(it->m_szName); + it->aaaStatus = it->lv1Status; + it->sts1setTimer = GetTickCount(); + sts1setTime = 0; + it->bStatusChanged = statusChanged = true; + changeState(*it, mode, STATUS1_SET); + } + else if (mouseStationaryTimer >= sts2Time && currentMode == it->lv1Status && currentMode != it->lv2Status && (it->optionFlags & FLAG_SETNA) && (it->statusFlags & StatusModeToProtoFlag(currentMode))) { + /* from ACTIVE to STATUS2_SET */ + it->m_lastStatus = it->originalStatusMode = Proto_GetStatus(it->m_szName); + it->aaaStatus = it->lv2Status; + it->bStatusChanged = statusChanged = true; + changeState(*it, mode, STATUS2_SET); + } + } + + if (it->curState == STATUS1_SET) { + if ((mouseStationaryTimer < sts1Time && !mode) && !(it->optionFlags & FLAG_RESET)) { + /* from STATUS1_SET to HIDDEN_ACTIVE */ + changeState(*it, mode, HIDDEN_ACTIVE); + it->m_lastStatus = Proto_GetStatus(it->m_szName); + } + else if (((mouseStationaryTimer < sts1Time) && !mode) && + ((it->optionFlags & FLAG_LV2ONINACTIVE) || (!(it->optionFlags & FLAG_SETNA))) && + (it->optionFlags & FLAG_RESET)) { + /* from STATUS1_SET to SET_ORGSTATUS */ + changeState(*it, mode, SET_ORGSTATUS); + } + else if ((it->optionFlags & FLAG_SETNA) && sts1setTime >= sts2Time) { + /* when set STATUS2, currentMode doesn't have to be in the selected status list (statusFlags) */ + /* from STATUS1_SET to STATUS2_SET */ + it->m_lastStatus = Proto_GetStatus(it->m_szName); + it->aaaStatus = it->lv2Status; + it->bStatusChanged = statusChanged = true; + changeState(*it, mode, STATUS2_SET); + } + } + + if (it->curState == STATUS2_SET) { + if (mouseStationaryTimer < sts2Time && !mode && (it->optionFlags & FLAG_RESET)) { + /* from STATUS2_SET to SET_ORGSTATUS */ + changeState(*it, mode, SET_ORGSTATUS); + } + else if (mouseStationaryTimer < sts2Time && !mode && !(it->optionFlags & FLAG_RESET)) { + /* from STATUS2_SET to HIDDEN_ACTIVE */ + /* Remember: after status1 is set, and "only on inactive" is NOT set, it implies !reset. */ + changeState(*it, mode, HIDDEN_ACTIVE); + it->m_lastStatus = Proto_GetStatus(it->m_szName); + } + } + + if (it->curState == HIDDEN_ACTIVE) { + if (it->bManualStatus) { + /* HIDDEN_ACTIVE to ACTIVE */ + // it->bStatusChanged = false; + changeState(*it, mode, ACTIVE); + it->sts1setTimer = 0; + it->bManualStatus = false; + } + else if ((it->optionFlags & FLAG_SETNA) && currentMode == it->lv1Status && + currentMode != it->lv2Status && (it->statusFlags & StatusModeToProtoFlag(currentMode)) && + (mouseStationaryTimer >= sts2Time || (sts1setTime >= sts2Time && !(it->optionFlags & FLAG_LV2ONINACTIVE)))) { + /* HIDDEN_ACTIVE to STATUS2_SET */ + it->m_lastStatus = it->originalStatusMode = Proto_GetStatus(it->m_szName); + it->aaaStatus = it->lv2Status; + it->bStatusChanged = statusChanged = true; + changeState(*it, mode, STATUS2_SET); + } + } + if (it->curState == SET_ORGSTATUS) { + /* SET_ORGSTATUS to ACTIVE */ + it->m_lastStatus = Proto_GetStatus(it->m_szName); + it->aaaStatus = it->originalStatusMode; + confirm = (it->optionFlags & FLAG_CONFIRM) ? TRUE : confirm; + it->bStatusChanged = statusChanged = true; + changeState(*it, mode, ACTIVE); + it->sts1setTimer = 0; + } + it->bManualStatus = false; + } + + if (confirm || statusChanged) { + TProtoSettings ps(protoList); // make a copy of data not to pollute main array + for (auto &it : ps) + it->m_status = it->aaaStatus; + + if (confirm) + confirmDialog = ShowConfirmDialogEx(&ps, db_get_w(0, AAAMODULENAME, SETTING_CONFIRMDELAY, 5)); + else if (statusChanged) + SetStatusEx(ps); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Windows hooks + +static int HookWindowsHooks(int hookMiranda, int hookAll) +{ + if (hookMiranda) { + if (monitorKeyboard && hMirandaKeyBoardHook == nullptr) + hMirandaKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, MirandaKeyBoardHookFunction, nullptr, GetCurrentThreadId()); + if (monitorMouse && hMirandaMouseHook == nullptr) + hMirandaMouseHook = SetWindowsHookEx(WH_MOUSE, MirandaMouseHookFunction, nullptr, GetCurrentThreadId()); + } + if (hookAll) { + if (monitorKeyboard && hKeyBoardHook == nullptr) + hKeyBoardHook = SetWindowsHookEx(WH_KEYBOARD, KeyBoardHookFunction, nullptr, GetCurrentThreadId()); + if (monitorMouse && hMouseHook == nullptr) + hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseHookFunction, nullptr, GetCurrentThreadId()); + } + + return 0; +} + +static int UnhookWindowsHooks() +{ + UnhookWindowsHookEx(hMouseHook); + UnhookWindowsHookEx(hKeyBoardHook); + UnhookWindowsHookEx(hMirandaMouseHook); + UnhookWindowsHookEx(hMirandaKeyBoardHook); + + hMouseHook = hKeyBoardHook = hMirandaMouseHook = hMirandaKeyBoardHook = nullptr; + return 0; +} + +static LRESULT CALLBACK MirandaMouseHookFunction(int code, WPARAM wParam, LPARAM lParam) +{ + if (code >= 0) { + PMOUSEHOOKSTRUCT mouseInfo = (PMOUSEHOOKSTRUCT)lParam; + POINT pt = mouseInfo->pt; + + /* TioDuke's KeyBoardNotifyExt: only update if a Miranda window is focused */ + DWORD pid; + GetWindowThreadProcessId(GetForegroundWindow(), &pid); + if (pid != GetCurrentProcessId()) + return CallNextHookEx(hMirandaMouseHook, code, wParam, lParam); + + if (pt.x != lastMousePos.x || pt.y != lastMousePos.y) { + lastMousePos = pt; + lastMirandaInput = GetTickCount(); + } + } + + return CallNextHookEx(hMirandaMouseHook, code, wParam, lParam); +} + +static LRESULT CALLBACK MirandaKeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam) +{ + if (code >= 0) { + if (ignoreAltCombo) { + if (((GetKeyState(VK_MENU) < 0) || (wParam == VK_MENU)) || + ((GetKeyState(VK_TAB) < 0) || (wParam == VK_TAB)) || + ((GetKeyState(VK_SHIFT) < 0) || (wParam == VK_SHIFT)) || + ((GetKeyState(VK_CONTROL) < 0) || (wParam == VK_CONTROL)) || + ((GetKeyState(VK_ESCAPE) < 0) || (wParam == VK_ESCAPE)) || + ((GetKeyState(VK_LWIN) < 0) || (wParam == VK_LWIN)) || + ((GetKeyState(VK_RWIN) < 0) || (wParam == VK_RWIN))) { + return CallNextHookEx(hMirandaKeyBoardHook, code, wParam, lParam); + } + } + + switch (wParam) { + case VK_NUMLOCK: + case VK_CAPITAL: + case VK_SCROLL: + if (!ignoreLockKeys) + lastMirandaInput = GetTickCount(); + break; + + case VK_TAB: + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + case VK_ESCAPE: + case VK_LWIN: + case VK_RWIN: + if (!ignoreSysKeys) + lastMirandaInput = GetTickCount(); + break; + + default: + lastMirandaInput = GetTickCount(); + break; + } + } + + return CallNextHookEx(hMirandaKeyBoardHook, code, wParam, lParam); +} + +static LRESULT CALLBACK MouseHookFunction(int code, WPARAM wParam, LPARAM lParam) +{ + if (code >= 0) { + PMOUSEHOOKSTRUCT mouseInfo = (PMOUSEHOOKSTRUCT)lParam; + POINT pt = mouseInfo->pt; + + /* TioDuke's KeyBoardNotifyExt: also grab clicks */ + if ((wParam >= WM_NCLBUTTONDOWN && wParam <= WM_NCXBUTTONDBLCLK && wParam != 0x00AA) || (wParam >= WM_LBUTTONDOWN && wParam <= WM_XBUTTONDBLCLK)) + lastInput = GetTickCount(); + + if (pt.x != lastMousePos.x || pt.y != lastMousePos.y) { + lastMousePos = pt; + lastInput = GetTickCount(); + } + } + + return CallNextHookEx(hMouseHook, code, wParam, lParam); +} + +static LRESULT CALLBACK KeyBoardHookFunction(int code, WPARAM wParam, LPARAM lParam) +{ + if (code >= 0) { + if (ignoreAltCombo) { + if (((GetKeyState(VK_MENU) < 0) || (wParam == VK_MENU)) || + ((GetKeyState(VK_TAB) < 0) || (wParam == VK_TAB)) || + ((GetKeyState(VK_SHIFT) < 0) || (wParam == VK_SHIFT)) || + ((GetKeyState(VK_CONTROL) < 0) || (wParam == VK_CONTROL)) || + ((GetKeyState(VK_ESCAPE) < 0) || (wParam == VK_ESCAPE)) || + ((GetKeyState(VK_LWIN) < 0) || (wParam == VK_LWIN)) || + ((GetKeyState(VK_RWIN) < 0) || (wParam == VK_RWIN))) { + return CallNextHookEx(hKeyBoardHook, code, wParam, lParam); + } + } + + switch (wParam) { + case VK_NUMLOCK: + case VK_CAPITAL: + case VK_SCROLL: + if (!ignoreLockKeys) + lastInput = GetTickCount(); + break; + + case VK_TAB: + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + case VK_ESCAPE: + case VK_LWIN: + case VK_RWIN: + if (!ignoreSysKeys) + lastInput = GetTickCount(); + break; + + default: + lastInput = GetTickCount(); + break; + } + } + + return CallNextHookEx(hKeyBoardHook, code, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Inits & stuff + +static int AutoAwayShutdown(WPARAM, LPARAM) +{ + AAAUnloadOptions(); + return 0; +} + +int AAAModuleLoaded(WPARAM, LPARAM) +{ + hEvents[0] = HookEvent(ME_OPT_INITIALISE, AutoAwayOptInitialise); + hEvents[1] = HookEvent(ME_SYSTEM_PRESHUTDOWN, AutoAwayShutdown); + hEvents[2] = HookEvent(ME_PROTO_ACK, ProcessProtoAck); + + mouseStationaryTimer = 0; + lastInput = lastMirandaInput = GetTickCount(); + + //////////////////////////////////////////////////////////////////////////////////////// + + AAALoadOptions(); + return 0; +} + +void AdvancedAutoAwayLoad() +{ + AAALangPack = GetPluginLangId(MIID_LAST, 0); + + g_bAAASettingSame = db_get_b(0, AAAMODULENAME, SETTING_SAMESETTINGS, 0); + + if (g_bMirandaLoaded) + AAAModuleLoaded(0, 0); + else + HookEvent(ME_SYSTEM_MODULESLOADED, AAAModuleLoaded); +} + +void AdvancedAutoAwayUnload() +{ + if (g_bMirandaLoaded) + AutoAwayShutdown(0, 0); + + KillModuleOptions(AAALangPack); + + for (auto &it : hEvents) { + UnhookEvent(it); + it = nullptr; + } + + protoList.destroy(); +} diff --git a/plugins/StatusManager/src/advancedautoaway.h b/plugins/StatusManager/src/advancedautoaway.h new file mode 100644 index 0000000000..53c8502be0 --- /dev/null +++ b/plugins/StatusManager/src/advancedautoaway.h @@ -0,0 +1,48 @@ +/* + AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef __ADVANCED_AUTOAWAY_HEADER +#define __ADVANCED_AUTOAWAY_HEADER + +#define AAAMODULENAME "AdvancedAutoAway" +#define SETTING_IGNLOCK "IgnoreLockKeys" +#define SETTING_IGNSYSKEYS "IgnoreSysKeys" +#define SETTING_IGNALTCOMBO "IgnoreAltCombo" +#define SETTING_SAMESETTINGS "SameAutoAwaySettings" +#define SETTING_ALL "ALLPROTOS" +#define SETTING_MSGCUSTOM "Custom" +#define SETTING_STATUSMSG "Msg" +#define SETTING_CONFIRMDELAY "ConfirmTimeout" +#define SETTING_ENTERIDLE "EnterIdle" + +#define SETTING_AWAYTIME_DEFAULT 5 +#define SETTING_NATIME_DEFAULT 20 +#define SETTING_AWAYCHECKTIMEINSECS "CheckInterval" + +#define SETTING_MONITORMOUSE "MonitorMouse" +#define SETTING_MONITORKEYBOARD "MonitorKeyboard" + +void AdvancedAutoAwayLoad(); +void AdvancedAutoAwayUnload(); + +int LoadAutoAwaySetting(SMProto&, char *protoName); +void AAALoadOptions(); + +extern bool g_bAAASettingSame; + +#endif diff --git a/plugins/StatusManager/src/commonstatus.cpp b/plugins/StatusManager/src/commonstatus.cpp index 371dfeae1a..f95ec3f89c 100644 --- a/plugins/StatusManager/src/commonstatus.cpp +++ b/plugins/StatusManager/src/commonstatus.cpp @@ -21,6 +21,20 @@ #include "stdafx.h" +StatusModeMap statusModes[MAX_STATUS_COUNT] = +{ + { ID_STATUS_OFFLINE, PF2_OFFLINE }, + { ID_STATUS_ONLINE, PF2_ONLINE }, + { ID_STATUS_AWAY, PF2_SHORTAWAY }, + { ID_STATUS_NA, PF2_LONGAWAY }, + { ID_STATUS_OCCUPIED, PF2_LIGHTDND }, + { ID_STATUS_DND, PF2_HEAVYDND }, + { ID_STATUS_FREECHAT, PF2_FREECHAT }, + { ID_STATUS_INVISIBLE, PF2_INVISIBLE }, + { ID_STATUS_ONTHEPHONE, PF2_ONTHEPHONE }, + { ID_STATUS_OUTTOLUNCH, PF2_OUTTOLUNCH } +}; + // handles for hooks and other Miranda thingies static HANDLE hCSStatusChangedExEvent; diff --git a/plugins/StatusManager/src/commonstatus.h b/plugins/StatusManager/src/commonstatus.h index 217903ff79..2408323478 100644 --- a/plugins/StatusManager/src/commonstatus.h +++ b/plugins/StatusManager/src/commonstatus.h @@ -63,9 +63,6 @@ #define MAX_STATUS ID_STATUS_CURRENT #define MIN_STATUS ID_STATUS_OFFLINE #define DEF_CLOSE_TIME 5 //secs -#define PF2_OFFLINE 0x00000200 -static int statusModeList[] = { ID_STATUS_OFFLINE, ID_STATUS_ONLINE, ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND, ID_STATUS_FREECHAT, ID_STATUS_INVISIBLE, ID_STATUS_ONTHEPHONE, ID_STATUS_OUTTOLUNCH }; -static int statusModePf2List[] = { PF2_OFFLINE, PF2_ONLINE, PF2_SHORTAWAY, PF2_LONGAWAY, PF2_LIGHTDND, PF2_HEAVYDND, PF2_FREECHAT, PF2_INVISIBLE, PF2_ONTHEPHONE, PF2_OUTTOLUNCH }; wchar_t *GetDefaultStatusMessage(PROTOCOLSETTINGEX *ps, int status); int GetActualStatus(PROTOCOLSETTINGEX *protoSetting); @@ -91,14 +88,23 @@ bool IsSuitableProto(PROTOACCOUNT *pa); #define FLAG_ONTS 0x0200 // db: on terminal session disconnect #define FLAG_ENTERIDLE 0x0400 // db: enter idle with AA mode -typedef enum +#define PF2_OFFLINE 0x0200 + +struct StatusModeMap +{ + int iStatus, iFlag; +}; + +extern StatusModeMap statusModes[MAX_STATUS_COUNT]; + +enum STATES { ACTIVE, // user is active STATUS1_SET, // first status change happened STATUS2_SET, // second status change happened SET_ORGSTATUS, // user was active again, original status will be restored HIDDEN_ACTIVE // user is active, but this is not shown to the outside world -} STATES; +}; struct SMProto : public PROTOCOLSETTINGEX, public MZeroedObject { diff --git a/plugins/StatusManager/src/confirmdialog.cpp b/plugins/StatusManager/src/confirmdialog.cpp index 0491a77c94..c784102d9e 100644 --- a/plugins/StatusManager/src/confirmdialog.cpp +++ b/plugins/StatusManager/src/confirmdialog.cpp @@ -338,19 +338,20 @@ static INT_PTR CALLBACK ConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LP actualStatus = currentStatus; } - for (int i = 0; i < _countof(statusModeList); i++) { - if (((flags & statusModePf2List[i]) || (statusModePf2List[i] == PF2_OFFLINE)) && (!((!(flags)& Proto_Status2Flag(statusModePf2List[i]))) || ((CallProtoService(proto->m_szName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0)&Proto_Status2Flag(statusModePf2List[i]))))) { - wchar_t *statusMode = Clist_GetStatusModeDescription(statusModeList[i], 0); + for (auto &it : statusModes) { + int pf5 = CallProtoService(proto->m_szName, PS_GETCAPS, PFLAGNUM_5, 0); + if (((flags & it.iFlag) || it.iFlag == PF2_OFFLINE) && (!((!(flags) & Proto_Status2Flag(it.iFlag))) || (pf5 & Proto_Status2Flag(it.iFlag)))) { + wchar_t *statusMode = Clist_GetStatusModeDescription(it.iStatus, 0); item = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)statusMode); - SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, item, statusModeList[i]); - if (statusModeList[i] == proto->m_status) + SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, item, it.iStatus); + if (it.iStatus == proto->m_status) SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETCURSEL, item, 0); } } // enable status box EnableWindow(GetDlgItem(hwndDlg, IDC_STATUS), (ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), -1, LVNI_SELECTED) >= 0)); - if ((!((CallProtoService(proto->m_szName, PS_GETCAPS, PFLAGNUM_1, 0)&PF1_MODEMSGSEND)&~PF1_INDIVMODEMSG)) || (!(CallProtoService(proto->m_szName, PS_GETCAPS, PFLAGNUM_3, 0)&Proto_Status2Flag(actualStatus)))) + if ((!((CallProtoService(proto->m_szName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) & ~PF1_INDIVMODEMSG)) || (!(CallProtoService(proto->m_szName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(actualStatus)))) EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), FALSE); else if (proto->m_status == ID_STATUS_LAST || proto->m_status == ID_STATUS_CURRENT) EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), TRUE); diff --git a/plugins/StatusManager/src/keepstatus.cpp b/plugins/StatusManager/src/keepstatus.cpp new file mode 100644 index 0000000000..cbb52e8777 --- /dev/null +++ b/plugins/StatusManager/src/keepstatus.cpp @@ -0,0 +1,1102 @@ +/* + KeepStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "stdafx.h" + +int KSLangPack; + +static HANDLE hConnectionEvent = nullptr; +static HANDLE hServices[4], hEvents[2]; + +static mir_cs GenTimerCS, GenStatusCS, CheckContinueslyCS; + +static HANDLE hProtoAckHook = nullptr; +static HANDLE hStatusChangeHook = nullptr; +static HANDLE hCSStatusChangeHook = nullptr; +static HANDLE hCSStatusChangeExHook = nullptr; + +static HWND hMessageWindow = nullptr; + +static UINT_PTR checkConnectionTimerId = 0; +static UINT_PTR afterCheckTimerId = 0; +static UINT_PTR processAckTimerId = 0; +static UINT_PTR checkContinTimerId = 0; +static UINT_PTR checkConnectingTimerId = 0; +static int retryCount = 0; +static BOOL bLastPingResult = TRUE; +// variables (options) +static int maxRetries = 0; +static int initDelay = 0; +static int currentDelay = 0; +static int maxDelay = 0; +static int ackDelay = 500; +static int increaseExponential = 0; +static int showConnectionPopups = 0; +// prototypes +static int StartTimer(int timer, int timeout, BOOL restart); +static int StopTimer(int timer); +static int ProcessProtoAck(WPARAM wParam, LPARAM lParam); +static VOID CALLBACK CheckConnectingTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); +static VOID CALLBACK CheckAckStatusTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); +static int StatusChange(WPARAM wParam, LPARAM lParam); +static int CSStatusChange(WPARAM wParam, LPARAM lParam); +static int CSStatusChangeEx(WPARAM wParam, LPARAM lParam); +static VOID CALLBACK CheckConnectionTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); +static int StopChecking(); +static VOID CALLBACK AfterCheckTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); +static VOID CALLBACK CheckContinueslyTimer(HWND hwnd, UINT message, UINT_PTR idEvent, DWORD dwTime); +INT_PTR IsProtocolEnabledService(WPARAM wParam, LPARAM lParam); + +static int ProcessPopup(int reason, LPARAM lParam); +LRESULT CALLBACK KSPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +static DWORD CALLBACK MessageWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +// options.c +extern int KeepStatusOptionsInit(WPARAM wparam, LPARAM); + +///////////////////////////////////////////////////////////////////////////////////////// + +void KSUnloadOptions() +{ + UnhookEvent(hProtoAckHook); + UnhookEvent(hStatusChangeHook); + UnhookEvent(hCSStatusChangeHook); + UnhookEvent(hCSStatusChangeExHook); + hProtoAckHook = hStatusChangeHook = hCSStatusChangeHook = hCSStatusChangeExHook = nullptr; + + if (IsWindow(hMessageWindow)) + DestroyWindow(hMessageWindow); + + if (StartTimer(IDT_CHECKCONTIN, -1, FALSE)) + WSACleanup(); + + StopTimer(IDT_CHECKCONN | IDT_PROCESSACK | IDT_AFTERCHECK | IDT_CHECKCONTIN | IDT_CHECKCONNECTING); +} + +int KSLoadOptions() +{ + KSUnloadOptions(); + + if (db_get_b(0, KSMODULENAME, SETTING_CHECKCONNECTION, FALSE)) { + if (db_get_b(0, KSMODULENAME, SETTING_CONTCHECK, FALSE)) { + if (db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE)) { + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); + } + StartTimer(IDT_CHECKCONTIN, 0, FALSE); + } + increaseExponential = db_get_b(0, KSMODULENAME, SETTING_INCREASEEXPONENTIAL, FALSE); + currentDelay = initDelay = 1000 * db_get_dw(0, KSMODULENAME, SETTING_INITDELAY, DEFAULT_INITDELAY); + maxDelay = 1000 * db_get_dw(0, KSMODULENAME, SETTING_MAXDELAY, DEFAULT_MAXDELAY); + maxRetries = db_get_b(0, KSMODULENAME, SETTING_MAXRETRIES, 0); + if (maxRetries == 0) + maxRetries = -1; + hProtoAckHook = HookEvent(ME_PROTO_ACK, ProcessProtoAck); + hStatusChangeHook = HookEvent(ME_CLIST_STATUSMODECHANGE, StatusChange); + if (ServiceExists(ME_CS_STATUSCHANGE)) + hCSStatusChangeHook = HookEvent(ME_CS_STATUSCHANGE, CSStatusChange); + hCSStatusChangeExHook = HookEvent(ME_CS_STATUSCHANGEEX, CSStatusChangeEx); + if (db_get_b(0, KSMODULENAME, SETTING_CHECKAPMRESUME, 0)) { + if (!IsWindow(hMessageWindow)) { + hMessageWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); + } + } + retryCount = 0; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int SMProto::AssignStatus(int iStatus, int iLastStatus, wchar_t *pwszMsg) +{ + if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) + return -1; + if (iStatus != ID_STATUS_OFFLINE && m_status == ID_STATUS_DISABLED) + return -2; + if (!db_get_b(0, KSMODULENAME, SETTING_NOLOCKED, 0) && Proto_GetAccount(m_szName)->IsLocked()) + return -3; + + mir_cslock lck(GenStatusCS); + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s_enabled", m_szName); + m_lastStatus = (iLastStatus == 0) ? m_status : iLastStatus; + if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) + m_status = ID_STATUS_DISABLED; + else if (iStatus == ID_STATUS_LAST) + m_status = m_lastStatus; + else + m_status = iStatus; + + log_infoA("KeepStatus: assigning status %d (%d, %d) to %s", m_status, m_lastStatus, iLastStatus, m_szName); + + if (pwszMsg != nullptr && mir_wstrcmp(pwszMsg, m_szMsg)) { + if (m_szMsg != nullptr) + mir_free(m_szMsg); + + m_szMsg = mir_wstrdup(pwszMsg); + } + else if (pwszMsg != m_szMsg) { + if (m_szMsg != nullptr) + mir_free(m_szMsg); + + m_szMsg = nullptr; + } + return 0; +} + +int SMProto::GetStatus() const +{ + switch (m_status) { + case ID_STATUS_CURRENT: + return Proto_GetStatus(m_szName); + case ID_STATUS_LAST: + return m_lastStatus; + default: + return m_status; + } +} + +static int SetCurrentStatus() +{ + TProtoSettings ps(protoList); + for (auto &p : ps) { + int realStatus = Proto_GetStatus(p->m_szName); + int curStatus = p->GetStatus(); + if (curStatus == ID_STATUS_DISABLED) + continue; + if (curStatus == realStatus) { + p->m_status = ID_STATUS_DISABLED; + continue; + } + + log_infoA("KeepStatus: status for %s differs: stored = %d, real = %d", p->m_szName, curStatus, realStatus); + + // force offline before reconnecting? + if (realStatus != ID_STATUS_OFFLINE && db_get_b(0, KSMODULENAME, SETTING_FIRSTOFFLINE, FALSE)) { + log_infoA("KeepStatus: Setting %s offline before making a new connection attempt", p->m_szName); + CallProtoService(p->m_szName, PS_SETSTATUS, (WPARAM)ID_STATUS_OFFLINE, 0); + } + } + ProcessPopup(KS_CONN_STATE_RETRY, (LPARAM)ps.getArray()); + return SetStatusEx(ps); +} + +static int StatusChange(WPARAM wParam, LPARAM lParam) +{ + char *szProto = (char *)lParam; + if (szProto == nullptr) { // global status change + for (auto &it : protoList) + it->AssignStatus(wParam, 0, it->m_szMsg); + } + else { + for (auto &it : protoList) + if (!mir_strcmp(it->m_szName, szProto)) + it->AssignStatus(wParam, 0, it->m_szMsg); + } + + return 0; +} + +static int CSStatusChange(WPARAM wParam, LPARAM) +{ + // the status was changed by commonstatus (old) + if (wParam != 0) { + PROTOCOLSETTING **protoSettings = *(PROTOCOLSETTING***)wParam; + if (protoSettings == nullptr) + return -1; + + for (int i = 0; i < protoList.getCount(); i++) { + auto psi = protoSettings[i]; + if (psi->szName == nullptr) + continue; + + for (auto &it : protoList) { + if (it->m_szName == nullptr) + continue; + + if (!mir_strcmp(psi->szName, it->m_szName)) + it->AssignStatus(psi->status, psi->lastStatus, it->m_szMsg); + } + } + } + + return 0; +} + +static int CSStatusChangeEx(WPARAM wParam, LPARAM pCount) +{ + // the status was changed by commonstatus (new) + if (wParam != 0) { + PROTOCOLSETTINGEX** protoSettings = *(PROTOCOLSETTINGEX***)wParam; + if (protoSettings == nullptr) + return -1; + + for (int i = 0; i < pCount; i++) { + auto psi = protoSettings[i]; + if (psi->m_szName == nullptr) + continue; + + for (auto &it : protoList) { + if (it->m_szName == nullptr) + continue; + + if (!mir_strcmp(psi->m_szName, it->m_szName)) + it->AssignStatus(psi->m_status, psi->m_lastStatus, psi->m_szMsg); + } + } + } + + return 0; +} + +struct TimerInfo +{ + int timer; + int timeout; + BOOL restart; +}; + +static INT_PTR CALLBACK StartTimerApcProc(void *param) +{ + TimerInfo *ti = (TimerInfo *)param; + int res = 0; + + mir_cslock lck(GenTimerCS); + log_debugA("StartTimer: %d, %d, %d", ti->timer, ti->timeout, ti->restart); + log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); + if (ti->timer & IDT_PROCESSACK) { + res = (processAckTimerId == 0) ? 0 : 1; + if (((processAckTimerId == 0) && (checkConnectionTimerId == 0)) || (ti->restart)) { + if (ti->timeout != -1) { + if (ti->restart) + KillTimer(nullptr, processAckTimerId); + if (ti->timeout == 0) + ti->timeout = ackDelay; + processAckTimerId = SetTimer(nullptr, 0, ti->timeout, CheckAckStatusTimer); + } + } + } + + if (ti->timer & IDT_CHECKCONN) { + res = (checkConnectionTimerId == 0 ? 0 : 1) || res; + if ((checkConnectionTimerId == 0) || (ti->restart)) { + if (ti->timeout != -1) { + if (ti->restart) + KillTimer(nullptr, checkConnectionTimerId); + + if (ti->timeout == 0) + ti->timeout = initDelay; + checkConnectionTimerId = SetTimer(nullptr, 0, ti->timeout, CheckConnectionTimer); + } + } + } + + if (ti->timer & IDT_AFTERCHECK) { + res = (afterCheckTimerId == 0 ? 0 : 1) || res; + if ((afterCheckTimerId == 0) || (ti->restart)) { + if (ti->timeout != -1) { + if (ti->restart) + KillTimer(nullptr, afterCheckTimerId); + + if (ti->timeout == 0) + ti->timeout = initDelay / 2; + afterCheckTimerId = SetTimer(nullptr, 0, ti->timeout, AfterCheckTimer); + } + } + } + + if (ti->timer & IDT_CHECKCONTIN) { + res = (checkContinTimerId == 0 ? 0 : 1) || res; + if ((checkContinTimerId == 0) || (ti->restart)) { + if (ti->timeout != -1) { + if (ti->restart) + KillTimer(nullptr, checkContinTimerId); + + if (ti->timeout == 0) + ti->timeout = 1000 * db_get_dw(0, KSMODULENAME, SETTING_CNTDELAY, CHECKCONTIN_DELAY); + checkContinTimerId = SetTimer(nullptr, 0, ti->timeout, CheckContinueslyTimer); + } + } + } + + if (ti->timer & IDT_CHECKCONNECTING) { + res = (checkConnectingTimerId == 0 ? 0 : 1) || res; + if ((checkConnectingTimerId == 0) || (ti->restart)) { + if (ti->timeout != -1) { + if (ti->restart) + KillTimer(nullptr, checkConnectingTimerId); + if (ti->timeout == 0) + ti->timeout = initDelay / 2; + checkConnectingTimerId = SetTimer(nullptr, 0, ti->timeout, CheckConnectingTimer); + } + } + } + + log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); + log_debugA("StartTimer done %d", res); + return res; +} + +static int StartTimer(int timer, int timeout, BOOL restart) +{ + TimerInfo ti = { timer, timeout, restart }; + return CallFunctionSync(&StartTimerApcProc, &ti); +} + +static int StopTimer(int timer) +{ + int res = 0; + + mir_cslock lck(GenTimerCS); + log_debugA("StopTimer %d", timer); + log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); + + if (timer & IDT_PROCESSACK) { + if (processAckTimerId == 0) + res = 0; + else { + KillTimer(nullptr, processAckTimerId); + processAckTimerId = 0; + res = 1; + } + } + + if (timer & IDT_CHECKCONN) { + if (checkConnectionTimerId == 0) + res = 0 || res; + else { + KillTimer(nullptr, checkConnectionTimerId); + checkConnectionTimerId = 0; + res = 1; + } + } + + if (timer & IDT_AFTERCHECK) { + if (afterCheckTimerId == 0) + res = 0 || res; + else { + KillTimer(nullptr, afterCheckTimerId); + afterCheckTimerId = 0; + res = 1; + } + } + + if (timer & IDT_CHECKCONTIN) { + if (checkContinTimerId == 0) + res = 0 || res; + else { + KillTimer(nullptr, checkContinTimerId); + checkContinTimerId = 0; + res = 1; + } + } + + if (timer & IDT_CHECKCONNECTING) { + if (checkConnectingTimerId == 0) + res = 0 || res; + else { + KillTimer(nullptr, checkConnectingTimerId); + checkConnectingTimerId = 0; + res = 1; + } + } + + log_debugA("ack: %u, chk: %u, aft: %u, cnt: %u, con: %u", processAckTimerId, checkConnectionTimerId, afterCheckTimerId, checkContinTimerId, checkConnectingTimerId); + log_debugA("StopTimer done %d", res); + return res; +} + +static int ProcessProtoAck(WPARAM, LPARAM lParam) +{ + ACKDATA *ack = (ACKDATA*)lParam; + if (ack->type != ACKTYPE_STATUS && ack->type != ACKTYPE_LOGIN) + return 0; + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s_enabled", ack->szModule); + if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) + return 0; + + if (ack->type == ACKTYPE_STATUS && ack->result == ACKRESULT_SUCCESS) { + for (auto &it : protoList) + if (!mir_strcmp(it->m_szName, ack->szModule)) + it->lastStatusAckTime = GetTickCount(); + + StartTimer(IDT_PROCESSACK, 0, FALSE); + return 0; + } + + if (ack->type == ACKTYPE_LOGIN) { + if (ack->lParam == LOGINERR_OTHERLOCATION) { + for (auto &it : protoList) { + if (!mir_strcmp(ack->szModule, it->m_szName)) { + it->AssignStatus(ID_STATUS_OFFLINE); + if (db_get_b(0, KSMODULENAME, SETTING_CNCOTHERLOC, 0)) { + StopTimer(IDT_PROCESSACK); + for (auto &jt : protoList) + jt->AssignStatus(ID_STATUS_OFFLINE); + } + + NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_OTHERLOCATION, (LPARAM)it->m_szName); + ProcessPopup(KS_CONN_STATE_OTHERLOCATION, (LPARAM)ack->szModule); + } + } + } + else if (ack->result == ACKRESULT_FAILED) { + // login failed + NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_LOGINERROR, (LPARAM)ack->szModule); + + switch (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING)) { + case LOGINERR_CANCEL: + log_infoA("KeepStatus: cancel on login error (%s)", ack->szModule); + for (auto &it : protoList) + if (!mir_strcmp(ack->szModule, it->m_szName)) + it->AssignStatus(ID_STATUS_OFFLINE); + + ProcessPopup(KS_CONN_STATE_LOGINERROR, (LPARAM)ack->szModule); + StopChecking(); + break; + + case LOGINERR_SETDELAY: + { + int newDelay = 1000 * db_get_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, DEFAULT_MAXDELAY); + log_infoA("KeepStatus: set delay to %d ms on login error (%s)", newDelay, ack->szModule); + StartTimer(IDT_CHECKCONN, newDelay, TRUE); + } + ProcessPopup(KS_CONN_STATE_LOGINERROR, (LPARAM)ack->szModule); + break; + + default: + case LOGINERR_NOTHING: + StartTimer(IDT_PROCESSACK, 0, FALSE); + break; + } + } + } + + return 0; +} + +static VOID CALLBACK CheckConnectingTimer(HWND, UINT, UINT_PTR, DWORD) +{ + StopTimer(IDT_CHECKCONNECTING); + + for (auto &it : protoList) { + int curStatus = it->GetStatus(); + if (IsStatusConnecting(curStatus)) { // connecting + int maxConnectingTime = db_get_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, 0); + if (maxConnectingTime > 0) { + if ((unsigned int)maxConnectingTime <= ((GetTickCount() - it->lastStatusAckTime) / 1000)) { + // set offline + log_infoA("KeepStatus: %s is too long connecting; setting offline", it->m_szName); + CallProtoService(it->m_szName, PS_SETSTATUS, (WPARAM)ID_STATUS_OFFLINE, 0); + } + } + } + } +} + +static VOID CALLBACK CheckAckStatusTimer(HWND, UINT, UINT_PTR, DWORD) +{ + bool needChecking = false; + + StopTimer(IDT_PROCESSACK); + for (auto &it : protoList) { + int curStatus = it->GetStatus(); + int newStatus = Proto_GetStatus(it->m_szName); + // ok, np + if (curStatus == ID_STATUS_CURRENT || curStatus == ID_STATUS_DISABLED || curStatus == newStatus || newStatus > MAX_STATUS) + continue; + + if (IsStatusConnecting(newStatus)) { // connecting + int maxConnectingTime = db_get_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, 0); + if (maxConnectingTime > 0) + StartTimer(IDT_CHECKCONNECTING, (maxConnectingTime * 1000 - (GetTickCount() - it->lastStatusAckTime)), FALSE); + } + // keepstatus' administration was wrong! + else if (newStatus != ID_STATUS_OFFLINE) + it->AssignStatus(newStatus); + + // connection lost + else if (newStatus == ID_STATUS_OFFLINE) {// start checking connection + if (!StartTimer(IDT_CHECKCONN, -1, FALSE)) { /* check if not already checking */ + needChecking = true; + log_infoA("KeepStatus: connection lost! (%s)", it->m_szName); + NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_LOST, (LPARAM)it->m_szName); + ProcessPopup(KS_CONN_STATE_LOST, (LPARAM)it->m_szName); + } + } + } + + if (needChecking) + StartTimer(IDT_CHECKCONN, initDelay, FALSE); +} + +static VOID CALLBACK CheckConnectionTimer(HWND, UINT, UINT_PTR, DWORD) +{ + log_debugA("CheckConnectionTimer"); + bool setStatus = false; + + for (auto &it : protoList) { + int realStatus = Proto_GetStatus(it->m_szName); + int shouldBeStatus = it->GetStatus(); + if (shouldBeStatus == ID_STATUS_LAST) + shouldBeStatus = it->m_lastStatus; + if (shouldBeStatus == ID_STATUS_DISABLED) + continue; + if ((shouldBeStatus != realStatus) && (realStatus == ID_STATUS_OFFLINE) || (realStatus < MIN_STATUS)) { + setStatus = true; + break; + } + } + + // one of the status was wrong + if (setStatus && (maxRetries == -1 || retryCount < maxRetries)) { + if (increaseExponential) + currentDelay = min(2 * currentDelay, maxDelay); + + if (((db_get_b(0, KSMODULENAME, SETTING_CHKINET, 0)) && (!InternetGetConnectedState(nullptr, 0))) || ((db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE)) && (!bLastPingResult))) { + // no network + NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_RETRYNOCONN, (LPARAM)retryCount + 1); + ProcessPopup(KS_CONN_STATE_RETRYNOCONN, 0); + } + else { + NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_RETRY, (LPARAM)retryCount + 1); + SetCurrentStatus(); // set the status + } + retryCount += 1; + StartTimer(IDT_AFTERCHECK, min(currentDelay, AFTERCHECK_DELAY) / 2, FALSE); + StartTimer(IDT_CHECKCONN, currentDelay, TRUE); // restart this timer + } + else // all status set ok already, or stop checking + StopChecking(); + + log_debugA("CheckConnectionTimer done"); +} + +static int StopChecking() +{ + StopTimer(IDT_CHECKCONN | IDT_PROCESSACK | IDT_AFTERCHECK | IDT_CHECKCONNECTING); + + BOOL isOk = TRUE; + for (auto &it : protoList) { + int curStatus = it->GetStatus(); + int newStatus = Proto_GetStatus(it->m_szName); + if (newStatus != curStatus) { + it->AssignStatus(newStatus); + isOk = FALSE; + break; + } + } + + NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_STOPPEDCHECKING, (LPARAM)isOk); + ProcessPopup(KS_CONN_STATE_STOPPEDCHECKING, (LPARAM)isOk); + log_infoA("KeepStatus: stop checking (%s)", isOk ? "success" : "failure"); + retryCount = 0; + currentDelay = initDelay; + + return 0; +} + +static VOID CALLBACK AfterCheckTimer(HWND, UINT, UINT_PTR, DWORD) +{ + // after each connection check, this function is called to see if connection was recovered + StopTimer(IDT_AFTERCHECK); + + bool setStatus = false; + + for (auto &it : protoList) { + int realStatus = Proto_GetStatus(it->m_szName); + int shouldBeStatus = it->GetStatus(); + if (shouldBeStatus == ID_STATUS_LAST) // this should never happen + shouldBeStatus = it->m_lastStatus; + if (shouldBeStatus == ID_STATUS_DISABLED) // (on ignoring proto) + continue; + if ((shouldBeStatus != realStatus) && (realStatus == ID_STATUS_OFFLINE) || (realStatus < MIN_STATUS)) + setStatus = true; + } + + if (!setStatus || retryCount == maxRetries) + StopChecking(); +} + +static void CheckContinuouslyFunction(void *) +{ + Thread_SetName("KeepStatus: CheckContinuouslyFunction"); + + static int pingFailures = 0; + + // one at the time is enough, do it the 'easy' way + mir_cslock lck(CheckContinueslyCS); + + // do a ping, even if reconnecting + bool doPing = false; + for (auto &it : protoList) { + int shouldBeStatus = it->GetStatus(); + if (shouldBeStatus == ID_STATUS_LAST) + shouldBeStatus = it->m_lastStatus; + + if (shouldBeStatus == ID_STATUS_DISABLED) + continue; + + if (shouldBeStatus != ID_STATUS_OFFLINE) { + log_debugA("CheckContinuouslyFunction: %s should be %d", it->m_szName, shouldBeStatus); + doPing = true; + } + } + + if (!doPing) { + log_debugA("CheckContinuouslyFunction: All protocols should be offline, no need to check connection"); + return; + } + + BOOL ping = db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE); + if (ping) { + DBVARIANT dbv; + if (db_get(0, KSMODULENAME, SETTING_PINGHOST, &dbv)) + ping = FALSE; + else { + char *start, *end; + char host[MAX_PATH]; + DWORD *addr; + struct hostent *hostent; + char reply[sizeof(ICMP_ECHO_REPLY) + 8]; + + bLastPingResult = FALSE; + HANDLE hICMPFile = (HANDLE)IcmpCreateFile(); + if (hICMPFile == INVALID_HANDLE_VALUE) { + bLastPingResult = TRUE; + log_infoA("KeepStatus: icmp.dll error (2)"); + } + if (bLastPingResult == FALSE) { + start = dbv.pszVal; + while ((*start != '\0') && (!bLastPingResult)) { + end = start; + while ((*end != ' ') && (*end != '\0')) + end++; + memset(host, '\0', sizeof(host)); + strncpy(host, start, end - start); + hostent = gethostbyname(host); + if (hostent != nullptr) { + addr = (DWORD *)(*hostent->h_addr_list); + bLastPingResult = (IcmpSendEcho(hICMPFile, *addr, nullptr, 0, nullptr, reply, sizeof(ICMP_ECHO_REPLY) + 8, 5000) != 0); + + if (bLastPingResult) + pingFailures = 0; + else + pingFailures++; + + log_debugA("CheckContinuouslyFunction: pinging %s (result: %d/%d)", host, bLastPingResult, pingFailures); + } + else log_debugA("CheckContinuouslyFunction: unable to resolve %s", host); + + start = end; + while (*start == ' ') + start++; + } + } + IcmpCloseHandle(hICMPFile); + } + db_free(&dbv); + } + + if (StartTimer(IDT_CHECKCONN, -1, FALSE)) // already connecting, leave + return; + + if (((!ping) && (!InternetGetConnectedState(nullptr, 0))) || ((ping) && (!bLastPingResult) && (pingFailures >= db_get_w(0, KSMODULENAME, SETTING_PINGCOUNT, DEFAULT_PINGCOUNT)))) { + pingFailures = 0; + + for (auto &pa : Accounts()) { + if (!IsSuitableProto(pa)) + continue; + + if (IsStatusConnecting(pa->iRealStatus)) { + log_debugA("CheckContinuouslyFunction: %s is connecting", pa->szModuleName); + continue; // connecting, leave alone + } + if (IsProtocolEnabledService(0, (LPARAM)pa->szModuleName)) { + log_debugA("CheckContinuouslyFunction: forcing %s offline", pa->szModuleName); + CallProtoService(pa->szModuleName, PS_SETSTATUS, (WPARAM)ID_STATUS_OFFLINE, 0); + } + } + + if (StartTimer(IDT_CHECKCONN | IDT_PROCESSACK, -1, FALSE)) {// are our 'set offlines' noticed? + log_debugA("CheckContinuouslyFunction: currently checking"); + return; + } + + log_infoA("KeepStatus: connection lost! (continuesly check)"); + NotifyEventHooks(hConnectionEvent, (WPARAM)KS_CONN_STATE_LOST, 0); + ProcessPopup(KS_CONN_STATE_LOST, 0); + maxRetries = db_get_b(0, KSMODULENAME, SETTING_MAXRETRIES, 0); + if (maxRetries == 0) + maxRetries = -1; + StartTimer(IDT_CHECKCONN, initDelay, FALSE); + } +} + +static VOID CALLBACK CheckContinueslyTimer(HWND, UINT, UINT_PTR, DWORD) +{ + if (db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE)) + mir_forkthread(CheckContinuouslyFunction); + else + CheckContinuouslyFunction(nullptr); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// popup + +static INT_PTR ShowPopup(const wchar_t *msg, HICON hIcon) +{ + POPUPDATAT ppd = {}; + ppd.lchIcon = hIcon; + wcsncpy(ppd.lptzContactName, TranslateT("Keep status"), MAX_CONTACTNAME); + wcsncpy(ppd.lptzText, msg, MAX_SECONDLINE); + if (db_get_b(0, KSMODULENAME, SETTING_POPUP_USEWINCOLORS, 0)) { + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + } + else if (!db_get_b(0, KSMODULENAME, SETTING_POPUP_USEDEFCOLORS, 0)) { + ppd.colorBack = db_get_dw(0, KSMODULENAME, SETTING_POPUP_BACKCOLOR, 0xAAAAAA); + ppd.colorText = db_get_dw(0, KSMODULENAME, SETTING_POPUP_TEXTCOLOR, 0x0000CC); + } + ppd.PluginWindowProc = KSPopupDlgProc; + + switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYFROMPU)) { + case POPUP_DELAYCUSTOM: + ppd.iSeconds = (int)db_get_dw(0, KSMODULENAME, SETTING_POPUP_TIMEOUT, 0); + if (ppd.iSeconds == 0) + ppd.iSeconds = currentDelay / 1000 - 1; + break; + + case POPUP_DELAYPERMANENT: + ppd.iSeconds = -1; + break; + + case POPUP_DELAYFROMPU: + default: + ppd.iSeconds = 0; + break; + } + return PUAddPopupT(&ppd); +} + +static wchar_t* GetHumanName(LPARAM lParam) +{ + PROTOACCOUNT *ProtoAccount = Proto_GetAccount((char*)lParam); + return (ProtoAccount != nullptr) ? ProtoAccount->tszAccountName : TranslateT("Protocol"); +} + +static int ProcessPopup(int reason, LPARAM lParam) +{ + if (!db_get_b(0, KSMODULENAME, SETTING_SHOWCONNECTIONPOPUPS, FALSE) || !ServiceExists(MS_POPUP_ADDPOPUPT)) + return -1; + + HICON hIcon = nullptr; + CMStringW wszText; + + switch (reason) { + case KS_CONN_STATE_OTHERLOCATION: // lParam = 1 proto + if (!db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE)) + return -1; + + hIcon = Skin_LoadProtoIcon((char*)lParam, SKINICON_STATUS_OFFLINE); + wszText.Format(TranslateT("%s connected from another location"), GetHumanName(lParam)); + break; + + case KS_CONN_STATE_LOGINERROR: // lParam = 1 proto + if (!db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE)) + return -1; + + hIcon = Skin_LoadProtoIcon((char*)lParam, SKINICON_STATUS_OFFLINE); + if (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING) == LOGINERR_CANCEL) + wszText.Format(TranslateT("%s login error, cancel reconnecting"), GetHumanName(lParam)); + else if (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING) == LOGINERR_SETDELAY) + wszText.Format(TranslateT("%s login error (next retry (%d) in %d s)"), GetHumanName(lParam), retryCount + 1, db_get_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, DEFAULT_MAXDELAY)); + else + return -1; + break; + + case KS_CONN_STATE_LOST: // lParam = 1 proto, or nullptr + if (!db_get_b(0, KSMODULENAME, SETTING_PUCONNLOST, TRUE)) + return -1; + + if (lParam) { // указатель на имя модуля. + hIcon = Skin_LoadProtoIcon((char*)lParam, SKINICON_STATUS_OFFLINE); + wszText.Format(TranslateT("%s status error (next retry (%d) in %d s)"), GetHumanName(lParam), retryCount + 1, currentDelay / 1000); + } + else wszText.Format(TranslateT("Status error (next retry (%d) in %d s)"), retryCount + 1, currentDelay / 1000); + break; + + case KS_CONN_STATE_RETRY: // lParam = PROTOCOLSETTINGEX** + if (!db_get_b(0, KSMODULENAME, SETTING_PUCONNRETRY, TRUE)) + return -1; + + if (lParam) { + PROTOCOLSETTINGEX **ps = (PROTOCOLSETTINGEX **)lParam; + + if (retryCount == maxRetries - 1) + wszText.Format(TranslateT("Resetting status... (last try (%d))"), retryCount + 1); + else + wszText.Format(TranslateT("Resetting status... (next retry (%d) in %d s)"), retryCount + 2, currentDelay / 1000); + wszText.Append(L"\r\n"); + for (int i = 0; i < protoList.getCount(); i++) { + PROTOCOLSETTINGEX *p = ps[i]; + if (p->m_status == ID_STATUS_DISABLED) + continue; + + if (mir_wstrlen(p->m_tszAccName) > 0) + if (db_get_b(0, KSMODULENAME, SETTING_PUSHOWEXTRA, TRUE)) + wszText.AppendFormat(TranslateT("%s\t(will be set to %s)\r\n"), p->m_tszAccName, Clist_GetStatusModeDescription(p->m_status, 0)); + } + + hIcon = Skin_LoadProtoIcon(ps[0]->m_szName, SKINICON_STATUS_OFFLINE); + wszText.TrimRight(); + } + break; + + case KS_CONN_STATE_RETRYNOCONN: // lParam = nullptr + if (!db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE)) + return -1; + + if (retryCount == maxRetries - 1) + wszText.Format(TranslateT("No internet connection seems available... (last try (%d))"), retryCount + 1); + else + wszText.Format(TranslateT("No internet connection seems available... (next retry (%d) in %d s)"), retryCount + 2, currentDelay / 1000); + break; + + case KS_CONN_STATE_STOPPEDCHECKING: // lParam == BOOL succes + if (!db_get_b(0, KSMODULENAME, SETTING_PURESULT, TRUE)) + return -1; + + if (lParam) { + hIcon = Skin_LoadIcon(SKINICON_STATUS_ONLINE); + wszText.Format(TranslateT("Status was set ok")); + } + else wszText.Format(TranslateT("Giving up")); + break; + } + if (hIcon == nullptr) + hIcon = Skin_LoadIcon(SKINICON_STATUS_OFFLINE); + + log_info(L"KeepStatus: %s", wszText.c_str()); + return ShowPopup(wszText, hIcon); +} + +LRESULT CALLBACK KSPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_CONTEXTMENU: // right + case WM_COMMAND: // left + switch (db_get_b(0, KSMODULENAME, + (message == WM_COMMAND) ? SETTING_POPUP_LEFTCLICK : SETTING_POPUP_RIGHTCLICK, + POPUP_ACT_CLOSEPOPUP)) { + case POPUP_ACT_CANCEL: + // cancel timer + StopChecking(); + PUDeletePopup(hWnd); + break; + + case POPUP_ACT_CLOSEPOPUP: + // close the popup + PUDeletePopup(hWnd); + break; + } + break; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// services + +INT_PTR StopReconnectingService(WPARAM, LPARAM) +{ + int ret = StartTimer(IDT_CHECKCONN | IDT_AFTERCHECK, -1, FALSE); + StopChecking(); + return ret; +} + +INT_PTR EnableProtocolService(WPARAM wParam, LPARAM lParam) +{ + char *szProto = (char *)lParam; + if (szProto == nullptr) + return -1; + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s_enabled", szProto); + if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) // 'hard' disabled + return -1; + + int ret = -2; + for (auto &it : protoList) { + if (!mir_strcmp(szProto, it->m_szName)) { + if (wParam) + it->AssignStatus(Proto_GetStatus(it->m_szName)); + else + it->AssignStatus(ID_STATUS_DISABLED); + + ret = 0; + break; + } + } + return ret; +} + +INT_PTR IsProtocolEnabledService(WPARAM, LPARAM lParam) +{ + char *szProto = (char *)lParam; + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s_enabled", szProto); + if (!db_get_b(0, KSMODULENAME, dbSetting, 1)) + return FALSE; + + for (auto &it : protoList) + if (!mir_strcmp(szProto, it->m_szName)) + return it->GetStatus() != ID_STATUS_DISABLED; + + return FALSE; +} + +INT_PTR AnnounceStatusChangeService(WPARAM, LPARAM lParam) +{ + PROTOCOLSETTINGEX *newSituation = (PROTOCOLSETTINGEX *)lParam; + log_infoA("Another plugin announced a status change to %d for %s", newSituation->m_status, newSituation->m_szName == nullptr ? "all" : newSituation->m_szName); + + for (auto &it : protoList) + if (!mir_strcmp(it->m_szName, newSituation->m_szName)) + it->AssignStatus(newSituation->m_status, newSituation->m_lastStatus, newSituation->m_szMsg); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// window for suspend + +static DWORD CALLBACK MessageWndProc(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static TProtoSettings *ps = nullptr; + + switch (msg) { + case WM_POWERBROADCAST: + switch (wParam) { + case PBT_APMSUSPEND: + log_infoA("KeepStatus: suspend state detected: %08X %08X", wParam, lParam); + if (ps == nullptr) { + ps = new TProtoSettings(protoList); + for (auto &it : *ps) + EnableProtocolService(0, (LPARAM)it->m_szName); + + // set proto's offline, the clist will not try to reconnect in that case + Clist_SetStatusMode(ID_STATUS_OFFLINE); + } + break; + + case PBT_APMRESUMESUSPEND: + case PBT_APMRESUMECRITICAL: + // case PBT_APMRESUMEAUTOMATIC: ? + log_infoA("KeepStatus: resume from suspend state"); + if (ps != nullptr) { + for (auto &it : *ps) { + SMProto *p = protoList.find(it); + if (p) + p->AssignStatus(it->m_status, it->m_lastStatus, it->m_szMsg); + } + delete ps; + ps = nullptr; + } + StartTimer(IDT_PROCESSACK, 0, FALSE); + break; + } + break; + + case WM_DESTROY: + if (ps != nullptr) { + delete ps; + ps = nullptr; + } + break; + } + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// init stuff + +static int onShutdown(WPARAM, LPARAM) +{ + KSUnloadOptions(); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int KSModuleLoaded(WPARAM, LPARAM) +{ + hMessageWindow = nullptr; + KSLoadOptions(); + + hEvents[0] = HookEvent(ME_OPT_INITIALISE, KeepStatusOptionsInit); + hEvents[1] = HookEvent(ME_SYSTEM_PRESHUTDOWN, onShutdown); + return 0; +} + +void KeepStatusLoad() +{ + KSLangPack = GetPluginLangId(MIID_LAST, 0); + + if (g_bMirandaLoaded) + KSModuleLoaded(0, 0); + else + HookEvent(ME_SYSTEM_MODULESLOADED, KSModuleLoaded); + + hConnectionEvent = CreateHookableEvent(ME_KS_CONNECTIONEVENT); + + hServices[0] = CreateServiceFunction(MS_KS_STOPRECONNECTING, StopReconnectingService); + hServices[1] = CreateServiceFunction(MS_KS_ENABLEPROTOCOL, EnableProtocolService); + hServices[2] = CreateServiceFunction(MS_KS_ISPROTOCOLENABLED, IsProtocolEnabledService); + hServices[3] = CreateServiceFunction(MS_KS_ANNOUNCESTATUSCHANGE, AnnounceStatusChangeService); +} + +void KeepStatusUnload() +{ + if (g_bMirandaLoaded) + onShutdown(0, 0); + + KillModuleOptions(KSLangPack); + + for (auto &it : hServices) { + DestroyServiceFunction(it); + it = nullptr; + } + + for (auto &it : hEvents) { + UnhookEvent(it); + it = nullptr; + } + + DestroyHookableEvent(hConnectionEvent); hConnectionEvent = nullptr; +} diff --git a/plugins/StatusManager/src/keepstatus.h b/plugins/StatusManager/src/keepstatus.h new file mode 100644 index 0000000000..e4b1f5a7a4 --- /dev/null +++ b/plugins/StatusManager/src/keepstatus.h @@ -0,0 +1,112 @@ +/* + KeepStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __KEEPSTATUS_HEADER +#define __KEEPSTATUS_HEADER + +#define KSMODULENAME "KeepStatus" +#define SETTING_CHECKCONNECTION "CheckConnection" +#define SETTING_MAXRETRIES "MaxRetries" +#define SETTING_INCREASEEXPONENTIAL "IncreaseExponential" +#define SETTING_INITDELAY "InitDelay" +#define SETTING_MAXDELAY "MaxDelay" +#define SETTING_SHOWCONNECTIONPOPUPS "ShowConnectionPopups" +#define SETTING_CHKINET "CheckInet" +#define SETTING_CNCOTHERLOC "CancelIfOtherLocation" +#define SETTING_LOGINERR "OnLoginErr" +#define SETTING_LOGINERR_DELAY "OnLoginErrDelay" +#define SETTING_CONTCHECK "ContinueslyCheck" +#define SETTING_BYPING "ByPingingHost" +#define SETTING_PINGHOST "HostToPing" +#define SETTING_CHECKAPMRESUME "CheckAPMResume" +#define SETTING_FIRSTOFFLINE "FirstOffline" +#define SETTING_NOLOCKED "NoLocked" +#define SETTING_MAXCONNECTINGTIME "MaxConnectingTime" +#define SETTING_PINGCOUNT "PingCount" +#define DEFAULT_PINGCOUNT 1 +#define SETTING_CNTDELAY "CntDelay" +#define STATUSCHANGEDELAY 500 // ms +#define DEFAULT_MAXRETRIES 0 +#define DEFAULT_INITDELAY 10 // s +#define DEFAULT_MAXDELAY 900 // s +#define AFTERCHECK_DELAY 10000 //ms (divided by 2) +#define CHECKCONTIN_DELAY 10 // s +#define SETTING_POPUP_DELAYTYPE "PopupDelayType" +#define SETTING_POPUP_USEWINCOLORS "PopupUseWinColors" +#define SETTING_POPUP_USEDEFCOLORS "PopupUseDefColors" +#define SETTING_POPUP_BACKCOLOR "PopupBackColor" +#define SETTING_POPUP_TEXTCOLOR "PopupTextColor" +#define SETTING_POPUP_TIMEOUT "PopupTimeout" +#define SETTING_POPUP_LEFTCLICK "PopupLeftClickAction" +#define SETTING_POPUP_RIGHTCLICK "PopupRightClickAction" +#define SETTING_PUOTHER "PopupShowOther" +#define SETTING_PUCONNLOST "PopupShowConnLost" +#define SETTING_PUCONNRETRY "PopupShowConnRetry" +#define SETTING_PURESULT "PopupShowResult" +#define SETTING_PUSHOWEXTRA "PopupShowExtra" +#define POPUP_ACT_NOTHING 0 +#define POPUP_ACT_CANCEL 1 +#define POPUP_ACT_CLOSEPOPUP 2 +#define POPUP_DELAYFROMPU 0 +#define POPUP_DELAYCUSTOM 1 +#define POPUP_DELAYPERMANENT 2 +#define LOGINERR_NOTHING 0 +#define LOGINERR_CANCEL 1 +#define LOGINERR_SETDELAY 2 + +#define IDT_PROCESSACK 0x01 +#define IDT_CHECKCONN 0x02 +#define IDT_AFTERCHECK 0x04 +#define IDT_CHECKCONTIN 0x08 +#define IDT_CHECKCONNECTING 0x10 + +// action +#define SETTING_ENABLECHECKING "EnableChecking" +// trigger +#define TRIGGERNAME "KeepStatus: Connection state change" +#define TRIGGER_CONNLOST 0x01 +#define TRIGGER_LOGINERROR 0x02 +#define TRIGGER_OTHERLOC 0x04 +#define TRIGGER_CONNRETRY 0x08 +#define TRIGGER_CONNSUCCESS 0x10 +#define TRIGGER_CONNGIVEUP 0x20 +#define SETTING_TRIGGERON "TriggerOn" + +/* old; replaced by PROTOCOLSETTINGEX see m_statusplugins.h */ +typedef struct { + char *szName; // pointer to protocol modulename + WORD status; // the status + WORD lastStatus;// last status +} PROTOCOLSETTING; + +/* old; replaced by ME_CS_STATUSCHANGE see m_statusplugins.h */ +// wParam = PROTOCOLSETTING** +// lParam = 0 +#define ME_CS_STATUSCHANGE "CommonStatus/StatusChange" + +///////////////////////////////////////////////////////////////////////////////////////// +// keepstatus.cpp + +void KeepStatusLoad(); +void KeepStatusUnload(); +int KSLoadOptions(); + +LRESULT CALLBACK KSPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +#endif //__KEEPSTATUS_HEADER diff --git a/plugins/StatusManager/src/ks_options.cpp b/plugins/StatusManager/src/ks_options.cpp new file mode 100644 index 0000000000..11428347db --- /dev/null +++ b/plugins/StatusManager/src/ks_options.cpp @@ -0,0 +1,487 @@ +/* + KeepStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// +// Basic options + +static INT_PTR CALLBACK DlgProcKSBasicOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + LVCOLUMN lvCol; + LVITEM lvItem; + DBVARIANT dbv; + + SetDlgItemInt(hwndDlg, IDC_MAXRETRIES, db_get_b(0, KSMODULENAME, SETTING_MAXRETRIES, DEFAULT_MAXRETRIES), FALSE); + SetDlgItemInt(hwndDlg, IDC_INITDELAY, db_get_dw(0, KSMODULENAME, SETTING_INITDELAY, DEFAULT_INITDELAY), FALSE); + CheckDlgButton(hwndDlg, IDC_CHECKCONNECTION, db_get_b(0, KSMODULENAME, SETTING_CHECKCONNECTION, FALSE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWCONNECTIONPOPUPS, (db_get_b(0, KSMODULENAME, SETTING_SHOWCONNECTIONPOPUPS, FALSE) && ServiceExists(MS_POPUP_SHOWMESSAGE)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CHKINET, db_get_b(0, KSMODULENAME, SETTING_CHKINET, FALSE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CONTCHECK, db_get_b(0, KSMODULENAME, SETTING_CONTCHECK, FALSE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_BYPING, db_get_b(0, KSMODULENAME, SETTING_BYPING, FALSE) ? BST_CHECKED : BST_UNCHECKED); + if (!db_get_s(0, KSMODULENAME, SETTING_PINGHOST, &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_PINGHOST, dbv.pszVal); + db_free(&dbv); + } + + // proto list + HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST); + ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); + memset(&lvCol, 0, sizeof(lvCol)); + lvCol.mask = LVCF_WIDTH | LVCF_TEXT; + lvCol.pszText = TranslateT("Protocol"); + lvCol.cx = 118; + ListView_InsertColumn(hList, 0, &lvCol); + // fill the list + memset(&lvItem, 0, sizeof(lvItem)); + lvItem.mask = LVIF_TEXT | LVIF_PARAM; + lvItem.iItem = 0; + lvItem.iSubItem = 0; + + for (auto &pa : Accounts()) { + if (!IsSuitableProto(pa)) + continue; + + lvItem.pszText = pa->tszAccountName; + lvItem.lParam = (LPARAM)pa->szModuleName; + ListView_InsertItem(hList, &lvItem); + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s_enabled", pa->szModuleName); + ListView_SetCheckState(hList, lvItem.iItem, db_get_b(0, KSMODULENAME, dbSetting, TRUE)); + lvItem.iItem++; + } + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXRETRIES), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWCONNECTIONPOPUPS), ServiceExists(MS_POPUP_SHOWMESSAGE) && IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_INITDELAY), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOLLIST), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CHKINET), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CONTCHECK), IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BYPING), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK) && IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)) ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PINGHOST), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK)) && (IsDlgButtonChecked(hwndDlg, IDC_BYPING) && IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)) ? TRUE : FALSE); + } + break; + + case WM_COMMAND: + if (((HIWORD(wParam) == EN_CHANGE) || (HIWORD(wParam) == BN_CLICKED)) && ((HWND)lParam == GetFocus())) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + // something changed + switch (LOWORD(wParam)) { + case IDC_CHECKCONNECTION: + case IDC_CONTCHECK: + case IDC_BYPING: + BOOL bEnabled = IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXRETRIES), bEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWCONNECTIONPOPUPS), ServiceExists(MS_POPUP_SHOWMESSAGE) && bEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_INITDELAY), bEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOLLIST), bEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_CHKINET), bEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_CONTCHECK), bEnabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BYPING), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK) && bEnabled) ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PINGHOST), (IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK)) && (IsDlgButtonChecked(hwndDlg, IDC_BYPING) && bEnabled) ? TRUE : FALSE); + break; + } + break; + + case WM_NOTIFY: + if (((NMHDR*)lParam)->idFrom == IDC_PROTOCOLLIST) { + switch (((NMHDR*)lParam)->code) { + case LVN_ITEMCHANGED: + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_PROTOCOLLIST)) && ((nmlv->uNewState^nmlv->uOldState)&LVIS_STATEIMAGEMASK)) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + } + + switch (((LPNMHDR)lParam)->code) { + case PSN_WIZFINISH: + KSLoadOptions(); + break; + + case PSN_APPLY: + db_set_b(0, KSMODULENAME, SETTING_MAXRETRIES, (BYTE)GetDlgItemInt(hwndDlg, IDC_MAXRETRIES, nullptr, FALSE)); + db_set_b(0, KSMODULENAME, SETTING_CHECKCONNECTION, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CHECKCONNECTION)); + db_set_b(0, KSMODULENAME, SETTING_SHOWCONNECTIONPOPUPS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWCONNECTIONPOPUPS)); + db_set_dw(0, KSMODULENAME, SETTING_INITDELAY, (DWORD)GetDlgItemInt(hwndDlg, IDC_INITDELAY, nullptr, FALSE)); + db_set_b(0, KSMODULENAME, SETTING_CHKINET, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CHKINET)); + db_set_b(0, KSMODULENAME, SETTING_CONTCHECK, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CONTCHECK)); + db_set_b(0, KSMODULENAME, SETTING_BYPING, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_BYPING)); + if (IsDlgButtonChecked(hwndDlg, IDC_BYPING)) { + int len = SendDlgItemMessage(hwndDlg, IDC_PINGHOST, WM_GETTEXTLENGTH, 0, 0); + if (len > 0) { + ptrA host((char*)mir_alloc(len + 1)); + GetDlgItemTextA(hwndDlg, IDC_PINGHOST, host, len + 1); + db_set_s(0, KSMODULENAME, SETTING_PINGHOST, host); + } + } + + HWND hList = GetDlgItem(hwndDlg, IDC_PROTOCOLLIST); + LVITEM lvItem; + lvItem.mask = LVIF_PARAM; + for (int i = 0; i < ListView_GetItemCount(hList); i++) { + lvItem.iItem = i; + lvItem.iSubItem = 0; + ListView_GetItem(hList, &lvItem); + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s_enabled", (char *)lvItem.lParam); + db_set_b(0, KSMODULENAME, dbSetting, (BYTE)ListView_GetCheckState(hList, lvItem.iItem)); + } + } + break; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Advanced options + +static INT_PTR CALLBACK DlgProcKSAdvOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetDlgItemInt(hwndDlg, IDC_MAXDELAY, db_get_dw(0, KSMODULENAME, SETTING_MAXDELAY, DEFAULT_MAXDELAY), FALSE); + SetDlgItemInt(hwndDlg, IDC_MAXCONNECTINGTIME, db_get_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, 0), FALSE); + CheckDlgButton(hwndDlg, IDC_INCREASEEXPONENTIAL, db_get_b(0, KSMODULENAME, SETTING_INCREASEEXPONENTIAL, FALSE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CNCOTHERLOC, (db_get_b(0, KSMODULENAME, SETTING_CNCOTHERLOC, FALSE)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_LOGINERR, db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING) == LOGINERR_NOTHING ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hwndDlg, IDC_CHECKAPMRESUME, (db_get_b(0, KSMODULENAME, SETTING_CHECKAPMRESUME, FALSE)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_FIRSTOFFLINE, (db_get_b(0, KSMODULENAME, SETTING_FIRSTOFFLINE, FALSE)) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_NOLOCKED, (db_get_b(0, KSMODULENAME, SETTING_NOLOCKED, FALSE)) ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_LOGINERR_DELAY, db_get_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, DEFAULT_MAXDELAY), FALSE); + SetDlgItemInt(hwndDlg, IDC_PINGCOUNT, db_get_w(0, KSMODULENAME, SETTING_PINGCOUNT, DEFAULT_PINGCOUNT), FALSE); + SetDlgItemInt(hwndDlg, IDC_CNTDELAY, db_get_dw(0, KSMODULENAME, SETTING_CNTDELAY, CHECKCONTIN_DELAY), FALSE); + + switch (db_get_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_CANCEL)) { + case LOGINERR_SETDELAY: + CheckRadioButton(hwndDlg, IDC_LOGINERR_CANCEL, IDC_LOGINERR_SETDELAY, IDC_LOGINERR_SETDELAY); + break; + default: + case LOGINERR_CANCEL: + CheckRadioButton(hwndDlg, IDC_LOGINERR_CANCEL, IDC_LOGINERR_SETDELAY, IDC_LOGINERR_CANCEL); + break; + } + + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_CANCEL), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_SETDELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_DELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY) && IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + break; + + case WM_COMMAND: + if (((HIWORD(wParam) == EN_CHANGE) || (HIWORD(wParam) == BN_CLICKED)) && ((HWND)lParam == GetFocus())) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + // something changed + switch (LOWORD(wParam)) { + case IDC_LOGINERR: + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_CANCEL), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_SETDELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_DELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY) && IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + break; + + case IDC_LOGINERR_CANCEL: + case IDC_LOGINERR_SETDELAY: + CheckRadioButton(hwndDlg, IDC_LOGINERR_CANCEL, IDC_LOGINERR_SETDELAY, LOWORD(wParam)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOGINERR_DELAY), IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY) && IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + break; + } + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case PSN_WIZFINISH: + KSLoadOptions(); + break; + + case PSN_APPLY: + db_set_b(0, KSMODULENAME, SETTING_INCREASEEXPONENTIAL, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_INCREASEEXPONENTIAL)); + db_set_dw(0, KSMODULENAME, SETTING_MAXDELAY, (DWORD)GetDlgItemInt(hwndDlg, IDC_MAXDELAY, nullptr, FALSE)); + db_set_dw(0, KSMODULENAME, SETTING_MAXCONNECTINGTIME, (DWORD)GetDlgItemInt(hwndDlg, IDC_MAXCONNECTINGTIME, nullptr, FALSE)); + db_set_b(0, KSMODULENAME, SETTING_FIRSTOFFLINE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_FIRSTOFFLINE)); + db_set_b(0, KSMODULENAME, SETTING_NOLOCKED, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_NOLOCKED)); + db_set_b(0, KSMODULENAME, SETTING_CNCOTHERLOC, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CNCOTHERLOC)); + db_set_b(0, KSMODULENAME, SETTING_LOGINERR, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)); + if (IsDlgButtonChecked(hwndDlg, IDC_LOGINERR)) { + if (IsDlgButtonChecked(hwndDlg, IDC_LOGINERR_SETDELAY)) { + db_set_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_SETDELAY); + db_set_dw(0, KSMODULENAME, SETTING_LOGINERR_DELAY, GetDlgItemInt(hwndDlg, IDC_LOGINERR_DELAY, nullptr, FALSE)); + } + else db_set_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_CANCEL); + } + else db_set_b(0, KSMODULENAME, SETTING_LOGINERR, LOGINERR_NOTHING); + + db_set_b(0, KSMODULENAME, SETTING_CHECKAPMRESUME, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_CHECKAPMRESUME)); + db_set_w(0, KSMODULENAME, SETTING_PINGCOUNT, (WORD)GetDlgItemInt(hwndDlg, IDC_PINGCOUNT, nullptr, FALSE)); + db_set_dw(0, KSMODULENAME, SETTING_CNTDELAY, (DWORD)GetDlgItemInt(hwndDlg, IDC_CNTDELAY, nullptr, FALSE) == 0 ? CHECKCONTIN_DELAY : GetDlgItemInt(hwndDlg, IDC_CNTDELAY, nullptr, FALSE)); + } + break; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Popup options + +static INT_PTR CALLBACK PopupOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static bool bFreeze = false; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + bFreeze = true; + + // left action + switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_CANCEL)) { + case POPUP_ACT_CLOSEPOPUP: + CheckDlgButton(hwndDlg, IDC_LCLOSE, BST_CHECKED); + break; + + case POPUP_ACT_CANCEL: + CheckDlgButton(hwndDlg, IDC_LCANCEL, BST_CHECKED); + break; + + case POPUP_ACT_NOTHING: + default: + CheckDlgButton(hwndDlg, IDC_LNOTHING, BST_CHECKED); + break; + } + + // right action + switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_CANCEL)) { + case POPUP_ACT_CLOSEPOPUP: + CheckDlgButton(hwndDlg, IDC_RCLOSE, BST_CHECKED); + break; + + case POPUP_ACT_CANCEL: + CheckDlgButton(hwndDlg, IDC_RCANCEL, BST_CHECKED); + break; + + case POPUP_ACT_NOTHING: + default: + CheckDlgButton(hwndDlg, IDC_RNOTHING, BST_CHECKED); + break; + } + + // delay + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYCUSTOM), ServiceExists(MS_POPUP_ADDPOPUPT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYFROMPU), ServiceExists(MS_POPUP_ADDPOPUPT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYPERMANENT), ServiceExists(MS_POPUP_ADDPOPUPT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), ServiceExists(MS_POPUP_ADDPOPUPT)); + switch (db_get_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYFROMPU)) { + case POPUP_DELAYCUSTOM: + CheckDlgButton(hwndDlg, IDC_DELAYCUSTOM, BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), ServiceExists(MS_POPUP_ADDPOPUPT)); + break; + + case POPUP_DELAYPERMANENT: + CheckDlgButton(hwndDlg, IDC_DELAYPERMANENT, BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), FALSE); + break; + + case POPUP_DELAYFROMPU: + default: + CheckDlgButton(hwndDlg, IDC_DELAYFROMPU, BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), FALSE); + break; + } + // delay + SetDlgItemInt(hwndDlg, IDC_DELAY, db_get_dw(0, KSMODULENAME, SETTING_POPUP_TIMEOUT, 0), FALSE); + // back color + SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_SETCOLOUR, 0, db_get_dw(0, KSMODULENAME, SETTING_POPUP_BACKCOLOR, 0xAAAAAA)); + // text + SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOR, CPM_SETCOLOUR, 0, db_get_dw(0, KSMODULENAME, SETTING_POPUP_TEXTCOLOR, 0x0000CC)); + // wincolors + CheckDlgButton(hwndDlg, IDC_WINCOLORS, db_get_b(0, KSMODULENAME, SETTING_POPUP_USEWINCOLORS, 0) ? BST_CHECKED : BST_UNCHECKED); + // defaultcolors + CheckDlgButton(hwndDlg, IDC_DEFAULTCOLORS, ((db_get_b(0, KSMODULENAME, SETTING_POPUP_USEDEFCOLORS, 0)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS))) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); + EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULTCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS))); + EnableWindow(GetDlgItem(hwndDlg, IDC_WINCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS))); + // popup types + CheckDlgButton(hwndDlg, IDC_PUCONNLOST, db_get_b(0, KSMODULENAME, SETTING_PUCONNLOST, TRUE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PUOTHER, db_get_b(0, KSMODULENAME, SETTING_PUOTHER, TRUE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PUCONNRETRY, db_get_b(0, KSMODULENAME, SETTING_PUCONNRETRY, TRUE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PURESULT, db_get_b(0, KSMODULENAME, SETTING_PURESULT, TRUE) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PUSHOWEXTRA, db_get_b(0, KSMODULENAME, SETTING_PUSHOWEXTRA, TRUE) ? BST_CHECKED : BST_UNCHECKED); + bFreeze = false; + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_WINCOLORS: + case IDC_DEFAULTCOLORS: + EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR), ((BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) && (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)))); + EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULTCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS))); + EnableWindow(GetDlgItem(hwndDlg, IDC_WINCOLORS), (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS))); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case IDC_DELAYFROMPU: + case IDC_DELAYPERMANENT: + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), FALSE); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case IDC_DELAYCUSTOM: + EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), TRUE); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case IDC_BGCOLOR: + case IDC_TEXTCOLOR: + case IDC_DELAY: + case IDC_LNOTHING: + case IDC_LCLOSE: + case IDC_LCANCEL: + case IDC_RNOTHING: + case IDC_RCLOSE: + case IDC_RCANCEL: + case IDC_PUCONNLOST: + case IDC_PUOTHER: + case IDC_PUCONNRETRY: + case IDC_PURESULT: + case IDC_PUSHOWEXTRA: + if (!bFreeze) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case IDC_PREV: + { + POPUPDATAT ppd = {}; + ppd.lchIcon = Skin_LoadIcon(SKINICON_STATUS_OFFLINE); + wcsncpy(ppd.lptzContactName, TranslateT("Keep status"), MAX_CONTACTNAME); + wcsncpy(ppd.lptzText, TranslateT("You broke the Internet!"), MAX_SECONDLINE); + if (IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)) { + ppd.colorBack = GetSysColor(COLOR_BTNFACE); + ppd.colorText = GetSysColor(COLOR_WINDOWTEXT); + } + else if (IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)) { + ppd.colorBack = 0; + ppd.colorText = 0; + } + else { + ppd.colorBack = SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_GETCOLOUR, 0, 0); + ppd.colorText = SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOR, CPM_GETCOLOUR, 0, 0); + } + ppd.PluginWindowProc = KSPopupDlgProc; + ppd.PluginData = nullptr; + if (IsDlgButtonChecked(hwndDlg, IDC_DELAYFROMPU)) { + ppd.iSeconds = 0; + } + else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM)) { + ppd.iSeconds = GetDlgItemInt(hwndDlg, IDC_DELAY, nullptr, FALSE); + } + else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYPERMANENT)) { + ppd.iSeconds = -1; + } + PUAddPopupT(&ppd); + } + break; + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->code == PSN_APPLY) { + // left action + if (IsDlgButtonChecked(hwndDlg, IDC_LNOTHING)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_NOTHING); + else if (IsDlgButtonChecked(hwndDlg, IDC_LCLOSE)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_CLOSEPOPUP); + else if (IsDlgButtonChecked(hwndDlg, IDC_LCANCEL)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_LEFTCLICK, POPUP_ACT_CANCEL); + // right action + if (IsDlgButtonChecked(hwndDlg, IDC_RNOTHING)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_NOTHING); + else if (IsDlgButtonChecked(hwndDlg, IDC_RCLOSE)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_CLOSEPOPUP); + else if (IsDlgButtonChecked(hwndDlg, IDC_RCANCEL)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_RIGHTCLICK, POPUP_ACT_CANCEL); + // delay + if (IsDlgButtonChecked(hwndDlg, IDC_DELAYFROMPU)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYFROMPU); + else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYCUSTOM); + else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYPERMANENT)) + db_set_b(0, KSMODULENAME, SETTING_POPUP_DELAYTYPE, POPUP_DELAYPERMANENT); + // delay + db_set_dw(0, KSMODULENAME, SETTING_POPUP_TIMEOUT, GetDlgItemInt(hwndDlg, IDC_DELAY, nullptr, FALSE)); + // back color + db_set_dw(0, KSMODULENAME, SETTING_POPUP_BACKCOLOR, SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_GETCOLOUR, 0, 0)); + // text color + db_set_dw(0, KSMODULENAME, SETTING_POPUP_TEXTCOLOR, SendDlgItemMessage(hwndDlg, IDC_TEXTCOLOR, CPM_GETCOLOUR, 0, 0)); + // use win + db_set_b(0, KSMODULENAME, SETTING_POPUP_USEWINCOLORS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS)); + // use def + db_set_b(0, KSMODULENAME, SETTING_POPUP_USEDEFCOLORS, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS)); + // store types + db_set_b(0, KSMODULENAME, SETTING_PUCONNLOST, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUCONNLOST)); + db_set_b(0, KSMODULENAME, SETTING_PUOTHER, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUOTHER)); + db_set_b(0, KSMODULENAME, SETTING_PUCONNRETRY, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUCONNRETRY)); + db_set_b(0, KSMODULENAME, SETTING_PURESULT, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PURESULT)); + db_set_b(0, KSMODULENAME, SETTING_PUSHOWEXTRA, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_PUSHOWEXTRA)); + } + break; + } + + return 0; +} + +int KeepStatusOptionsInit(WPARAM wparam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = {}; + odp.hInstance = g_plugin.getInst(); + odp.szGroup.a = LPGEN("Status"); + odp.szTitle.a = LPGEN("Keep status"); + odp.flags = ODPF_BOLDGROUPS; + + odp.szTab.a = LPGEN("Basic"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_KS_BASIC); + odp.pfnDlgProc = DlgProcKSBasicOpts; + Options_AddPage(wparam, &odp, KSLangPack); + + odp.szTab.a = LPGEN("Advanced"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_KS_ADV); + odp.pfnDlgProc = DlgProcKSAdvOpts; + Options_AddPage(wparam, &odp, KSLangPack); + + if (ServiceExists(MS_POPUP_ADDPOPUPT)) { + memset(&odp, 0, sizeof(odp)); + odp.position = 150000000; + odp.szGroup.a = LPGEN("Popups"); + odp.hInstance = g_plugin.getInst(); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_PUOPT_KEEPSTATUS); + odp.szTitle.a = LPGEN("Keep status"); + odp.pfnDlgProc = PopupOptDlgProc; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wparam, &odp, KSLangPack); + } + return 0; +} diff --git a/plugins/StatusManager/src/ss_options.cpp b/plugins/StatusManager/src/ss_options.cpp new file mode 100644 index 0000000000..2ef03d852a --- /dev/null +++ b/plugins/StatusManager/src/ss_options.cpp @@ -0,0 +1,879 @@ +/* + StartupStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "stdafx.h" + +char* OptName(int i, const char* setting) +{ + static char buf[100]; + mir_snprintf(buf, "%d_%s", i, setting); + return buf; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Command line processing + +static char* GetStatusDesc(int status) +{ + switch (status) { + case ID_STATUS_AWAY: return "away"; + case ID_STATUS_NA: return "na"; + case ID_STATUS_DND: return "dnd"; + case ID_STATUS_OCCUPIED: return "occupied"; + case ID_STATUS_FREECHAT: return "freechat"; + case ID_STATUS_ONLINE: return "online"; + case ID_STATUS_OFFLINE: return "offline"; + case ID_STATUS_INVISIBLE: return "invisible"; + case ID_STATUS_ONTHEPHONE: return "onthephone"; + case ID_STATUS_OUTTOLUNCH: return "outtolunch"; + case ID_STATUS_LAST: return "last"; + } + return "offline"; +} + +static char* GetCMDLArguments(TProtoSettings& protoSettings) +{ + if (protoSettings.getCount() == 0) + return nullptr; + + char *cmdl, *pnt; + pnt = cmdl = (char*)mir_alloc(mir_strlen(protoSettings[0].m_szName) + mir_strlen(GetStatusDesc(protoSettings[0].m_status)) + 4); + + for (int i = 0; i < protoSettings.getCount(); i++) { + *pnt++ = '/'; + mir_strcpy(pnt, protoSettings[i].m_szName); + pnt += mir_strlen(protoSettings[i].m_szName); + *pnt++ = '='; + mir_strcpy(pnt, GetStatusDesc(protoSettings[i].m_status)); + pnt += mir_strlen(GetStatusDesc(protoSettings[i].m_status)); + if (i != protoSettings.getCount() - 1) { + *pnt++ = ' '; + *pnt++ = '\0'; + cmdl = (char*)mir_realloc(cmdl, mir_strlen(cmdl) + mir_strlen(protoSettings[i + 1].m_szName) + mir_strlen(GetStatusDesc(protoSettings[i + 1].m_status)) + 4); + pnt = cmdl + mir_strlen(cmdl); + } + } + + if (db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, FALSE) == TRUE) { + *pnt++ = ' '; + *pnt++ = '\0'; + cmdl = (char*)mir_realloc(cmdl, mir_strlen(cmdl) + 12); + pnt = cmdl + mir_strlen(cmdl); + mir_strcpy(pnt, "/showdialog"); + pnt += 11; + *pnt = '\0'; + } + + return cmdl; +} + +static char* GetCMDL(TProtoSettings& protoSettings) +{ + char path[MAX_PATH]; + GetModuleFileNameA(nullptr, path, MAX_PATH); + + char* cmdl = (char*)mir_alloc(mir_strlen(path) + 4); + mir_snprintf(cmdl, mir_strlen(path) + 4, "\"%s\" ", path); + + char* args = GetCMDLArguments(protoSettings); + if (args) { + cmdl = (char*)mir_realloc(cmdl, mir_strlen(cmdl) + mir_strlen(args) + 1); + mir_strcat(cmdl, args); + mir_free(args); + } + return cmdl; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Link processing + +static wchar_t* GetLinkDescription(TProtoSettings& protoSettings) +{ + if (protoSettings.getCount() == 0) + return nullptr; + + CMStringW result(SHORTCUT_DESC); + for (auto &p : protoSettings) { + wchar_t *status; + if (p->m_status == ID_STATUS_LAST) + status = TranslateT(""); + else if (p->m_status == ID_STATUS_CURRENT) + status = TranslateT(""); + else if (p->m_status >= MIN_STATUS && p->m_status <= MAX_STATUS) + status = Clist_GetStatusModeDescription(p->m_status, 0); + else + status = nullptr; + if (status == nullptr) + status = TranslateT(""); + + result.AppendChar('\r'); + result.Append(p->m_tszAccName); + result.AppendChar(':'); + result.AppendChar(' '); + result.Append(status); + } + + return mir_wstrndup(result, result.GetLength()); +} + +class CCmdlDlg : public CDlgBase +{ + TProtoSettings ps; + + CCtrlButton btnLink, btnCopy; + +public: + CCmdlDlg(int iProfileNo) + : CDlgBase(g_plugin, IDD_CMDLOPTIONS), + btnCopy(this, IDC_COPY), + btnLink(this, IDC_SHORTCUT), + ps(protoList) + { + GetProfile(iProfileNo, ps); + } + + void OnInitDialog() override + { + char* cmdl = GetCMDL(ps); + SetDlgItemTextA(m_hwnd, IDC_CMDL, cmdl); + mir_free(cmdl); + } + + void onClick_Copy(CCtrlButton*) + { + if (OpenClipboard(m_hwnd)) { + EmptyClipboard(); + + char cmdl[2048]; + GetDlgItemTextA(m_hwnd, IDC_CMDL, cmdl, _countof(cmdl)); + HGLOBAL cmdlGlob = GlobalAlloc(GMEM_MOVEABLE, sizeof(cmdl)); + if (cmdlGlob != nullptr) { + LPTSTR cmdlStr = (LPTSTR)GlobalLock(cmdlGlob); + memcpy(cmdlStr, &cmdl, sizeof(cmdl)); + GlobalUnlock(cmdlGlob); + SetClipboardData(CF_TEXT, cmdlGlob); + } + CloseClipboard(); + } + } + + void onClick_Link(CCtrlButton*) + { + wchar_t savePath[MAX_PATH]; + if (SHGetSpecialFolderPath(nullptr, savePath, CSIDL_DESKTOPDIRECTORY, FALSE)) + wcsncat_s(savePath, SHORTCUT_FILENAME, _countof(savePath) - mir_wstrlen(savePath)); + else + mir_snwprintf(savePath, L".\\%s", SHORTCUT_FILENAME); + + // Get a pointer to the IShellLink interface. + IShellLink *psl; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); + if (SUCCEEDED(hres)) { + ptrA args(GetCMDLArguments(ps)); + ptrW desc(GetLinkDescription(ps)); + + // Set the path to the shortcut target, and add the + // description. + wchar_t path[MAX_PATH]; + GetModuleFileName(nullptr, path, _countof(path)); + psl->SetPath(path); + psl->SetDescription(desc); + psl->SetArguments(_A2T(args)); + + // Query IShellLink for the IPersistFile interface for saving the + // shortcut in persistent storage. + IPersistFile *ppf; + hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); + + if (SUCCEEDED(hres)) { + // Save the link by calling IPersistFile::Save. + hres = ppf->Save(savePath, TRUE); + ppf->Release(); + } + psl->Release(); + } + } +}; + +static INT_PTR CALLBACK StartupStatusOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static BOOL bInitDone = FALSE; + + switch (msg) { + case WM_INITDIALOG: + bInitDone = FALSE; + + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_SETPROFILE, db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OVERRIDE, db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWDIALOG, db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETWINSTATE, db_get_b(0, SSMODULENAME, SETTING_SETWINSTATE, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETWINLOCATION, db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETDOCKED, db_get_b(0, SSMODULENAME, SETTING_SETDOCKED, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETWINSIZE, db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OFFLINECLOSE, db_get_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTODIAL, db_get_b(0, SSMODULENAME, SETTING_AUTODIAL, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOHANGUP, db_get_b(0, SSMODULENAME, SETTING_AUTOHANGUP, 0) ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_SETPROFILEDELAY, db_get_dw(0, SSMODULENAME, SETTING_SETPROFILEDELAY, 500), FALSE); + SetDlgItemInt(hwndDlg, IDC_DLGTIMEOUT, db_get_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, 5), FALSE); + SetDlgItemInt(hwndDlg, IDC_XPOS, db_get_dw(0, SSMODULENAME, SETTING_XPOS, 0), TRUE); + SetDlgItemInt(hwndDlg, IDC_YPOS, db_get_dw(0, SSMODULENAME, SETTING_YPOS, 0), TRUE); + SetDlgItemInt(hwndDlg, IDC_WIDTH, db_get_dw(0, SSMODULENAME, SETTING_WIDTH, 0), FALSE); + SetDlgItemInt(hwndDlg, IDC_HEIGHT, db_get_dw(0, SSMODULENAME, SETTING_HEIGHT, 0), FALSE); + { + int val = db_get_b(0, SSMODULENAME, SETTING_DOCKED, DOCKED_NONE); + int item = SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_ADDSTRING, 0, (LPARAM)TranslateT("Left")); + SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETITEMDATA, (WPARAM)item, (LPARAM)DOCKED_LEFT); + if (val == DOCKED_LEFT) + SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETCURSEL, (WPARAM)item, 0); + + item = SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_ADDSTRING, 0, (LPARAM)TranslateT("Right")); + SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETITEMDATA, (WPARAM)item, (LPARAM)DOCKED_RIGHT); + if (val == DOCKED_RIGHT) + SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETCURSEL, (WPARAM)item, 0); + + item = SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_ADDSTRING, 0, (LPARAM)TranslateT("None")); + SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETITEMDATA, (WPARAM)item, (LPARAM)DOCKED_NONE); + if (val == DOCKED_NONE) + SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_SETCURSEL, (WPARAM)item, 0); + } + + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SETPROFILEDELAY), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_OVERRIDE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DLGTIMEOUT), IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_WINSTATE), IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_XPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_YPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); + SendMessage(hwndDlg, UM_REINITPROFILES, 0, 0); + SendMessage(hwndDlg, UM_REINITDOCKED, 0, 0); + SendMessage(hwndDlg, UM_REINITWINSTATE, 0, 0); + SendMessage(hwndDlg, UM_REINITWINSIZE, 0, 0); + SetTimer(hwndDlg, 0, 100, nullptr); + bInitDone = TRUE; + break; + + case WM_TIMER: + if (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION) && BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)) { + SetDlgItemTextA(hwndDlg, IDC_CURWINSIZE, ""); + SetDlgItemTextA(hwndDlg, IDC_CURWINLOC, ""); + break; + } + else { + wchar_t text[128]; + mir_snwprintf(text, TranslateT("size: %d x %d"), + db_get_dw(0, MODULE_CLIST, SETTING_WIDTH, 0), + db_get_dw(0, MODULE_CLIST, SETTING_HEIGHT, 0)); + SetDlgItemText(hwndDlg, IDC_CURWINSIZE, text); + + mir_snwprintf(text, TranslateT("loc: %d x %d"), + db_get_dw(0, MODULE_CLIST, SETTING_XPOS, 0), + db_get_dw(0, MODULE_CLIST, SETTING_YPOS, 0)); + SetDlgItemText(hwndDlg, IDC_CURWINLOC, text); + } + break; + + case UM_REINITPROFILES: + // creates profile combo box according to 'dat' + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_RESETCONTENT, 0, 0); + { + int defProfile; + int profileCount = GetProfileCount((WPARAM)&defProfile, 0); + for (int i = 0; i < profileCount; i++) { + wchar_t profileName[128]; + if (GetProfileName(i, (LPARAM)profileName)) + continue; + + int item = SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_ADDSTRING, 0, (LPARAM)profileName); + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETITEMDATA, item, i); + } + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETCURSEL, defProfile, 0); + } + break; + + case UM_REINITDOCKED: + EnableWindow(GetDlgItem(hwndDlg, IDC_SETDOCKED), db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 1)); + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_SETDOCKED))) + CheckDlgButton(hwndDlg, IDC_SETDOCKED, BST_UNCHECKED); + + EnableWindow(GetDlgItem(hwndDlg, IDC_DOCKED), IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)); + break; + + case UM_REINITWINSTATE: + { + int val = db_get_b(0, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_RESETCONTENT, 0, 0); + + int item = SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_ADDSTRING, 0, (LPARAM)TranslateT("Hidden")); + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETITEMDATA, item, (LPARAM)SETTING_STATE_HIDDEN); + if (val == SETTING_STATE_HIDDEN) + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETCURSEL, item, 0); + + if (!db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 0)) { + item = SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_ADDSTRING, 0, (LPARAM)TranslateT("Minimized")); + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETITEMDATA, item, SETTING_STATE_MINIMIZED); + if (val == SETTING_STATE_MINIMIZED) + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETCURSEL, item, 0); + } + item = SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_ADDSTRING, 0, (LPARAM)TranslateT("Normal")); + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETITEMDATA, item, SETTING_STATE_NORMAL); + if (val == SETTING_STATE_NORMAL || (val == SETTING_STATE_MINIMIZED) && db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 0)) + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_SETCURSEL, item, 0); + } + break; + + case UM_REINITWINSIZE: + EnableWindow(GetDlgItem(hwndDlg, IDC_WIDTH), IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_HEIGHT), !db_get_b(0, MODULE_CLUI, SETTING_AUTOSIZE, 0) && IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)); + + case WM_COMMAND: + if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == LBN_SELCHANGE || HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == EN_CHANGE) + if (bInitDone) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + + switch (LOWORD(wParam)) { + case IDC_SETPROFILE: + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SETPROFILEDELAY), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); + EnableWindow(GetDlgItem(hwndDlg, IDC_OVERRIDE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); + break; + case IDC_SHOWDIALOG: + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DLGTIMEOUT), IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); + break; + case IDC_SETWINSTATE: + EnableWindow(GetDlgItem(hwndDlg, IDC_WINSTATE), IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)); + break; + case IDC_SETDOCKED: + EnableWindow(GetDlgItem(hwndDlg, IDC_DOCKED), IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)); + break; + case IDC_SETWINLOCATION: + EnableWindow(GetDlgItem(hwndDlg, IDC_XPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); + EnableWindow(GetDlgItem(hwndDlg, IDC_YPOS), IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); + break; + case IDC_SETWINSIZE: + SendMessage(hwndDlg, UM_REINITWINSIZE, 0, 0); + break; + case IDC_SHOWCMDL: + { + int defProfile = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); + CCmdlDlg *pDlg = new CCmdlDlg(defProfile); + pDlg->Show(); + break; + } + } + break; + + case WM_SHOWWINDOW: + if (wParam == FALSE) + break; + + bInitDone = FALSE; + SendMessage(hwndDlg, UM_REINITPROFILES, 0, 0); + SendMessage(hwndDlg, UM_REINITDOCKED, 0, 0); + SendMessage(hwndDlg, UM_REINITWINSTATE, 0, 0); + SendMessage(hwndDlg, UM_REINITWINSIZE, 0, 0); + bInitDone = TRUE; + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case PSN_WIZFINISH: + SSLoadMainOptions(); + break; + + case PSN_APPLY: + db_set_b(0, SSMODULENAME, SETTING_SETPROFILE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)) + db_set_dw(0, SSMODULENAME, SETTING_SETPROFILEDELAY, GetDlgItemInt(hwndDlg, IDC_SETPROFILEDELAY, nullptr, FALSE)); + + if (IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)) { + int val = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); + db_set_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, (WORD)val); + } + db_set_b(0, SSMODULENAME, SETTING_OVERRIDE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_OVERRIDE)); + db_set_b(0, SSMODULENAME, SETTING_SHOWDIALOG, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)) + db_set_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, GetDlgItemInt(hwndDlg, IDC_DLGTIMEOUT, nullptr, FALSE)); + + db_set_b(0, SSMODULENAME, SETTING_SETWINSTATE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)) { + int val = (int)SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_GETCURSEL, 0, 0), 0); + db_set_b(0, SSMODULENAME, SETTING_WINSTATE, (BYTE)val); + } + db_set_b(0, SSMODULENAME, SETTING_SETDOCKED, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)) { + int val = (int)SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_GETCURSEL, 0, 0), 0); + db_set_b(0, SSMODULENAME, SETTING_DOCKED, (BYTE)val); + } + db_set_b(0, SSMODULENAME, SETTING_SETWINLOCATION, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)) { + db_set_dw(0, SSMODULENAME, SETTING_XPOS, GetDlgItemInt(hwndDlg, IDC_XPOS, nullptr, TRUE)); + db_set_dw(0, SSMODULENAME, SETTING_YPOS, GetDlgItemInt(hwndDlg, IDC_YPOS, nullptr, TRUE)); + } + db_set_b(0, SSMODULENAME, SETTING_SETWINSIZE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)) { + db_set_dw(0, SSMODULENAME, SETTING_WIDTH, GetDlgItemInt(hwndDlg, IDC_WIDTH, nullptr, FALSE)); + db_set_dw(0, SSMODULENAME, SETTING_HEIGHT, GetDlgItemInt(hwndDlg, IDC_HEIGHT, nullptr, FALSE)); + } + db_set_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_OFFLINECLOSE)); + db_set_b(0, SSMODULENAME, SETTING_AUTODIAL, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_AUTODIAL)); + db_set_b(0, SSMODULENAME, SETTING_AUTOHANGUP, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_AUTOHANGUP)); + } + break; + } + + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// new profile dialog + +class CAddProfileDlg : public CDlgBase +{ + CCtrlEdit edtProfile; + CCtrlButton btnOk; + +public: + CAddProfileDlg() + : CDlgBase(g_plugin, IDD_ADDPROFILE), + btnOk(this, IDOK), + edtProfile(this, IDC_PROFILENAME) + { + edtProfile.OnChange = Callback(this, &CAddProfileDlg::onChange_Edit); + } + + void OnInitDialog() override + { + btnOk.Disable(); + } + + void OnApply() override + { + ptrW profileName(edtProfile.GetText()); + SendMessage(m_hwndParent, UM_ADDPROFILE, 0, (LPARAM)profileName.get()); + } + + void OnDestroy() override + { + EnableWindow(m_hwndParent, TRUE); + } + + void onChange_Edit(CCtrlEdit*) + { + btnOk.Enable(edtProfile.SendMsg(EM_LINELENGTH, 0, 0) > 0); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// advanced options dialog + +static int DeleteSetting(const char *szSetting, void *lParam) +{ + LIST *p = (LIST *)lParam; + p->insert(mir_strdup(szSetting)); + return 0; +} + +class CSSAdvancedOptDlg : public CDlgBase +{ + bool bNeedRebuildMenu; + + OBJLIST arProfiles; + + void ReinitProfiles() + { + // creates profile combo box according to 'dat' + cmbProfile.ResetContent(); + for (auto &it : arProfiles) + cmbProfile.AddString(it->tszName, arProfiles.indexOf(&it)); + + cmbProfile.SetCurSel(0); + SetProfile(); + } + + void SetProfile() + { + int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); + chkCreateTTB.SetState(arProfiles[sel].createTtb); + chkShowDialog.SetState(arProfiles[sel].showDialog); + chkCreateMMI.SetState(arProfiles[sel].createMmi); + chkInSubmenu.SetState(arProfiles[sel].inSubMenu); + chkInSubmenu.Enable(arProfiles[sel].createMmi); + chkRegHotkey.SetState(arProfiles[sel].regHotkey); + edtHotkey.SendMsg(HKM_SETHOTKEY, arProfiles[sel].hotKey, 0); + edtHotkey.Enable(arProfiles[sel].regHotkey); + + // fill proto list + lstAccount.ResetContent(); + for (auto &it : arProfiles[sel].ps) + lstAccount.AddString(it->m_tszAccName, (LPARAM)it); + lstAccount.SetCurSel(0); + + SetProtocol(); + } + + void SetProtocol() + { + int idx = lstAccount.GetCurSel(); + if (idx != -1) { + // fill status box + SMProto* ps = (SMProto*)lstAccount.GetItemData(idx); + + int flags = (CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_2, 0))&~(CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_5, 0)); + lstStatus.ResetContent(); + for (auto &it : statusModes) { + if ((flags & it.iFlag) || (it.iStatus == ID_STATUS_OFFLINE)) { + int item = lstStatus.AddString(Clist_GetStatusModeDescription(it.iStatus, 0), it.iStatus); + if (ps->m_status == it.iStatus) + lstStatus.SetCurSel(item); + } + } + + int item = lstStatus.AddString(TranslateT(""), ID_STATUS_CURRENT); + if (ps->m_status == ID_STATUS_CURRENT) + lstStatus.SetCurSel(item); + + item = lstStatus.AddString(TranslateT(""), ID_STATUS_LAST); + if (ps->m_status == ID_STATUS_LAST) + lstStatus.SetCurSel(item); + } + + SetStatusMsg(); + } + + // set status message + void SetStatusMsg() + { + bool bStatusMsg = false; + int idx = lstAccount.GetCurSel(); + if (idx != -1) { + SMProto *ps = (SMProto*)lstAccount.GetItemData(idx); + + CheckRadioButton(m_hwnd, IDC_MIRANDAMSG, IDC_CUSTOMMSG, ps->m_szMsg != nullptr ? IDC_CUSTOMMSG : IDC_MIRANDAMSG); + if (ps->m_szMsg != nullptr) + edtStatusMsg.SetText(ps->m_szMsg); + + bStatusMsg = ((((CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND & ~PF1_INDIVMODEMSG)) && + (CallProtoService(ps->m_szName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(ps->m_status))) || (ps->m_status == ID_STATUS_CURRENT) || (ps->m_status == ID_STATUS_LAST)); + } + chkMiranda.Enable(bStatusMsg); + chkCustom.Enable(bStatusMsg); + btnHelp.Enable(bStatusMsg && chkCustom.GetState()); + edtStatusMsg.Enable(bStatusMsg && chkCustom.GetState()); + } + + CCtrlEdit edtStatusMsg, edtHotkey; + CCtrlCombo cmbProfile; + CCtrlCheck chkMiranda, chkCustom, chkCreateMMI, chkInSubmenu, chkRegHotkey, chkCreateTTB, chkShowDialog; + CCtrlButton btnAdd, btnDelete, btnHelp; + CCtrlListBox lstStatus, lstAccount; + +public: + CSSAdvancedOptDlg() : + CDlgBase(g_plugin, IDD_OPT_STATUSPROFILES), + cmbProfile(this, IDC_PROFILE), + btnAdd(this, IDC_ADDPROFILE), + btnHelp(this, IDC_VARIABLESHELP), + btnDelete(this, IDC_DELPROFILE), + chkCustom(this, IDC_CUSTOMMSG), + chkMiranda(this, IDC_MIRANDAMSG), + chkCreateMMI(this, IDC_CREATEMMI), + chkInSubmenu(this, IDC_INSUBMENU), + chkRegHotkey(this, IDC_REGHOTKEY), + chkCreateTTB(this, IDC_CREATETTB), + chkShowDialog(this, IDC_SHOWDIALOG), + edtHotkey(this, IDC_HOTKEY), + edtStatusMsg(this, IDC_STATUSMSG), + lstStatus(this, IDC_STATUS), + lstAccount(this, IDC_PROTOCOL), + arProfiles(5), + bNeedRebuildMenu(false) + { + btnAdd.OnClick = Callback(this, &CSSAdvancedOptDlg::onClick_Add); + btnHelp.OnClick = Callback(this, &CSSAdvancedOptDlg::onClick_Help); + btnDelete.OnClick = Callback(this, &CSSAdvancedOptDlg::onClick_Delete); + + cmbProfile.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_Profile); + + chkCreateMMI.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_CreateMMI); + chkInSubmenu.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_InSubmenu); + chkCustom.OnChange = chkMiranda.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_StatusMsg); + chkRegHotkey.OnChange = chkCreateTTB.OnChange = chkShowDialog.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_Option); + + edtHotkey.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_Hotkey); + edtStatusMsg.OnChange = Callback(this, &CSSAdvancedOptDlg::onChange_EdtStatusMsg); + + lstStatus.OnSelChange = Callback(this, &CSSAdvancedOptDlg::onChange_Status); + lstAccount.OnSelChange = Callback(this, &CSSAdvancedOptDlg::onChange_Account); + + m_OnFinishWizard = Callback(this, &CSSAdvancedOptDlg::OnFinishWizard); + } + + void OnFinishWizard(void*) + { + SSLoadMainOptions(); + } + + virtual void OnInitDialog() override + { + chkCreateMMI.SetText(TranslateT("Create a status menu item")); + + int defProfile; + int profileCount = GetProfileCount((WPARAM)&defProfile, 0); + if (profileCount == 0) { + profileCount = 1; + defProfile = 0; + NotifyChange(); + } + + for (int i = 0; i < profileCount; i++) { + PROFILEOPTIONS *ppo = new PROFILEOPTIONS; + TProtoSettings &ar = ppo->ps; + + if (GetProfile(i, ar) == -1) { + /* create an empty profile */ + if (i == defProfile) + ppo->tszName = mir_wstrdup(TranslateT("default")); + else + ppo->tszName = mir_wstrdup(TranslateT("unknown")); + } + else { + ppo->tszName = db_get_wsa(0, SSMODULENAME, OptName(i, SETTING_PROFILENAME)); + if (ppo->tszName == nullptr) { + if (i == defProfile) + ppo->tszName = mir_wstrdup(TranslateT("default")); + else + ppo->tszName = mir_wstrdup(TranslateT("unknown")); + } + ppo->createTtb = db_get_b(0, SSMODULENAME, OptName(i, SETTING_CREATETTBBUTTON), 0); + ppo->showDialog = db_get_b(0, SSMODULENAME, OptName(i, SETTING_SHOWCONFIRMDIALOG), 0); + ppo->createMmi = db_get_b(0, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), 0); + ppo->inSubMenu = db_get_b(0, SSMODULENAME, OptName(i, SETTING_INSUBMENU), 1); + ppo->regHotkey = db_get_b(0, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), 0); + ppo->hotKey = db_get_w(0, SSMODULENAME, OptName(i, SETTING_HOTKEY), MAKEWORD((char)('0' + i), HOTKEYF_CONTROL | HOTKEYF_SHIFT)); + } + arProfiles.insert(ppo); + } + if (hTTBModuleLoadedHook == nullptr) + chkCreateTTB.Disable(); + + ReinitProfiles(); + ShowWindow(GetDlgItem(m_hwnd, IDC_VARIABLESHELP), ServiceExists(MS_VARS_SHOWHELPEX) ? SW_SHOW : SW_HIDE); + } + + virtual void OnApply() override + { + int oldCount = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); + for (int i = 0; i < oldCount; i++) { + LIST arSettings(10); + db_enum_settings(0, DeleteSetting, SSMODULENAME, &arSettings); + + char setting[128]; + int len = mir_snprintf(setting, "%d_", i); + for (auto &it : arSettings) { + if (!strncmp(setting, it, len)) + db_unset(0, SSMODULENAME, it); + mir_free(it); + } + } + + for (auto &it : arProfiles) { + int i = arProfiles.indexOf(&it); + db_set_b(0, SSMODULENAME, OptName(i, SETTING_SHOWCONFIRMDIALOG), it->showDialog); + db_set_b(0, SSMODULENAME, OptName(i, SETTING_CREATETTBBUTTON), it->createTtb); + db_set_b(0, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), it->createMmi); + db_set_b(0, SSMODULENAME, OptName(i, SETTING_INSUBMENU), it->inSubMenu); + db_set_b(0, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), it->regHotkey); + db_set_w(0, SSMODULENAME, OptName(i, SETTING_HOTKEY), it->hotKey); + db_set_ws(0, SSMODULENAME, OptName(i, SETTING_PROFILENAME), it->tszName); + + for (auto jt : it->ps) { + if (jt->m_szMsg != nullptr) { + char setting[128]; + mir_snprintf(setting, "%s_%s", jt->m_szName, SETTING_PROFILE_STSMSG); + db_set_ws(0, SSMODULENAME, OptName(i, setting), jt->m_szMsg); + } + db_set_w(0, SSMODULENAME, OptName(i, jt->m_szName), jt->m_status); + } + } + db_set_w(0, SSMODULENAME, SETTING_PROFILECOUNT, (WORD)arProfiles.getCount()); + + // Rebuild status menu + if (bNeedRebuildMenu) + Menu_ReloadProtoMenus(); + } + + // add a profile + void onClick_Add(CCtrlButton*) + { + CAddProfileDlg *pDlg = new CAddProfileDlg(); + pDlg->SetParent(m_hwnd); + pDlg->Show(); + EnableWindow(m_hwnd, FALSE); + } + + void onClick_Delete(CCtrlButton*) + { + // wparam == profile no + int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); + if (arProfiles.getCount() == 1) { + MessageBox(nullptr, TranslateT("At least one profile must exist"), TranslateT("Status manager"), MB_OK); + return; + } + + arProfiles.remove(sel); + + int defProfile; + GetProfileCount((WPARAM)&defProfile, 0); + if (sel == defProfile) { + MessageBox(nullptr, TranslateT("Your default profile will be changed"), TranslateT("Status manager"), MB_OK); + db_set_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + } + ReinitProfiles();; + } + + void onClick_Help(CCtrlButton*) + { + variables_showhelp(m_hwnd, IDC_STATUSMSG, VHF_INPUT | VHF_EXTRATEXT | VHF_HELP | VHF_FULLFILLSTRUCT | VHF_HIDESUBJECTTOKEN, nullptr, "Protocol ID"); + } + + void onChange_Status(CCtrlListBox*) + { + int idx = lstAccount.GetCurSel(); + if (idx != -1) { + SMProto* ps = (SMProto*)lstAccount.GetItemData(idx); + ps->m_status = lstStatus.GetItemData(lstStatus.GetCurSel()); + NotifyChange(); + } + SetStatusMsg(); + } + + void onChange_Account(CCtrlListBox*) + { + SetProtocol(); + } + + void onChange_Profile(CCtrlCombo*) + { + SetProfile(); + } + + void onChange_StatusMsg(CCtrlCheck*) + { + int len; + SMProto* ps = (SMProto*)lstAccount.GetItemData(lstAccount.GetCurSel()); + if (ps->m_szMsg != nullptr) + mir_free(ps->m_szMsg); + + ps->m_szMsg = nullptr; + if (chkCustom.GetState()) { + len = edtStatusMsg.SendMsg(WM_GETTEXTLENGTH, 0, 0); + ps->m_szMsg = (wchar_t*)mir_calloc(sizeof(wchar_t) * (len + 1)); + GetDlgItemText(m_hwnd, IDC_STATUSMSG, ps->m_szMsg, (len + 1)); + } + SetStatusMsg(); + } + + void onChange_Hotkey(CCtrlEdit*) + { + int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); + arProfiles[sel].hotKey = edtHotkey.SendMsg(HKM_GETHOTKEY, 0, 0); + } + + void onChange_EdtStatusMsg(CCtrlEdit*) + { + // update the status message in memory, this is done on each character tick, not nice + // but it works + SMProto* ps = (SMProto*)lstAccount.GetItemData(lstAccount.GetCurSel()); + if (ps->m_szMsg != nullptr) { + if (*ps->m_szMsg) + mir_free(ps->m_szMsg); + ps->m_szMsg = nullptr; + } + int len = edtStatusMsg.SendMsg(WM_GETTEXTLENGTH, 0, 0); + ps->m_szMsg = (wchar_t*)mir_calloc(sizeof(wchar_t) * (len + 1)); + GetDlgItemText(m_hwnd, IDC_STATUSMSG, ps->m_szMsg, (len + 1)); + } + + void onChange_CreateMMI(CCtrlCheck*) + { + chkInSubmenu.Enable(chkCreateMMI.GetState()); + onChange_InSubmenu(nullptr); + } + + void onChange_InSubmenu(CCtrlCheck*) + { + bNeedRebuildMenu = TRUE; + onChange_Option(nullptr); + } + + void onChange_Option(CCtrlCheck*) + { + int sel = cmbProfile.GetItemData(cmbProfile.GetCurSel()); + PROFILEOPTIONS &po = arProfiles[sel]; + po.createMmi = chkCreateMMI.GetState(); + po.inSubMenu = chkInSubmenu.GetState(); + po.createTtb = chkCreateTTB.GetState(); + po.regHotkey = chkRegHotkey.GetState(); + po.showDialog = chkShowDialog.GetState(); + edtHotkey.Enable(chkRegHotkey.GetState()); + } + + virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override + { + switch (msg) { + case UM_ADDPROFILE: + wchar_t *tszName = (wchar_t*)lParam; + if (tszName == nullptr) + break; + + PROFILEOPTIONS* ppo = new PROFILEOPTIONS; + ppo->tszName = mir_wstrdup(tszName); + arProfiles.insert(ppo); + + ReinitProfiles(); + break; + } + + return CDlgBase::DlgProc(msg, wParam, lParam); + } +}; + +int StartupStatusOptionsInit(WPARAM wparam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = {}; + odp.hInstance = g_plugin.getInst(); + odp.szGroup.a = LPGEN("Status"); + odp.szTitle.a = LPGEN("Startup status"); + odp.flags = ODPF_BOLDGROUPS; + + odp.szTab.a = LPGEN("General"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_STARTUPSTATUS); + odp.pfnDlgProc = StartupStatusOptDlgProc; + Options_AddPage(wparam, &odp, SSLangPack); + + odp.szTab.a = LPGEN("Status profiles"); + odp.pszTemplate = nullptr; + odp.pfnDlgProc = nullptr; + odp.pDialog = new CSSAdvancedOptDlg(); + Options_AddPage(wparam, &odp, SSLangPack); + return 0; +} diff --git a/plugins/StatusManager/src/ss_profiles.cpp b/plugins/StatusManager/src/ss_profiles.cpp new file mode 100644 index 0000000000..f678db190d --- /dev/null +++ b/plugins/StatusManager/src/ss_profiles.cpp @@ -0,0 +1,332 @@ +/* + StartupStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "stdafx.h" + +#define MAX_MMITEMS 6 + +struct PROFILECE +{ + int profile; + ptrA szProto; + ptrW msg; +}; + +static OBJLIST arProfiles(1); + +extern int protoCount; + +static int menuprofiles[MAX_MMITEMS]; +static int mcount = 0; + +static UINT_PTR releaseTtbTimerId = 0; + +static HANDLE hTBModuleLoadedHook; +static HANDLE hMessageHook = nullptr; + +static HWND hMessageWindow = nullptr; +static HKINFO *hkInfo = nullptr; +static int hkiCount = 0; + +static HANDLE* ttbButtons = nullptr; +static int ttbButtonCount = 0; + +HANDLE hTTBModuleLoadedHook; + +static INT_PTR profileService(WPARAM, LPARAM, LPARAM param) +{ + LoadAndSetProfile((WPARAM)menuprofiles[param], 0); + return 0; +} + +static int CreateMainMenuItems(WPARAM, LPARAM) +{ + CMenuItem mi(g_plugin); + mi.position = 2000100000; + mi.flags = CMIF_UNICODE; + mcount = 0; + int count = GetProfileCount(0, 0); + for (int i = 0; i < count && mcount < MAX_MMITEMS; i++) { + wchar_t profilename[128]; + if (!db_get_b(0, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), 0) || GetProfileName(i, (LPARAM)profilename)) + continue; + + if (db_get_b(0, SSMODULENAME, OptName(i, SETTING_INSUBMENU), 1) && !mi.root) { + mi.root = g_plugin.addRootMenu(MO_STATUS, LPGENW("Status profiles"), 2000100000); + Menu_ConfigureItem(mi.root, MCI_OPT_UID, "1AB30D51-BABA-4B27-9288-1A12278BAD8D"); + } + + char servicename[128]; + mir_snprintf(servicename, "%s%d", MS_SS_MENUSETPROFILEPREFIX, mcount); + CreateServiceFunctionParam(servicename, profileService, mcount); + + mi.name.w = profilename; + mi.position = 2000100000 + mcount; + mi.pszService = servicename; + if (Menu_AddStatusMenuItem(&mi)) + menuprofiles[mcount++] = i; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR GetProfileName(WPARAM wParam, LPARAM lParam) +{ + int profile = (int)wParam; + if (profile < 0) // get default profile + profile = db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + + int count = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); + if (profile >= count && count > 0) + return -1; + + wchar_t* buf = (wchar_t*)lParam; + if (count == 0) { + wcsncpy(buf, TranslateT("default"), 128 - 1); + return 0; + } + + DBVARIANT dbv; + char setting[80]; + mir_snprintf(setting, "%d_%s", profile, SETTING_PROFILENAME); + if (db_get_ws(0, SSMODULENAME, setting, &dbv)) + return -1; + + wcsncpy(buf, dbv.ptszVal, 128 - 1); buf[127] = 0; + db_free(&dbv); + return 0; +} + +INT_PTR GetProfileCount(WPARAM wParam, LPARAM) +{ + int *def = (int*)wParam; + int count = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); + if (def != nullptr) { + *def = db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + if (*def >= count) + *def = 0; + } + + return count; +} + +wchar_t* GetStatusMessage(int profile, const char *szProto) +{ + char dbSetting[80]; + mir_snprintf(dbSetting, "%d_%s_%s", profile, szProto, SETTING_PROFILE_STSMSG); + + for (auto &p : arProfiles) { + if (p->profile == profile && !mir_strcmp(p->szProto, szProto)) { + p->msg = db_get_wsa(0, SSMODULENAME, dbSetting); + return p->msg; + } + } + + PROFILECE *pce = new PROFILECE; + pce->profile = profile; + pce->szProto = mir_strdup(szProto); + pce->msg = db_get_wsa(0, SSMODULENAME, dbSetting); + arProfiles.insert(pce); + + return pce->msg; +} + +void FillStatus(SMProto &ps, int profile) +{ + // load status + char setting[80]; + mir_snprintf(setting, "%d_%s", profile, ps.m_szName); + int iStatus = db_get_w(0, SSMODULENAME, setting, 0); + if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) + iStatus = DEFAULT_STATUS; + ps.m_status = iStatus; + + // load last status + mir_snprintf(setting, "%s%s", PREFIX_LAST, ps.m_szName); + iStatus = db_get_w(0, SSMODULENAME, setting, 0); + if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) + iStatus = DEFAULT_STATUS; + ps.m_lastStatus = iStatus; + + ps.m_szMsg = GetStatusMessage(profile, ps.m_szName); + if (ps.m_szMsg) + ps.m_szMsg = mir_wstrdup(ps.m_szMsg); +} + +int GetProfile(int profile, TProtoSettings &arSettings) +{ + if (profile < 0) // get default profile + profile = db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + + int count = db_get_w(0, SSMODULENAME, SETTING_PROFILECOUNT, 0); + if (profile >= count && count > 0) + return -1; + + for (auto &it : arSettings) + FillStatus(*it, profile); + + return (arSettings.getCount() == 0) ? -1 : 0; +} + +static void CALLBACK releaseTtbTimerFunction(HWND, UINT, UINT_PTR, DWORD) +{ + KillTimer(nullptr, releaseTtbTimerId); + for (int i = 0; i < ttbButtonCount; i++) + CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)ttbButtons[i], 0); +} + +INT_PTR LoadAndSetProfile(WPARAM iProfileNo, LPARAM) +{ + // wParam == profile no. + int profile = (int)iProfileNo; + TProtoSettings ps(protoList); + if (!GetProfile(profile, ps)) { + profile = (profile >= 0) ? profile : db_get_w(0, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + + char setting[64]; + mir_snprintf(setting, "%d_%s", profile, SETTING_SHOWCONFIRMDIALOG); + if (!db_get_b(0, SSMODULENAME, setting, 0)) + SetStatusEx(ps); + else + ShowConfirmDialogEx(&ps, db_get_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, 5)); + } + + // add timer here + if (hTTBModuleLoadedHook) + releaseTtbTimerId = SetTimer(nullptr, 0, 100, releaseTtbTimerFunction); + + return 0; +} + +static UINT GetFsModifiers(WORD wHotKey) +{ + UINT fsm = 0; + if (HIBYTE(wHotKey)&HOTKEYF_ALT) + fsm |= MOD_ALT; + if (HIBYTE(wHotKey)&HOTKEYF_CONTROL) + fsm |= MOD_CONTROL; + if (HIBYTE(wHotKey)&HOTKEYF_SHIFT) + fsm |= MOD_SHIFT; + if (HIBYTE(wHotKey)&HOTKEYF_EXT) + fsm |= MOD_WIN; + + return fsm; +} + +static DWORD CALLBACK MessageWndProc(HWND, UINT msg, WPARAM wParam, LPARAM) +{ + if (msg == WM_HOTKEY) { + for (int i = 0; i < hkiCount; i++) + if ((int)hkInfo[i].id == wParam) + LoadAndSetProfile((WPARAM)hkInfo[i].profile, 0); + } + + return TRUE; +} + +static int UnregisterHotKeys() +{ + if (hkInfo != nullptr) { + for (int i = 0; i < hkiCount; i++) { + UnregisterHotKey(hMessageWindow, (int)hkInfo[i].id); + GlobalDeleteAtom(hkInfo[i].id); + } + mir_free(hkInfo); + } + DestroyWindow(hMessageWindow); + + hkiCount = 0; + hkInfo = nullptr; + hMessageWindow = nullptr; + + return 0; +} + +// assumes UnregisterHotKeys was called before +static int RegisterHotKeys() +{ + hMessageWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); + + int count = GetProfileCount(0, 0); + for (int i = 0; i < count; i++) { + if (!db_get_b(0, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), 0)) + continue; + + WORD wHotKey = db_get_w(0, SSMODULENAME, OptName(i, SETTING_HOTKEY), 0); + hkInfo = (HKINFO*)mir_realloc(hkInfo, (hkiCount + 1)*sizeof(HKINFO)); + if (hkInfo == nullptr) + return -1; + + char atomname[255]; + mir_snprintf(atomname, "StatusProfile_%d", i); + hkInfo[hkiCount].id = GlobalAddAtomA(atomname); + if (hkInfo[hkiCount].id == 0) + continue; + + hkInfo[hkiCount].profile = i; + hkiCount++; + RegisterHotKey(hMessageWindow, (int)hkInfo[hkiCount - 1].id, GetFsModifiers(wHotKey), LOBYTE(wHotKey)); + } + + if (hkiCount == 0) + UnregisterHotKeys(); + + return 0; +} + +int SSLoadMainOptions() +{ + if (hTTBModuleLoadedHook) { + RemoveTopToolbarButtons(); + CreateTopToolbarButtons(0, 0); + } + + UnregisterHotKeys(); + RegisterHotKeys(); + return 0; +} + +int LoadProfileModule() +{ + CreateServiceFunction(MS_SS_LOADANDSETPROFILE, LoadAndSetProfile); + return 0; +} + +int InitProfileModule() +{ + hTTBModuleLoadedHook = HookEvent(ME_TTB_MODULELOADED, CreateTopToolbarButtons); + + HookEvent(ME_CLIST_PREBUILDSTATUSMENU, CreateMainMenuItems); + + CreateMainMenuItems(0, 0); + RegisterHotKeys(); + return 0; +} + +int DeinitProfilesModule() +{ + arProfiles.destroy(); + + UnregisterHotKeys(); + RemoveTopToolbarButtons(); + return 0; +} diff --git a/plugins/StatusManager/src/ss_toolbars.cpp b/plugins/StatusManager/src/ss_toolbars.cpp new file mode 100644 index 0000000000..e264d0126c --- /dev/null +++ b/plugins/StatusManager/src/ss_toolbars.cpp @@ -0,0 +1,72 @@ +/* + StartupStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "stdafx.h" + +#define MAX_MMITEMS 6 + +static LIST ttbButtons(1); + +static IconItem iconList[] = +{ + { LPGEN("Pressed toolbar icon"), "StartupStatus/TtbDown", IDI_TTBDOWN }, + { LPGEN("Released toolbar icon"), "StartupStatus/TtbUp", IDI_TTBUP }, +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +void RemoveTopToolbarButtons() +{ + for (auto &it : ttbButtons.rev_iter()) + CallService(MS_TTB_REMOVEBUTTON, (WPARAM)it, 0); + ttbButtons.destroy(); +} + +int CreateTopToolbarButtons(WPARAM, LPARAM) +{ + if (iconList[0].hIcolib == nullptr) + g_plugin.registerIcon("Toolbar/StartupStatus", iconList); + + int profileCount = CallService(MS_SS_GETPROFILECOUNT, 0, 0); + + TTBButton ttb = {}; + ttb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP; + ttb.pszService = MS_SS_LOADANDSETPROFILE; + for (int i = 0; i < profileCount; i++) { + char setting[80]; + mir_snprintf(setting, "%d_%s", i, SETTING_CREATETTBBUTTON); + if (!db_get_b(0, SSMODULENAME, setting, FALSE)) + continue; + + DBVARIANT dbv; + mir_snprintf(setting, "%d_%s", i, SETTING_PROFILENAME); + if (db_get(0, SSMODULENAME, setting, &dbv)) + continue; + + ttb.hIconHandleDn = iconList[0].hIcolib; + ttb.hIconHandleUp = iconList[1].hIcolib; + ttb.wParamDown = ttb.wParamUp = i; + ttb.name = ttb.pszTooltipUp = dbv.pszVal; + HANDLE ttbAddResult = g_plugin.addTTB(&ttb); + if (ttbAddResult) + ttbButtons.insert(ttbAddResult); + db_free(&dbv); + } + return 0; +} diff --git a/plugins/StatusManager/src/startupstatus.cpp b/plugins/StatusManager/src/startupstatus.cpp new file mode 100644 index 0000000000..f315ddfc97 --- /dev/null +++ b/plugins/StatusManager/src/startupstatus.cpp @@ -0,0 +1,461 @@ +/* + StartupStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "stdafx.h" + +int SSLangPack; + +static HANDLE hServices[3], hEvents[3]; +static UINT_PTR setStatusTimerId = 0; + +///////////////////////////////////////////////////////////////////////////////////////// + +static HANDLE hProtoAckHook, hCSStatusChangeHook, hStatusChangeHook; + +static HWND hMessageWindow; + +static BYTE showDialogOnStartup = 0; + +///////////////////////////////////////////////////////////////////////////////////////// +// command line options + +static PROTOCOLSETTINGEX* IsValidProtocol(TProtoSettings &protoSettings, const char *protoName) +{ + for (auto &it : protoSettings) + if (!it->ssDisabled && !strncmp(it->m_szName, protoName, mir_strlen(it->m_szName))) + return it; + + return nullptr; +} + +static int IsValidStatusDesc(char* statusDesc) +{ + if (!strncmp("away", statusDesc, 4)) + return ID_STATUS_AWAY; + if (!strncmp("na", statusDesc, 2)) + return ID_STATUS_NA; + if (!strncmp("dnd", statusDesc, 3)) + return ID_STATUS_DND; + if (!strncmp("occupied", statusDesc, 8)) + return ID_STATUS_OCCUPIED; + if (!strncmp("freechat", statusDesc, 8)) + return ID_STATUS_FREECHAT; + if (!strncmp("online", statusDesc, 6)) + return ID_STATUS_ONLINE; + if (!strncmp("offline", statusDesc, 7)) + return ID_STATUS_OFFLINE; + if (!strncmp("invisible", statusDesc, 9)) + return ID_STATUS_INVISIBLE; + if (!strncmp("onthephone", statusDesc, 10)) + return ID_STATUS_ONTHEPHONE; + if (!strncmp("outtolunch", statusDesc, 10)) + return ID_STATUS_OUTTOLUNCH; + if (!strncmp("last", statusDesc, 4)) + return ID_STATUS_LAST; + + return 0; +} + +static void ProcessCommandLineOptions(TProtoSettings& protoSettings) +{ + if (protoSettings.getCount() == 0) + return; + + char *cmdl = GetCommandLineA(); + while (*cmdl != '\0') { + while (*cmdl != '/') { + if (*cmdl == '\0') + return; + + cmdl++; + } + if (*cmdl == '\0') + return; + + cmdl++; + if (!strncmp(cmdl, "showdialog", 10)) { + showDialogOnStartup = TRUE; + continue; + } + char *protoName = cmdl; // first protocol ? + PROTOCOLSETTINGEX* protoSetting = IsValidProtocol(protoSettings, protoName); + if (protoSetting != nullptr) { + while (*cmdl != '=') { + if (*cmdl == '\0') + return; + + cmdl++; // skip to status + } + + if (*cmdl == '\0') + return; + + cmdl++; + char *statusDesc = cmdl; + int status = IsValidStatusDesc(statusDesc); + if (status != 0) + protoSetting->m_status = status; + } + } +} + +static void SetLastStatusMessages(TProtoSettings &ps) +{ + for (auto &it : ps) { + if (it->m_status != ID_STATUS_LAST) + continue; + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s%s", PREFIX_LASTMSG, it->m_szName); + it->m_szMsg = db_get_wsa(0, SSMODULENAME, dbSetting); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Account control event + +// 'allow override' +static int ProcessProtoAck(WPARAM, LPARAM lParam) +{ + // 'something' made a status change + ACKDATA *ack = (ACKDATA*)lParam; + if (ack->type != ACKTYPE_STATUS && ack->result != ACKRESULT_FAILED) + return 0; + + if (!db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) || protoList.getCount() == 0) + return 0; + + for (auto &it : protoList) { + if (!mir_strcmp(ack->szModule, it->m_szName)) { + it->ssDisabled = true; + log_debugA("StartupStatus: %s overridden by ME_PROTO_ACK, status will not be set", ack->szModule); + } + } + + return 0; +} + +static int StatusChange(WPARAM, LPARAM lParam) +{ + // change by menu + if (!db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) || protoList.getCount() == 0) + return 0; + + char *szProto = (char *)lParam; + if (szProto == nullptr) { // global status change + for (auto &it : protoList) { + it->ssDisabled = true; + log_debugA("StartupStatus: all protos overridden by ME_CLIST_STATUSMODECHANGE, status will not be set"); + } + } + else { + for (auto &it : protoList) { + if (!mir_strcmp(it->m_szName, szProto)) { + it->ssDisabled = true; + log_debugA("StartupStatus: %s overridden by ME_CLIST_STATUSMODECHANGE, status will not be set", szProto); + } + } + } + + return 0; +} + +static int CSStatusChangeEx(WPARAM wParam, LPARAM) +{ + // another status plugin made the change + if (!db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1) || protoList.getCount() == 0) + return 0; + + if (wParam != 0) { + PROTOCOLSETTINGEX** ps = *(PROTOCOLSETTINGEX***)wParam; + if (ps == nullptr) + return -1; + + for (int i = 0; i < protoList.getCount(); i++) { + for (auto &it : protoList) { + if (ps[i]->m_szName == nullptr || it->m_szName == nullptr) + continue; + + if (!mir_strcmp(ps[i]->m_szName, it->m_szName)) { + log_debugA("StartupStatus: %s overridden by MS_CS_SETSTATUSEX, status will not be set", ps[i]->m_szName); + it->ssDisabled = true; + } + } + } + } + + return 0; +} + +static void CALLBACK SetStatusTimed(HWND, UINT, UINT_PTR, DWORD) +{ + KillTimer(nullptr, setStatusTimerId); + UnhookEvent(hProtoAckHook); + UnhookEvent(hCSStatusChangeHook); + UnhookEvent(hStatusChangeHook); + + TProtoSettings ps(protoList); + for (auto &it : ps) + if (it->ssDisabled) + it->m_status = ID_STATUS_DISABLED; + + SetStatusEx(ps); +} + +static int OnOkToExit(WPARAM, LPARAM) +{ + // save last protocolstatus + for (auto &pa : Accounts()) { + if (!IsSuitableProto(pa)) + continue; + + if (!Proto_GetAccount(pa->szModuleName)) + continue; + + char lastName[128], lastMsg[128]; + mir_snprintf(lastName, "%s%s", PREFIX_LAST, pa->szModuleName); + db_set_w(0, SSMODULENAME, lastName, pa->iRealStatus); + mir_snprintf(lastMsg, "%s%s", PREFIX_LASTMSG, pa->szModuleName); + db_unset(0, SSMODULENAME, lastMsg); + + if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND & ~PF1_INDIVMODEMSG)) + continue; + + if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(pa->iRealStatus))) + continue; + + // NewAwaySys + if (ServiceExists(MS_NAS_GETSTATE)) { + NAS_PROTOINFO npi = { sizeof(npi) }; + npi.szProto = pa->szModuleName; + CallService(MS_NAS_GETSTATE, (WPARAM)&npi, 1); + if (npi.szMsg == nullptr) { + npi.status = 0; + npi.szProto = nullptr; + CallService(MS_NAS_GETSTATE, (WPARAM)&npi, 1); + } + if (npi.szMsg != nullptr) { + db_set_ws(0, SSMODULENAME, lastMsg, npi.tszMsg); + mir_free(npi.tszMsg); + } + } + } + + if (db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1) || db_get_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, 0)) + Clist_SetStatusMode(ID_STATUS_OFFLINE); + + return 0; +} + +static int OnShutdown(WPARAM, LPARAM) +{ + // set windowstate and docked for next startup + if (db_get_b(0, SSMODULENAME, SETTING_SETWINSTATE, 0)) { + int state = db_get_b(0, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); + HWND hClist = g_clistApi.hwndContactList; + BOOL isHidden = !IsWindowVisible(hClist); + switch (state) { + case SETTING_STATE_HIDDEN: + // try to use services where possible + if (!isHidden) + g_clistApi.pfnShowHide(); + break; + + case SETTING_STATE_MINIMIZED: + if (!db_get_b(0, MODULE_CLIST, SETTING_TOOLWINDOW, 0)) + ShowWindow(hClist, SW_SHOWMINIMIZED); + break; + + case SETTING_STATE_NORMAL: + // try to use services where possible (that's what they're for) + if (isHidden) + g_clistApi.pfnShowHide(); + break; + } + } + + // hangup + if (db_get_b(0, SSMODULENAME, SETTING_AUTOHANGUP, 0)) + InternetAutodialHangup(0); + + int state = db_get_b(0, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); + // set windowstate and docked for next startup + if (db_get_b(0, SSMODULENAME, SETTING_SETWINSTATE, 0)) + db_set_b(0, MODULE_CLIST, SETTING_WINSTATE, (BYTE)state); + + if (hMessageWindow) + DestroyWindow(hMessageWindow); + + protoList.destroy(); + return 0; +} + +/* Window proc for poweroff event */ +static DWORD CALLBACK MessageWndProc(HWND, UINT msg, WPARAM wParam, LPARAM) +{ + switch (msg) { + case WM_ENDSESSION: + log_debugA("WM_ENDSESSION"); + if (wParam) { + log_debugA("WM_ENDSESSION: calling exit"); + OnShutdown(0, 0); + log_debugA("WM_ENDSESSION: exit called"); + } + break; + } + + return TRUE; +} + +int SSModuleLoaded(WPARAM, LPARAM) +{ + InitProfileModule(); + + hEvents[0] = HookEvent(ME_OPT_INITIALISE, StartupStatusOptionsInit); + + /* shutdown hook for normal shutdown */ + hEvents[1] = HookEvent(ME_SYSTEM_OKTOEXIT, OnOkToExit); + hEvents[2] = HookEvent(ME_SYSTEM_PRESHUTDOWN, OnShutdown); + /* message window for poweroff */ + hMessageWindow = CreateWindowEx(0, L"STATIC", nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr); + SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); + + GetProfile(-1, protoList); + + // override with cmdl + ProcessCommandLineOptions(protoList); + if (protoList.getCount() == 0) + return 0;// no protocols are loaded + + SetLastStatusMessages(protoList); + showDialogOnStartup = (showDialogOnStartup || db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, 0)); + + // dial + if (showDialogOnStartup || db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1)) + if (db_get_b(0, SSMODULENAME, SETTING_AUTODIAL, 0)) + InternetAutodial(0, nullptr); + + // set the status! + if (showDialogOnStartup || db_get_b(0, SSMODULENAME, SETTING_SHOWDIALOG, 0)) + ShowConfirmDialogEx((TProtoSettings*)&protoList, db_get_dw(0, SSMODULENAME, SETTING_DLGTIMEOUT, 5)); + else if (db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1)) { + // set hooks for override + if (db_get_b(0, SSMODULENAME, SETTING_OVERRIDE, 1)) { + hProtoAckHook = HookEvent(ME_PROTO_ACK, ProcessProtoAck); + hCSStatusChangeHook = HookEvent(ME_CS_STATUSCHANGEEX, CSStatusChangeEx); + hStatusChangeHook = HookEvent(ME_CLIST_STATUSMODECHANGE, StatusChange); + } + setStatusTimerId = SetTimer(nullptr, 0, db_get_dw(0, SSMODULENAME, SETTING_SETPROFILEDELAY, 500), SetStatusTimed); + } + + // win size and location + if (db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0) || db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0)) { + HWND hClist = g_clistApi.hwndContactList; + + // store in db + if (db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0)) { + db_set_dw(0, MODULE_CLIST, SETTING_XPOS, db_get_dw(0, SSMODULENAME, SETTING_XPOS, 0)); + db_set_dw(0, MODULE_CLIST, SETTING_YPOS, db_get_dw(0, SSMODULENAME, SETTING_YPOS, 0)); + } + if (db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0)) { + db_set_dw(0, MODULE_CLIST, SETTING_WIDTH, db_get_dw(0, SSMODULENAME, SETTING_WIDTH, 0)); + if (!db_get_b(0, MODULE_CLUI, SETTING_AUTOSIZE, 0)) + db_set_dw(0, MODULE_CLIST, SETTING_HEIGHT, db_get_dw(0, SSMODULENAME, SETTING_HEIGHT, 0)); + } + + WINDOWPLACEMENT wndpl = { sizeof(wndpl) }; + if (GetWindowPlacement(hClist, &wndpl)) { + if (wndpl.showCmd == SW_SHOWNORMAL && !Clist_IsDocked()) { + RECT rc; + if (GetWindowRect(hClist, &rc)) { + int x = rc.left; + int y = rc.top; + int width = rc.right - rc.left; + int height = rc.bottom - rc.top; + if (db_get_b(0, SSMODULENAME, SETTING_SETWINLOCATION, 0)) { + x = db_get_dw(0, SSMODULENAME, SETTING_XPOS, x); + y = db_get_dw(0, SSMODULENAME, SETTING_YPOS, y); + } + if (db_get_b(0, SSMODULENAME, SETTING_SETWINSIZE, 0)) { + width = db_get_dw(0, SSMODULENAME, SETTING_WIDTH, width); + if (!db_get_b(0, MODULE_CLUI, SETTING_AUTOSIZE, 0)) + height = db_get_dw(0, SSMODULENAME, SETTING_HEIGHT, height); + } + MoveWindow(hClist, x, y, width, height, TRUE); + } + } + } + } + + return 0; +} + +static INT_PTR SrvGetProfile(WPARAM wParam, LPARAM lParam) +{ + return GetProfile((int)wParam, *(TProtoSettings*)lParam); +} + +void StartupStatusLoad() +{ + SSLangPack = GetPluginLangId(MIID_LAST, 0); + + if (g_bMirandaLoaded) + SSModuleLoaded(0, 0); + else + HookEvent(ME_SYSTEM_MODULESLOADED, SSModuleLoaded); + + if (db_get_b(0, SSMODULENAME, SETTING_SETPROFILE, 1) || db_get_b(0, SSMODULENAME, SETTING_OFFLINECLOSE, 0)) + db_set_w(0, "CList", "Status", (WORD)ID_STATUS_OFFLINE); + + // docking + if (db_get_b(0, SSMODULENAME, SETTING_SETDOCKED, 0)) { + int docked = db_get_b(0, SSMODULENAME, SETTING_DOCKED, DOCKED_NONE); + if (docked == DOCKED_LEFT || docked == DOCKED_RIGHT) + docked = -docked; + + db_set_b(0, MODULE_CLIST, SETTING_DOCKED, (BYTE)docked); + } + + // Create service functions; the get functions are created here; they don't rely on commonstatus + hServices[0] = CreateServiceFunction(MS_SS_GETPROFILE, SrvGetProfile); + hServices[1] = CreateServiceFunction(MS_SS_GETPROFILECOUNT, GetProfileCount); + hServices[2] = CreateServiceFunction(MS_SS_GETPROFILENAME, GetProfileName); + + LoadProfileModule(); +} + +void StartupStatusUnload() +{ + if (g_bMirandaLoaded) + OnShutdown(0, 0); + + KillModuleOptions(SSLangPack); + + for (auto &it : hServices) { + DestroyServiceFunction(it); + it = nullptr; + } + + for (auto &it : hEvents) { + UnhookEvent(it); + it = nullptr; + } + + DeinitProfilesModule(); +} diff --git a/plugins/StatusManager/src/startupstatus.h b/plugins/StatusManager/src/startupstatus.h new file mode 100644 index 0000000000..5d16d50843 --- /dev/null +++ b/plugins/StatusManager/src/startupstatus.h @@ -0,0 +1,138 @@ +/* + StartupStatus Plugin for Miranda-IM (www.miranda-im.org) + Copyright 2003-2006 P. Boon + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef __STARTUPSTATUSHEADER +#define __STARTUPSTATUSHEADER + +#define SSMODULENAME "StartupStatus" + +struct PROFILEOPTIONS : public MZeroedObject +{ + __inline PROFILEOPTIONS() : + ps(protoList) + {} + + __inline ~PROFILEOPTIONS() + { + mir_free(tszName); + } + + wchar_t *tszName; + TProtoSettings ps; + BOOL showDialog; + BOOL createTtb; + BOOL createMmi; + BOOL inSubMenu; + BOOL regHotkey; + WORD hotKey; +}; + +typedef struct { + ATOM id; + int profile; +} HKINFO; + +#define UM_REINITPROFILES WM_USER + 1 +#define UM_ADDPROFILE WM_USER + 5 +#define UM_REINITDOCKED WM_USER + 7 +#define UM_REINITWINSTATE WM_USER + 8 +#define UM_REINITWINSIZE WM_USER + 9 + +#define CLUIINTM_REDRAW (WM_USER+100) + +#define MODULE_CLIST "CList" +#define MODULE_CLUI "CLUI" +#define SETTING_STATUS "Status" + +#define SETTING_SETWINSTATE "SetState" +#define SETTING_WINSTATE "State" + +#define SETTING_SETDOCKED "SetDocked" +#define SETTING_DOCKED "Docked" + +#define SETTING_SHOWDIALOG "ShowDialog" +#define SETTING_OFFLINECLOSE "OfflineOnClose" +#define SETTING_SETPROFILE "SetStatusOnStartup" +#define SETTING_AUTODIAL "AutoDial" +#define SETTING_AUTOHANGUP "AutoHangup" + +#define SETTING_TOOLWINDOW "ToolWindow" + +#define SETTING_OVERRIDE "AllowOverride" + +#define SETTING_SETWINLOCATION "SetWinLoc" +#define SETTING_XPOS "x" +#define SETTING_YPOS "y" + +#define SETTING_SETWINSIZE "SetWinSize" +#define SETTING_WIDTH "Width" +#define SETTING_HEIGHT "Height" +#define SETTING_AUTOSIZE "AutoSize" + +#define SETTING_PROFILECOUNT "ProfileCount" +#define SETTING_DEFAULTPROFILE "DefaultProfile" +#define SETTING_PROFILENAME "ProfileName" +#define SETTING_CREATETTBBUTTON "CreateTTBButton" +#define SETTING_PROFILE_STSMSG "StatusMsg" +#define SETTING_SHOWCONFIRMDIALOG "profile_ShowDialog" +#define SETTING_CREATEMMITEM "CreateMMItem" +#define SETTING_INSUBMENU "InSubMenu" +#define SETTING_REGHOTKEY "RegHotKey" +#define SETTING_HOTKEY "HotKey" +#define SETTING_PROFILENO "ProfileNo" + +#define SETTING_SETPROFILEDELAY "SetStatusDelay" +#define SETTING_DLGTIMEOUT "DialogTimeout" + +#define SHORTCUT_DESC L"Miranda NG" +#define SHORTCUT_FILENAME L"\\Miranda NG.lnk" + +#define DOCKED_NONE 0 +#define DOCKED_LEFT 1 +#define DOCKED_RIGHT 2 + +#define MS_SS_MENUSETPROFILEPREFIX "StartupStatus/SetProfile_" + +// options +int StartupStatusOptionsInit(WPARAM wparam,LPARAM lparam); +char* OptName(int i, const char *setting); + +// startupstatus +void StartupStatusLoad(); +void StartupStatusUnload(); + +int SSLoadMainOptions(); + +// profile +void FillStatus(SMProto &ps, int profile); +int GetProfile(int profileID, TProtoSettings &arSettings); +wchar_t* GetStatusMessage(int profile, const char *szProto); + +INT_PTR LoadAndSetProfile(WPARAM wParam, LPARAM lParam); +INT_PTR GetProfileCount(WPARAM wParam, LPARAM lParam); +INT_PTR GetProfileName(WPARAM wParam, LPARAM lParam); + +extern HANDLE hTTBModuleLoadedHook; +void RemoveTopToolbarButtons(); +int CreateTopToolbarButtons(WPARAM wParam, LPARAM lParam); + +int LoadProfileModule(); +int InitProfileModule(); +int DeinitProfilesModule(); + +#endif //__STARTUPSTATUSHEADER diff --git a/plugins/StatusManager/src/stdafx.h b/plugins/StatusManager/src/stdafx.h index 6767d08ef4..e9343eab16 100644 --- a/plugins/StatusManager/src/stdafx.h +++ b/plugins/StatusManager/src/stdafx.h @@ -38,9 +38,9 @@ struct CMPlugin : public PLUGIN }; #include "commonstatus.h" -#include "KeepStatus\keepstatus.h" -#include "StartupStatus\startupstatus.h" -#include "AdvancedAutoAway\advancedautoaway.h" +#include "keepstatus.h" +#include "startupstatus.h" +#include "advancedautoaway.h" extern bool g_bMirandaLoaded; extern int AAALangPack, KSLangPack, SSLangPack; -- cgit v1.2.3