/* Contact Settings plugin for Miranda IM Copyright (c) 2007-2008 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 */ #ifndef __M_CONTACTSETTINGS_H #define __M_CONTACTSETTINGS_H typedef struct { int cbSize; // sizeof(CONTACTSETTINGSINIT) int Type; // one of CSIT_ constants; value of this field depends on what settings dialog was opened: contact settings or group settings union { HANDLE hContact; // used when Type == CSIT_CONTACT int groupID; // used when Type == CSIT_GROUP }; } CONTACTSETTINGSINIT; // CONTACTSETTINGSINIT::Type #define CSIT_CONTACT 1 // CONTACTSETTINGSINIT::hContact is valid #define CSIT_GROUP 2 // CONTACTSETTINGSINIT::groupID is valid; in general, if Type == CSIT_GROUP, you MUST call MS_CONTACTSETTINGS_ADDCONTROL and add _all_ your per-contact controls, independently of current group contents, because potentially the group can contain any contacts in future. /* ME_CONTACTSETTINGS_INITIALISE The user opened a contact settings dialog. Modules should do whatever initialisation they need and call MS_CONTACTSETTINGS_ADDCONTROL one or more times if they want controls displayed in the dialog wParam=(WPARAM)(CONTACTSETTINGSINIT*)csi lParam=0 */ #define ME_CONTACTSETTINGS_INITIALISE "ContactSettings/Init" /* MS_CONTACTSETTINGS_ADDCONTROL Must only be called during a ME_CONTACTSETTINGS_INITIALISE hook Adds a control to the contact settings dialog wParam=(WPARAM)(CONTACTSETTINGSINIT*)csi lParam=(LPARAM)(CONTACTSETTINGSCONTROL*)csc Returns 0 on success, nonzero on failure csi must have come straight from the wParam of ME_CONTACTSETTINGS_INITIALISE Strings in the structure can be released as soon as the service returns. */ // CONTACTSETTINGSCONTROL::Position #define CSPOS_SORTBYALPHABET 0x40000000 // recommended value for Position if you don't need a specific sorting order // Group = "Notifications": #define CSPOS_NOTIFICATIONS_SERVICES 0x20000000 // recommended control position for notification SERVICE PROVIDERS (popups, osd, tickers, etc). Notification plugins that use these services should use CSPOS_SORTBYALPHABET, so that notification service provider settings are above any other specific notification settings. // CONTACTSETTINGSCONTROL::Flags #define CSCF_UNICODE 1 // string fields in CONTACTSETTINGSCONTROL and CSCONTROLSTATE are WCHAR* #define CSCF_DONT_TRANSLATE_STRINGS 2 // specifies that strings in CONTACTSETTINGSCONTROL and CSCONTROLSTATE are translated already #ifdef _UNICODE #define CSCF_TCHAR CSCF_UNICODE #else #define CSCF_TCHAR 0 #endif // CONTACTSETTINGSCONTROL::ControlType typedef enum { CSCT_LABEL = -1, // CSCT_LABEL is used internally in ContactSettings, and mustn't be used by other plugins CSCT_CHECKBOX, // checkbox control CSCT_COMBOBOX // combobox control with a title above it } CSCONTROLTYPE; // some common values for CONTACTSETTINGSCONTROL::ptszGroup #define CSGROUP_NOTIFICATIONS LPGENT("Notifications") // special values for CONTACTSETTINGSCONTROL::szModule #define CSMODULE_PROTO "%proto%" // ContactSettings will replace this by contact's protocol module name struct CSCONTROLSTATE { #ifdef __cplusplus CSCONTROLSTATE(): ptszName(NULL) {dbvValue.type = 0; dbvValue.dVal = 0; dbvValue.pbVal = 0; } CSCONTROLSTATE(char *pszName, BYTE Value) { this->pszName = pszName; dbvValue.type = DBVT_BYTE; dbvValue.bVal = Value; } CSCONTROLSTATE(char *pszName, char Value) { this->pszName = pszName; dbvValue.type = DBVT_BYTE; dbvValue.cVal = Value; } CSCONTROLSTATE(char *pszName, WORD Value) { this->pszName = pszName; dbvValue.type = DBVT_WORD; dbvValue.wVal = Value; } CSCONTROLSTATE(char *pszName, short Value) { this->pszName = pszName; dbvValue.type = DBVT_WORD; dbvValue.sVal = Value; } CSCONTROLSTATE(char *pszName, DWORD Value) { this->pszName = pszName; dbvValue.type = DBVT_DWORD; dbvValue.dVal = Value; } CSCONTROLSTATE(char *pszName, long Value) { this->pszName = pszName; dbvValue.type = DBVT_DWORD; dbvValue.lVal = Value; } CSCONTROLSTATE(char *pszName, const char *szValue) { this->pszName = pszName; dbvValue.type = DBVT_ASCIIZ; dbvValue.pszVal = (char*)szValue; } CSCONTROLSTATE(char *pszName, const WCHAR *wszValue) { this->pszName = pszName; dbvValue.type = DBVT_WCHAR; dbvValue.pwszVal = (WCHAR*)wszValue; } CSCONTROLSTATE(WCHAR *pwszName, BYTE Value) { this->pwszName = pwszName; dbvValue.type = DBVT_BYTE; dbvValue.bVal = Value; } CSCONTROLSTATE(WCHAR *pwszName, char Value) { this->pwszName = pwszName; dbvValue.type = DBVT_BYTE; dbvValue.cVal = Value; } CSCONTROLSTATE(WCHAR *pwszName, WORD Value) { this->pwszName = pwszName; dbvValue.type = DBVT_WORD; dbvValue.wVal = Value; } CSCONTROLSTATE(WCHAR *pwszName, short Value) { this->pwszName = pwszName; dbvValue.type = DBVT_WORD; dbvValue.sVal = Value; } CSCONTROLSTATE(WCHAR *pwszName, DWORD Value) { this->pwszName = pwszName; dbvValue.type = DBVT_DWORD; dbvValue.dVal = Value; } CSCONTROLSTATE(WCHAR *pwszName, long Value) { this->pwszName = pwszName; dbvValue.type = DBVT_DWORD; dbvValue.lVal = Value; } CSCONTROLSTATE(WCHAR *pwszName, const char *szValue) { this->pwszName = pwszName; dbvValue.type = DBVT_ASCIIZ; dbvValue.pszVal = (char*)szValue; } CSCONTROLSTATE(WCHAR *pwszName, const WCHAR *wszValue) { this->pwszName = pwszName; dbvValue.type = DBVT_WCHAR; dbvValue.pwszVal = (WCHAR*)wszValue; } #endif union { TCHAR *ptszName; // item text for CSCT_COMBOBOX; not used for CSCT_CHECKBOX char *pszName; WCHAR *pwszName; }; DBVARIANT dbvValue; // database value for this state }; // WARNING: do not use Translate(TS) for ptszTitle, ptszGroup, ptszTooltip or CSCONTROLSTATE::ptszName as they are translated by ContactSettings. The only exception is when you use CSCF_DONT_TRANSLATE_STRINGS flag typedef struct { int cbSize; // sizeof(CONTACTSETTINGSCONTROL) int cbStateSize; // sizeof(CSCONTROLSTATE) int Position; // position in the group, lower numbers are topmost. CSPOS_SORTBYALPHABET is recommended if you don't need a specific sorting order DWORD Flags; // a combination of CSCF_ constants CSCONTROLTYPE ControlType; // one of CSCT_ constants union { TCHAR *ptszTitle; // label above the control char *pszTitle; WCHAR *pwszTitle; }; union { TCHAR *ptszGroup; // group title (several controls may be grouped together); may be NULL. char *pszGroup; WCHAR *pwszGroup; }; union { TCHAR *ptszTooltip; // tooltip for the control; may be NULL char *pszTooltip; WCHAR *pwszTooltip; }; const char *szModule; // database module; may contain variables (see above; currently the only existing variable is CSMODULE_PROTO) const char *szSetting; // database setting int StateNum; // number of possible states; always 2 or 3 for CSCT_CHECKBOX, and can be any number starting from 2 for CSCT_COMBOBOX int DefState; // default state index CSCONTROLSTATE *pStates; // array of StateNum items, describing all possible control states. Can be NULL for CSCT_COMBOBOX, in this case ContactSettings will use DBVT_BYTE database values, 0 is unchecked, 1 is checked, 2 is indeterminate. Can't be NULL for CSCT_COMBOBOX. DWORD ValueMask; // in most cases simply set this to 0. when not 0, it allows to define a bit mask to access separate bits of a db value instead of reading/writing the whole value. is valid only for DBVT_BYTE, DBVT_WORD and DBVT_DWORD values } CONTACTSETTINGSCONTROL; #define MS_CONTACTSETTINGS_ADDCONTROL "ContactSettings/AddControl" typedef struct { int cbSize; // sizeof(CONTACTSETTINGSCHANGEINFO) HANDLE hContact; const char *szModule; // variables in szModule and szSetting are NOT parsed, i.e. ContactSettings copies the values straight from CONTACTSETTINGSCONTROL const char *szSetting; } CONTACTSETTINGSCHANGEINFO; /* ME_CONTACTSETTINGS_SETTINGCHANGED Called for every changed setting when the user applied changes in a contact settings dialog wParam=(WPARAM)(CONTACTSETTINGSCHANGEINFO*)csci lParam=0 This event will be triggered many times rapidly when a whole bunch of values are set. Modules which hook this should be aware of this fact and quickly return if they are not interested in the value that has been changed. */ #define ME_CONTACTSETTINGS_SETTINGCHANGED "ContactSettings/SettingChanged" /* MS_CONTACTSETTINGS_SHOWDIALOG Shows Contact Settings dialog for a contact wParam=hContact lParam=0 */ #define MS_CONTACTSETTINGS_SHOWDIALOG "ContactSettings/ShowDialog" /* MS_CONTACTSETTINGS_SHOWGROUPDIALOG. Not implemented yet. Shows dialog for a group wParam=groupId (0 is the main group) lParam=0 */ #define MS_CONTACTSETTINGS_SHOWGROUPDIALOG "ContactSettings/ShowGroupDialog" /* Example of use: // in ME_SYSTEM_MODULESLOADED handler: HookEvent(ME_CONTACTSETTINGS_INITIALISE, ContactSettingsInit); // ME_CONTACTSETTINGS_INITIALISE handler static int ContactSettingsInit(WPARAM wParam, LPARAM lParam) { CONTACTSETTINGSINIT *csi = (CONTACTSETTINGSINIT*)wParam; // check first whether to add controls or not // we need to get a protocol name for that, if it's a contact settings dialog: char *szProto = (csi->Type == CSIT_CONTACT) ? (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)csi->hContact, 0) : NULL; // in general, you MUST add all your controls if csi->Type == CSIT_GROUP (i.e. user opened a group settings dialog), otherwise your plugin won't support group settings well: if ((csi->Type == CSIT_GROUP) || // otherwise (for a contact settings dialog), you can add controls depending on some conditions, like protocol caps, etc. // in this example, we check whether the protocol has a PS_GETCUSTOMSTATUSICON service (i.e. does it support xstatuses or not): (csi->Type == CSIT_CONTACT && szProto && ProtoServiceExists(szProto, PS_GETCUSTOMSTATUSICON))) // your plugin must ignore cases when csi->Type is neither CSIT_GROUP nor CSIT_CONTACT { CONTACTSETTINGSCONTROL csc = {0}; csc.cbSize = sizeof(csc); csc.Position = CSPOS_SORTBYALPHABET; csc.Flags = CSCF_TCHAR; csc.ControlType = CSCT_COMBOBOX; csc.StateNum = 3; csc.ptszTitle = LPGENT("XStatus change notifications:") _T("\0") LPGENT("Ignore") _T("\0") LPGENT("Notify always") _T("\0") LPGENT("Use global settings") _T("\0"); csc.ptszGroup = CSGROUP_NOTIFICATIONS; csc.ptszTooltip = LPGENT("Tooltip text"); csc.pszDBSetting = "ModuleName/XSNotifications"; csc.DefValue = 2; // "Use global settings" CallService(MS_CONTACTSETTINGS_ADDCONTROL, wParam, (LPARAM)&csc); // and CSCT_CHECKBOX example: csc.Position = CSPOS_SORTBYALPHABET; csc.Flags = CSCF_TCHAR; csc.ControlType = CSCT_CHECKBOX; csc.StateNum = 3; csc.ptszTitle = LPGENT("Other setting"); csc.ptszGroup = LPGENT("Some group"); csc.ptszTooltip = LPGENT("Tooltip text"); csc.pszDBSetting = "ModuleName/OtherSetting"; csc.DefValue = 2; // BST_INDETERMINATE CallService(MS_CONTACTSETTINGS_ADDCONTROL, wParam, (LPARAM)&csc); } return 0; } */ #endif // __M_CONTACTSETTINGS_H