From 26aed6878b3c891b618eb83469de75a623e80361 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 7 Jul 2012 17:46:01 +0000 Subject: - forgotten /Core module: stdaway git-svn-id: http://svn.miranda-ng.org/main/trunk@816 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/core/modules.cpp | 6 +- src/core/stdaway/awaymsg.cpp | 183 ++++++++ src/core/stdaway/commonheaders.cpp | 2 + src/core/stdaway/commonheaders.h | 93 ++++ src/core/stdaway/main.cpp | 75 ++++ src/core/stdaway/resource.rc | 121 ++++++ src/core/stdaway/sendmsg.cpp | 630 ++++++++++++++++++++++++++++ src/core/stdaway/stdaway_10.vcxproj | 218 ++++++++++ src/core/stdaway/stdaway_10.vcxproj.filters | 47 +++ src/core/stdaway/version.h | 14 + src/core/stdaway/version.rc | 38 ++ src/core/stduserinfo/contacts.cpp | 509 ++++++++++++++++++++++ 12 files changed, 1931 insertions(+), 5 deletions(-) create mode 100644 src/core/stdaway/awaymsg.cpp create mode 100644 src/core/stdaway/commonheaders.cpp create mode 100644 src/core/stdaway/commonheaders.h create mode 100644 src/core/stdaway/main.cpp create mode 100644 src/core/stdaway/resource.rc create mode 100644 src/core/stdaway/sendmsg.cpp create mode 100644 src/core/stdaway/stdaway_10.vcxproj create mode 100644 src/core/stdaway/stdaway_10.vcxproj.filters create mode 100644 src/core/stdaway/version.h create mode 100644 src/core/stdaway/version.rc create mode 100644 src/core/stduserinfo/contacts.cpp (limited to 'src/core') diff --git a/src/core/modules.cpp b/src/core/modules.cpp index 462d6b27c3..423bd3471a 100644 --- a/src/core/modules.cpp +++ b/src/core/modules.cpp @@ -49,7 +49,6 @@ int LoadSkinIcons(void); int LoadSkinSounds(void); int LoadSkinHotkeys(void); int LoadUserInfoModule(void); // ui: user info -int LoadAwayMsgModule(void); // ui: setting away messages int LoadVisibilityModule(void); // ui: visibility control int LoadCLUIModule(void); // ui: CList UI int LoadPluginOptionsModule(void); // ui: plugin viewer @@ -57,7 +56,6 @@ int LoadAddContactModule(void); // ui: authcontrol contacts int LoadUtilsModule(void); // ui: utils (has a few window classes, like HyperLink) int LoadCLCModule(void); // window class: CLC control int LoadButtonModule(void); // window class: button class -int LoadContactsModule(void); // random: contact int LoadFontserviceModule(void); // ui: font manager int LoadIcoLibModule(void); // ui: icons manager int LoadServiceModePlugin(void); @@ -118,7 +116,6 @@ int LoadDefaultModules(void) NetlibInitSsl(); if ( LoadProtocolsModule()) return 1; LoadDbAccounts(); // retrieves the account array from a database - if ( LoadContactsModule()) return 1; if ( LoadContactListModule()) return 1; if ( LoadAddContactModule()) return 1; if ( LoadNewPluginsModule()) return 1; // will call Load(void) on everything, clist will load first @@ -129,11 +126,10 @@ int LoadDefaultModules(void) //order becomes less important below here if ( LoadFindAddModule()) return 1; - if ( LoadAwayMsgModule()) return 1; if ( LoadIgnoreModule()) return 1; if ( LoadVisibilityModule()) return 1; - for (int i=1; i < 10; i++) { + for (int i=0; i < 11; i++) { if ( pluginDefault[i].pImpl ) continue; diff --git a/src/core/stdaway/awaymsg.cpp b/src/core/stdaway/awaymsg.cpp new file mode 100644 index 0000000000..ccc0ae740c --- /dev/null +++ b/src/core/stdaway/awaymsg.cpp @@ -0,0 +1,183 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + +int LoadAwayMessageSending(void); + +static HANDLE hAwayMsgMenuItem; +static HANDLE hWindowList; + +struct AwayMsgDlgData { + HANDLE hContact; + HANDLE hSeq; + HANDLE hAwayMsgEvent; +}; +#define HM_AWAYMSG (WM_USER+10) +static INT_PTR CALLBACK ReadAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + AwayMsgDlgData *dat = (AwayMsgDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch(message) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + dat = (AwayMsgDlgData*)mir_alloc(sizeof(AwayMsgDlgData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + + dat->hContact = (HANDLE)lParam; + dat->hAwayMsgEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_AWAYMSG); + dat->hSeq = (HANDLE)CallContactService(dat->hContact, PSS_GETAWAYMSG, 0, 0); + WindowList_Add(hWindowList, hwndDlg, dat->hContact); + + { + TCHAR str[256], format[128]; + TCHAR* contactName = pcli->pfnGetContactDisplayName(dat->hContact, 0); + char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)dat->hContact, 0); + WORD dwStatus = DBGetContactSettingWord(dat->hContact, szProto, "Status", ID_STATUS_OFFLINE); + TCHAR* status = pcli->pfnGetStatusModeDescription(dwStatus, 0); + + GetWindowText(hwndDlg, format, SIZEOF(format)); + mir_sntprintf(str, SIZEOF(str), format, status, contactName); + SetWindowText(hwndDlg, str); + + GetDlgItemText(hwndDlg, IDC_RETRIEVING, format, SIZEOF(format)); + mir_sntprintf(str, SIZEOF(str), format, status); + SetDlgItemText(hwndDlg, IDC_RETRIEVING, str); + + Window_SetProtoIcon_IcoLib(hwndDlg, szProto, dwStatus); + } + if (dat->hSeq == NULL) + { + ACKDATA ack = {0}; + ack.cbSize = sizeof(ack); + ack.hContact = dat->hContact; + ack.type = ACKTYPE_AWAYMSG; + ack.result = ACKRESULT_SUCCESS; + SendMessage(hwndDlg, HM_AWAYMSG, 0, (LPARAM)&ack); + } + Utils_RestoreWindowPosition(hwndDlg, (HANDLE)lParam, "SRAway", "AwayMsgDlg"); + return TRUE; + + case HM_AWAYMSG: + { + ACKDATA *ack = (ACKDATA*)lParam; + if (ack->hContact != dat->hContact || ack->type != ACKTYPE_AWAYMSG) break; + if (ack->result != ACKRESULT_SUCCESS) break; + if (dat->hAwayMsgEvent && ack->hProcess == dat->hSeq) { UnhookEvent(dat->hAwayMsgEvent); dat->hAwayMsgEvent = NULL; } + + SetDlgItemText(hwndDlg, IDC_MSG, (const TCHAR*)ack->lParam); + + ShowWindow(GetDlgItem(hwndDlg, IDC_RETRIEVING), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_MSG), SW_SHOW); + SetDlgItemText(hwndDlg, IDOK, TranslateT("&Close")); + break; + } + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDCANCEL: + case IDOK: + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + if (dat->hAwayMsgEvent) UnhookEvent(dat->hAwayMsgEvent); + Utils_SaveWindowPosition(hwndDlg, dat->hContact, "SRAway", "AwayMsgDlg"); + WindowList_Remove(hWindowList, hwndDlg); + Window_FreeIcon_IcoLib(hwndDlg); + mir_free(dat); + break; + } + return FALSE; +} + +static INT_PTR GetMessageCommand(WPARAM wParam, LPARAM) +{ + HWND hwnd; + if (hwnd = WindowList_Find(hWindowList, (HANDLE)wParam)) { + SetForegroundWindow(hwnd); + SetFocus(hwnd); + } + else CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_READAWAYMSG), NULL, ReadAwayMsgDlgProc, wParam); + return 0; +} + +static int AwayMsgPreBuildMenu(WPARAM wParam, LPARAM) +{ + CLISTMENUITEM clmi; + TCHAR str[128]; + char *szProto; + + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + ZeroMemory(&clmi, sizeof(clmi)); + clmi.cbSize = sizeof(clmi); + clmi.flags = CMIM_FLAGS | CMIF_NOTOFFLINE | CMIF_HIDDEN | CMIF_TCHAR; + + if (szProto != NULL) { + int chatRoom = szProto ? DBGetContactSettingByte((HANDLE)wParam, szProto, "ChatRoom", 0) : 0; + if ( !chatRoom) { + int status = DBGetContactSettingWord((HANDLE)wParam, szProto, "Status", ID_STATUS_OFFLINE); + mir_sntprintf(str, SIZEOF(str), TranslateT("Re&ad %s Message"), pcli->pfnGetStatusModeDescription(status, 0)); + clmi.ptszName = str; + if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGRECV) { + if (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(status)) { + clmi.flags = CMIM_FLAGS | CMIM_NAME | CMIF_NOTOFFLINE | CMIM_ICON | CMIF_TCHAR; + clmi.hIcon = LoadSkinProtoIcon(szProto, status); + } } } } + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hAwayMsgMenuItem, (LPARAM)&clmi); + IcoLib_ReleaseIcon(clmi.hIcon, 0); + return 0; +} + +static int AwayMsgPreShutdown(WPARAM, LPARAM) +{ + if (hWindowList) WindowList_BroadcastAsync(hWindowList, WM_CLOSE, 0, 0); + return 0; +} + +int LoadAwayMsgModule(void) +{ + CLISTMENUITEM mi = { 0 }; + + hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + CreateServiceFunction(MS_AWAYMSG_SHOWAWAYMSG, GetMessageCommand); + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_NOTOFFLINE; + mi.pszName = LPGEN("Re&ad Status Message"); + mi.pszService = MS_AWAYMSG_SHOWAWAYMSG; + hAwayMsgMenuItem = Menu_AddContactMenuItem(&mi); + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, AwayMsgPreBuildMenu); + HookEvent(ME_SYSTEM_PRESHUTDOWN, AwayMsgPreShutdown); + return LoadAwayMessageSending(); +} diff --git a/src/core/stdaway/commonheaders.cpp b/src/core/stdaway/commonheaders.cpp new file mode 100644 index 0000000000..95b2201163 --- /dev/null +++ b/src/core/stdaway/commonheaders.cpp @@ -0,0 +1,2 @@ +#include "commonheaders.h" + diff --git a/src/core/stdaway/commonheaders.h b/src/core/stdaway/commonheaders.h new file mode 100644 index 0000000000..c9ed5a65d2 --- /dev/null +++ b/src/core/stdaway/commonheaders.h @@ -0,0 +1,93 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +// to enable all 0.9.0 core functions +#define MIRANDA_VER 0x0A00 + +#define WINVER 0x0700 +#define _WIN32_WINNT 0x0700 +#define _WIN32_IE 0x0601 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "version.h" + +#include "../../resource.h" +#include "../stdplug.h" + +extern HINSTANCE hInst; diff --git a/src/core/stdaway/main.cpp b/src/core/stdaway/main.cpp new file mode 100644 index 0000000000..7b9b12772d --- /dev/null +++ b/src/core/stdaway/main.cpp @@ -0,0 +1,75 @@ +/* + +Standard away message processing module for Myranda IM + +Copyright (C) 2012 George Hazan + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "commonheaders.h" + +int LoadAwayMsgModule(void); + +CLIST_INTERFACE* pcli; +HINSTANCE hInst; +int hLangpack; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + MIRANDA_VERSION_DWORD, + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {E58558E3-83E7-44EF-8E39-D9E0541956DF} + { 0xe58558e3, 0x83e7, 0x44ef, {0x8e, 0x39, 0xd9, 0xe0, 0x54, 0x19, 0x56, 0xdf}} +}; + +static const MUUID interfaces[] = { MIID_SRAWAY, MIID_LAST }; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + hInst = hinstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +extern "C" int __declspec(dllexport) Load(void) +{ + mir_getLP(&pluginInfo); + + pcli = ( CLIST_INTERFACE* )CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)hInst); + + LoadAwayMsgModule(); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + return 0; +} diff --git a/src/core/stdaway/resource.rc b/src/core/stdaway/resource.rc new file mode 100644 index 0000000000..67ab10e988 --- /dev/null +++ b/src/core/stdaway/resource.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\..\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_AWAYMSG DIALOGEX 0, 0, 263, 151 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Status Messages",IDC_STATIC,4,5,255,142 + COMBOBOX IDC_STATUS,12,19,240,97,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Do not reply to requests for this message",IDC_DONTREPLY, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,37,227,10 + CONTROL "Do not pop up dialog asking for new message",IDC_NODIALOG, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,50,227,10 + CONTROL "By default, use the same message as last time",IDC_USEPREVIOUS, + "Button",BS_AUTORADIOBUTTON,23,65,227,10 + CONTROL "By default, use this message:",IDC_USESPECIFIC,"Button",BS_AUTORADIOBUTTON,23,78,227,10 + EDITTEXT IDC_MSG,33,91,219,38,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL + LTEXT "Use %time% for the current time, %date% for the current date",IDC_STATIC,33,131,219,8 +END + +IDD_MODERNOPT_STATUS DIALOGEX 0, 0, 369, 113 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + COMBOBOX IDC_STATUS,2,54,16,97,CBS_DROPDOWNLIST | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + CONTROL "Do not reply to requests for this message",IDC_DONTREPLY, + "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,0,33,10,10 + CONTROL "Do not pop up dialog asking for new message",IDC_NODIALOG, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,93,264,10 + CONTROL "By default, use the same message as last time",IDC_USEPREVIOUS, + "Button",BS_AUTORADIOBUTTON,105,13,227,10 + CONTROL "By default, use this message:",IDC_USESPECIFIC,"Button",BS_AUTORADIOBUTTON,105,26,227,10 + EDITTEXT IDC_MSG,125,39,244,38,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL + CTEXT "Use %time% for the current time, %date% for the current date",IDC_STATIC,125,78,244,8,SS_CENTERIMAGE + LTEXT "Status messages:",IDC_TXT_TITLE1,0,0,246,8 + LISTBOX IDC_LST_STATUS,10,13,90,95,LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPT_AWAYMSG, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 259 + TOPMARGIN, 4 + BOTTOMMARGIN, 147 + END + + IDD_MODERNOPT_STATUS, DIALOG + BEGIN + VERTGUIDE, 10 + VERTGUIDE, 100 + VERTGUIDE, 105 + VERTGUIDE, 218 + BOTTOMMARGIN, 103 + HORZGUIDE, 8 + HORZGUIDE, 13 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\..\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include \r\n" + "#include \r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED diff --git a/src/core/stdaway/sendmsg.cpp b/src/core/stdaway/sendmsg.cpp new file mode 100644 index 0000000000..721a99af9b --- /dev/null +++ b/src/core/stdaway/sendmsg.cpp @@ -0,0 +1,630 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + + +static DWORD protoModeMsgFlags; +static HWND hwndStatusMsg; + +static bool Proto_IsAccountEnabled(PROTOACCOUNT* pa) +{ + return pa && ((pa->bIsEnabled && !pa->bDynDisabled) || pa->bOldProto); +} + +static bool Proto_IsAccountLocked(PROTOACCOUNT* pa) +{ + return pa && DBGetContactSettingByte(NULL, pa->szModuleName, "LockMainStatus", 0) != 0; +} + +static const TCHAR *GetDefaultMessage(int status) +{ + switch(status) { + case ID_STATUS_AWAY: return TranslateT("I've been away since %time%."); + case ID_STATUS_NA: return TranslateT("Give it up, I'm not in!"); + case ID_STATUS_OCCUPIED: return TranslateT("Not right now."); + case ID_STATUS_DND: return TranslateT("Give a guy some peace, would ya?"); + case ID_STATUS_FREECHAT: return TranslateT("I'm a chatbot!"); + case ID_STATUS_ONLINE: return TranslateT("Yep, I'm here."); + case ID_STATUS_OFFLINE: return TranslateT("Nope, not here."); + case ID_STATUS_INVISIBLE: return TranslateT("I'm hiding from the mafia."); + case ID_STATUS_ONTHEPHONE: return TranslateT("That'll be the phone."); + case ID_STATUS_OUTTOLUNCH: return TranslateT("Mmm...food."); + case ID_STATUS_IDLE: return TranslateT("idleeeeeeee"); + } + return NULL; +} + +static const char *StatusModeToDbSetting(int status, const char *suffix) +{ + const char *prefix; + static char str[64]; + + switch(status) + { + case ID_STATUS_AWAY: prefix = "Away"; break; + case ID_STATUS_NA: prefix = "Na"; break; + case ID_STATUS_DND: prefix = "Dnd"; break; + case ID_STATUS_OCCUPIED: prefix = "Occupied"; break; + case ID_STATUS_FREECHAT: prefix = "FreeChat"; break; + case ID_STATUS_ONLINE: prefix = "On"; break; + case ID_STATUS_OFFLINE: prefix = "Off"; break; + case ID_STATUS_INVISIBLE: prefix = "Inv"; break; + case ID_STATUS_ONTHEPHONE: prefix = "Otp"; break; + case ID_STATUS_OUTTOLUNCH: prefix = "Otl"; break; + case ID_STATUS_IDLE: prefix = "Idl"; break; + default: return NULL; + } + mir_snprintf(str, SIZEOF(str), "%s%s", prefix, suffix); + return str; +} + +static bool GetStatusModeByte(int status, const char *suffix) +{ + return db_get_b(NULL, "SRAway", StatusModeToDbSetting(status, suffix), 0) != 0; +} + +static void SetStatusModeByte(int status, const char *suffix, BYTE value) +{ + db_set_b(NULL, "SRAway", StatusModeToDbSetting(status, suffix), value); +} + +static TCHAR* GetAwayMessage(int statusMode, char *szProto) +{ + if (szProto && !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(statusMode))) + return NULL; + + if ( GetStatusModeByte(statusMode, "Ignore")) + return NULL; + + DBVARIANT dbv; + if ( GetStatusModeByte(statusMode, "UsePrev")) { + if ( DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Msg"), &dbv)) + dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusMode)); + } + else { + if ( DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusMode, "Default"), &dbv)) + dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusMode)); + + for (int i=0; dbv.ptszVal[i]; i++) { + if (dbv.ptszVal[i] != '%') + continue; + + TCHAR substituteStr[128]; + if ( !_tcsnicmp(dbv.ptszVal + i, _T("%time%"), 6)) { + MIRANDA_IDLE_INFO mii = {0}; + mii.cbSize = sizeof(mii); + CallService(MS_IDLE_GETIDLEINFO, 0, (LPARAM)&mii); + + if (mii.idleType == 1) { + int mm; + SYSTEMTIME t; + GetLocalTime(&t); + mm = t.wMinute + t.wHour * 60 - mii.idleTime; + if (mm < 0) mm += 60 * 24; + t.wMinute = mm % 60; + t.wHour = mm / 60; + GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &t, NULL, substituteStr, SIZEOF(substituteStr)); + } + else GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, NULL, NULL, substituteStr, SIZEOF(substituteStr)); + } + else if ( !_tcsnicmp(dbv.ptszVal + i, _T("%date%"), 6)) + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, substituteStr, SIZEOF(substituteStr)); + else continue; + + if (lstrlen(substituteStr) > 6) + dbv.ptszVal = (TCHAR*)mir_realloc(dbv.ptszVal, (lstrlen(dbv.ptszVal) + 1 + lstrlen(substituteStr) - 6) * sizeof(TCHAR)); + MoveMemory(dbv.ptszVal + i + lstrlen(substituteStr), dbv.ptszVal + i + 6, (lstrlen(dbv.ptszVal) - i - 5) * sizeof(TCHAR)); + CopyMemory(dbv.ptszVal+i, substituteStr, lstrlen(substituteStr) * sizeof(TCHAR)); + } + } + return dbv.ptszVal; +} + +static WNDPROC OldMessageEditProc; + +static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_CHAR: + if (wParam == '\n' && GetKeyState(VK_CONTROL) & 0x8000) + { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) //ctrl-a + { + SendMessage(hwnd, EM_SETSEL, 0, -1); + return 0; + } + if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) // ctrl-w + { + SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return 0; + } + if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000) //ctrl-backspace + { + DWORD start, end; + TCHAR *text; + int textLen; + SendMessage(hwnd, EM_GETSEL, (WPARAM)&end, 0); + SendMessage(hwnd, WM_KEYDOWN, VK_LEFT, 0); + SendMessage(hwnd, EM_GETSEL, (WPARAM)&start, 0); + textLen = GetWindowTextLength(hwnd); + text = (TCHAR *)alloca(sizeof(TCHAR) * (textLen + 1)); + GetWindowText(hwnd, text, textLen + 1); + memmove(text + start, text + end, sizeof(TCHAR) * (textLen + 1 - end)); + SetWindowText(hwnd, text); + SendMessage(hwnd, EM_SETSEL, start, start); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd); + return 0; + } + break; + } + return CallWindowProc(OldMessageEditProc, hwnd, msg, wParam, lParam); +} + +void ChangeAllProtoMessages(char *szProto, int statusMode, TCHAR *msg) +{ + if (szProto == NULL) { + int nAccounts; + PROTOACCOUNT** accounts; + ProtoEnumAccounts(&nAccounts, &accounts); + + for (int i=0; i < nAccounts; i++) + { + PROTOACCOUNT* pa = accounts[i]; + if ( !Proto_IsAccountEnabled(pa)) continue; + if ((CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) && + !Proto_IsAccountLocked(pa)) + CallProtoService(pa->szModuleName, PS_SETAWAYMSGT, statusMode, (LPARAM)msg); + } + } + else CallProtoService(szProto, PS_SETAWAYMSGT, statusMode, (LPARAM)msg); +} + +struct SetAwayMsgData +{ + int statusMode; + int countdown; + TCHAR okButtonFormat[64]; + char *szProto; + HANDLE hPreshutdown; +}; +struct SetAwasMsgNewData +{ + char *szProto; + int statusMode; +}; + +#define DM_SRAWAY_SHUTDOWN WM_USER+10 + +static INT_PTR CALLBACK SetAwayMsgDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + SetAwayMsgData* dat = (SetAwayMsgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch(message) { + case WM_INITDIALOG: + { + SetAwasMsgNewData *newdat = (SetAwasMsgNewData*)lParam; + TranslateDialogDefault(hwndDlg); + dat = (SetAwayMsgData*)mir_alloc(sizeof(SetAwayMsgData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + dat->statusMode = newdat->statusMode; + dat->szProto = newdat->szProto; + mir_free(newdat); + SendDlgItemMessage(hwndDlg, IDC_MSG, EM_LIMITTEXT, 1024, 0); + OldMessageEditProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MSG), GWLP_WNDPROC, (LONG_PTR)MessageEditSubclassProc); + { + TCHAR str[256], format[128]; + GetWindowText(hwndDlg, format, SIZEOF(format)); + mir_sntprintf(str, SIZEOF(str), format, pcli->pfnGetStatusModeDescription(dat->statusMode, 0)); + SetWindowText(hwndDlg, str); + } + GetDlgItemText(hwndDlg, IDOK, dat->okButtonFormat, SIZEOF(dat->okButtonFormat)); + { + TCHAR *msg = GetAwayMessage(dat->statusMode, dat->szProto); + SetDlgItemText(hwndDlg, IDC_MSG, msg); + mir_free(msg); + } + dat->countdown = 6; + SendMessage(hwndDlg, WM_TIMER, 0, 0); + Window_SetProtoIcon_IcoLib(hwndDlg, dat->szProto, dat->statusMode); + Utils_RestoreWindowPosition(hwndDlg, NULL, "SRAway", "AwayMsgDlg"); + SetTimer(hwndDlg, 1, 1000, 0); + dat->hPreshutdown = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, DM_SRAWAY_SHUTDOWN); + } + return TRUE; + + case WM_TIMER: + if (--dat->countdown >= 0) { + TCHAR str[64]; + mir_sntprintf(str, SIZEOF(str), dat->okButtonFormat, dat->countdown); + SetDlgItemText(hwndDlg, IDOK, str); + } + else { + KillTimer(hwndDlg, 1); + PostMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + + case WM_CLOSE: + { + TCHAR *msg = GetAwayMessage(dat->statusMode, dat->szProto); + ChangeAllProtoMessages(dat->szProto, dat->statusMode, msg); + mir_free(msg); + } + DestroyWindow(hwndDlg); + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + if (dat->countdown < 0) { + TCHAR str[1024]; + GetDlgItemText(hwndDlg, IDC_MSG, str, SIZEOF(str)); + ChangeAllProtoMessages(dat->szProto, dat->statusMode, str); + DBWriteContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(dat->statusMode, "Msg"), str); + DestroyWindow(hwndDlg); + } + else PostMessage(hwndDlg, WM_CLOSE, 0, 0); + break; + + case IDC_MSG: + if (dat->countdown >= 0) { + KillTimer(hwndDlg, 1); + SetDlgItemText(hwndDlg, IDOK, TranslateT("OK")); + dat->countdown = -1; + } + break; + } + break; + + case DM_SRAWAY_SHUTDOWN: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + Utils_SaveWindowPosition(hwndDlg, NULL, "SRAway", "AwayMsgDlg"); + KillTimer(hwndDlg, 1); + UnhookEvent(dat->hPreshutdown); + Window_FreeIcon_IcoLib(hwndDlg); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MSG), GWLP_WNDPROC, (LONG_PTR)OldMessageEditProc); + mir_free(dat); + hwndStatusMsg = NULL; + break; + } + return FALSE; +} + +static int StatusModeChange(WPARAM wParam, LPARAM lParam) +{ + BOOL bScreenSaverRunning = FALSE; + int statusMode = (int)wParam; + char *szProto = (char*)lParam; + + if (protoModeMsgFlags == 0) return 0; + + // If its a global change check the complete PFLAGNUM_3 flags to see if a popup might be needed + if ( !szProto) + { + if ( !(protoModeMsgFlags & Proto_Status2Flag(statusMode))) + return 0; + } + else + { + // If its a single protocol check the PFLAGNUM_3 for the single protocol + if ( !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) || + !(CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_3, 0) & Proto_Status2Flag(statusMode))) + return 0; + } + + SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &bScreenSaverRunning, FALSE); + if (GetStatusModeByte(statusMode, "Ignore")) + ChangeAllProtoMessages(szProto, statusMode, NULL); + + else if (bScreenSaverRunning || ( !GetAsyncKeyState(VK_CONTROL) && GetStatusModeByte(statusMode, "NoDlg"))) { + TCHAR *msg = GetAwayMessage(statusMode, szProto); + ChangeAllProtoMessages(szProto, statusMode, msg); + mir_free(msg); + } + else { + SetAwasMsgNewData *newdat = (SetAwasMsgNewData*)mir_alloc(sizeof(SetAwasMsgNewData)); + newdat->szProto = szProto; + newdat->statusMode = statusMode; + if (hwndStatusMsg) + DestroyWindow(hwndStatusMsg); + hwndStatusMsg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SETAWAYMSG), + NULL, SetAwayMsgDlgProc, (LPARAM)newdat); + } + return 0; +} + +static const int statusModes[] = +{ + ID_STATUS_OFFLINE, ID_STATUS_ONLINE, ID_STATUS_AWAY, ID_STATUS_NA, ID_STATUS_OCCUPIED, ID_STATUS_DND, + ID_STATUS_FREECHAT, ID_STATUS_INVISIBLE, ID_STATUS_OUTTOLUNCH, ID_STATUS_ONTHEPHONE, ID_STATUS_IDLE +}; + +struct AwayMsgInfo +{ + int ignore; + int noDialog; + int usePrevious; + TCHAR msg[1024]; +}; +struct AwayMsgDlgData +{ + struct AwayMsgInfo info[ SIZEOF(statusModes) ]; + int oldPage; +}; + +static INT_PTR CALLBACK DlgProcAwayMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + AwayMsgDlgData *dat = (AwayMsgDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + HWND hLst = GetDlgItem(hwndDlg, IDC_LST_STATUS); + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + dat = (AwayMsgDlgData*)mir_alloc(sizeof(AwayMsgDlgData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + dat->oldPage = -1; + for (int i=0; i < SIZEOF(statusModes); i++) + { + if ( !(protoModeMsgFlags & Proto_Status2Flag(statusModes[i]))) + continue; + + int j; + if (hLst) { + j = SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_ADDSTRING, 0, (LPARAM)pcli->pfnGetStatusModeDescription(statusModes[i], 0)); + SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_SETITEMDATA, j, statusModes[i]); + } + else { + j = SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)pcli->pfnGetStatusModeDescription(statusModes[i], 0)); + SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETITEMDATA, j, statusModes[i]); + } + + dat->info[j].ignore = GetStatusModeByte(statusModes[i], "Ignore"); + dat->info[j].noDialog = GetStatusModeByte(statusModes[i], "NoDlg"); + dat->info[j].usePrevious = GetStatusModeByte(statusModes[i], "UsePrev"); + + DBVARIANT dbv; + if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusModes[i], "Default"), &dbv)) + if (DBGetContactSettingTString(NULL, "SRAway", StatusModeToDbSetting(statusModes[i], "Msg"), &dbv)) + dbv.ptszVal = mir_tstrdup(GetDefaultMessage(statusModes[i])); + lstrcpy(dat->info[j].msg, dbv.ptszVal); + mir_free(dbv.ptszVal); + } + if (hLst) + SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_SETCURSEL, 0, 0); + else + SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_SETCURSEL, 0, 0); + SendMessage(hwndDlg, WM_COMMAND, hLst ? MAKEWPARAM(IDC_LST_STATUS, LBN_SELCHANGE) : MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); + } + return TRUE; + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT)lParam; + if (mis->CtlID == IDC_LST_STATUS) + mis->itemHeight = 20; + break; + } + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam; + if (dis->CtlID != IDC_LST_STATUS) break; + if (dis->itemID < 0) break; + + TCHAR buf[128]; + SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETTEXT, dis->itemID, (LPARAM)buf); + + if (dis->itemState & (ODS_SELECTED|ODS_FOCUS)) { + FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT)); + SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else { + FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_WINDOW)); + SetTextColor(dis->hDC, GetSysColor(COLOR_WINDOWTEXT)); + } + + RECT rc = dis->rcItem; + DrawIconEx(dis->hDC, 3, (rc.top + rc.bottom - 16) / 2, LoadSkinnedProtoIcon(NULL, dis->itemData), 16, 16, 0, NULL, DI_NORMAL); + rc.left += 25; + SetBkMode(dis->hDC, TRANSPARENT); + DrawText(dis->hDC, buf, -1, &rc, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX); + break; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_LST_STATUS: + case IDC_STATUS: + if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == LBN_SELCHANGE)) { + int i = hLst ? + SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETCURSEL, 0, 0) : + SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCURSEL, 0, 0); + if (dat->oldPage != -1) { + dat->info[dat->oldPage].ignore = IsDlgButtonChecked(hwndDlg, IDC_DONTREPLY); + dat->info[dat->oldPage].noDialog = IsDlgButtonChecked(hwndDlg, IDC_NODIALOG); + dat->info[dat->oldPage].usePrevious = IsDlgButtonChecked(hwndDlg, IDC_USEPREVIOUS); + GetDlgItemText(hwndDlg, IDC_MSG, dat->info[dat->oldPage].msg, SIZEOF(dat->info[dat->oldPage].msg)); + } + CheckDlgButton(hwndDlg, IDC_DONTREPLY, i < 0 ? 0 : dat->info[i].ignore); + CheckDlgButton(hwndDlg, IDC_NODIALOG, i < 0 ? 0 : dat->info[i].noDialog); + CheckDlgButton(hwndDlg, IDC_USEPREVIOUS, i < 0 ? 0 : dat->info[i].usePrevious); + CheckDlgButton(hwndDlg, IDC_USESPECIFIC, i < 0 ? 0 : !dat->info[i].usePrevious); + + SetDlgItemText(hwndDlg, IDC_MSG, i < 0 ? _T("") : dat->info[i].msg); + + EnableWindow(GetDlgItem(hwndDlg, IDC_NODIALOG), i < 0 ? 0 : !dat->info[i].ignore); + EnableWindow(GetDlgItem(hwndDlg, IDC_USEPREVIOUS), i < 0 ? 0 : !dat->info[i].ignore); + EnableWindow(GetDlgItem(hwndDlg, IDC_USESPECIFIC), i < 0 ? 0 : !dat->info[i].ignore); + EnableWindow(GetDlgItem(hwndDlg, IDC_MSG), i < 0 ? 0 : !(dat->info[i].ignore || dat->info[i].usePrevious)); + dat->oldPage = i; + } + return 0; + + case IDC_DONTREPLY: + case IDC_USEPREVIOUS: + case IDC_USESPECIFIC: + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); + break; + + case IDC_MSG: + if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) + return 0; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch(((LPNMHDR)lParam)->code) { + case PSN_APPLY: + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_STATUS, CBN_SELCHANGE), 0); + { + int i = hLst ? (SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETCOUNT, 0, 0) - 1) : + (SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETCOUNT, 0, 0) - 1); + for (; i >= 0; i--) { + int status = hLst ? + SendDlgItemMessage(hwndDlg, IDC_LST_STATUS, LB_GETITEMDATA, i, 0): + SendDlgItemMessage(hwndDlg, IDC_STATUS, CB_GETITEMDATA, i, 0); + SetStatusModeByte(status, "Ignore", (BYTE)dat->info[i].ignore); + SetStatusModeByte(status, "NoDlg", (BYTE)dat->info[i].noDialog); + SetStatusModeByte(status, "UsePrev", (BYTE)dat->info[i].usePrevious); + db_set_ts(NULL, "SRAway", StatusModeToDbSetting(status, "Default"), dat->info[i].msg); + } + return TRUE; + } + } + break; + } + break; + + case WM_DESTROY: + mir_free(dat); + break; + } + return FALSE; +} + +static int AwayMsgOptInitialise(WPARAM wParam, LPARAM) +{ + if (protoModeMsgFlags == 0) + return 0; + + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = 870000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AWAYMSG); + odp.pszTitle = LPGEN("Status Messages"); + odp.pszGroup = LPGEN("Status"); + odp.pfnDlgProc = DlgProcAwayMsgOpts; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + return 0; +} + +static int AwayMsgSendModernOptInit(WPARAM wParam, LPARAM) +{ + if (protoModeMsgFlags == 0) + return 0; + + static const int iBoldControls[] = + { + IDC_TXT_TITLE1, IDC_TXT_TITLE2, IDC_TXT_TITLE3, + MODERNOPT_CTRL_LAST + }; + + MODERNOPTOBJECT obj = {0}; + obj.cbSize = sizeof(obj); + obj.hInstance = hInst; + obj.dwFlags = MODEROPT_FLG_TCHAR | MODEROPT_FLG_NORESIZE; + obj.iSection = MODERNOPT_PAGE_STATUS; + obj.iType = MODERNOPT_TYPE_SECTIONPAGE; + obj.iBoldControls = (int*)iBoldControls; + obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_STATUS); + obj.pfnDlgProc = DlgProcAwayMsgOpts; + obj.lpzHelpUrl = "http://wiki.miranda-im.org/"; + CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); + return 0; +} + +static int AwayMsgSendAccountsChanged(WPARAM, LPARAM) +{ + protoModeMsgFlags = 0; + + int nAccounts; + PROTOACCOUNT** accounts; + ProtoEnumAccounts(&nAccounts, &accounts); + for (int i=0; i < nAccounts; i++) { + if ( !Proto_IsAccountEnabled(accounts[i])) + continue; + + protoModeMsgFlags |= CallProtoService(accounts[i]->szModuleName, PS_GETCAPS, PFLAGNUM_3, 0); + } + + return 0; +} + +static int AwayMsgSendModulesLoaded(WPARAM, LPARAM) +{ + AwayMsgSendAccountsChanged(0, 0); + + HookEvent(ME_CLIST_STATUSMODECHANGE, StatusModeChange); + HookEvent(ME_MODERNOPT_INITIALIZE, AwayMsgSendModernOptInit); + HookEvent(ME_OPT_INITIALISE, AwayMsgOptInitialise); + return 0; +} + +//remember to mir_free() the return value +static INT_PTR sttGetAwayMessageT(WPARAM wParam, LPARAM lParam) +{ + return (INT_PTR)GetAwayMessage((int)wParam, (char*)lParam); +} + + +static INT_PTR sttGetAwayMessage(WPARAM wParam, LPARAM lParam) +{ + TCHAR* msg = GetAwayMessage((int)wParam, (char*)lParam); + char* res = mir_t2a(msg); + mir_free(msg); + return (INT_PTR)res; +} + + +int LoadAwayMessageSending(void) +{ + HookEvent(ME_SYSTEM_MODULESLOADED, AwayMsgSendModulesLoaded); + HookEvent(ME_PROTO_ACCLISTCHANGED, AwayMsgSendAccountsChanged); + + CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSG, sttGetAwayMessage); + CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSGW, sttGetAwayMessageT); + return 0; +} diff --git a/src/core/stdaway/stdaway_10.vcxproj b/src/core/stdaway/stdaway_10.vcxproj new file mode 100644 index 0000000000..ac5c17f3d0 --- /dev/null +++ b/src/core/stdaway/stdaway_10.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + stdaway + {C14D6E0D-810E-4599-A6E0-17298AFA0501} + + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Core\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Core\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Full + OnlyExplicitInline + Size + ..\..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;ADDCONTACTPLUS_EXPORTS;%(PreprocessorDefinitions) + true + false + true + Fast + Level3 + 4996;%(DisableSpecificWarnings) + Use + commonheaders.h + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include\msapi;..\..\..\include + + + miranda32.lib;ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + true + true + true + 0x3ae00000 + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + Disabled + ..\..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;ADDCONTACTPLUS_EXPORTS;%(PreprocessorDefinitions) + false + true + EnableFastChecks + MultiThreadedDebugDLL + true + Level3 + EditAndContinue + 4996;%(DisableSpecificWarnings) + Use + commonheaders.h + false + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include\msapi;..\..\..\include + + + miranda32.lib;ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + true + 0x3ae00000 + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + Full + OnlyExplicitInline + Size + ..\..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;_USRDLL;ADDCONTACTPLUS_EXPORTS;%(PreprocessorDefinitions) + true + false + true + Fast + Level3 + 4996;%(DisableSpecificWarnings) + Use + commonheaders.h + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\..\include\msapi;..\..\..\include + + + miranda64.lib;ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + true + true + true + 0x3ae00000 + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + Disabled + ..\..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_WINDOWS;_USRDLL;ADDCONTACTPLUS_EXPORTS;%(PreprocessorDefinitions) + false + true + EnableFastChecks + MultiThreadedDebugDLL + true + Level3 + 4996;%(DisableSpecificWarnings) + Use + commonheaders.h + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\..\include\msapi;..\..\..\include + + + miranda64.lib;ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + true + 0x3ae00000 + false + $(IntDir)$(TargetName).lib + Windows + $(SolutionDir)\lib + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/stdaway/stdaway_10.vcxproj.filters b/src/core/stdaway/stdaway_10.vcxproj.filters new file mode 100644 index 0000000000..5bd397eed2 --- /dev/null +++ b/src/core/stdaway/stdaway_10.vcxproj.filters @@ -0,0 +1,47 @@ + + + + + {5c074c9e-6c66-4233-bbd3-a50170fccf47} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {e30af2c4-42d4-4342-8eb9-2dbca157c6bb} + h;hpp;hxx;hm;inl + + + {9208a050-ffae-47fa-bc98-4ca4f79d37d7} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/src/core/stdaway/version.h b/src/core/stdaway/version.h new file mode 100644 index 0000000000..dfb0703db4 --- /dev/null +++ b/src/core/stdaway/version.h @@ -0,0 +1,14 @@ + +#include + +#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION +#define __VERSION_STRING MIRANDA_VERSION_STRING + +#define __PLUGIN_NAME "stdaway" +#define __INTERNAL_NAME "stdaway" +#define __FILENAME "stdaway.dll" +#define __DESCRIPTION "Core module for the away messages processing." +#define __AUTHOR "Myranda team" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "http://nightly.miranda.im" +#define __COPYRIGHT "© 2012 Myranda team" diff --git a/src/core/stdaway/version.rc b/src/core/stdaway/version.rc new file mode 100644 index 0000000000..e637f0cb33 --- /dev/null +++ b/src/core/stdaway/version.rc @@ -0,0 +1,38 @@ +// Microsoft Visual C++ generated resource script. +// +#include "afxres.h" +#include "version.h" + +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#endif //_WIN32 + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", __DESCRIPTION + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "ProductName", __PLUGIN_NAME + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/src/core/stduserinfo/contacts.cpp b/src/core/stduserinfo/contacts.cpp new file mode 100644 index 0000000000..03c546b64c --- /dev/null +++ b/src/core/stduserinfo/contacts.cpp @@ -0,0 +1,509 @@ +/* +Miranda IM + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" + +#define NAMEORDERCOUNT 8 +static TCHAR* nameOrderDescr[ NAMEORDERCOUNT ] = +{ + _T("My custom name (not moveable)"), + _T("Nick"), + _T("FirstName"), + _T("E-mail"), + _T("LastName"), + _T("Username"), + _T("FirstName LastName"), + _T("'(Unknown Contact)' (not moveable)") +}; + +BYTE nameOrder[NAMEORDERCOUNT]; + +static int GetDatabaseString(CONTACTINFO *ci, const char* setting, DBVARIANT* dbv) +{ + if (strcmp(ci->szProto, "CList") && CallProtoService(ci->szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_INFOSETTINGSVC) + { + DBCONTACTGETSETTING cgs = { ci->szProto, setting, dbv }; + dbv->type = (ci->dwFlag & CNF_UNICODE) ? DBVT_WCHAR : DBVT_ASCIIZ; + + int res = CallProtoService(ci->szProto, PS_GETINFOSETTING, (WPARAM)ci->hContact, (LPARAM)&cgs); + if (res != CALLSERVICE_NOTFOUND) return res; + } + + if (ci->dwFlag & CNF_UNICODE) + return DBGetContactSettingWString(ci->hContact, ci->szProto, setting, dbv); + + return DBGetContactSettingString(ci->hContact, ci->szProto, setting, dbv); +} + +static int ProcessDatabaseValueDefault(CONTACTINFO *ci, const char* setting) +{ + DBVARIANT dbv; + if ( !GetDatabaseString(ci, setting, &dbv)) { + switch (dbv.type) { + case DBVT_ASCIIZ: + if ( !dbv.pszVal[0]) break; + case DBVT_WCHAR: + if ( !dbv.pwszVal[0]) break; + ci->type = CNFT_ASCIIZ; + ci->pszVal = dbv.ptszVal; + return 0; + } + DBFreeVariant(&dbv); + } + + if (DBGetContactSetting(ci->hContact, ci->szProto, setting, &dbv)) + return 1; + + switch (dbv.type) { + case DBVT_BYTE: + ci->type = CNFT_BYTE; + ci->bVal = dbv.bVal; + return 0; + case DBVT_WORD: + ci->type = CNFT_WORD; + ci->wVal = dbv.wVal; + return 0; + case DBVT_DWORD: + ci->type = CNFT_DWORD; + ci->dVal = dbv.dVal; + return 0; + } + + DBFreeVariant(&dbv); + return 1; +} + +static INT_PTR GetContactInfo(WPARAM, LPARAM lParam) { + DBVARIANT dbv; + CONTACTINFO *ci = (CONTACTINFO*)lParam; + + if (ci == NULL) return 1; + if (ci->szProto == NULL) ci->szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEACCOUNT, (WPARAM)ci->hContact, 0); + if (ci->szProto == NULL) return 1; + ci->type = 0; + switch(ci->dwFlag & 0x7F) { + case CNF_FIRSTNAME: return ProcessDatabaseValueDefault(ci, "FirstName"); + case CNF_LASTNAME: return ProcessDatabaseValueDefault(ci, "LastName"); + case CNF_NICK: return ProcessDatabaseValueDefault(ci, "Nick"); + case CNF_EMAIL: return ProcessDatabaseValueDefault(ci, "e-mail"); + case CNF_CITY: return ProcessDatabaseValueDefault(ci, "City"); + case CNF_STATE: return ProcessDatabaseValueDefault(ci, "State"); + case CNF_PHONE: return ProcessDatabaseValueDefault(ci, "Phone"); + case CNF_HOMEPAGE: return ProcessDatabaseValueDefault(ci, "Homepage"); + case CNF_ABOUT: return ProcessDatabaseValueDefault(ci, "About"); + case CNF_AGE: return ProcessDatabaseValueDefault(ci, "Age"); + case CNF_GENDER: return ProcessDatabaseValueDefault(ci, "Gender"); + case CNF_FAX: return ProcessDatabaseValueDefault(ci, "Fax"); + case CNF_CELLULAR: return ProcessDatabaseValueDefault(ci, "Cellular"); + case CNF_BIRTHDAY: return ProcessDatabaseValueDefault(ci, "BirthDay"); + case CNF_BIRTHMONTH: return ProcessDatabaseValueDefault(ci, "BirthMonth"); + case CNF_BIRTHYEAR: return ProcessDatabaseValueDefault(ci, "BirthYear"); + case CNF_STREET: return ProcessDatabaseValueDefault(ci, "Street"); + case CNF_ZIP: return ProcessDatabaseValueDefault(ci, "ZIP"); + case CNF_LANGUAGE1: return ProcessDatabaseValueDefault(ci, "Language1"); + case CNF_LANGUAGE2: return ProcessDatabaseValueDefault(ci, "Language2"); + case CNF_LANGUAGE3: return ProcessDatabaseValueDefault(ci, "Language3"); + case CNF_CONAME: return ProcessDatabaseValueDefault(ci, "Company"); + case CNF_CODEPT: return ProcessDatabaseValueDefault(ci, "CompanyDepartment"); + case CNF_COPOSITION: return ProcessDatabaseValueDefault(ci, "CompanyPosition"); + case CNF_COSTREET: return ProcessDatabaseValueDefault(ci, "CompanyStreet"); + case CNF_COCITY: return ProcessDatabaseValueDefault(ci, "CompanyCity"); + case CNF_COSTATE: return ProcessDatabaseValueDefault(ci, "CompanyState"); + case CNF_COZIP: return ProcessDatabaseValueDefault(ci, "CompanyZIP"); + case CNF_COHOMEPAGE: return ProcessDatabaseValueDefault(ci, "CompanyHomepage"); + + case CNF_CUSTOMNICK: + { + char* saveProto = ci->szProto; ci->szProto = "CList"; + if (ci->hContact != NULL && !ProcessDatabaseValueDefault(ci, "MyHandle")) { + ci->szProto = saveProto; + return 0; + } + ci->szProto = saveProto; + break; + } + case CNF_COUNTRY: + case CNF_COCOUNTRY: + if ( !GetDatabaseString(ci, (ci->dwFlag & 0x7F) == CNF_COUNTRY ? "CountryName" : "CompanyCountryName", &dbv)) + return 0; + + if ( !DBGetContactSetting(ci->hContact, ci->szProto, (ci->dwFlag & 0x7F) == CNF_COUNTRY ? "Country" : "CompanyCountry", &dbv)) { + if (dbv.type == DBVT_WORD) { + int i, countryCount; + struct CountryListEntry *countries; + CallService(MS_UTILS_GETCOUNTRYLIST, (WPARAM)&countryCount, (LPARAM)&countries); + for (i=0;idwFlag & CNF_UNICODE) { + int cbLen = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)countries[i].szName, -1, NULL, 0); + WCHAR* buf = (WCHAR*)mir_alloc(sizeof(WCHAR)*(cbLen+1)); + if (buf != NULL) + MultiByteToWideChar(CP_ACP, 0, (LPCSTR)countries[i].szName, -1, buf, cbLen); + ci->pszVal = (TCHAR*)buf; + } + else ci->pszVal = (TCHAR*)mir_strdup(countries[i].szName); + + ci->type = CNFT_ASCIIZ; + DBFreeVariant(&dbv); + return 0; + } + } + else return ProcessDatabaseValueDefault(ci, (ci->dwFlag & 0x7F) == CNF_COUNTRY ? "Country" : "CompanyCountry"); + DBFreeVariant(&dbv); + } + break; + + case CNF_FIRSTLAST: + if ( !GetDatabaseString(ci, "FirstName", &dbv)) { + DBVARIANT dbv2; + if ( !GetDatabaseString(ci, "LastName", &dbv2)) { + ci->type = CNFT_ASCIIZ; + if (ci->dwFlag & CNF_UNICODE) { + size_t len = wcslen(dbv.pwszVal) + wcslen(dbv2.pwszVal) + 2; + WCHAR* buf = (WCHAR*)mir_alloc(sizeof(WCHAR)*len); + if (buf != NULL) + wcscat(wcscat(wcscpy(buf, dbv.pwszVal), L" "), dbv2.pwszVal); + ci->pszVal = (TCHAR*)buf; + } + else { + size_t len = strlen(dbv.pszVal) + strlen(dbv2.pszVal) + 2; + char* buf = (char*)mir_alloc(len); + if (buf != NULL) + strcat(strcat(strcpy(buf, dbv.pszVal), " "), dbv2.pszVal); + ci->pszVal = (TCHAR*)buf; + } + DBFreeVariant(&dbv); + DBFreeVariant(&dbv2); + return 0; + } + DBFreeVariant(&dbv); + } + break; + + case CNF_UNIQUEID: + { + char *uid = (char*)CallProtoService(ci->szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); + if ((INT_PTR)uid != CALLSERVICE_NOTFOUND && uid) + if ( !ProcessDatabaseValueDefault(ci, uid)) + return 0; + + break; + } + case CNF_DISPLAYUID: + { + if ( !ProcessDatabaseValueDefault(ci, "display_uid")) + return 0; + char *uid = (char*)CallProtoService(ci->szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); + if ((INT_PTR)uid != CALLSERVICE_NOTFOUND && uid) + if ( !ProcessDatabaseValueDefault(ci, uid)) + return 0; + + break; + } + case CNF_DISPLAYNC: + case CNF_DISPLAY: + { + int i; + for (i=0; i < NAMEORDERCOUNT; i++) { + switch(nameOrder[i]) { + case 0: // custom name + { + // make sure we aren't in CNF_DISPLAYNC mode + // don't get custom name for NULL contact + char* saveProto = ci->szProto; ci->szProto = "CList"; + if (ci->hContact != NULL && (ci->dwFlag&0x7F) == CNF_DISPLAY && !ProcessDatabaseValueDefault(ci, "MyHandle")) { + ci->szProto = saveProto; + return 0; + } + ci->szProto = saveProto; + break; + } + case 1: + if ( !ProcessDatabaseValueDefault(ci, "Nick")) // nick + return 0; + break; + case 2: + if ( !ProcessDatabaseValueDefault(ci, "FirstName")) // First Name + return 0; + break; + case 3: + if ( !ProcessDatabaseValueDefault(ci, "e-mail")) // E-mail + return 0; + break; + case 4: + if ( !ProcessDatabaseValueDefault(ci, "LastName")) // Last Name + return 0; + break; + case 5: // Unique id + { + // protocol must define a PFLAG_UNIQUEIDSETTING + char *uid = (char*)CallProtoService(ci->szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); + if ((INT_PTR)uid != CALLSERVICE_NOTFOUND && uid) { + if ( !GetDatabaseString(ci, uid, &dbv)) { + if (dbv.type == DBVT_BYTE || dbv.type == DBVT_WORD || dbv.type == DBVT_DWORD) { + long value = (dbv.type == DBVT_BYTE) ? dbv.bVal:(dbv.type == DBVT_WORD ? dbv.wVal : dbv.dVal); + if (ci->dwFlag & CNF_UNICODE) { + WCHAR buf[ 40 ]; + _ltow(value, buf, 10); + ci->pszVal = (TCHAR*)mir_wstrdup(buf); + } + else { + char buf[ 40 ]; + _ltoa(value, buf, 10); + ci->pszVal = (TCHAR*)mir_strdup(buf); + } + ci->type = CNFT_ASCIIZ; + return 0; + } + if (dbv.type == DBVT_ASCIIZ && !(ci->dwFlag & CNF_UNICODE)) { + ci->type = CNFT_ASCIIZ; + ci->pszVal = dbv.ptszVal; + return 0; + } + if (dbv.type == DBVT_WCHAR && (ci->dwFlag & CNF_UNICODE)) { + ci->type = CNFT_ASCIIZ; + ci->pszVal = dbv.ptszVal; + return 0; + } } } + break; + } + case 6: // first + last name + if ( !GetDatabaseString(ci, "FirstName", &dbv)) { + DBVARIANT dbv2; + if ( !GetDatabaseString(ci, "LastName", &dbv2)) { + ci->type = CNFT_ASCIIZ; + + if (ci->dwFlag & CNF_UNICODE) { + size_t len = wcslen(dbv.pwszVal) + wcslen(dbv2.pwszVal) + 2; + WCHAR* buf = (WCHAR*)mir_alloc(sizeof(WCHAR)*len); + if (buf != NULL) + wcscat(wcscat(wcscpy(buf, dbv.pwszVal), L" "), dbv2.pwszVal); + ci->pszVal = (TCHAR*)buf; + } + else { + size_t len = strlen(dbv.pszVal) + strlen(dbv2.pszVal) + 2; + char* buf = (char*)mir_alloc(len); + if (buf != NULL) + strcat(strcat(strcpy(buf, dbv.pszVal), " "), dbv2.pszVal); + ci->pszVal = (TCHAR*)buf; + } + + DBFreeVariant(&dbv); + DBFreeVariant(&dbv2); + return 0; + } + DBFreeVariant(&dbv); + } + break; + + case 7: + if (ci->dwFlag & CNF_UNICODE) + ci->pszVal = (TCHAR*)mir_wstrdup(TranslateW(L"'(Unknown Contact)'")); + else + ci->pszVal = (TCHAR*)mir_strdup(Translate("'(Unknown Contact)'")); + ci->type = CNFT_ASCIIZ; + return 0; + } } } + break; + + case CNF_TIMEZONE: { + HANDLE hTz = tmi.createByContact(ci->hContact, TZF_KNOWNONLY); + if (hTz) + { + LPTIME_ZONE_INFORMATION tzi = tmi.getTzi(hTz); + int offset = tzi->Bias + tzi->StandardBias; + + char str[80]; + mir_snprintf(str, SIZEOF(str), offset ? "UTC%+d:%02d" : "UTC", offset / -60, abs(offset % 60)); + ci->pszVal = ci->dwFlag & CNF_UNICODE ? (TCHAR*)mir_a2u(str) : (TCHAR*)mir_strdup(str); + ci->type = CNFT_ASCIIZ; + return 0; + } + break; + } + case CNF_MYNOTES: { + char* saveProto = ci->szProto; ci->szProto = "UserInfo"; + if ( !ProcessDatabaseValueDefault(ci, "MyNotes")) { + ci->szProto = saveProto; + return 0; + } + ci->szProto = saveProto; + break; + } } + + return 1; +} + +struct ContactOptionsData { + int dragging; + HTREEITEM hDragItem; +}; + +static INT_PTR CALLBACK ContactOpts(HWND hwndDlg, UINT msg, WPARAM, LPARAM lParam) +{ struct ContactOptionsData *dat; + + dat = (struct ContactOptionsData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { TranslateDialogDefault(hwndDlg); + dat = (struct ContactOptionsData*)mir_alloc(sizeof(struct ContactOptionsData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + dat->dragging = 0; + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_NAMEORDER), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_NAMEORDER), GWL_STYLE)|TVS_NOHSCROLL); + { TVINSERTSTRUCT tvis; + int i; + tvis.hParent = NULL; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT|TVIF_PARAM; + for (i=0; i < SIZEOF(nameOrderDescr); i++) { + tvis.item.lParam = nameOrder[i]; + tvis.item.pszText = TranslateTS(nameOrderDescr[ nameOrder[i]]); + TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), &tvis); + } } + return TRUE; + } + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case 0: + if (((LPNMHDR)lParam)->code == PSN_APPLY) + { DBCONTACTWRITESETTING cws; + TVITEM tvi; + int i; + cws.szModule = "Contact"; + cws.szSetting = "NameOrder"; + cws.value.type = DBVT_BLOB; + cws.value.cpbVal = SIZEOF(nameOrderDescr); + cws.value.pbVal = nameOrder; + tvi.hItem = TreeView_GetRoot(GetDlgItem(hwndDlg, IDC_NAMEORDER)); + i=0; + while (tvi.hItem != NULL) { + tvi.mask = TVIF_PARAM | TVIF_HANDLE; + TreeView_GetItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), &tvi); + nameOrder[i++] = (BYTE)tvi.lParam; + tvi.hItem = TreeView_GetNextSibling(GetDlgItem(hwndDlg, IDC_NAMEORDER), tvi.hItem); + } + CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)(HANDLE)NULL, (LPARAM)&cws); + CallService(MS_CLIST_INVALIDATEDISPLAYNAME, (WPARAM)INVALID_HANDLE_VALUE, 0); + } + break; + case IDC_NAMEORDER: + if (((LPNMHDR)lParam)->code == TVN_BEGINDRAGA) { + LPNMTREEVIEWA notify = (LPNMTREEVIEWA)lParam; + if (notify->itemNew.lParam == 0 || notify->itemNew.lParam == SIZEOF(nameOrderDescr)-1) + break; + SetCapture(hwndDlg); + dat->dragging = 1; + dat->hDragItem = ((LPNMTREEVIEW)lParam)->itemNew.hItem; + TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), dat->hDragItem); + } + break; + } + break; + case WM_MOUSEMOVE: + if ( !dat->dragging) break; + { TVHITTESTINFO hti; + hti.pt.x = (short)LOWORD(lParam); + hti.pt.y = (short)HIWORD(lParam); + ClientToScreen(hwndDlg, &hti.pt); + ScreenToClient(GetDlgItem(hwndDlg, IDC_NAMEORDER), &hti.pt); + TreeView_HitTest(GetDlgItem(hwndDlg, IDC_NAMEORDER), &hti); + if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT)) { + hti.pt.y-=TreeView_GetItemHeight(GetDlgItem(hwndDlg, IDC_NAMEORDER))/2; + TreeView_HitTest(GetDlgItem(hwndDlg, IDC_NAMEORDER), &hti); + TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_NAMEORDER), hti.hItem, 1); + } + else { + if (hti.flags&TVHT_ABOVE) SendDlgItemMessage(hwndDlg, IDC_NAMEORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); + if (hti.flags&TVHT_BELOW) SendDlgItemMessage(hwndDlg, IDC_NAMEORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); + TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_NAMEORDER), NULL, 0); + } + } + break; + case WM_LBUTTONUP: + if ( !dat->dragging) break; + TreeView_SetInsertMark(GetDlgItem(hwndDlg, IDC_NAMEORDER), NULL, 0); + dat->dragging = 0; + ReleaseCapture(); + { TVHITTESTINFO hti; + TVITEM tvi; + hti.pt.x = (short)LOWORD(lParam); + hti.pt.y = (short)HIWORD(lParam); + ClientToScreen(hwndDlg, &hti.pt); + ScreenToClient(GetDlgItem(hwndDlg, IDC_NAMEORDER), &hti.pt); + hti.pt.y-=TreeView_GetItemHeight(GetDlgItem(hwndDlg, IDC_NAMEORDER))/2; + TreeView_HitTest(GetDlgItem(hwndDlg, IDC_NAMEORDER), &hti); + if (dat->hDragItem == hti.hItem) break; + tvi.mask = TVIF_HANDLE|TVIF_PARAM; + tvi.hItem = hti.hItem; + TreeView_GetItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), &tvi); + if (tvi.lParam == SIZEOF(nameOrderDescr)-1) break; + if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT)) { + TVINSERTSTRUCT tvis; + TCHAR name[128]; + tvis.item.mask = TVIF_HANDLE|TVIF_PARAM|TVIF_TEXT|TVIF_PARAM; + tvis.item.stateMask = 0xFFFFFFFF; + tvis.item.pszText = name; + tvis.item.cchTextMax = SIZEOF(name); + tvis.item.hItem = dat->hDragItem; + TreeView_GetItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), &tvis.item); + TreeView_DeleteItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), dat->hDragItem); + tvis.hParent = NULL; + tvis.hInsertAfter = hti.hItem; + TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_NAMEORDER), &tvis)); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + case WM_DESTROY: + mir_free(dat); + break; + } + return FALSE; +} + +static int ContactOptInit(WPARAM wParam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = -1000000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CONTACT); + odp.pszGroup = LPGEN("Customize"); + odp.pszTitle = LPGEN("Contacts"); + odp.pfnDlgProc = ContactOpts; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + return 0; +} + +int LoadContactsModule(void) +{ + for (BYTE i=0; i < NAMEORDERCOUNT; i++) + nameOrder[i] = i; + + DBVARIANT dbv; + if ( !DBGetContactSetting(NULL, "Contact", "NameOrder", &dbv)) { + CopyMemory(nameOrder, dbv.pbVal, dbv.cpbVal); + DBFreeVariant(&dbv); + } + + CreateServiceFunction(MS_CONTACT_GETCONTACTINFO, GetContactInfo); + HookEvent(ME_OPT_INITIALISE, ContactOptInit); + return 0; +} -- cgit v1.2.3