diff options
Diffstat (limited to 'plugins/NewAwaySysMod/Properties.h')
-rw-r--r-- | plugins/NewAwaySysMod/Properties.h | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/plugins/NewAwaySysMod/Properties.h b/plugins/NewAwaySysMod/Properties.h new file mode 100644 index 0000000000..6b981bd77e --- /dev/null +++ b/plugins/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<HICON> 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<CProtoState> 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;
+};
|