diff options
author | aunsane <aunsane@gmail.com> | 2017-01-06 16:19:32 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2017-01-06 20:10:47 +0300 |
commit | b7336b2fc97092442ce643532f67466868a87812 (patch) | |
tree | 718b87c37090fe8bf7ae88b9d5da9b3b957c3e3c /plugins/StatusManager/src/StartupStatus | |
parent | ac1d88965de3022be2f484c2f58185ae75b4fe00 (diff) |
StatusManager: #662
- files splitted by folders
- main.cpp cleanup
- project cleanup
Diffstat (limited to 'plugins/StatusManager/src/StartupStatus')
5 files changed, 2039 insertions, 0 deletions
diff --git a/plugins/StatusManager/src/StartupStatus/ss_options.cpp b/plugins/StatusManager/src/StartupStatus/ss_options.cpp new file mode 100644 index 0000000000..644be1f1e6 --- /dev/null +++ b/plugins/StatusManager/src/StartupStatus/ss_options.cpp @@ -0,0 +1,929 @@ +/* + 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" + +///////////////////////////////////////////////////////////////////////////////////////// + +TSettingsList* GetCurrentProtoSettings() +{ + int count; + PROTOACCOUNT **protos; + Proto_EnumAccounts(&count, &protos); + + TSettingsList *result = new TSettingsList(count, SSCompareSettings); + if (result == NULL) + return NULL; + + for (int i=0; i < count; i++) + if ( IsSuitableProto(protos[i])) + result->insert( new TSSSetting(protos[i])); + + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// 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(TSettingsList& protoSettings) +{ + if ( protoSettings.getCount() == NULL ) + return NULL; + + char *cmdl, *pnt; + pnt = cmdl = ( char* )malloc(mir_strlen(protoSettings[0].szName) + mir_strlen(GetStatusDesc(protoSettings[0].status)) + 4); + + for (int i=0; i < protoSettings.getCount(); i++ ) { + *pnt++ = '/'; + mir_strcpy(pnt, protoSettings[i].szName); + pnt += mir_strlen(protoSettings[i].szName); + *pnt++ = '='; + mir_strcpy(pnt, GetStatusDesc(protoSettings[i].status)); + pnt += mir_strlen(GetStatusDesc(protoSettings[i].status)); + if (i != protoSettings.getCount()-1) { + *pnt++ = ' '; + *pnt++ = '\0'; + cmdl = ( char* )realloc(cmdl, mir_strlen(cmdl) + mir_strlen(protoSettings[i+1].szName) + mir_strlen(GetStatusDesc(protoSettings[i+1].status)) + 4); + pnt = cmdl + mir_strlen(cmdl); + } } + + if ( db_get_b( NULL, SSMODULENAME, SETTING_SHOWDIALOG, FALSE ) == TRUE ) { + *pnt++ = ' '; + *pnt++ = '\0'; + cmdl = ( char* )realloc(cmdl, mir_strlen(cmdl) + 12); + pnt = cmdl + mir_strlen(cmdl); + mir_strcpy(pnt, "/showdialog"); + pnt += 11; + *pnt = '\0'; + } + + return cmdl; +} + +static char* GetCMDL(TSettingsList& protoSettings) +{ + char path[MAX_PATH]; + GetModuleFileNameA(NULL, path, MAX_PATH); + + char* cmdl = ( char* )malloc(mir_strlen(path) + 4); + mir_snprintf(cmdl, mir_strlen(path) + 4, "\"%s\" ", path); + + char* args = GetCMDLArguments(protoSettings); + if ( args ) { + cmdl = ( char* )realloc(cmdl, mir_strlen(cmdl) + mir_strlen(args) + 1); + mir_strcat(cmdl, args); + free(args); + } + return cmdl; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Link processing + +static wchar_t* GetLinkDescription(TSettingsList& protoSettings) +{ + if ( protoSettings.getCount() == 0 ) + return NULL; + + CMStringW result(SHORTCUT_DESC); + for (int i=0; i < protoSettings.getCount(); i++) { + TSSSetting &p = protoSettings[i]; + + wchar_t *status; + if ( p.status == ID_STATUS_LAST) + status = TranslateT("<last>"); + else if (p.status == ID_STATUS_CURRENT) + status = TranslateT("<current>"); + else if (p.status >= MIN_STATUS && p.status <= MAX_STATUS) + status = pcli->pfnGetStatusModeDescription(p.status, 0); + else + status = NULL; + if (status == NULL) + status = TranslateT("<unknown>"); + + result.AppendChar('\r'); + result.Append(p.tszAccName); + result.AppendChar(':'); + result.AppendChar(' '); + result.Append(status); + } + + return mir_wstrndup(result, result.GetLength()); +} + +HRESULT CreateLink(TSettingsList& protoSettings) +{ + wchar_t savePath[MAX_PATH]; + if (SHGetSpecialFolderPath(NULL, savePath, 0x10, 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, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, ( void** )&psl); + if (SUCCEEDED(hres)) { + char *args = GetCMDLArguments(protoSettings); + wchar_t *desc = GetLinkDescription(protoSettings); + + // Set the path to the shortcut target, and add the + // description. + wchar_t path[MAX_PATH]; + GetModuleFileName(NULL, 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(); + free(args); + free(desc); + } + + return hres; +} + +INT_PTR CALLBACK CmdlOptionsDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + static TSettingsList* optionsProtoSettings; + + switch(msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + optionsProtoSettings = (TSettingsList*)lParam; + char* cmdl = GetCMDL(*optionsProtoSettings); + SetDlgItemTextA(hwndDlg, IDC_CMDL, cmdl); + free(cmdl); + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_COPY: + if ( OpenClipboard( hwndDlg )) { + EmptyClipboard(); + + char cmdl[2048]; + GetDlgItemTextA(hwndDlg,IDC_CMDL, cmdl, _countof(cmdl)); + HGLOBAL cmdlGlob = GlobalAlloc(GMEM_MOVEABLE, sizeof(cmdl)); + if (cmdlGlob == NULL) { + CloseClipboard(); + break; + } + LPTSTR cmdlStr = ( LPTSTR )GlobalLock(cmdlGlob); + memcpy(cmdlStr, &cmdl, sizeof(cmdl)); + GlobalUnlock(cmdlGlob); + SetClipboardData(CF_TEXT, cmdlGlob); + CloseClipboard(); + } + break; + + case IDC_SHORTCUT: + CreateLink(*optionsProtoSettings); + break; + + case IDC_OK: + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + delete optionsProtoSettings; optionsProtoSettings = 0; + break; + } + + return 0; +} + +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(NULL, SSMODULENAME, SETTING_SETPROFILE, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OVERRIDE, db_get_b(NULL, SSMODULENAME, SETTING_OVERRIDE, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWDIALOG, db_get_b(NULL, SSMODULENAME, SETTING_SHOWDIALOG, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETWINSTATE, db_get_b(NULL, SSMODULENAME, SETTING_SETWINSTATE, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETWINLOCATION, db_get_b(NULL, SSMODULENAME, SETTING_SETWINLOCATION, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETDOCKED, db_get_b(NULL, SSMODULENAME, SETTING_SETDOCKED, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SETWINSIZE, db_get_b(NULL, SSMODULENAME, SETTING_SETWINSIZE, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_OFFLINECLOSE, db_get_b(NULL, SSMODULENAME, SETTING_OFFLINECLOSE, 1) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTODIAL, db_get_b(NULL, SSMODULENAME, SETTING_AUTODIAL, 0) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOHANGUP, db_get_b(NULL, SSMODULENAME, SETTING_AUTOHANGUP, 0) ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(hwndDlg, IDC_SETPROFILEDELAY, db_get_dw(NULL, SSMODULENAME, SETTING_SETPROFILEDELAY, 500), FALSE); + SetDlgItemInt(hwndDlg, IDC_DLGTIMEOUT, db_get_dw(NULL, SSMODULENAME, SETTING_DLGTIMEOUT, 5), FALSE); + SetDlgItemInt(hwndDlg, IDC_XPOS, db_get_dw(NULL, SSMODULENAME, SETTING_XPOS, 0), TRUE); + SetDlgItemInt(hwndDlg, IDC_YPOS, db_get_dw(NULL, SSMODULENAME, SETTING_YPOS, 0), TRUE); + SetDlgItemInt(hwndDlg, IDC_WIDTH, db_get_dw(NULL, SSMODULENAME, SETTING_WIDTH, 0), FALSE); + SetDlgItemInt(hwndDlg, IDC_HEIGHT, db_get_dw(NULL, SSMODULENAME, SETTING_HEIGHT, 0), FALSE); + { + int val = db_get_b(NULL, 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, NULL); + 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(NULL, MODULE_CLIST, SETTING_WIDTH, 0), + db_get_dw(NULL, MODULE_CLIST, SETTING_HEIGHT, 0)); + SetDlgItemText(hwndDlg, IDC_CURWINSIZE, text); + + mir_snwprintf(text, TranslateT("loc: %d x %d"), + db_get_dw(NULL, MODULE_CLIST, SETTING_XPOS, 0), + db_get_dw(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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); + + TSettingsList* ps = GetCurrentProtoSettings(); + if ( ps ) { + GetProfile( defProfile, *ps ); + for ( int i=0; i < ps->getCount(); i++ ) + if ( (*ps)[i].szMsg != NULL ) + (*ps)[i].szMsg = wcsdup( (*ps)[i].szMsg ); + + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CMDLOPTIONS), hwndDlg, CmdlOptionsDlgProc, (LPARAM)ps); + } + 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: + if (((LPNMHDR)lParam)->code == PSN_APPLY) { + int val; + + db_set_b(NULL, SSMODULENAME, SETTING_SETPROFILE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE)) + db_set_dw(NULL, SSMODULENAME, SETTING_SETPROFILEDELAY, GetDlgItemInt(hwndDlg, IDC_SETPROFILEDELAY, NULL, FALSE)); + + if (IsDlgButtonChecked(hwndDlg, IDC_SETPROFILE) || IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)) { + val = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); + db_set_w(NULL, SSMODULENAME, SETTING_DEFAULTPROFILE, (WORD)val); + } + db_set_b(NULL, SSMODULENAME, SETTING_OVERRIDE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_OVERRIDE)); + db_set_b(NULL, SSMODULENAME, SETTING_SHOWDIALOG, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)); + if (IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG)) + db_set_dw(NULL, SSMODULENAME, SETTING_DLGTIMEOUT, GetDlgItemInt(hwndDlg, IDC_DLGTIMEOUT, NULL, FALSE)); + + db_set_b(NULL, SSMODULENAME, SETTING_SETWINSTATE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETWINSTATE)) { + val = (int)SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_WINSTATE, CB_GETCURSEL, 0, 0), 0); + db_set_b(NULL, SSMODULENAME, SETTING_WINSTATE, (BYTE)val); + } + db_set_b(NULL, SSMODULENAME, SETTING_SETDOCKED, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETDOCKED)) { + val = (int)SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_DOCKED, CB_GETCURSEL, 0, 0), 0); + db_set_b(NULL, SSMODULENAME, SETTING_DOCKED, (BYTE)val); + } + db_set_b(NULL, SSMODULENAME, SETTING_SETWINLOCATION, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETWINLOCATION)) { + db_set_dw(NULL, SSMODULENAME, SETTING_XPOS, GetDlgItemInt(hwndDlg, IDC_XPOS, NULL, TRUE)); + db_set_dw(NULL, SSMODULENAME, SETTING_YPOS, GetDlgItemInt(hwndDlg, IDC_YPOS, NULL, TRUE)); + } + db_set_b(NULL, SSMODULENAME, SETTING_SETWINSIZE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)); + if (IsDlgButtonChecked(hwndDlg, IDC_SETWINSIZE)) { + db_set_dw(NULL, SSMODULENAME, SETTING_WIDTH, GetDlgItemInt(hwndDlg, IDC_WIDTH, NULL, FALSE)); + db_set_dw(NULL, SSMODULENAME, SETTING_HEIGHT, GetDlgItemInt(hwndDlg, IDC_HEIGHT, NULL, FALSE)); + } + db_set_b(NULL, SSMODULENAME, SETTING_OFFLINECLOSE, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_OFFLINECLOSE)); + db_set_b(NULL, SSMODULENAME, SETTING_AUTODIAL, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_AUTODIAL)); + db_set_b(NULL, SSMODULENAME, SETTING_AUTOHANGUP, (BYTE)IsDlgButtonChecked(hwndDlg, IDC_AUTOHANGUP)); + } + break; + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////// +// for db cleanup + +static int DeleteSetting(const char *szSetting, LPARAM lParam) +{ + LIST<char> *p = (LIST<char> *)lParam; + p->insert(mir_strdup(szSetting)); + return 0; +} + +static int ClearDatabase(char* filter) +{ + LIST<char> arSettings(10); + db_enum_settings(NULL, DeleteSetting, SSMODULENAME, &arSettings); + + for (int i = 0; i < arSettings.getCount(); i++) { + if ((filter == NULL) || (!strncmp(filter, arSettings[i], mir_strlen(filter)))) + db_unset(NULL, SSMODULENAME, arSettings[i]); + mir_free(arSettings[i]); + } + + if (filter == NULL) + db_unset(NULL, "AutoAway", "Confirm"); + + return 0; +} + + +static OBJLIST<PROFILEOPTIONS> arProfiles(5); + +INT_PTR CALLBACK addProfileDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HWND hwndParent; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + hwndParent = (HWND)lParam; + EnableWindow(GetDlgItem(hwndDlg, IDC_OK), FALSE); + break; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_OK) { + wchar_t profileName[128]; + GetDlgItemText(hwndDlg, IDC_PROFILENAME, profileName, _countof(profileName)); + SendMessage(hwndParent, UM_ADDPROFILE, 0, (LPARAM)profileName); + // done and exit + DestroyWindow(hwndDlg); + } + else if (LOWORD(wParam) == IDC_CANCEL) { + DestroyWindow(hwndDlg); + } + else if (LOWORD(wParam) == IDC_PROFILENAME) { + (SendDlgItemMessage(hwndDlg, IDC_PROFILENAME, EM_LINELENGTH, 0, 0) > 0) ? EnableWindow(GetDlgItem(hwndDlg, IDC_OK), TRUE) : EnableWindow(GetDlgItem(hwndDlg, IDC_OK), FALSE); + } + break; + + case WM_DESTROY: + EnableWindow(hwndParent, TRUE); + break; + } + + return 0; +} + +static INT_PTR CALLBACK StatusProfilesOptDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + static BOOL bNeedRebuildMenu = FALSE; + static BOOL bInitDone = FALSE; + + switch(msg) { + case WM_INITDIALOG: + bInitDone = false; + + TranslateDialogDefault(hwndDlg); + SetDlgItemText(hwndDlg, IDC_CREATEMMI, TranslateT("Create a status menu item")); + { + int defProfile; + int profileCount = GetProfileCount((WPARAM)&defProfile, 0); + if (profileCount == 0) { + profileCount = 1; + defProfile = 0; + } + + for (int i=0; i < profileCount; i++) { + PROFILEOPTIONS *ppo = new PROFILEOPTIONS; + ppo->ps = GetCurrentProtoSettings(); + TSettingsList& 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 { + for (int j=0; j < ar.getCount(); j++) + if ( ar[j].szMsg != NULL) + ar[j].szMsg = wcsdup( ar[j].szMsg ); + + ppo->tszName = db_get_wsa(NULL, SSMODULENAME, OptName(i, SETTING_PROFILENAME)); + if (ppo->tszName == NULL) { + if (i == defProfile) + ppo->tszName = mir_wstrdup( TranslateT("default")); + else + ppo->tszName = mir_wstrdup( TranslateT("unknown")); + } + ppo->createTtb = db_get_b(NULL, SSMODULENAME, OptName(i, SETTING_CREATETTBBUTTON), 0); + ppo->showDialog = db_get_b(NULL, SSMODULENAME, OptName(i, SETTING_SHOWCONFIRMDIALOG), 0); + ppo->createMmi = db_get_b(NULL, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), 0); + ppo->inSubMenu = db_get_b(NULL, SSMODULENAME, OptName(i, SETTING_INSUBMENU), 1); + ppo->regHotkey = db_get_b(NULL, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), 0); + ppo->hotKey = db_get_w(NULL, SSMODULENAME, OptName(i, SETTING_HOTKEY), MAKEWORD((char)('0'+i), HOTKEYF_CONTROL|HOTKEYF_SHIFT)); + } + arProfiles.insert(ppo); + } + if (hTTBModuleLoadedHook == NULL) + EnableWindow(GetDlgItem(hwndDlg, IDC_CREATETTB), FALSE); + + SendMessage(hwndDlg, UM_REINITPROFILES, 0, 0); + ShowWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), ServiceExists(MS_VARS_SHOWHELPEX)?SW_SHOW:SW_HIDE); + bInitDone = true; + } + break; + + case UM_REINITPROFILES: + bInitDone = false; + { + // creates profile combo box according to 'dat' + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_RESETCONTENT, 0, 0); + for (int i=0; i < arProfiles.getCount(); i++ ) { + int item = SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_ADDSTRING, 0, (LPARAM)arProfiles[i].tszName); + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETITEMDATA, (WPARAM)item, (LPARAM)i); + } + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETCURSEL, 0, 0); + SendMessage(hwndDlg, UM_SETPROFILE, 0, 0); + } + bInitDone = true; + break; + + case UM_SETPROFILE: + { + int sel = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); + CheckDlgButton(hwndDlg, IDC_CREATETTB, arProfiles[sel].createTtb ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SHOWDIALOG, arProfiles[sel].showDialog ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_CREATEMMI, arProfiles[sel].createMmi ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_INSUBMENU, arProfiles[sel].inSubMenu ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_INSUBMENU), IsDlgButtonChecked(hwndDlg, IDC_CREATEMMI)); + CheckDlgButton(hwndDlg, IDC_REGHOTKEY, arProfiles[sel].regHotkey ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_HOTKEY, HKM_SETHOTKEY, arProfiles[sel].hotKey, 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), IsDlgButtonChecked(hwndDlg, IDC_REGHOTKEY)); + SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_RESETCONTENT, 0, 0); + + // fill proto list + TSettingsList& ar = *arProfiles[sel].ps; + for ( int i=0; i < ar.getCount(); i++ ) { + int item = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_ADDSTRING, 0, (LPARAM)ar[i].tszAccName ); + SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_SETITEMDATA, (WPARAM)item, (LPARAM)&ar[i]); + } + SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_SETCURSEL, 0, 0); + SendMessage(hwndDlg, UM_SETPROTOCOL, 0, 0); + } + break; + + case UM_SETPROTOCOL: + { + int idx = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETCURSEL, 0, 0); + if ( idx != -1 ) { + // fill status box + TSSSetting* ps = ( TSSSetting* )SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETITEMDATA, idx, 0); + + int flags = (CallProtoService(ps->szName, PS_GETCAPS, PFLAGNUM_2, 0))&~(CallProtoService(ps->szName, PS_GETCAPS, PFLAGNUM_5, 0)); + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_RESETCONTENT, 0, 0); + for ( int i=0; i < _countof(statusModeList); i++ ) { + if ( (flags&statusModePf2List[i]) || (statusModeList[i] == ID_STATUS_OFFLINE)) { + int item = SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_ADDSTRING, 0, (LPARAM)pcli->pfnGetStatusModeDescription(statusModeList[i], 0)); + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_SETITEMDATA, (WPARAM)item, (LPARAM)statusModeList[i]); + if (ps->status == statusModeList[i]) + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_SETCURSEL, (WPARAM)item, 0); + } + } + + int item = SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_ADDSTRING, 0, (LPARAM)TranslateT("<current>")); + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_SETITEMDATA, (WPARAM)item, (LPARAM)ID_STATUS_CURRENT); + if (ps->status == ID_STATUS_CURRENT) + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_SETCURSEL, (WPARAM)item, 0); + + item = SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_ADDSTRING, 0, (LPARAM)TranslateT("<last>")); + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_SETITEMDATA, (WPARAM)item, (LPARAM)ID_STATUS_LAST); + if (ps->status == ID_STATUS_LAST) + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_SETCURSEL, (WPARAM)item, 0); + } + + SendMessage(hwndDlg, UM_SETSTATUSMSG, 0, 0); + } + break; + + case UM_SETSTATUSMSG: + { + // set status message + BOOL bStatusMsg = FALSE; + int idx = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETCURSEL, 0, 0); + if ( idx != -1 ) { + TSSSetting* ps = ( TSSSetting* )SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETITEMDATA, idx, 0); + + CheckRadioButton(hwndDlg, IDC_MIRANDAMSG, IDC_CUSTOMMSG, ps->szMsg!=NULL?IDC_CUSTOMMSG:IDC_MIRANDAMSG); + if (ps->szMsg != NULL) + SetDlgItemText(hwndDlg, IDC_STATUSMSG, ps->szMsg); + + bStatusMsg = ( (((CallProtoService(ps->szName, PS_GETCAPS, PFLAGNUM_1, 0)&PF1_MODEMSGSEND&~PF1_INDIVMODEMSG)) && + (CallProtoService(ps->szName, PS_GETCAPS, PFLAGNUM_3, 0)&Proto_Status2Flag(ps->status))) || (ps->status == ID_STATUS_CURRENT) || (ps->status == ID_STATUS_LAST)); + } + EnableWindow(GetDlgItem(hwndDlg, IDC_MIRANDAMSG), bStatusMsg); + EnableWindow(GetDlgItem(hwndDlg, IDC_CUSTOMMSG), bStatusMsg); + EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSMSG), bStatusMsg&&IsDlgButtonChecked(hwndDlg, IDC_CUSTOMMSG)); + EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLESHELP), bStatusMsg&&IsDlgButtonChecked(hwndDlg, IDC_CUSTOMMSG)); + } + break; + + case UM_ADDPROFILE: + { + wchar_t *tszName = (wchar_t*)lParam; + if (tszName == NULL) + break; + + PROFILEOPTIONS* ppo = new PROFILEOPTIONS; + ppo->tszName = mir_wstrdup(tszName); + ppo->ps = GetCurrentProtoSettings(); + arProfiles.insert(ppo); + + SendMessage(hwndDlg, UM_REINITPROFILES, 0, 0); + } + break; + + case UM_DELPROFILE: { + // wparam == profile no + int i=(int)wParam; + + if ( arProfiles.getCount() == 1) { + MessageBox(NULL, TranslateT("At least one profile must exist"), TranslateT("Status manager"), MB_OK); + break; + } + + arProfiles.remove(i); + + int defProfile; + GetProfileCount((WPARAM)&defProfile, 0); + if (i == defProfile) { + MessageBox(NULL, TranslateT("Your default profile will be changed"), TranslateT("Status manager"), MB_OK); + db_set_w(NULL, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + } + SendMessage(hwndDlg, UM_REINITPROFILES, 0, 0); + break; + } + + case WM_COMMAND: + if ( ((HIWORD(wParam) == EN_CHANGE) || (HIWORD(wParam) == BN_CLICKED) || (HIWORD(wParam) == LBN_SELCHANGE)) && ((HWND)lParam == GetFocus())) + if ( bInitDone ) + SendMessage(GetParent(hwndDlg),PSM_CHANGED,0,0); + + switch (LOWORD(wParam)) { + case IDC_STATUS: + if (HIWORD(wParam) == LBN_SELCHANGE) { + int idx = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETCURSEL, 0, 0); + if ( idx != -1 ) { + TSSSetting* ps = ( TSSSetting* )SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETITEMDATA, idx, 0); + ps->status = (int)SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_STATUS, LB_GETCURSEL, 0, 0), 0); + } + SendMessage(hwndDlg, UM_SETSTATUSMSG, 0, 0); + } + break; + + case IDC_PROFILE: + if (HIWORD(wParam) != CBN_SELCHANGE) + break; + + SendMessage(hwndDlg, UM_SETPROFILE, 0, 0); + break; + + case IDC_PROTOCOL: + if (HIWORD(wParam) != LBN_SELCHANGE) + break; + + SendMessage(hwndDlg, UM_SETPROTOCOL, 0, 0); + break; + + case IDC_MIRANDAMSG: + case IDC_CUSTOMMSG: + { + int len; + TSSSetting* ps = ( TSSSetting* )SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETCURSEL, 0, 0), 0); + if (ps->szMsg != NULL) + free(ps->szMsg); + + ps->szMsg = NULL; + if (IsDlgButtonChecked(hwndDlg, IDC_CUSTOMMSG)) { + len = SendDlgItemMessage(hwndDlg, IDC_STATUSMSG, WM_GETTEXTLENGTH, 0, 0); + ps->szMsg = (wchar_t*)calloc(sizeof(wchar_t), len+1); + GetDlgItemText(hwndDlg, IDC_STATUSMSG, ps->szMsg, (len + 1)); + } + SendMessage(hwndDlg, UM_SETSTATUSMSG, 0, 0); + } + break; + + case IDC_STATUSMSG: + if (HIWORD(wParam) == EN_CHANGE) { + // update the status message in memory, this is done on each character tick, not nice + // but it works + TSSSetting* ps = ( TSSSetting* )SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, LB_GETCURSEL, 0, 0), 0); + if (ps->szMsg != NULL) { + if ( *ps->szMsg ) + free(ps->szMsg); + ps->szMsg = NULL; + } + int len = SendDlgItemMessage(hwndDlg, IDC_STATUSMSG, WM_GETTEXTLENGTH, 0, 0); + ps->szMsg = (wchar_t*)calloc(sizeof(wchar_t), len+1); + GetDlgItemText(hwndDlg, IDC_STATUSMSG, ps->szMsg, (len + 1)); + } + break; + + case IDC_CREATEMMI: + EnableWindow(GetDlgItem(hwndDlg, IDC_INSUBMENU), IsDlgButtonChecked(hwndDlg, IDC_CREATEMMI)); + case IDC_INSUBMENU: + bNeedRebuildMenu = TRUE; + case IDC_REGHOTKEY: + case IDC_CREATETTB: + case IDC_SHOWDIALOG: + { + int sel = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); + PROFILEOPTIONS& po = arProfiles[sel]; + po.createMmi = IsDlgButtonChecked(hwndDlg, IDC_CREATEMMI); + po.inSubMenu = IsDlgButtonChecked(hwndDlg, IDC_INSUBMENU); + po.createTtb = IsDlgButtonChecked(hwndDlg, IDC_CREATETTB); + po.regHotkey = IsDlgButtonChecked(hwndDlg, IDC_REGHOTKEY); + po.showDialog = IsDlgButtonChecked(hwndDlg, IDC_SHOWDIALOG); + EnableWindow(GetDlgItem(hwndDlg, IDC_HOTKEY), IsDlgButtonChecked(hwndDlg, IDC_REGHOTKEY)); + } + break; + + case IDC_HOTKEY: + if (HIWORD(wParam) == EN_CHANGE) { + int sel = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); + arProfiles[sel].hotKey = (WORD)SendDlgItemMessage(hwndDlg, IDC_HOTKEY, HKM_GETHOTKEY, 0, 0); + } + break; + + case IDC_ADDPROFILE: + // add a profile + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ADDPROFILE), hwndDlg, addProfileDlgProc, (LPARAM)hwndDlg); + EnableWindow(hwndDlg, FALSE); + break; + + case IDC_DELPROFILE: + { + int sel = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, + SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); + SendMessage(hwndDlg, UM_DELPROFILE, (WPARAM)sel, 0); + } + break; + + case IDC_VARIABLESHELP: + variables_showhelp(hwndDlg, IDC_STATUSMSG, VHF_INPUT|VHF_EXTRATEXT|VHF_HELP|VHF_FULLFILLSTRUCT|VHF_HIDESUBJECTTOKEN, NULL, "Protocol ID"); + break; + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->code == PSN_APPLY) { + char setting[128]; + int oldCount = db_get_w(NULL, SSMODULENAME, SETTING_PROFILECOUNT, 0); + for (int i=0; i < oldCount; i++) { + mir_snprintf(setting, "%d_", i); + ClearDatabase(setting); + } + for (int i=0; i < arProfiles.getCount(); i++) { + PROFILEOPTIONS& po = arProfiles[i]; + db_set_b(NULL, SSMODULENAME, OptName(i, SETTING_SHOWCONFIRMDIALOG), po.showDialog); + db_set_b(NULL, SSMODULENAME, OptName(i, SETTING_CREATETTBBUTTON), po.createTtb); + db_set_b(NULL, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), po.createMmi); + db_set_b(NULL, SSMODULENAME, OptName(i, SETTING_INSUBMENU), po.inSubMenu); + db_set_b(NULL, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), po.regHotkey); + db_set_w(NULL, SSMODULENAME, OptName(i, SETTING_HOTKEY), po.hotKey); + db_set_ws(NULL, SSMODULENAME, OptName(i, SETTING_PROFILENAME), po.tszName); + + TSettingsList& ar = *po.ps; + for (int j=0; j < ar.getCount(); j++) { + if ( ar[j].szMsg != NULL ) { + mir_snprintf(setting, "%s_%s", ar[j].szName, SETTING_PROFILE_STSMSG); + db_set_ws(NULL, SSMODULENAME, OptName(i, setting), ar[j].szMsg); + } + db_set_w(NULL, SSMODULENAME, OptName(i, ar[j].szName), ar[j].status); + } + } + db_set_w(NULL, SSMODULENAME, SETTING_PROFILECOUNT, (WORD)arProfiles.getCount()); + + // Rebuild status menu + if (bNeedRebuildMenu) + pcli->pfnReloadProtoMenus(); + + SSLoadMainOptions(); + } + break; + + case WM_DESTROY: + arProfiles.destroy(); + break; + } + + return 0; +} + +int StartupStatusOptionsInit(WPARAM wparam,LPARAM) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.hInstance = hInst; + 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); + + odp.szTab.a = LPGEN("Status profiles"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_STATUSPROFILES); + odp.pfnDlgProc = StatusProfilesOptDlgProc; + Options_AddPage(wparam,&odp); + return 0; +} + +char* OptName(int i, const char* setting) +{ + static char buf[100]; + mir_snprintf(buf, "%d_%s", i, setting); + return buf; +} diff --git a/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp b/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp new file mode 100644 index 0000000000..8abeeaa495 --- /dev/null +++ b/plugins/StatusManager/src/StartupStatus/ss_profiles.cpp @@ -0,0 +1,347 @@ +/* + 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 + +extern HINSTANCE hInst; +extern int protoCount; + +static int menuprofiles[MAX_MMITEMS]; +static HANDLE hProfileServices[MAX_MMITEMS]; +static int mcount = 0; + +static PROFILECE *pce = NULL; +static int pceCount = 0; + +static UINT_PTR releaseTtbTimerId = 0; + +static HANDLE hTBModuleLoadedHook; +static HANDLE hLoadAndSetProfileService; +static HANDLE hMessageHook = NULL; + +static HWND hMessageWindow = NULL; +static HKINFO *hkInfo = NULL; +static int hkiCount = 0; + +static HANDLE* ttbButtons = NULL; +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; + 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(NULL, SSMODULENAME, OptName(i, SETTING_CREATEMMITEM), 0) || GetProfileName(i, (LPARAM)profilename)) + continue; + + if (db_get_b(NULL, SSMODULENAME, OptName(i, SETTING_INSUBMENU), 1) && !mi.root) { + mi.root = Menu_CreateRoot(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); + hProfileServices[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(NULL, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + + int count = db_get_w(NULL, 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(NULL, 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(NULL, SSMODULENAME, SETTING_PROFILECOUNT, 1); + if (def != 0) { + *def = db_get_w(NULL, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + if (*def >= count) + *def = 0; + } + + return count; +} + +wchar_t *GetStatusMessage(int profile, char *szProto) +{ + char dbSetting[80]; + DBVARIANT dbv; + + for (int i = 0; i < pceCount; i++) { + if ((pce[i].profile == profile) && (!mir_strcmp(pce[i].szProto, szProto))) { + mir_snprintf(dbSetting, "%d_%s_%s", profile, szProto, SETTING_PROFILE_STSMSG); + if (!db_get_ws(NULL, SSMODULENAME, dbSetting, &dbv)) { // reload from db + pce[i].msg = (wchar_t*)realloc(pce[i].msg, sizeof(wchar_t)*(mir_wstrlen(dbv.ptszVal) + 1)); + if (pce[i].msg != NULL) { + mir_wstrcpy(pce[i].msg, dbv.ptszVal); + } + db_free(&dbv); + } + else { + if (pce[i].msg != NULL) { + free(pce[i].msg); + pce[i].msg = NULL; + } + } + return pce[i].msg; + } + } + pce = (PROFILECE*)realloc(pce, (pceCount + 1)*sizeof(PROFILECE)); + if (pce == NULL) + return NULL; + + pce[pceCount].profile = profile; + pce[pceCount].szProto = _strdup(szProto); + pce[pceCount].msg = NULL; + mir_snprintf(dbSetting, "%d_%s_%s", profile, szProto, SETTING_PROFILE_STSMSG); + if (!db_get_ws(NULL, SSMODULENAME, dbSetting, &dbv)) { + pce[pceCount].msg = wcsdup(dbv.ptszVal); + db_free(&dbv); + } + pceCount++; + + return pce[pceCount - 1].msg; +} + +int GetProfile(int profile, TSettingsList& arSettings) +{ + if (profile < 0) // get default profile + profile = db_get_w(NULL, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + + int count = db_get_w(NULL, SSMODULENAME, SETTING_PROFILECOUNT, 0); + if (profile >= count && count > 0) + return -1; + + arSettings.destroy(); + + // if count == 0, continue so the default profile will be returned + PROTOACCOUNT** protos; + Proto_EnumAccounts(&count, &protos); + + for (int i = 0; i < count; i++) + if (IsSuitableProto(protos[i])) + arSettings.insert(new TSSSetting(profile, protos[i])); + + return (arSettings.getCount() == 0) ? -1 : 0; +} + +static void CALLBACK releaseTtbTimerFunction(HWND, UINT, UINT_PTR, DWORD) +{ + KillTimer(NULL, 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; + TSettingsList profileSettings(10, SSCompareSettings); + if (!GetProfile(profile, profileSettings)) { + profile = (profile >= 0) ? profile : db_get_w(NULL, SSMODULENAME, SETTING_DEFAULTPROFILE, 0); + + char setting[64]; + mir_snprintf(setting, "%d_%s", profile, SETTING_SHOWCONFIRMDIALOG); + if (!db_get_b(NULL, SSMODULENAME, setting, 0)) + CallService(MS_CS_SETSTATUSEX, (WPARAM)&profileSettings, 0); + else + CallService(MS_CS_SHOWCONFIRMDLGEX, (WPARAM)&profileSettings, (LPARAM)db_get_dw(NULL, SSMODULENAME, SETTING_DLGTIMEOUT, 5)); + } + + // add timer here + if (hTTBModuleLoadedHook) + releaseTtbTimerId = SetTimer(NULL, 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 != NULL) { + for (int i = 0; i < hkiCount; i++) { + UnregisterHotKey(hMessageWindow, (int)hkInfo[i].id); + GlobalDeleteAtom(hkInfo[i].id); + } + free(hkInfo); + } + DestroyWindow(hMessageWindow); + + hkiCount = 0; + hkInfo = NULL; + hMessageWindow = NULL; + + return 0; +} + +// assumes UnregisterHotKeys was called before +static int RegisterHotKeys() +{ + hMessageWindow = CreateWindowEx(0, L"STATIC", NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); + + int count = GetProfileCount(0, 0); + for (int i = 0; i < count; i++) { + if (!db_get_b(NULL, SSMODULENAME, OptName(i, SETTING_REGHOTKEY), 0)) + continue; + + WORD wHotKey = db_get_w(NULL, SSMODULENAME, OptName(i, SETTING_HOTKEY), 0); + hkInfo = (HKINFO*)realloc(hkInfo, (hkiCount + 1)*sizeof(HKINFO)); + if (hkInfo == NULL) + 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() +{ + hLoadAndSetProfileService = CreateServiceFunction(MS_SS_LOADANDSETPROFILE, LoadAndSetProfile); + return 0; +} + +int UnloadProfileModule() +{ + DestroyServiceFunction(hLoadAndSetProfileService); + return 0; +} + +int InitProfileModule() +{ + hTTBModuleLoadedHook = HookEvent(ME_TTB_MODULELOADED, CreateTopToolbarButtons); + + HookEvent(ME_CLIST_PREBUILDSTATUSMENU, CreateMainMenuItems); + + CreateMainMenuItems(0, 0); + RegisterHotKeys(); + return 0; +} + +int DeinitProfilesModule() +{ + for (int i = 0; i < mcount; i++) + DestroyServiceFunction(hProfileServices[i]); + + if (pce) { + for (int i = 0; i < pceCount; i++) + free(pce[i].szProto); + free(pce); + } + + UnregisterHotKeys(); + RemoveTopToolbarButtons(); + return 0; +} diff --git a/plugins/StatusManager/src/StartupStatus/ss_toolbars.cpp b/plugins/StatusManager/src/StartupStatus/ss_toolbars.cpp new file mode 100644 index 0000000000..e9d153670a --- /dev/null +++ b/plugins/StatusManager/src/StartupStatus/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<void> ttbButtons(1); + +static IconItem iconList[] = +{ + { LPGEN("Pressed toolbar icon"), "StartupStatus/TtbDown", IDI_TTBDOWN }, + { LPGEN("Released toolbar icon"), "StartupStatus/TtbUp", IDI_TTBUP }, +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +void RemoveTopToolbarButtons() +{ + for (int i=ttbButtons.getCount()-1; i >= 0; i--) + CallService(MS_TTB_REMOVEBUTTON, (WPARAM)ttbButtons[i], 0); + ttbButtons.destroy(); +} + +int CreateTopToolbarButtons(WPARAM, LPARAM) +{ + if (iconList[0].hIcolib == NULL) + Icon_Register(hInst, "Toolbar/StartupStatus", iconList, _countof(iconList)); + + int profileCount = CallService(MS_SS_GETPROFILECOUNT, 0, 0); + + TTBButton ttb = { 0 }; + 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(NULL, SSMODULENAME, setting, FALSE)) + continue; + + DBVARIANT dbv; + mir_snprintf(setting, "%d_%s", i, SETTING_PROFILENAME); + if (db_get(NULL, 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 = TopToolbar_AddButton(&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 new file mode 100644 index 0000000000..2af4dc146d --- /dev/null +++ b/plugins/StatusManager/src/StartupStatus/startupstatus.cpp @@ -0,0 +1,524 @@ +/* + 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" + +static UINT_PTR setStatusTimerId = 0; + +static TSettingsList startupSettings(10, SSCompareSettings); + +TSSSetting::TSSSetting(PROTOACCOUNT *pa) +{ + cbSize = sizeof(PROTOCOLSETTINGEX); + szName = pa->szModuleName; + tszAccName = pa->tszAccountName; + status = lastStatus = CallProtoService(pa->szModuleName, PS_GETSTATUS, 0, 0); + szMsg = NULL; +} + +TSSSetting::TSSSetting(int profile, PROTOACCOUNT *pa) +{ + cbSize = sizeof(PROTOCOLSETTINGEX); + + // copy name + szName = pa->szModuleName; + tszAccName = pa->tszAccountName; + + // load status + char setting[80]; + mir_snprintf(setting, "%d_%s", profile, pa->szModuleName); + int iStatus = db_get_w(NULL, SSMODULENAME, setting, 0); + if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) + iStatus = DEFAULT_STATUS; + status = iStatus; + + // load last status + mir_snprintf(setting, "%s%s", PREFIX_LAST, szName); + iStatus = db_get_w(NULL, SSMODULENAME, setting, 0); + if (iStatus < MIN_STATUS || iStatus > MAX_STATUS) + iStatus = DEFAULT_STATUS; + lastStatus = iStatus; + + szMsg = GetStatusMessage(profile, szName); + if (szMsg) + szMsg = wcsdup(szMsg); +} + +TSSSetting::~TSSSetting() +{ + free(szMsg); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static HANDLE hProtoAckHook, hCSStatusChangeHook, hStatusChangeHook; + +static HWND hMessageWindow; + +static BYTE showDialogOnStartup = 0; + +///////////////////////////////////////////////////////////////////////////////////////// +// command line options + +static PROTOCOLSETTINGEX* IsValidProtocol(TSettingsList& protoSettings, char* protoName) +{ + for (int i = 0; i < protoSettings.getCount(); i++) + if (!strncmp(protoSettings[i].szName, protoName, mir_strlen(protoSettings[i].szName))) + return &protoSettings[i]; + + return NULL; +} + +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(TSettingsList& 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 != NULL) { + 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->status = status; + } + } +} + +static void SetLastStatusMessages(TSettingsList &ps) +{ + for (int i = 0; i < ps.getCount(); i++) { + if (ps[i].status != ID_STATUS_LAST) + continue; + + char dbSetting[128]; + mir_snprintf(dbSetting, "%s%s", PREFIX_LASTMSG, ps[i].szName); + + DBVARIANT dbv; + if (ps[i].szMsg == NULL && !db_get_ws(NULL, SSMODULENAME, dbSetting, &dbv)) { + ps[i].szMsg = wcsdup(dbv.ptszVal); // remember this won't be freed + db_free(&dbv); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Account control event + +int OnSSAccChanged(WPARAM wParam, LPARAM lParam) +{ + PROTOACCOUNT *pa = (PROTOACCOUNT*)lParam; + switch (wParam) { + case PRAC_ADDED: + startupSettings.insert(new TSSSetting(-1, pa)); + break; + + case PRAC_REMOVED: + for (int i = 0; i < startupSettings.getCount(); i++) { + if (!mir_strcmp(startupSettings[i].szName, pa->szModuleName)) { + startupSettings.remove(i); + break; + } + } + break; + } + + return 0; +} + +// '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(NULL, SSMODULENAME, SETTING_OVERRIDE, 1) || startupSettings.getCount() == 0) + return 0; + + for (int i = 0; i < startupSettings.getCount(); i++) { + if (!mir_strcmp(ack->szModule, startupSettings[i].szName)) { + startupSettings[i].szName = ""; + 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(NULL, SSMODULENAME, SETTING_OVERRIDE, 1) || startupSettings.getCount() == 0) + return 0; + + char *szProto = (char *)lParam; + if (szProto == NULL) { // global status change + for (int i = 0; i < startupSettings.getCount(); i++) { + startupSettings[i].szName = ""; + log_debugA("StartupStatus: all protos overridden by ME_CLIST_STATUSMODECHANGE, status will not be set"); + } + } + else { + for (int i = 0; i < startupSettings.getCount(); i++) { + if (!mir_strcmp(startupSettings[i].szName, szProto)) { + startupSettings[i].szName = ""; + 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(NULL, SSMODULENAME, SETTING_OVERRIDE, 1) || startupSettings.getCount() == 0) + return 0; + + if (wParam != 0) { + PROTOCOLSETTINGEX** ps = *(PROTOCOLSETTINGEX***)wParam; + if (ps == NULL) + return -1; + + for (int i = 0; i < startupSettings.getCount(); i++) { + for (int j = 0; j < startupSettings.getCount(); j++) { + if (ps[i]->szName == NULL || startupSettings[j].szName == NULL) + continue; + + if (!mir_strcmp(ps[i]->szName, startupSettings[j].szName)) { + log_debugA("StartupStatus: %s overridden by MS_CS_SETSTATUSEX, status will not be set", ps[i]->szName); + // use a hack to disable this proto + startupSettings[j].szName = ""; + } + } + } + } + + return 0; +} + +static void CALLBACK SetStatusTimed(HWND, UINT, UINT_PTR, DWORD) +{ + KillTimer(NULL, setStatusTimerId); + UnhookEvent(hProtoAckHook); + UnhookEvent(hCSStatusChangeHook); + UnhookEvent(hStatusChangeHook); + CallService(MS_CS_SETSTATUSEX, (WPARAM)&startupSettings, 0); +} + +static int OnOkToExit(WPARAM, LPARAM) +{ + // save last protocolstatus + int count; + PROTOACCOUNT** protos; + Proto_EnumAccounts(&count, &protos); + + for (int i = 0; i < count; i++) { + PROTOACCOUNT *pa = protos[i]; + 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(NULL, SSMODULENAME, lastName, (WORD)CallProtoService(pa->szModuleName, PS_GETSTATUS, 0, 0)); + mir_snprintf(lastMsg, "%s%s", PREFIX_LASTMSG, pa->szModuleName); + db_unset(NULL, SSMODULENAME, lastMsg); + + if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND & ~PF1_INDIVMODEMSG)) + continue; + + int status = CallProtoService(pa->szModuleName, PS_GETSTATUS, 0, 0); + if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(status))) + 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 == NULL) { + npi.status = 0; + npi.szProto = NULL; + CallService(MS_NAS_GETSTATE, (WPARAM)&npi, 1); + } + if (npi.szMsg != NULL) { + db_set_ws(NULL, SSMODULENAME, lastMsg, npi.tszMsg); + mir_free(npi.tszMsg); + } + } + } + + if (db_get_b(NULL, SSMODULENAME, SETTING_SETPROFILE, 1) || db_get_b(NULL, SSMODULENAME, SETTING_OFFLINECLOSE, 0)) { + if (ServiceExists(MS_CLIST_SETSTATUSMODE)) + CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_OFFLINE, 0); + else + log_debugA("StartupStatus: MS_CLIST_SETSTATUSMODE not available!"); + } + + return 0; +} + +static int OnShutdown(WPARAM, LPARAM) +{ + DeinitProfilesModule(); + UnloadProfileModule(); + + // set windowstate and docked for next startup + if (db_get_b(NULL, SSMODULENAME, SETTING_SETWINSTATE, 0)) { + int state = db_get_b(NULL, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); + HWND hClist = pcli->hwndContactList; + BOOL isHidden = !IsWindowVisible(hClist); + switch (state) { + case SETTING_STATE_HIDDEN: + // try to use services where possible + if (!isHidden) + pcli->pfnShowHide(); + break; + + case SETTING_STATE_MINIMIZED: + if (!db_get_b(NULL, 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) + pcli->pfnShowHide(); + break; + } + } + + // hangup + if (db_get_b(NULL, SSMODULENAME, SETTING_AUTOHANGUP, 0)) + InternetAutodialHangup(0); + + int state = db_get_b(NULL, SSMODULENAME, SETTING_WINSTATE, SETTING_STATE_NORMAL); + // set windowstate and docked for next startup + if (db_get_b(NULL, SSMODULENAME, SETTING_SETWINSTATE, 0)) + db_set_b(NULL, MODULE_CLIST, SETTING_WINSTATE, (BYTE)state); + + if (hMessageWindow) + DestroyWindow(hMessageWindow); + + startupSettings.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) +{ + protoList = (OBJLIST<PROTOCOLSETTINGEX>*)&startupSettings; + + InitProfileModule(); + + HookEvent(ME_PROTO_ACCLISTCHANGED, OnSSAccChanged); + HookEvent(ME_OPT_INITIALISE, StartupStatusOptionsInit); + + /* shutdown hook for normal shutdown */ + HookEvent(ME_SYSTEM_OKTOEXIT, OnOkToExit); + HookEvent(ME_SYSTEM_PRESHUTDOWN, OnShutdown); + /* message window for poweroff */ + hMessageWindow = CreateWindowEx(0, L"STATIC", NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + SetWindowLongPtr(hMessageWindow, GWLP_WNDPROC, (LONG_PTR)MessageWndProc); + + GetProfile(-1, startupSettings); + + // override with cmdl + ProcessCommandLineOptions(startupSettings); + if (startupSettings.getCount() == 0) + return 0;// no protocols are loaded + + SetLastStatusMessages(startupSettings); + showDialogOnStartup = (showDialogOnStartup || db_get_b(NULL, SSMODULENAME, SETTING_SHOWDIALOG, 0)); + + // dial + if (showDialogOnStartup || db_get_b(NULL, SSMODULENAME, SETTING_SETPROFILE, 1)) + if (db_get_b(NULL, SSMODULENAME, SETTING_AUTODIAL, 0)) + InternetAutodial(0, NULL); + + // set the status! + if (showDialogOnStartup || db_get_b(NULL, SSMODULENAME, SETTING_SHOWDIALOG, 0)) + CallService(MS_CS_SHOWCONFIRMDLGEX, (WPARAM)&startupSettings, db_get_dw(NULL, SSMODULENAME, SETTING_DLGTIMEOUT, 5)); + else if (db_get_b(NULL, SSMODULENAME, SETTING_SETPROFILE, 1)) { + // set hooks for override + if (db_get_b(NULL, SSMODULENAME, SETTING_OVERRIDE, 1)) { + hProtoAckHook = HookEvent(ME_PROTO_ACK, ProcessProtoAck); + hCSStatusChangeHook = HookEvent(ME_CS_STATUSCHANGEEX, CSStatusChangeEx); + hStatusChangeHook = HookEvent(ME_CLIST_STATUSMODECHANGE, StatusChange); + } + setStatusTimerId = SetTimer(NULL, 0, db_get_dw(NULL, SSMODULENAME, SETTING_SETPROFILEDELAY, 500), SetStatusTimed); + } + + // win size and location + if (db_get_b(NULL, SSMODULENAME, SETTING_SETWINLOCATION, 0) || db_get_b(NULL, SSMODULENAME, SETTING_SETWINSIZE, 0)) { + HWND hClist = pcli->hwndContactList; + + // store in db + if (db_get_b(NULL, SSMODULENAME, SETTING_SETWINLOCATION, 0)) { + db_set_dw(NULL, MODULE_CLIST, SETTING_XPOS, db_get_dw(NULL, SSMODULENAME, SETTING_XPOS, 0)); + db_set_dw(NULL, MODULE_CLIST, SETTING_YPOS, db_get_dw(NULL, SSMODULENAME, SETTING_YPOS, 0)); + } + if (db_get_b(NULL, SSMODULENAME, SETTING_SETWINSIZE, 0)) { + db_set_dw(NULL, MODULE_CLIST, SETTING_WIDTH, db_get_dw(NULL, SSMODULENAME, SETTING_WIDTH, 0)); + if (!db_get_b(NULL, MODULE_CLUI, SETTING_AUTOSIZE, 0)) + db_set_dw(NULL, MODULE_CLIST, SETTING_HEIGHT, db_get_dw(NULL, 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(NULL, SSMODULENAME, SETTING_SETWINLOCATION, 0)) { + x = db_get_dw(NULL, SSMODULENAME, SETTING_XPOS, x); + y = db_get_dw(NULL, SSMODULENAME, SETTING_YPOS, y); + } + if (db_get_b(NULL, SSMODULENAME, SETTING_SETWINSIZE, 0)) { + width = db_get_dw(NULL, SSMODULENAME, SETTING_WIDTH, width); + if (!db_get_b(NULL, MODULE_CLUI, SETTING_AUTOSIZE, 0)) + height = db_get_dw(NULL, SSMODULENAME, SETTING_HEIGHT, height); + } + MoveWindow(hClist, x, y, width, height, TRUE); + } } } } + + return 0; +} + +HANDLE hSSModuleLoadedHook = NULL, + hGetProfileService, + hGetProfileCountService, + hGetProfileNameService; + +void StartupStatusLoad() +{ + hSSModuleLoadedHook = HookEvent(ME_SYSTEM_MODULESLOADED, SSModuleLoaded); + + if (db_get_b(NULL, SSMODULENAME, SETTING_SETPROFILE, 1) || + db_get_b(NULL, SSMODULENAME, SETTING_OFFLINECLOSE, 0)) + db_set_w(NULL, "CList", "Status", (WORD)ID_STATUS_OFFLINE); + + // docking + if (db_get_b(NULL, SSMODULENAME, SETTING_SETDOCKED, 0)) { + int docked = db_get_b(NULL, SSMODULENAME, SETTING_DOCKED, DOCKED_NONE); + if (docked == DOCKED_LEFT || docked == DOCKED_RIGHT) + docked = -docked; + + db_set_b(NULL, MODULE_CLIST, SETTING_DOCKED, (BYTE)docked); + } + + // Create service functions; the get functions are created here; they don't rely on commonstatus + hGetProfileService = CreateServiceFunction(MS_SS_GETPROFILE, SrvGetProfile); + hGetProfileCountService = CreateServiceFunction(MS_SS_GETPROFILECOUNT, GetProfileCount); + hGetProfileNameService = CreateServiceFunction(MS_SS_GETPROFILENAME, GetProfileName); + + LoadProfileModule(); +} + +void StartupStatusUnload() +{ + DeinitProfilesModule(); + UnloadProfileModule(); + + DestroyServiceFunction(hGetProfileService); + DestroyServiceFunction(hGetProfileCountService); + DestroyServiceFunction(hGetProfileNameService); + + UnhookEvent(hSSModuleLoadedHook); +} diff --git a/plugins/StatusManager/src/StartupStatus/startupstatus.h b/plugins/StatusManager/src/StartupStatus/startupstatus.h new file mode 100644 index 0000000000..5686e03981 --- /dev/null +++ b/plugins/StatusManager/src/StartupStatus/startupstatus.h @@ -0,0 +1,167 @@ +/* + 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 TSSSetting : public PROTOCOLSETTINGEX, public MZeroedObject +{ + TSSSetting(PROTOACCOUNT *pa); + TSSSetting(int profile, PROTOACCOUNT *pa); + ~TSSSetting(); +}; + +static int SSCompareSettings(const TSSSetting *p1, const TSSSetting *p2) +{ + return mir_strcmp(p1->szName, p2->szName); +} + +typedef OBJLIST<TSSSetting> TSettingsList; + +struct PROFILECE +{ + int profile; + char *szProto; + wchar_t *msg; +}; + +struct PROFILEOPTIONS : public MZeroedObject +{ + __inline ~PROFILEOPTIONS() + { + delete ps; + mir_free(tszName); + } + + wchar_t *tszName; + TSettingsList* 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_SETPROFILE WM_USER + 2 +#define UM_SETPROTOCOL WM_USER + 3 +#define UM_SETSTATUSMSG WM_USER + 4 +#define UM_ADDPROFILE WM_USER + 5 +#define UM_DELPROFILE WM_USER + 6 +#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(); + +TSettingsList* GetCurrentProtoSettings(); + +// profile +int GetProfile(int profileID, TSettingsList& arSettings ); +wchar_t *GetStatusMessage(int profile, char *szProto); + +static INT_PTR SrvGetProfile(WPARAM wParam, LPARAM lParam) +{ + return GetProfile((int)wParam, *(TSettingsList*)lParam); +} + +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 UnloadProfileModule(); +int InitProfileModule(); +int DeinitProfilesModule(); + +#endif //__STARTUPSTATUSHEADER |