/* AdvancedAutoAway Plugin for Miranda-IM (www.miranda-im.org) KeepStatus Plugin for Miranda-IM (www.miranda-im.org) 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 TIMER_ID 1 // variables static HWND win; static int timeOut; struct TConfirmSetting : public PROTOCOLSETTINGEX { TConfirmSetting(const PROTOCOLSETTINGEX& x) { memcpy(this, &x, sizeof(PROTOCOLSETTINGEX)); if (szMsg) szMsg = wcsdup(szMsg); } ~TConfirmSetting() { free(szMsg); } }; static int CompareSettings(const TConfirmSetting* p1, const TConfirmSetting* p2) { return mir_strcmp(p1->szName, p2->szName); } static OBJLIST *confirmSettings; static INT_PTR CALLBACK StatusMessageDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static PROTOCOLSETTINGEX* protoSetting = NULL; switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); protoSetting = (PROTOCOLSETTINGEX *)lParam; if (protoSetting->szMsg == NULL) { wchar_t* smsg = GetDefaultStatusMessage(protoSetting, GetActualStatus(protoSetting)); if (smsg != NULL) { SetDlgItemText(hwndDlg, IDC_STSMSG, smsg); mir_free(smsg); } } else SetDlgItemText(hwndDlg, IDC_STSMSG, protoSetting->szMsg); { wchar_t desc[512]; mir_snwprintf(desc, TranslateT("Set %s message for %s."), pcli->pfnGetStatusModeDescription(GetActualStatus(protoSetting), 0), protoSetting->tszAccName); SetDlgItemText(hwndDlg, IDC_DESCRIPTION, desc); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_OK: { int len = SendDlgItemMessage(hwndDlg, IDC_STSMSG, WM_GETTEXTLENGTH, 0, 0); if (len > 0) { protoSetting->szMsg = (wchar_t*)realloc(protoSetting->szMsg, sizeof(wchar_t)*(len + 1)); if (protoSetting->szMsg != NULL) GetDlgItemText(hwndDlg, IDC_STSMSG, protoSetting->szMsg, len + 1); } SendMessage(GetParent(hwndDlg), UM_STSMSGDLGCLOSED, TRUE, 0); EndDialog(hwndDlg, IDC_OK); } break; case IDC_CANCEL: SendMessage(GetParent(hwndDlg), UM_STSMSGDLGCLOSED, 0, 0); EndDialog(hwndDlg, IDC_CANCEL); break; } break; } return FALSE; } static int SetStatusList(HWND hwndDlg) { if (confirmSettings->getCount() == 0) return -1; HWND hList = GetDlgItem(hwndDlg, IDC_STARTUPLIST); wchar_t buf[100]; // create items LVITEM lvItem = { 0 }; lvItem.mask = LVIF_TEXT | LVIF_PARAM; for (int i = 0; i < confirmSettings->getCount(); i++) { lvItem.pszText = (*confirmSettings)[i].tszAccName; if (ListView_GetItemCount(hList) < confirmSettings->getCount()) ListView_InsertItem(hList, &lvItem); int actualStatus; switch ((*confirmSettings)[i].status) { case ID_STATUS_LAST: actualStatus = (*confirmSettings)[i].lastStatus; break; case ID_STATUS_CURRENT: actualStatus = CallProtoService((*confirmSettings)[i].szName, PS_GETSTATUS, 0, 0); break; default: actualStatus = (*confirmSettings)[i].status; } wchar_t* status = pcli->pfnGetStatusModeDescription(actualStatus, 0); switch ((*confirmSettings)[i].status) { case ID_STATUS_LAST: mir_snwprintf(buf, L"%s (%s)", TranslateT(""), status); ListView_SetItemText(hList, lvItem.iItem, 1, buf); break; case ID_STATUS_CURRENT: mir_snwprintf(buf, L"%s (%s)", TranslateT(""), status); ListView_SetItemText(hList, lvItem.iItem, 1, buf); break; default: ListView_SetItemText(hList, lvItem.iItem, 1, status); } // status message if (!((!((CallProtoService((*confirmSettings)[i].szName, PS_GETCAPS, (WPARAM)PFLAGNUM_1, 0)&PF1_MODEMSGSEND)&~PF1_INDIVMODEMSG)) || (!(CallProtoService((*confirmSettings)[i].szName, PS_GETCAPS, (WPARAM)PFLAGNUM_3, 0)&Proto_Status2Flag(actualStatus))))) { wchar_t *msg = GetDefaultStatusMessage(&(*confirmSettings)[i], actualStatus); if (msg != NULL) { wchar_t* fMsg = variables_parsedup(msg, (*confirmSettings)[i].tszAccName, NULL); ListView_SetItemText(hList, lvItem.iItem, 2, fMsg); mir_free(fMsg); mir_free(msg); } else ListView_SetItemText(hList, lvItem.iItem, 2, TranslateT("")); } else ListView_SetItemText(hList, lvItem.iItem, 2, TranslateT("")); ListView_SetColumnWidth(hList, 0, LVSCW_AUTOSIZE); ListView_SetColumnWidth(hList, 2, LVSCW_AUTOSIZE); lvItem.lParam = (LPARAM)&(*confirmSettings)[i]; ListView_SetItem(hList, &lvItem); lvItem.iItem++; } // grey out status box EnableWindow(GetDlgItem(hwndDlg, IDC_STATUS), (ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), -1, LVNI_SELECTED) >= 0)); return 0; } static INT_PTR CALLBACK ConfirmDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); { HWND hList = GetDlgItem(hwndDlg, IDC_STARTUPLIST); SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); // create columns LVCOLUMN lvCol = { 0 }; lvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; lvCol.pszText = TranslateT("Protocol"); ListView_InsertColumn(hList, 0, &lvCol); lvCol.cx = 100; lvCol.pszText = TranslateT("Status"); ListView_InsertColumn(hList, 1, &lvCol); lvCol.pszText = TranslateT("Message"); ListView_InsertColumn(hList, 2, &lvCol); } // create items SetStatusList(hwndDlg); EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), FALSE); // fill profile combo box if (!ServiceExists(MS_SS_GETPROFILE)) EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), FALSE); else { int defaultProfile; int profileCount = (int)CallService(MS_SS_GETPROFILECOUNT, (WPARAM)&defaultProfile, 0); for (int i = 0; i < profileCount; i++) { wchar_t profileName[128]; CallService(MS_SS_GETPROFILENAME, i, (LPARAM)profileName); int item = SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_ADDSTRING, 0, (LPARAM)profileName); SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETITEMDATA, item, i); } if (profileCount == 0) EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILE), FALSE); else SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_SETCURSEL, defaultProfile, 0); } // start timer if (timeOut > 0) { wchar_t text[32]; mir_snwprintf(text, TranslateT("Closing in %d"), timeOut); SetDlgItemText(hwndDlg, IDC_CLOSE, text); SetTimer(hwndDlg, TIMER_ID, 1000, NULL); } return TRUE; case WM_TIMER: { wchar_t text[32]; mir_snwprintf(text, TranslateT("Closing in %d"), timeOut - 1); SetDlgItemText(hwndDlg, IDC_CLOSE, text); if (timeOut <= 0) { KillTimer(hwndDlg, TIMER_ID); SendMessage(hwndDlg, UM_CLOSECONFIRMDLG, 0, 0); } else timeOut--; } break; case WM_COMMAND: // stop timer KillTimer(hwndDlg, TIMER_ID); SetDlgItemText(hwndDlg, IDC_CLOSE, TranslateT("Close")); if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == BN_CLICKED) || (HIWORD(wParam) == NM_CLICK)) { // something clicked switch (LOWORD(wParam)) { case IDC_PROFILE: { int profile = (int)SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROFILE, CB_GETCURSEL, 0, 0), 0); for (int i = 0; i < confirmSettings->getCount(); i++) if ((*confirmSettings)[i].szMsg != NULL) { free((*confirmSettings)[i].szMsg); (*confirmSettings)[i].szMsg = NULL; } CallService(MS_SS_GETPROFILE, (WPARAM)profile, (LPARAM)confirmSettings); for (int i = 0; i < confirmSettings->getCount(); i++) if ((*confirmSettings)[i].szMsg != NULL) // we free this later, copy to our memory space (*confirmSettings)[i].szMsg = wcsdup((*confirmSettings)[i].szMsg); SetStatusList(hwndDlg); } break; case IDC_STATUS: { LVITEM lvItem = { 0 }; lvItem.mask = LVIF_TEXT | LVIF_PARAM; lvItem.iSubItem = 0; lvItem.iItem = ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), -1, LVNI_SELECTED); if (lvItem.iItem == -1) break; ListView_GetItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), &lvItem); PROTOCOLSETTINGEX* proto = (PROTOCOLSETTINGEX*)lvItem.lParam; int actualStatus = proto->status = (int)SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0), 0); // LAST STATUS if (proto->status == ID_STATUS_LAST) { wchar_t last[80]; mir_snwprintf(last, L"%s (%s)", TranslateT(""), pcli->pfnGetStatusModeDescription(proto->lastStatus, 0)); ListView_SetItemText(GetDlgItem(hwndDlg, IDC_STARTUPLIST), lvItem.iItem, 1, last); actualStatus = proto->lastStatus; } // CURRENT STATUS else if (proto->status == ID_STATUS_CURRENT) { int currentStatus = CallProtoService(proto->szName, PS_GETSTATUS, 0, 0); wchar_t current[80]; mir_snwprintf(current, L"%s (%s)", TranslateT(""), pcli->pfnGetStatusModeDescription(currentStatus, 0)); ListView_SetItemText(GetDlgItem(hwndDlg, IDC_STARTUPLIST), lvItem.iItem, 1, current); actualStatus = currentStatus; } else ListView_SetItemText(GetDlgItem(hwndDlg, IDC_STARTUPLIST), lvItem.iItem, 1, pcli->pfnGetStatusModeDescription(proto->status, 0)); if ((!((CallProtoService(proto->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_1, 0)&PF1_MODEMSGSEND)&~PF1_INDIVMODEMSG)) || (!(CallProtoService(proto->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_3, 0)&Proto_Status2Flag(actualStatus)))) EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), FALSE); else if ((proto->status == ID_STATUS_LAST) || (proto->status == ID_STATUS_CURRENT)) EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), TRUE); else EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), (CallProtoService(proto->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_3, 0)&Proto_Status2Flag(actualStatus)) ? TRUE : FALSE); SetStatusList(hwndDlg); } break; case IDC_SETSTSMSG: { LVITEM lvItem = { 0 }; lvItem.mask = LVIF_TEXT | LVIF_PARAM; lvItem.iSubItem = 0; lvItem.iItem = ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), -1, LVNI_SELECTED); if (lvItem.iItem == -1) break; ListView_GetItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), &lvItem); DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SETSTSMSGDIALOG), hwndDlg, StatusMessageDlgProc, lvItem.lParam); } break; case IDC_CLOSE: SendMessage(hwndDlg, UM_CLOSECONFIRMDLG, 0, 0); break; case IDC_CANCEL: DestroyWindow(hwndDlg); break; } } break; case WM_NOTIFY: switch (((NMHDR*)lParam)->idFrom) { case IDC_STARTUPLIST: if (((NMHDR*)lParam)->code == NM_CLICK) { KillTimer(hwndDlg, TIMER_ID); SetDlgItemText(hwndDlg, IDC_CLOSE, TranslateT("Close")); LVITEM lvItem = { 0 }; lvItem.mask = LVIF_TEXT | LVIF_PARAM; lvItem.iSubItem = 0; lvItem.iItem = ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), -1, LVNI_SELECTED); if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_STARTUPLIST), &lvItem) == FALSE) { SetStatusList(hwndDlg); break; } PROTOCOLSETTINGEX *proto = (PROTOCOLSETTINGEX*)lvItem.lParam; int flags = CallProtoService(proto->szName, PS_GETCAPS, PFLAGNUM_2, 0) & ~CallProtoService(proto->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0); // clear box and add new status, loop status and check if compatible with proto SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_RESETCONTENT, 0, 0); int actualStatus = proto->status; // last wchar_t buf[100]; mir_snwprintf(buf, L"%s (%s)", TranslateT(""), pcli->pfnGetStatusModeDescription(proto->lastStatus, 0)); int item = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)buf); SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, item, ID_STATUS_LAST); if (proto->status == ID_STATUS_LAST) { SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETCURSEL, item, 0); actualStatus = proto->lastStatus; } // current int currentStatus = CallProtoService(proto->szName, PS_GETSTATUS, 0, 0); mir_snwprintf(buf, L"%s (%s)", TranslateT(""), pcli->pfnGetStatusModeDescription(currentStatus, 0)); item = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)buf); SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, item, ID_STATUS_CURRENT); if (proto->status == ID_STATUS_CURRENT) { SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETCURSEL, item, 0); 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->szName, PS_GETCAPS, (WPARAM)PFLAGNUM_5, 0)&Proto_Status2Flag(statusModePf2List[i]))))) { wchar_t *statusMode = pcli->pfnGetStatusModeDescription(statusModeList[i], 0); item = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)statusMode); SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, item, statusModeList[i]); if (statusModeList[i] == proto->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->szName, PS_GETCAPS, PFLAGNUM_1, 0)&PF1_MODEMSGSEND)&~PF1_INDIVMODEMSG)) || (!(CallProtoService(proto->szName, PS_GETCAPS, PFLAGNUM_3, 0)&Proto_Status2Flag(actualStatus)))) EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), FALSE); else if (proto->status == ID_STATUS_LAST || proto->status == ID_STATUS_CURRENT) EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), TRUE); else EnableWindow(GetDlgItem(hwndDlg, IDC_SETSTSMSG), (CallProtoService(proto->szName, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(actualStatus)) ? TRUE : FALSE); } } break; case UM_STSMSGDLGCLOSED: SetStatusList(hwndDlg); break; case UM_CLOSECONFIRMDLG: CallService(MS_CS_SETSTATUSEX, (WPARAM)confirmSettings, 0); DestroyWindow(hwndDlg); break; case WM_DESTROY: delete confirmSettings; confirmSettings = 0; break; } return 0; } INT_PTR ShowConfirmDialogEx(WPARAM wParam, LPARAM lParam) { if (wParam == 0) return -1; delete confirmSettings; confirmSettings = new OBJLIST(10, CompareSettings); OBJLIST& param = *(OBJLIST*)wParam; for (int i = 0; i < param.getCount(); i++) confirmSettings->insert(new TConfirmSetting(param[i])); timeOut = lParam; if (timeOut < 0) timeOut = DEF_CLOSE_TIME; if (GetWindow(win, 0) == NULL) { win = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CONFIRMDIALOG), NULL, ConfirmDlgProc, NULL); EnableWindow(win, TRUE); } return (INT_PTR)win; }