From 7ad4550af9bf16f3a6212edfc1f425082065b095 Mon Sep 17 00:00:00 2001 From: watcherhd Date: Mon, 13 Jun 2011 08:59:23 +0000 Subject: added NewAwaySysMod git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@137 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- NewAwaySysMod/Properties.h | 605 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 605 insertions(+) create mode 100644 NewAwaySysMod/Properties.h (limited to 'NewAwaySysMod/Properties.h') diff --git a/NewAwaySysMod/Properties.h b/NewAwaySysMod/Properties.h new file mode 100644 index 0000000..6b981bd --- /dev/null +++ b/NewAwaySysMod/Properties.h @@ -0,0 +1,605 @@ +/* + New Away System - plugin for Miranda IM + Copyright (c) 2005-2007 Chervov Dmitry + + 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 + +#include "Common.h" +#include "MsgTree.h" +#include "ContactList.h" +#include "statusmodes.h" + +#define DB_STATUSMSG "StatusMsg" +#define DB_ENABLEREPLY "EnableReply" +#define DB_IGNOREREQUESTS "IgnoreRequests" +//#define DB_POPUPNOTIFY "UsePopups" +#define DB_UNK_CONTACT_PREFIX "Unk" // DB_ENABLEREPLY, DB_IGNOREREQUESTS and DB_POPUPNOTIFY settings prefix for not-on-list contacts + +class _CWndUserData +{ +public: + _CWndUserData(): MsgTree(NULL), CList(NULL) {} + + CMsgTree *MsgTree; + CCList *CList; +}; + + +class CWndUserData +{ +public: + CWndUserData(HWND hWnd): hWnd(hWnd) + { + _ASSERT(hWnd); + dat = (_CWndUserData*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (!dat) + { + dat = new _CWndUserData; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)dat); + } + } + + ~CWndUserData() + { + _ASSERT(dat == (_CWndUserData*)GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (!dat->MsgTree && !dat->CList) // TODO: Uninitialized Memory Read on closing the options dialog - fix it + { + SetWindowLongPtr(hWnd, GWLP_USERDATA, NULL); + delete dat; // TODO: memory leak - this is never executed - fix it + } + } + + CMsgTree *GetMsgTree() {return dat->MsgTree;} + void SetMsgTree(CMsgTree *MsgTree) {dat->MsgTree = MsgTree;} + CCList *GetCList() {return dat->CList;} + void SetCList(CCList *CList) {dat->CList = CList;} + +private: + HWND hWnd; + _CWndUserData *dat; +}; + +#define IL_SKINICON 0x80000000 +#define IL_PROTOICON 0x40000000 + +#define ILI_NOICON (-1) +#define ILI_EVENT_MESSAGE 0 +#define ILI_EVENT_URL 1 +#define ILI_EVENT_FILE 2 +#define ILI_PROTO_ONL 3 +#define ILI_PROTO_AWAY 4 +#define ILI_PROTO_NA 5 +#define ILI_PROTO_OCC 6 +#define ILI_PROTO_DND 7 +#define ILI_PROTO_FFC 8 +#define ILI_PROTO_INV 9 +#define ILI_PROTO_OTP 10 +#define ILI_PROTO_OTL 11 +#define ILI_DOT 12 +#define ILI_MSGICON 13 +#define ILI_IGNORE 14 +#define ILI_SOE_DISABLED 15 +#define ILI_SOE_ENABLED 16 +#define ILI_NEWMESSAGE 17 +#define ILI_NEWCATEGORY 18 +#define ILI_SAVE 19 +#define ILI_SAVEASNEW 20 +#define ILI_DELETE 21 +#define ILI_SETTINGS 22 +#define ILI_STATUS_OTHER 23 + +static int Icons[] = { + SKINICON_EVENT_MESSAGE | IL_SKINICON, SKINICON_EVENT_URL | IL_SKINICON, SKINICON_EVENT_FILE | IL_SKINICON, + ID_STATUS_ONLINE | IL_PROTOICON, ID_STATUS_AWAY | IL_PROTOICON, ID_STATUS_NA | IL_PROTOICON, ID_STATUS_OCCUPIED | IL_PROTOICON, ID_STATUS_DND | IL_PROTOICON, ID_STATUS_FREECHAT | IL_PROTOICON, ID_STATUS_INVISIBLE | IL_PROTOICON, ID_STATUS_ONTHEPHONE | IL_PROTOICON, ID_STATUS_OUTTOLUNCH | IL_PROTOICON, + IDI_DOT, IDI_MSGICON, IDI_IGNORE, IDI_SOE_ENABLED, IDI_SOE_DISABLED, IDI_NEWMESSAGE, IDI_NEWCATEGORY, IDI_SAVE, IDI_SAVEASNEW, IDI_DELETE, IDI_SETTINGS, IDI_STATUS_OTHER +}; + + +class CIconList +{ +public: + ~CIconList() + { + int I; + for (I = 0; I < IconList.GetSize(); I++) + { + if (IconList[I]) + { + DestroyIcon(IconList[I]); + } + } + } + + HICON& operator [] (int nIndex) {return IconList[nIndex];} + void ReloadIcons() + { + int cxIcon = GetSystemMetrics(SM_CXSMICON); + int cyIcon = GetSystemMetrics(SM_CYSMICON); + int I; + for (I = 0; I < lengthof(Icons); I++) + { + if (IconList.GetSize() > I && IconList[I]) + { + DestroyIcon(IconList[I]); + } + if (Icons[I] & IL_SKINICON) + { + IconList.SetAtGrow(I) = (HICON)CopyImage(LoadSkinnedIcon(Icons[I] & ~IL_SKINICON), IMAGE_ICON, cxIcon, cyIcon, LR_COPYFROMRESOURCE); + } else if (Icons[I] & IL_PROTOICON) + { + IconList.SetAtGrow(I) = (HICON)CopyImage(LoadSkinnedProtoIcon(NULL, Icons[I] & ~IL_PROTOICON), IMAGE_ICON, cxIcon, cyIcon, LR_COPYFROMRESOURCE); + } else + { + IconList.SetAtGrow(I) = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(Icons[I]), IMAGE_ICON, cxIcon, cyIcon, 0); + } + } + } + +private: + TMyArray IconList; +}; + +extern CIconList g_IconList; + + +class CProtoStates; + +class CProtoState +{ +public: + CProtoState(const char* szProto, CProtoStates* Parent): szProto(szProto), Parent(Parent), Status(szProto, Parent), AwaySince(szProto, Parent) {} + + class CStatus + { + public: + CStatus(const char* szProto, CProtoStates* GrandParent): szProto(szProto), GrandParent(GrandParent), Status(ID_STATUS_OFFLINE) {} + CStatus& operator = (int Status); + operator int() {return Status;} + friend class CProtoState; + private: + int Status; + CString szProto; + CProtoStates* GrandParent; + } Status; + + class CAwaySince + { + public: + CAwaySince(const char* szProto, CProtoStates* GrandParent): szProto(szProto), GrandParent(GrandParent) {Reset();} + void Reset(); + operator LPSYSTEMTIME() {return &AwaySince;} + friend class CProtoState; + private: + SYSTEMTIME AwaySince; + CString szProto; + CProtoStates* GrandParent; + } AwaySince; + + class CCurStatusMsg + { + public: + CCurStatusMsg() {*this = NULL;} + CCurStatusMsg& operator = (TCString Msg) + { + CurStatusMsg = Msg; + SYSTEMTIME st; + GetLocalTime(&st); + SystemTimeToFileTime(&st, (LPFILETIME)&LastUpdateTime); // I'm too lazy to declare FILETIME structure and then copy its data to absolutely equivalent ULARGE_INTEGER structure, so we'll just pass a pointer to the ULARGE_INTEGER directly ;-P + return *this; + } + operator TCString() {return CurStatusMsg;} + DWORD GetUpdateTimeDifference() + { + ULARGE_INTEGER CurTime; + SYSTEMTIME st; + GetLocalTime(&st); + SystemTimeToFileTime(&st, (LPFILETIME)&CurTime); + return (DWORD)((CurTime.QuadPart - LastUpdateTime.QuadPart) / 10000); // in milliseconds + } + private: + TCString CurStatusMsg; + ULARGE_INTEGER LastUpdateTime; + } CurStatusMsg; + + class CTempMsg + { // we use temporary messages to keep user-defined per-protocol messages intact, when changing messages through MS_NAS_SETSTATE, or when autoaway becomes active etc.. temporary messages are automatically resetted when protocol status changes + public: + CTempMsg(): iIsSet(0) {} + CTempMsg& operator = (TCString Msg) {this->Msg = Msg; iIsSet = true; return *this;} + operator TCString() + { + _ASSERT(iIsSet); + return Msg; + } + void Unset() {iIsSet = false;} + int IsSet() {return iIsSet;} + + private: + int iIsSet; // as we need TempMsg to support every possible value, including NULL and "", we'll use this variable to specify whether TempMsg is set + TCString Msg; + } TempMsg; + + void SetParent(CProtoStates* Parent) + { + this->Parent = Parent; + Status.GrandParent = Parent; + AwaySince.GrandParent = Parent; + } + + CString &GetProto() {return szProto;} + +//NightFox: fix? +//private: +public: + CString szProto; + CProtoStates* Parent; +}; + + +class CProtoStates // this class stores all protocols' dynamic data +{ +public: + CProtoStates() {} + + CProtoStates(const CProtoStates &States) {*this = States;} + CProtoStates& operator = (const CProtoStates& States) + { + ProtoStates = States.ProtoStates; + int I; + for (I = 0; I < ProtoStates.GetSize(); I++) + { + ProtoStates[I].SetParent(this); + } + return *this; + } + + CProtoState& operator[](const char *szProto) + { + int I; + for (I = 0; I < ProtoStates.GetSize(); I++) + { + if (ProtoStates[I].GetProto() == szProto) + { + return ProtoStates[I]; + } + } + if (!szProto) // we need to be sure that we have _all_ protocols in the list, before dealing with global status, so we're adding them here. + { + int ProtoCount; + PROTOCOLDESCRIPTOR **proto; + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&ProtoCount, (LPARAM)&proto); + int I; + for (I = 0; I < ProtoCount; I++) + { + if (proto[I]->type == PROTOTYPE_PROTOCOL) + { + (*this)[proto[I]->szName]; // add a protocol if it isn't in the list yet + } + } + } + return ProtoStates[ProtoStates.AddElem(CProtoState(szProto, this))]; + } + + friend class CProtoState; + friend class CProtoState::CStatus; + friend class CProtoState::CAwaySince; + +private: + CProtoState& operator[](int nIndex) {return ProtoStates[nIndex];} + int GetSize() {return ProtoStates.GetSize();} + + TMyArray ProtoStates; +}; + +extern CProtoStates g_ProtoStates; + + +static struct +{ + int Status; + char *Setting; +} StatusSettings[] = { + ID_STATUS_OFFLINE, "Off", + ID_STATUS_ONLINE, "Onl", + ID_STATUS_AWAY, "Away", + ID_STATUS_NA, "Na", + ID_STATUS_DND, "Dnd", + ID_STATUS_OCCUPIED, "Occ", + ID_STATUS_FREECHAT, "Ffc", + ID_STATUS_INVISIBLE, "Inv", + ID_STATUS_ONTHEPHONE, "Otp", + ID_STATUS_OUTTOLUNCH, "Otl", + ID_STATUS_IDLE, "Idle" +}; + + +class CProtoSettings +{ +public: + CProtoSettings(const char *szProto = NULL, int iStatus = 0): szProto(szProto), Status(iStatus, szProto) + { + Autoreply.Parent = this; + } + + CString ProtoStatusToDBSetting(const char *Prefix, int MoreOpt_PerStatusID = 0) + { + if (!MoreOpt_PerStatusID || g_MoreOptPage.GetDBValueCopy(MoreOpt_PerStatusID)) + { + int I; + for (I = 0; I < lengthof(StatusSettings); I++) + { + if (Status == StatusSettings[I].Status) + { + return szProto ? (CString(Prefix) + "_" + szProto + "_" + StatusSettings[I].Setting) : (CString(Prefix) + StatusSettings[I].Setting); + } + } + } + return szProto ? (CString(Prefix) + "_" + szProto) : CString(Prefix); + } + + class CAutoreply + { + public: + CAutoreply& operator = (const int Value) + { + CString Setting(Parent->szProto ? Parent->ProtoStatusToDBSetting(DB_ENABLEREPLY, IDC_MOREOPTDLG_PERSTATUSPROTOSETTINGS) : DB_ENABLEREPLY); + if (DBGetContactSettingByte(NULL, MOD_NAME, Setting, VAL_USEDEFAULT) == Value) + { + return *this; // prevent deadlocks when calling UpdateSOEButtons + } + if (Value != VAL_USEDEFAULT) + { + DBWriteContactSettingByte(NULL, MOD_NAME, Setting, Value != 0); + } else + { + DBDeleteContactSetting(NULL, MOD_NAME, Setting); + } + /*if (!Parent->szProto) + { + UpdateSOEButtons(); + }*/ + return *this; + } + operator int() {return DBGetContactSettingByte(NULL, MOD_NAME, Parent->szProto ? Parent->ProtoStatusToDBSetting(DB_ENABLEREPLY, IDC_MOREOPTDLG_PERSTATUSPROTOSETTINGS) : DB_ENABLEREPLY, Parent->szProto ? VAL_USEDEFAULT : AUTOREPLY_DEF_REPLY);} + int IncludingParents() // takes into account global data also, if per-protocol setting is not defined + { + _ASSERT(Parent->szProto); + int Value = *this; + return (Value == VAL_USEDEFAULT) ? CProtoSettings(NULL).Autoreply : Value; + } + friend class CProtoSettings; + private: + CProtoSettings *Parent; + } Autoreply; + + class CStatus + { + public: + CStatus(int iStatus = 0, const char *szProto = NULL): Status(iStatus), szProto(szProto) {} + CStatus& operator = (int Status) {this->Status = Status; return *this;} + operator int() + { + if (!Status) + { + Status = g_ProtoStates[szProto].Status; + } + return Status; + } + private: + int Status; + const char *szProto; + } Status; + + void SetMsgFormat(int Flags, TCString Message); + TCString GetMsgFormat(int Flags, int *pOrder = NULL); + +//NightFox: fix? +//private: +public: + const char *szProto; +}; + + +__inline CString StatusToDBSetting(int Status, const char *Prefix, int MoreOpt_PerStatusID = 0) +{ + if (!MoreOpt_PerStatusID || g_MoreOptPage.GetDBValueCopy(MoreOpt_PerStatusID)) + { + int I; + for (I = 0; I < lengthof(StatusSettings); I++) + { + if (Status == StatusSettings[I].Status) + { + return CString(Prefix) + StatusSettings[I].Setting; + } + } + } + return CString(Prefix); +} + + +__inline CString ContactStatusToDBSetting(int Status, const char *Prefix, int MoreOpt_PerStatusID, HANDLE hContact) +{ + if (hContact == INVALID_HANDLE_VALUE) + { // it's a not-on-list contact + return CString(DB_UNK_CONTACT_PREFIX) + Prefix; + } + if (hContact) + { + StatusToDBSetting(Status, Prefix, MoreOpt_PerStatusID); + } + return CString(Prefix); +} + + +class CContactSettings +{ +public: + CContactSettings(int iStatus = 0, HANDLE hContact = NULL): Status(iStatus, hContact), hContact(hContact) + { + Ignore.Parent = this; + Autoreply.Parent = this; +// PopupNotify.Parent = this; + } + + CString ContactStatusToDBSetting(const char *Prefix, int MoreOpt_PerStatusID = 0) + { + return ::ContactStatusToDBSetting((hContact != INVALID_HANDLE_VALUE) ? Status : NULL, Prefix, MoreOpt_PerStatusID, hContact); + } + + class CIgnore + { + public: + CIgnore& operator = (const int Value) + { + CString Setting(Parent->ContactStatusToDBSetting(DB_IGNOREREQUESTS, IDC_MOREOPTDLG_PERSTATUSPERSONALSETTINGS)); + HANDLE hContact = (Parent->hContact != INVALID_HANDLE_VALUE) ? Parent->hContact : NULL; + if (Value) + { + DBWriteContactSettingByte(hContact, MOD_NAME, Setting, 1); + } else + { + DBDeleteContactSetting(hContact, MOD_NAME, Setting); + } + return *this; + } + operator int() {return DBGetContactSettingByte((Parent->hContact != INVALID_HANDLE_VALUE) ? Parent->hContact : NULL, MOD_NAME, Parent->ContactStatusToDBSetting(DB_IGNOREREQUESTS, IDC_MOREOPTDLG_PERSTATUSPERSONALSETTINGS), 0);} + friend class CContactSettings; + private: + CContactSettings *Parent; + } Ignore; + + class CAutoreply + { + public: + CAutoreply& operator = (const int Value) + { + CString Setting(Parent->ContactStatusToDBSetting(DB_ENABLEREPLY, IDC_MOREOPTDLG_PERSTATUSPERSONALSETTINGS)); + HANDLE hContact = (Parent->hContact != INVALID_HANDLE_VALUE) ? Parent->hContact : NULL; + if (DBGetContactSettingByte(hContact, MOD_NAME, Setting, VAL_USEDEFAULT) == Value) + { + return *this; // prevent deadlocks when calling UpdateSOEButtons + } + if (Value != VAL_USEDEFAULT) + { + DBWriteContactSettingByte(hContact, MOD_NAME, Setting, Value != 0); + } else + { + DBDeleteContactSetting(hContact, MOD_NAME, Setting); + } + /*if (Parent->hContact != INVALID_HANDLE_VALUE) + { + UpdateSOEButtons(Parent->hContact); + }*/ + return *this; + } + operator int() {return DBGetContactSettingByte((Parent->hContact != INVALID_HANDLE_VALUE) ? Parent->hContact : NULL, MOD_NAME, Parent->ContactStatusToDBSetting(DB_ENABLEREPLY, IDC_MOREOPTDLG_PERSTATUSPERSONALSETTINGS), Parent->hContact ? VAL_USEDEFAULT : AUTOREPLY_DEF_REPLY);} + int IncludingParents(const char *szProtoOverride = NULL) // takes into account protocol and global data also, if per-contact setting is not defined + { + _ASSERT((Parent->hContact && Parent->hContact != INVALID_HANDLE_VALUE) || szProtoOverride); // we need either correct protocol or a correct hContact to determine its protocol + int Value = *this; + if (Value == VAL_USEDEFAULT) + { + const char *szProto = (Parent->hContact && Parent->hContact != INVALID_HANDLE_VALUE) ? (const char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)Parent->hContact, 0) : szProtoOverride; + return CProtoSettings(szProto).Autoreply.IncludingParents(); + } + return Value; + } + int GetNextToggleValue() + { + switch ((int)*this) + { + case VAL_USEDEFAULT: return 0; break; + case 0: return 1; break; + default: return Parent->hContact ? VAL_USEDEFAULT : AUTOREPLY_DEF_REPLY; break; + } + } + int Toggle() {return *this = GetNextToggleValue();} + friend class CContactSettings; + private: + CContactSettings *Parent; + } Autoreply; + +/* class CPopupNotify + { + public: + CPopupNotify& operator = (const int Value) + { + //CString Setting(Parent->ContactStatusToDBSetting(DB_POPUPNOTIFY, 0)); //IDC_MOREOPTDLG_PERSTATUSPERSONALSETTINGS + HANDLE hContact = (Parent->hContact != INVALID_HANDLE_VALUE) ? Parent->hContact : NULL; + if (DBGetContactSettingByte(hContact, MOD_NAME, Setting, VAL_USEDEFAULT) == Value) + { + return *this; // prevent deadlocks when calling UpdateSOEButtons + } + if (Value != VAL_USEDEFAULT) + { + DBWriteContactSettingByte(hContact, MOD_NAME, Setting, Value != 0); + } else + { + DBDeleteContactSetting(hContact, MOD_NAME, Setting); + } + if (!Parent->hContact) + { + //UpdateSOEButtons(); + } + return *this; + } + operator int() {return DBGetContactSettingByte((Parent->hContact != INVALID_HANDLE_VALUE) ? Parent->hContact : NULL, MOD_NAME, Parent->ContactStatusToDBSetting(DB_POPUPNOTIFY, 0), Parent->hContact ? VAL_USEDEFAULT : POPUP_DEF_USEPOPUPS);} //IDC_MOREOPTDLG_PERSTATUSPERSONALSETTINGS + int IncludingParents() // takes into account protocol and global data also, if per-contact setting is not defined + { + int Value = *this; + if (Value == VAL_USEDEFAULT) + { // PopupNotify setting is not per-status + return CContactSettings(ID_STATUS_ONLINE).PopupNotify; + } + return Value; + } + friend class CContactSettings; + private: + CContactSettings *Parent; + } PopupNotify; +*/ + class CStatus + { + public: + CStatus(int iStatus = 0, HANDLE hContact = NULL): Status(iStatus), hContact(hContact) {} + CStatus& operator = (int Status) {this->Status = Status; return *this;} + operator int() + { + if (!Status) + { + _ASSERT(hContact != INVALID_HANDLE_VALUE); + char *szProto = hContact ? (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0) : NULL; + Status = (szProto || !hContact) ? g_ProtoStates[szProto].Status : ID_STATUS_AWAY; + } + return Status; + } + friend class CPopupNotify; + friend class CAutoreply; + private: + int Status; + HANDLE hContact; + } Status; + + void SetMsgFormat(int Flags, TCString Message); + TCString GetMsgFormat(int Flags, int *pOrder = NULL, char *szProtoOverride = NULL); + +//NightFox: fix? +//private: +public: + HANDLE hContact; +}; -- cgit v1.2.3