/* New Away System - plugin for Miranda IM Copyright (c) 2005-2007 Chervov Dmitry Copyright (c) 2004-2005 Iksaif Entertainment Copyright (c) 2002-2003 Goblineye Entertainment 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 */ #pragma once #define _CRT_SECURE_NO_WARNINGS #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x0500 #define MIRANDA_VER 0x0600 #include #include #include #include #include #include #include #include #include #include #include "AggressiveOptimize.h" #include "resource.h" #include "newpluginapi.h" #include "m_clist.h" #include "m_system.h" #include "m_database.h" #include "m_clui.h" #include "m_langpack.h" #include "m_protosvc.h" #include "m_options.h" #include "..\..\protocols\IcqOscarJ\icq_constants.h" #include "m_skin.h" #include "m_plugins.h" #include "m_awaymsg.h" #include "m_utils.h" #include "m_history.h" #include "m_message.h" #include "m_userinfo.h" #include "m_icq.h" #define THEMEAPI // we don't need no uxtheme defines :-/ they break everything when trying to include tmschema.h later #include "win2k.h" #undef THEMEAPI #include "m_variables.h" //#include "m_toptoolbar.h" #include "m_popup.h" //#include "m_popupw.h" #include "m_metacontacts.h" #include "m_LogService.h" #include "..\CommonLibs\CString.h" #include "..\CommonLibs\Options.h" #pragma comment(lib,"comctl32.lib") #define VAR_AWAYSINCE_TIME "nas_awaysince_time" #define VAR_AWAYSINCE_DATE "nas_awaysince_date" #define VAR_STATDESC "nas_statdesc" #define VAR_MYNICK "nas_mynick" #define VAR_REQUESTCOUNT "nas_requestcount" #define VAR_MESSAGENUM "nas_messagecount" #define VAR_TIMEPASSED "nas_timepassed" #define VAR_PREDEFINEDMESSAGE "nas_predefinedmessage" #define VAR_PROTOCOL "nas_protocol" #define SENDSMSG_EVENT_MSG 0x1 #define SENDSMSG_EVENT_URL 0x2 #define SENDSMSG_EVENT_FILE 0x4 #define AWAY_MSGDATA_MAX 8000 // Flags for status database settings #define SF_OFF 0x1 #define SF_ONL 0x2 #define SF_AWAY 0x4 #define SF_NA 0x8 #define SF_OCC 0x10 #define SF_DND 0x20 #define SF_FFC 0x40 #define SF_INV 0x80 #define SF_OTP 0x100 #define SF_OTL 0x200 #define SF_OTHER 0x80000000 /* // Actions on popup click #define PCA_OPENMESSAGEWND 0 // open message window #define PCA_CLOSEPOPUP 1 // close popup #define PCA_OPENDETAILS 2 // open contact details window #define PCA_OPENMENU 3 // open contact menu #define PCA_OPENHISTORY 4 // open contact history #define PCA_OPENLOG 5 // open log file #define PCA_DONOTHING 6 // do nothing // Notification options defaults #define POPUP_DEF_POPUP_FORMAT TranslateT("?cinfo(%subject%,display) (?cinfo(%subject%,id)) is reading your %nas_statdesc% message:\r\n%extratext%") #define POPUP_DEF_USEPOPUPS 0 #define POPUP_DEF_LCLICKACTION PCA_OPENMESSAGEWND #define POPUP_DEF_RCLICKACTION PCA_CLOSEPOPUP #define POPUP_DEF_POPUP_BGCOLOUR 0xFFB5BC #define POPUP_DEF_POPUP_TEXTCOLOUR 0 #define POPUP_DEF_USEDEFBGCOLOUR 0 #define POPUP_DEF_USEDEFTEXTCOLOUR 0 #define POPUP_DEF_POPUPNOTIFYFLAGS (SF_ONL | SF_AWAY | SF_NA | SF_OCC | SF_DND | SF_FFC | SF_INV | SF_OTP | SF_OTL) #define POPUP_DEF_POPUPDELAY 0 #define POPUP_MAXPOPUPDELAY 9999 */ #define MOREOPTDLG_DEF_DONTPOPDLG (SF_ONL | SF_INV) #define MOREOPTDLG_DEF_USEBYDEFAULT 0 // Event flags (used for "reply on event" options) #define EF_MSG 1 #define EF_URL 2 #define EF_FILE 4 #define AUTOREPLY_DEF_REPLY 0 #define AUTOREPLY_DEF_REPLYONEVENT (EF_MSG | EF_URL | EF_FILE) #define AUTOREPLY_DEF_PREFIX TranslateT("Miranda IM autoreply >\r\n%extratext%") #define AUTOREPLY_DEF_DISABLEREPLY (SF_ONL | SF_INV) #define AUTOREPLY_IDLE_WINDOWS 0 #define AUTOREPLY_IDLE_MIRANDA 1 #define AUTOREPLY_DEF_IDLEREPLYVALUE AUTOREPLY_IDLE_WINDOWS #define AUTOREPLY_MAXPREFIXLEN 8000 #define VAL_USEDEFAULT 2 // undefined value for ignore/autoreply/notification settings in the db; must be 2 for proper ContactSettings support // Set Away Message dialog flags #define DF_SAM_SHOWMSGTREE 1 #define DF_SAM_SHOWCONTACTTREE 2 #define DF_SAM_DEFDLGFLAGS DF_SAM_SHOWMSGTREE // WriteAwayMsgInDB option flags: #define WRITE_LMSG 1 #define WRITE_RMSG 2 #define WRITE_INTERPRET 4 #define WRITE_CMSG 8 #define TOGGLE_SOE_COMMAND LPGENT("Toggle autoreply on/off") #define DISABLE_SOE_COMMAND LPGENT("Toggle autoreply off") #define ENABLE_SOE_COMMAND LPGENT("Toggle autoreply on") #define STR_XSTATUSDESC TranslateT("extended status") #define MOD_NAME "NewAwaySys" #define LOG_ID MOD_NAME // LogService log ID #define LOG_PREFIX MOD_NAME ": " // netlib.log prefix for all NAS' messages #define DB_SETTINGSVER "SettingsVer" #ifndef lengthof #define lengthof(s) (sizeof(s) / sizeof(*s)) #endif #define MS_NETLIB_LOG "Netlib/Log" #define UM_ICONSCHANGED (WM_USER + 121) // IDD_READAWAYMSG user-defined message constants #define UM_RAM_AWAYMSGACK (WM_USER + 10) // IDD_SETAWAYMSG user-defined message constants #define UM_SAM_SPLITTERMOVED (WM_USER + 1) #define UM_SAM_SAVEDLGSETTINGS (WM_USER + 2) #define UM_SAM_APPLYANDCLOSE (WM_USER + 3) #define UM_SAM_KILLTIMER (WM_USER + 4) #define UM_SAM_REPLYSETTINGCHANGED (WM_USER + 5) #define UM_SAM_PROTOSTATUSCHANGED (WM_USER + 6) // wParam = (char*)szProto #define UM_CLICK (WM_USER + 100) #define SAM_DB_DLGPOSX "SAMDlgPosX" #define SAM_DB_DLGPOSY "SAMDlgPosY" #define SAM_DB_DLGSIZEX "SAMDlgSizeX" #define SAM_DB_DLGSIZEY "SAMDlgSizeY" #define SAM_DB_MSGSPLITTERPOS "SAMMsgSplitterPos" #define SAM_DB_CONTACTSPLITTERPOS "SAMContactSplitterPos" #define DB_MESSAGECOUNT "MessageCount" #define DB_REQUESTCOUNT "RequestCount" #define DB_SENDCOUNT "SendCount" #define MESSAGES_DB_MSGTREEDEF "MsgTreeDef" #define MSGTREE_RECENT_OTHERGROUP _T("Other") // GetMsgFormat flags #define GMF_PERSONAL 1 // is also used to get global status message, when hContact = NULL (szProto = NULL) #define GMF_PROTOORGLOBAL 2 #define GMF_LASTORDEFAULT 4 // this flag doesn't require hContact or szProto #define GMF_TEMPORARY 8 // doesn't require status #define GMF_ANYCURRENT (GMF_TEMPORARY | GMF_PERSONAL | GMF_PROTOORGLOBAL) // SetMsgFormat flags #define SMF_PERSONAL 1 // is also used to set global status message, when hContact = NULL (szProto = NULL) #define SMF_LAST 2 #define SMF_TEMPORARY 4 // doesn't require status // VAR_PARSE_DATA flags #define VPF_XSTATUS 1 // use "extended status" instead of the usual status description in %nas_statdesc%, and XStatus message in %nas_message% // options dialog #define OPT_TITLE LPGENT("Away System") #define OPT_MAINGROUP LPGEN("Status") #define OPT_POPUPGROUP LPGEN("PopUps") #define MRM_MAX_GENERATED_TITLE_LEN 35 // maximum length of automatically generated title for recent messages int ICQStatusToGeneralStatus(int bICQStat); // TODO: get rid of these protocol-specific functions, if possible #define MS_AWAYSYS_SETCONTACTSTATMSG "AwaySys/SetContactStatMsg" #define MS_AWAYSYS_AUTOREPLY_TOGGLE "AwaySys/AutoreplyToggle" #define MS_AWAYSYS_AUTOREPLY_ON "AwaySys/AutoreplyOn" #define MS_AWAYSYS_AUTOREPLY_OFF "AwaySys/AutoreplyOff" #define MS_AWAYSYS_AUTOREPLY_USEDEFAULT "AwaySys/AutoreplyUseDefault" #define MS_AWAYSYS_VARIABLESHANDLER "AwaySys/VariablesHandler" #define MS_AWAYSYS_FREEVARMEM "AwaySys/FreeVarMem" // these are obsolete AwaySysMod services, though they're still here for compatibility with old plugins #define MS_AWAYSYS_SETSTATUSMODE "AwaySys/SetStatusMode" // change the status mode. wParam is new mode, lParam is new status message (AwaySys will interpret variables out of it), may be NULL. #define MS_AWAYSYS_IGNORENEXT "AwaySys/IgnoreNextStatusChange" //ignore nest status change typedef struct SetAwayMsgData_type { CString szProtocol; HANDLE hInitContact; // initial contact (filled by caller) TCString Message; // initial message, NULL means default bool IsModeless; // means the dialog was created with the CreateDialogParam function, not DialogBoxParam int ISW_Flags; // InvokeStatusWindow service flags } SetAwayMsgData; typedef struct READAWAYMSGDATA_TYPE { HANDLE hContact; // contact HANDLE hSeq; // sequence for stat msg request HANDLE hAwayMsgEvent; // hooked } READAWAYMSGDATA; typedef struct { char *szProto; TCString Message; DWORD UIN; int Flags; // a combination of VPF_ flags } VAR_PARSE_DATA; typedef struct { HANDLE hContact; int iStatusMode; TCString Proto; } DYNAMIC_NOTIFY_DATA; typedef struct { BYTE PopupLClickAction, PopupRClickAction; HANDLE hContact; HICON hStatusIcon; // needed here to destroy its handle on UM_FREEPLUGINDATA } PLUGIN_DATA; typedef struct { int cbSize; char *szProto; HANDLE hContact; char *szMsg; WORD status; } NAS_ISWINFOv1; #define MTYPE_AUTOONLINE 0xE7 // required to support ICQ Plus online status messages /* // additional m_popup.h declarations typedef struct { HANDLE lchContact; HICON lchIcon; WCHAR lpzContactName[MAX_CONTACTNAME]; WCHAR lpzText[MAX_SECONDLINE]; COLORREF colorBack; COLORREF colorText; WNDPROC PluginWindowProc; void * PluginData; int iSeconds; char cZero[16]; } POPUPDATAT; #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPW */ // Beware of conflicts between two different windows trying to use the same page at a time! // Other windows than the owner of the Page must copy the page to their own memory, // or use GetDBValueCopy to retrieve values extern COptPage g_MessagesOptPage; extern COptPage g_AutoreplyOptPage; //extern COptPage g_PopupOptPage; extern COptPage g_MoreOptPage; extern COptPage g_SetAwayMsgPage; extern HINSTANCE g_hInstance; extern HANDLE hMainThread; extern int g_Messages_RecentRootID, g_Messages_PredefinedRootID; extern VAR_PARSE_DATA VarParseData; extern bool g_fNoProcessing; extern int g_bIsIdle; extern INT_PTR (*g_OldCallService)(const char *, WPARAM, LPARAM); // AwaySys.cpp TCString GetDynamicStatMsg(HANDLE hContact, char *szProto = NULL, DWORD UIN = 0, int iStatus = 0); int IsAnICQProto(char *szProto); // Client.cpp void InitUpdateMsgs(); void ChangeProtoMessages(char* szProto, int iMode, TCString &Msg); int GetRecentGroupID(int iMode); TCString VariablesEscape(TCString Str); // SetAwayMsg.cpp INT_PTR CALLBACK SetAwayMsgDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); // ReadAwayMsg.cpp extern HANDLE g_hReadWndList; INT_PTR GetContactStatMsg(WPARAM wParam, LPARAM lParam); // AwayOpt.cpp int OptsDlgInit(WPARAM wParam, LPARAM lParam); // called on opening of the options dialog void InitOptions(); // called once when plugin is loaded //int ShowPopupNotification(COptPage &PopupNotifyData, HANDLE hContact, int iStatusMode); void ShowLog(TCString &LogFilePath); void ShowMsg(TCHAR *szFirstLine, TCHAR *szSecondLine = _T(""), bool IsErrorMsg = false, int Timeout = 0); #define AWAYSYS_STATUSMSGREQUEST_SOUND "AwaySysStatusMsgRequest" #define ME_AWAYSYS_WORKAROUND "AwaySys/_CallService" int _Workaround_CallService(const char *name, WPARAM wParam, LPARAM lParam); // MsgEventAdded.cpp int MsgEventAdded(WPARAM wParam, LPARAM lParam); // buttons //void UpdateSOEButtons(HANDLE hContact = NULL); INT_PTR ToggleSendOnEvent(WPARAM wParam, LPARAM lParam); //int Create_TopToolbar(WPARAM wParam, LPARAM lParam); static __inline int LogMessage(const char *Format, ...) { va_list va; char szText[8096]; strcpy(szText, LOG_PREFIX); va_start(va, Format); mir_vsnprintf(szText + (lengthof(LOG_PREFIX) - 1), sizeof(szText) - (lengthof(LOG_PREFIX) - 1), Format, va); va_end(va); return CallService(MS_NETLIB_LOG, NULL, (LPARAM)szText); } __inline int CallAllowedPS_SETAWAYMSG(const char *szProto, int iMode, const char *szMsg) { // we must use this function everywhere we want to call PS_SETAWAYMSG, otherwise NAS won't allow to change the message! LogMessage("PS_SETAWAYMSG called by NAS. szProto=%s, Status=%d, Msg:\n%s", szProto, iMode, szMsg ? szMsg : "NULL"); char str[MAXMODULELABELLENGTH]; strcpy(str, szProto); strcat(str, PS_SETAWAYMSG); return g_OldCallService(str, (WPARAM)iMode, (LPARAM)szMsg); } static __inline void my_variables_skin_helpbutton(HWND hwndDlg, UINT uIDButton) { HICON hIcon = ServiceExists(MS_VARS_GETSKINITEM) ? (HICON)CallService(MS_VARS_GETSKINITEM, 0, (LPARAM)VSI_HELPICON) : NULL; if (hIcon) { SendDlgItemMessage(hwndDlg, uIDButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); } } static __inline int my_variables_showhelp(HWND hwndDlg, UINT uIDEdit, int flags = 0, char *szSubjectDesc = NULL, char *szExtraDesc = NULL) { if (ServiceExists(MS_VARS_SHOWHELPEX)) { VARHELPINFO vhi = {0}; vhi.cbSize = sizeof(VARHELPINFO); vhi.flags = flags ? flags : (VHF_FULLDLG | VHF_SETLASTSUBJECT); vhi.hwndCtrl = GetDlgItem(hwndDlg, uIDEdit); vhi.szSubjectDesc = szSubjectDesc; vhi.szExtraTextDesc = szExtraDesc; return CallService(MS_VARS_SHOWHELPEX, (WPARAM)hwndDlg, (LPARAM)&vhi); } else { ShowMsg(TranslateT("New Away System"), TranslateT("Variables plugin is not installed"), true); return -1; } }