diff options
author | Kirill Volinsky <mataes2007@gmail.com> | 2012-05-18 22:02:50 +0000 |
---|---|---|
committer | Kirill Volinsky <mataes2007@gmail.com> | 2012-05-18 22:02:50 +0000 |
commit | f920ef497f3299ae24fe783ce03bdd93b419f764 (patch) | |
tree | bdaa9197c08d29ab141a6adfdd6cc0a68ddd3996 /plugins/MetaContacts | |
parent | 6c3b0571f0678da0512069869afaa284c054377e (diff) |
plugins folders renaming
git-svn-id: http://svn.miranda-ng.org/main/trunk@60 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MetaContacts')
29 files changed, 7921 insertions, 0 deletions
diff --git a/plugins/MetaContacts/IcoLib.h b/plugins/MetaContacts/IcoLib.h new file mode 100644 index 0000000000..1817df68dc --- /dev/null +++ b/plugins/MetaContacts/IcoLib.h @@ -0,0 +1,37 @@ +typedef struct {
+ int cbSize;
+ char *pszSection; //section name used to group icons
+ char *pszDescription; //description for options dialog
+ char *pszName; //name to refer to icon when playing and in db
+ //this name is miranda-wide. so use prefixes of your plugin
+ //e.g: "isee_connect", "clist_delete", etc
+ char *pszDefaultFile; //default icon file to use
+ int iDefaultIndex;
+} SKINICONDESC;
+
+typedef struct {
+ int cbSize;
+ char *pszSection;
+ char *pszDescription;
+ char *pszName;
+ char *pszDefaultFile;
+ int iDefaultIndex;
+ HICON hDefaultIcon;
+} SKINICONDESC2;
+
+//
+// Add a icon into options UI
+//
+// wParam = (WPARAM)0
+// lParam = (LPARAM)(SKINICONDESC*)sid;
+//
+#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon"
+//
+// Retrieve HICON with name specified in lParam
+// Returned HICON SHOULDN'T be destroyed, it managed by IcoLib
+//
+#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon"
+//
+// Icons change notification
+//
+#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged"
diff --git a/plugins/MetaContacts/MetaContacts translations/metacontacts_template.txt b/plugins/MetaContacts/MetaContacts translations/metacontacts_template.txt new file mode 100644 index 0000000000..18a000e683 --- /dev/null +++ b/plugins/MetaContacts/MetaContacts translations/metacontacts_template.txt @@ -0,0 +1,205 @@ +[MetaContacts]
+
+[Allows the joining of several subcontacts into one]
+
+[Error - Database corruption.\nPlugin disabled.]
+
+;menu
+[Toggle MetaContacts On/Off]
+
+[Convert to MetaContact]
+
+[Add to existing MetaContact...]
+
+[Edit MetaContact...]
+
+[Delete MetaContact]
+
+[Remove from MetaContact]
+
+[Force Default]
+
+[Unforce Default]
+
+[Set as MetaContact default]
+
+[Context]
+
+;dialog
+[History Copy]
+
+[Please wait while the contact's history is copied.]
+
+[History Remove]
+
+[Please wait while the contact's history is removed.]
+
+[Add to Existing MetaContact]
+
+[Please select a MetaContact:]
+
+[Editing]
+
+[&OK]
+
+[&Cancel]
+
+[&Apply]
+
+[&Remove]
+
+[&Set as Default]
+
+[Move &Up]
+
+[Move &Down]
+
+[Force use of default for sending (even if offline)]
+
+[Information]
+
+[Name:]
+
+[Contacts]
+
+[Contact]
+
+[Id]
+
+[Protocol]
+
+[Default]
+
+[Yes]
+
+[No]
+
+[Options]
+
+[Automatically set default contact on receipt of message]
+
+[Always send to default contact if not offline]
+
+[Suppress status notification for subcontacts]
+
+[Hide in status bar and status menu (*requires restart, uncheck to set proto icons)]
+
+[Use subcontact message windows]
+
+[Context Menu]
+
+[Contact Labels]
+
+[Use contact's unique id]
+
+[Use contact's display name]
+
+[Function]
+
+[Set default and open message window]
+
+[Show subcontact context menu]
+
+[Show user information]
+
+[Contact List]
+
+[Display subcontact nickname]
+
+[Display subcontact display name]
+
+[History (** beware - change at your own risk **)]
+
+[Copy subcontact history to MetaContact when creating or adding]
+
+[Number of days to copy (0=all):]
+
+[Keep MetaContact history synchronized with subcontacts]
+
+[Keep subcontact history synchronized with MetaContact]
+
+[Nick]
+
+[Sender]
+
+;message
+[Delete MetaContact?]
+
+[You are going to remove all the contacts associated with this MetaContact.\nThis will delete the MetaContact.\n\nProceed Anyway?]
+
+[Contact not present in the DB]
+
+[This contact seems not to be in the database.\nThe database could be corrupted.\nTry to remove it manually.]
+
+[MetaContact Conflict]
+
+[This contact is a MetaContact.\nYou can't add a MetaContact to another MetaContact.\n\nPlease choose another.]
+
+[Multiple MetaContacts]
+
+[This contact is already associated to a MetaContact.\nYou cannot add a contact to multiple MetaContacts.]
+
+[No suitable MetaContact found]
+
+[Either there is no MetaContact in the database (in this case you should first convert a contact into one)\nor there is none that can host this contact.\nAnother solution could be to convert this contact into a new MetaContact.\n\nConvert this contact into a new MetaContact?]
+
+[Adding %s...]
+
+[a contact]
+
+[No MetaContact selected]
+
+[Please select a MetaContact]
+
+[Assignment failure]
+
+[The operation failed: Assigning <%s> to <%s>]
+
+[Assignment Error]
+
+[Could not get MetaContact id]
+
+[Could not retreive MetaContact contact count]
+
+[Could not retreive contact protocol]
+
+[Contact is 'Not on List' - please add the contact to your contact list before assigning.]
+
+[MetaContact is full]
+
+[Could not write contact protocol to MetaContact]
+
+[Could not get unique id of contact]
+
+[Could not write unique id of contact to MetaContact]
+
+[Could not write nickname of contact to MetaContact]
+
+[Could not write clist displayname of contact to MetaContact]
+
+[Could not write contact status to MetaContact]
+
+[Could not write contact handle to MetaContact]
+
+[Could not write contact status string to MetaContact]
+
+[Could not write MetaContact id to contact]
+
+[Could not write MetaContact contact number to contact]
+
+[Could not write contact count to MetaContact]
+
+[No contacts found.]
+
+[There was a problem in assigning the contact to the MetaContact]
+
+[Database Corruption]
+
+[This will remove the MetaContact permanently.\n\nProceed Anyway?]
+
+[Are you sure?]
+
+; db corruption
+[MetaID: ]
+
+[MetaContact corrupted - the number of subcontacts is incorrect.\nDelete MetaContact?]
diff --git a/plugins/MetaContacts/MetaContacts.rc b/plugins/MetaContacts/MetaContacts.rc new file mode 100644 index 0000000000..1eee03456c --- /dev/null +++ b/plugins/MetaContacts/MetaContacts.rc @@ -0,0 +1,335 @@ +// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral (Default) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_METASELECT, DIALOG
+ BEGIN
+ LEFTMARGIN, 3
+ RIGHTMARGIN, 252
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 252
+ END
+
+ IDD_METAEDIT, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 378
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 255
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_METASELECT DIALOGEX 0, 0, 256, 259
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Add to Existing MetaContact"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CTEXT "Please select a MetaContact:",IDC_STATIC,27,11,201,14
+ DEFPUSHBUTTON "&Ok",IDOK,73,238,48,14
+ PUSHBUTTON "&Cancel",IDCANCEL,133,238,48,14
+ LISTBOX IDC_METALIST,44,28,168,168,LBS_NOINTEGRALHEIGHT | WS_VSCROLL
+ CONTROL "Sort Alphabetically",IDC_CHK_SRT,"Button",BS_AUTOCHECKBOX | BS_VCENTER | WS_TABSTOP,78,210,124,13
+END
+
+IDD_METAEDIT DIALOGEX 0, 0, 383, 260
+STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_STATICEDGE
+CAPTION "Editing"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "&OK",IDOK,106,241,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,166,241,50,14
+ LTEXT "Name:",IDC_STATIC,108,26,42,8
+ GROUPBOX "Information",IDC_STATIC,5,4,373,45
+ GROUPBOX "Contacts",IDC_FRAME,5,54,373,180
+ PUSHBUTTON "&Apply",IDC_VALIDATE,226,241,50,14
+ DEFPUSHBUTTON "&Remove",IDC_BTN_REM,53,181,50,14
+ PUSHBUTTON "&Set as Default",IDC_BTN_SETDEFAULT,107,181,50,14
+ PUSHBUTTON "Move &Up",IDC_BTN_UP,224,181,50,14
+ PUSHBUTTON "Move &Down",IDC_BTN_DOWN,279,181,50,14
+ EDITTEXT IDC_ED_NAME,158,23,135,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP
+ CONTROL "List1",IDC_LST_CONTACTS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,53,79,276,89,WS_EX_CLIENTEDGE
+ GROUPBOX "",IDC_STATIC,35,66,313,138
+ CONTROL "Force use of default for sending (even if offline)",IDC_CHK_FORCEDEFAULT,
+ "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,110,215,209,10
+ PUSHBUTTON "Send &Offline",IDC_BTN_SETOFFLINE,161,181,50,14
+END
+
+#endif // Neutral (Default) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// French (France) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // French (France) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral (Sys. Default) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUSD)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MCMENU ICON "mcmenu.ico"
+IDI_MCMENUOFF ICON "mcmenuof.ico"
+#endif // Neutral (Sys. Default) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Australia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ VERTGUIDE, 4
+ VERTGUIDE, 9
+ VERTGUIDE, 137
+ VERTGUIDE, 173
+ HORZGUIDE, 74
+ END
+
+ IDD_COPYPROGRESS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 83
+ END
+
+ IDD_DELPROGRESS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 83
+ END
+
+ IDD_PRIORITIES, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 259
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 150
+ END
+
+ IDD_HISTORY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 280
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 102
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPTIONS DIALOGEX 0, 0, 298, 178
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ CONTROL "Set default contact on receipt of message",IDC_CHK_SETDEFAULTRECV,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,9,290,10
+ CONTROL "Always send to default contact if not offline",IDC_CHK_ALWAYSUSEDEFAULT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,31,290,10
+ GROUPBOX "Options",IDC_STATIC,0,0,297,178
+ CONTROL "Suppress status notification for subcontacts",IDC_CHK_SUPPRESSSTATUS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,42,290,10
+ GROUPBOX "Context Menu",IDC_STATIC,4,79,289,58
+ CONTROL "Use contact's unique id",IDC_RAD_UID,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,100,112,10
+ CONTROL "Use contact's display name",IDC_RAD_DID,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,114,112,10
+ GROUPBOX "Contact Labels",IDC_STATIC,9,87,120,45,WS_GROUP
+ GROUPBOX "Function",IDC_STATIC,133,87,155,45,WS_GROUP
+ CONTROL "Set default and open message window",IDC_RAD_MSG,"Button",BS_AUTORADIOBUTTON | WS_GROUP,137,98,148,10
+ CONTROL "Show subcontact context menu",IDC_RAD_MENU,"Button",BS_AUTORADIOBUTTON | WS_GROUP,137,108,148,10
+ CONTROL "Show user information",IDC_RAD_INFO,"Button",BS_AUTORADIOBUTTON | WS_GROUP,137,118,148,10
+ GROUPBOX "Contact List",IDC_STATIC,4,139,289,33,WS_GROUP
+ CONTROL "Display subcontact nickname",IDC_RAD_NICK,"Button",BS_AUTORADIOBUTTON | WS_GROUP,9,149,144,10
+ CONTROL "Display subcontact display name",IDC_RAD_NAME,"Button",BS_AUTORADIOBUTTON | WS_GROUP,9,160,144,10
+ CONTROL "Hide in status bar and status menu (*requires restart, uncheck to set proto icons)",IDC_CHK_SUPPRESSPROTO,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,53,290,10
+ CONTROL "Use subcontact message windows",IDC_CHK_SUBWINDOW,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,64,165,10
+ CONTROL "Copy subcontact data",IDC_CHK_COPYDATA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,173,64,118,10
+ CONTROL "Lock name to first contact",IDC_CHK_LOCKHANDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,173,155,115,10
+ CONTROL "but only for the current conversation",IDC_CHK_TEMPDEFAULT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,20,260,10
+END
+
+IDD_COPYPROGRESS DIALOG 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION
+CAPTION "History Copy"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "Progress1",IDC_PROG,"msctls_progress32",0x0,28,49,130,13
+ CTEXT "Please wait while the contact's history is copied.",IDC_STATIC,9,27,167,8
+END
+
+IDD_DELPROGRESS DIALOG 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION
+CAPTION "History Remove"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "Progress1",IDC_PROG,"msctls_progress32",0x0,28,49,130,13
+ CTEXT "Please wait while the contact's history is removed.",IDC_STATIC,9,27,167,8
+END
+
+IDD_PRIORITIES DIALOGEX 0, 0, 266, 157
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Subcontact Priorities",IDC_STATIC,7,7,252,143
+ EDITTEXT IDC_ED_PRIORITY,157,78,40,14,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_SP_PRIORITY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,195,78,11,14
+ RTEXT "Rank:",IDC_STATIC,42,81,49,8
+ RTEXT "Status:",IDC_STATIC,30,57,61,8
+ COMBOBOX IDC_CMB_STATUS,98,53,112,87,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ RTEXT "Protocol:",IDC_STATIC,30,31,61,8
+ COMBOBOX IDC_CMB_PROTOCOL,98,28,112,112,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Reset All",IDC_BTN_RESET,87,119,91,14
+ CONTROL "Default",IDC_CHK_DEFAULT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,97,81,58,10
+ CTEXT "(Lower ranks are preferred)",IDC_STATIC,51,99,162,8
+END
+
+IDD_HISTORY DIALOGEX 0, 0, 287, 109
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Copy subcontact history to MetaContact when creating or adding",IDC_CHK_COPYHISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,23,258,10
+ RTEXT "Number of days to copy (0=all):",IDC_STATIC,13,37,125,8
+ EDITTEXT IDC_ED_DAYS,158,35,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Keep MetaContact history synchronized with subcontacts",IDC_CHK_METAHISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,60,258,10
+ CONTROL "Keep subcontact history synchronized with MetaContact",IDC_CHK_SUBHISTORY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,78,258,10
+ GROUPBOX "History (** beware - change at your own risk **)",IDC_STATIC,7,7,273,95,WS_GROUP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MCEDIT ICON "meta_edit.ico"
+IDI_MCREMOVE ICON "meta_remove2.ico"
+IDI_MCCONVERT ICON "meta_convert.ico"
+IDI_MCADD ICON "meta_add.ico"
+IDI_MCSETDEFAULT ICON "meta_set_as_default.ico"
+#endif // English (Australia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/MetaContacts/MetaContacts_10.sln b/plugins/MetaContacts/MetaContacts_10.sln new file mode 100644 index 0000000000..636c27ec9b --- /dev/null +++ b/plugins/MetaContacts/MetaContacts_10.sln @@ -0,0 +1,26 @@ +
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaContacts", "MetaContacts_10.vcxproj", "{0007BE9F-DD4D-4E9B-B1C8-C5049538F862}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Debug|Win32.Build.0 = Debug|Win32
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Debug|x64.ActiveCfg = Debug|x64
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Debug|x64.Build.0 = Debug|x64
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Release|Win32.ActiveCfg = Release|Win32
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Release|Win32.Build.0 = Release|Win32
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Release|x64.ActiveCfg = Release|x64
+ {0007BE9F-DD4D-4E9B-B1C8-C5049538F862}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/MetaContacts/MetaContacts_10.vcxproj b/plugins/MetaContacts/MetaContacts_10.vcxproj new file mode 100644 index 0000000000..03708a1f26 --- /dev/null +++ b/plugins/MetaContacts/MetaContacts_10.vcxproj @@ -0,0 +1,274 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>MetaContacts</ProjectName>
+ <ProjectGuid>{0007BE9F-DD4D-4E9B-B1C8-C5049538F862}</ProjectGuid>
+ <RootNamespace>MetaContacts</RootNamespace>
+ <Keyword>MFCProj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/MetaContacts.tlb</TypeLibraryName>
+ </Midl>
+ <ClCompile>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>metacontacts.h</PrecompiledHeaderFile>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ShowIncludes>false</ShowIncludes>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_AFXDLL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0c09</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>unicows.lib;user32.lib;gdi32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/MetaContacts.tlb</TypeLibraryName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>metacontacts.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <ShowIncludes>false</ShowIncludes>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <OmitFramePointers>false</OmitFramePointers>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_AFXDLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0c09</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>unicows.lib;user32.lib;gdi32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x22010000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <OmitFramePointers>false</OmitFramePointers>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>false</OmitFramePointers>
+ </ClCompile>
+ <Link>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="addto.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="edit.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="icons.c" />
+ <ClCompile Include="meta_api.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="meta_main.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="meta_menu.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="meta_options.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="meta_services.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="meta_utils.c">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+ <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_USRDLL;METACONTACTS_EXPORTS;_MBCS;_WINDLL;_AFXDLL</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="m_metacontacts.h" />
+ <ClInclude Include="metacontacts.h" />
+ <ClInclude Include="version.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="icon1.ico" />
+ <None Include="mcmenu.ico" />
+ <None Include="mcmenuof.ico" />
+ <None Include="meta_add.ico" />
+ <None Include="meta_convert.ico" />
+ <None Include="meta_edit.ico" />
+ <None Include="meta_remove2.ico" />
+ <None Include="meta_set_as_default.ico" />
+ <None Include="MetaContacts translations\metacontacts_template.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="MetaContacts.rc" />
+ <ResourceCompile Include="version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file diff --git a/plugins/MetaContacts/MetaContacts_10.vcxproj.filters b/plugins/MetaContacts/MetaContacts_10.vcxproj.filters new file mode 100644 index 0000000000..6caf9fe0c8 --- /dev/null +++ b/plugins/MetaContacts/MetaContacts_10.vcxproj.filters @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4a8bb46c-4423-42fc-9576-78cd8badfcff}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{a442bb73-5e8b-4eb0-b6c0-0534f3ca4b87}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{b4847f2a-7aa8-4577-a5a1-f7adf03537ec}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ <Filter Include="translation template">
+ <UniqueIdentifier>{a8acfb52-2cd1-4156-ad43-fcdd6773d45c}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="addto.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="edit.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="icons.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="meta_api.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="meta_main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="meta_menu.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="meta_options.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="meta_services.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="meta_utils.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="m_metacontacts.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="metacontacts.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Resource Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="icon1.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="mcmenu.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="mcmenuof.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="meta_add.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="meta_convert.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="meta_edit.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="meta_remove2.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="meta_set_as_default.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="MetaContacts translations\metacontacts_template.txt">
+ <Filter>translation template</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="MetaContacts.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file diff --git a/plugins/MetaContacts/addto.c b/plugins/MetaContacts/addto.c new file mode 100644 index 0000000000..3fcfcd2a62 --- /dev/null +++ b/plugins/MetaContacts/addto.c @@ -0,0 +1,301 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file addto.c
+*
+* Functions for the <b>'Add To'</b> Dialog.
+* Contains all the functions and all the structures
+* needed to display and control the <b>'Add To'</b> Dialog.
+*/
+#include "metacontacts.h"
+
+//! Holds information about a contact.
+typedef struct {
+ char *name; //!< Name of the contact
+ char *proto; //!< Protocol under which the contact has been registered
+ HANDLE hUser; //!< Identifier of the contact in the DB.
+}USERINFO;
+
+//! Holds information for the callback function.
+typedef struct {
+ USERINFO uInfo; //!< Information about the contact to add
+}ADDTO_INFO;
+
+/** Adds all the metacontacts desired in the listview.
+*
+* Adds all the metacontacts present in the database in the list,
+*
+* @param list : \c HANDLE to the list which will contain the columns.
+* @param nb_contacts : Number of loaded contacts.
+* @param contacts : A list of the contacts' identifiers
+*
+* @param id : Reference to a list of the MetaContacts IDs loaded in the listview.
+* Since this list is resized, its address must be passed.
+*
+* @return An integer specifying the number of rows added in the list.
+*/
+int FillList(HWND list, BOOL sort)
+{
+ DWORD metaID;
+ HANDLE hMetaUser = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ int i=0;
+ int index;
+ //BOOL mbs = FALSE;
+
+ while(hMetaUser) // The DB is searched through, to get all the metacontacts
+ {
+ if((metaID=DBGetContactSettingDword(hMetaUser,META_PROTO,META_ID,(DWORD)-1))==(DWORD)-1)
+ {
+ // This isn't a MetaContact, go to the next
+ hMetaUser = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hMetaUser,0);
+ continue;
+ }
+
+
+ {
+ // get contact display name from clist
+ char *szCDN = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hMetaUser, 0);
+
+ if(os_unicode_enabled) {
+ wchar_t *swzCDN = (wchar_t *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hMetaUser, GCDNF_UNICODE),
+ *swzContactDisplayName;
+
+ // detect if the clist provided unicode display name by comparing with non-unicode
+ if(szCDN && swzCDN && strncmp(szCDN, (char *)swzCDN, strlen(szCDN)) != 0) {
+ swzContactDisplayName = swzCDN;
+ } else {
+ // no? convert to unicode
+ if(szCDN) {
+ swzContactDisplayName = (wchar_t *) _alloca(sizeof(wchar_t) * (strlen(szCDN) + 1));
+ MultiByteToWideChar(CP_ACP, 0, (char *) szCDN, -1, swzContactDisplayName, (int)strlen((char *)szCDN) + 1);
+ } else {
+ swzContactDisplayName = TranslateW(L"(Unknown Contact)");
+ }
+ }
+
+ // don't insert huge strings that we have to compare with later
+ if(wcslen(swzContactDisplayName) > 1023)
+ swzContactDisplayName[1024] = 0;
+
+ if(sort) {
+ int j;
+ wchar_t buff[1024];
+ for(j = 0; j < i; j++) {
+ SendMessageW(list, LB_GETTEXT, j, (LPARAM)buff);
+ if(wcscmp(buff, swzContactDisplayName) > 0) break;
+ }
+ index = SendMessageW(list, LB_INSERTSTRING, (WPARAM)j, (LPARAM)swzContactDisplayName);
+ } else {
+ index = SendMessageW(list, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)swzContactDisplayName);
+ }
+ } else {
+ // don't insert huge strings that we have to compare with later
+ if(strlen(szCDN) > 1023)
+ szCDN[1024] = 0;
+
+ if(sort) {
+ int j;
+ char buff[1024];
+ for(j = 0; j < i; j++) {
+ SendMessage(list, LB_GETTEXT, j, (LPARAM)buff);
+ if(strcmp(buff, szCDN) > 0) break;
+ }
+ index = SendMessage(list, LB_INSERTSTRING, (WPARAM)j, (LPARAM)szCDN);
+ } else {
+ index = SendMessage(list, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)szCDN);
+ }
+ }
+
+ SendMessage(list, LB_SETITEMDATA, (WPARAM)index, (LPARAM)hMetaUser);
+ }
+
+ i++;
+
+ hMetaUser = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hMetaUser,0);
+ }
+ return i;
+}
+
+/** Build or update the list.
+*
+* @param list : \c HANDLE to the list which will contain the columns
+* @param id : Reference to a list that will contain all the MetaContacts IDs loaded in the listview
+* otherwise the list is only refilled \n (Warning : this value must be
+* set to \c TRUE only once per Dialog display, otherwise all columns will be doubled)
+*
+* @returns An integer specifying the number of rows inserted or \c -1 if there was a problem
+*/
+int BuildList(HWND list, BOOL sort)
+{
+ int ret=-1;
+ SendMessage(list, LB_RESETCONTENT, 0, 0);
+
+ ret = FillList(list, sort);
+
+ return ret;
+}
+
+/** Callback function for the <b>'Add To'</b> Dialog.
+*
+* All the UI is controlled here, from display to functionnalities.
+*
+* @param hwndDlg : \c HANDLE to the <b>'Add To'</b> \c Dialog.
+* @param uMsg : Specifies the message received by this dialog.
+* @param wParam : Specifies additional message-specific information.
+* @param lParam : Specifies additional message-specific information.
+*
+* @return \c TRUE if the dialog processed the message, \c FALSE if it did not.
+*/
+INT_PTR CALLBACK Meta_SelectDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault( hwndDlg );
+
+
+ if(DBGetContactSettingDword((HANDLE)lParam,META_PROTO,META_ID,(DWORD)-1)!=(DWORD)-1)
+ {
+ MessageBox(hwndDlg,Translate("This contact is a MetaContact.\nYou can't add a MetaContact to another MetaContact.\n\nPlease choose another."),
+ Translate("MetaContact Conflict"),MB_ICONERROR);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ if(DBGetContactSettingDword((HANDLE)lParam,META_PROTO,META_LINK,(DWORD)-1)!=(DWORD)-1)
+ {
+ MessageBox(hwndDlg,Translate("This contact is already associated to a MetaContact.\nYou cannot add a contact to multiple MetaContacts."),
+ Translate("Multiple MetaContacts"),MB_ICONERROR);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); // user data is contact handle
+
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx(I_ADD));
+ //SendMessage(GetDlgItem(hwndDlg,IDC_METALIST),LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FULLROWSELECT);
+
+ // Initialize the graphical part
+ CheckDlgButton(hwndDlg,IDC_ONLYAVAIL,BST_CHECKED); // Initially checked; display all metacontacts is only an option
+ // Besides, we can check if there is at least one metacontact to add the contact to.
+ if(BuildList(GetDlgItem(hwndDlg,IDC_METALIST), FALSE)<=0)
+ {
+ if(MessageBox(hwndDlg,Translate("Either there is no MetaContact in the database (in this case you should first convert a contact into one)\n"
+ "or there is none that can host this contact.\n"
+ "Another solution could be to convert this contact into a new MetaContact.\n\nConvert this contact into a new MetaContact?"),
+ Translate("No suitable MetaContact found"),MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON1)==IDYES)
+ Meta_Convert((WPARAM)lParam,0);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ else
+ {
+ // Get the name displayed in the CList...
+
+ // get contact display name from clist
+ char *szCDN = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)lParam, 0);
+ if(os_unicode_enabled) {
+ wchar_t *swzCDN = (wchar_t *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)lParam, GCDNF_UNICODE),
+ *swzContactDisplayName;
+ wchar_t buf[256];
+
+ // detect if the clist provided unicode display name by comparing with non-unicode
+ if(szCDN && swzCDN && strncmp(szCDN, (char *)swzCDN, strlen(szCDN)) != 0) {
+ swzContactDisplayName = swzCDN;
+ } else {
+ // no? convert to unicode
+ if(szCDN) {
+ swzContactDisplayName = (wchar_t *) _alloca(sizeof(wchar_t) * (strlen(szCDN) + 1));
+ MultiByteToWideChar(CP_ACP, 0, (char *) szCDN, -1, swzContactDisplayName, (int)strlen((char *)szCDN) + 1);
+ } else {
+ swzContactDisplayName = TranslateW(L"a contact");
+ }
+ }
+
+ // ... and set it to the Window title.
+ //MessageBoxW(hwndDlg, swzContactDisplayName, L"Setting window title", MB_OK);
+
+ // note - the swprintf function has changed (includes size_t for vc8+)
+ //swprintf(buf, 256, TranslateW(L"Adding %s..."), swzContactDisplayName);
+ // this *should* work for vc6, 7, and 8 (thx George)
+ _snwprintf(buf, 256, TranslateW(L"Adding %s..."), swzContactDisplayName);
+
+ SetWindowTextW(hwndDlg, buf);
+ } else {
+ char buf[256];
+ sprintf(buf,Translate("Adding %s..."), szCDN);
+ SetWindowText(hwndDlg, buf);
+ }
+
+ ShowWindow(hwndDlg,SW_SHOWNORMAL);
+ return TRUE;
+ }
+ }
+ case WM_COMMAND:
+ if(HIWORD(wParam)!=BN_CLICKED)
+ break; // Only clicks of buttons are relevant, let other COMMANDs through
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ HANDLE hMeta, hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ int item; // Get the index of the selected metacontact
+ if((item = SendMessage(GetDlgItem(hwndDlg, IDC_METALIST),LB_GETCURSEL, 0, 0))==-1)
+ return IDOK == MessageBox(hwndDlg,Translate("Please select a MetaContact"),Translate("No MetaContact selected"),MB_ICONHAND);
+
+ hMeta = (HANDLE)SendMessage(GetDlgItem(hwndDlg, IDC_METALIST), LB_GETITEMDATA, (WPARAM)item, 0);
+
+ {
+ if(!Meta_Assign(hContact,hMeta, FALSE))
+ {
+ MessageBox(hwndDlg, Translate("Assignment to the MetaContact failed."), Translate("Assignment failure"),MB_ICONERROR);
+ }
+ }
+ }
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_CHK_SRT:
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_METALIST), GWL_STYLE, GetWindowLong(GetDlgItem(hwndDlg, IDC_METALIST), GWL_STYLE) ^ LBS_SORT);
+ if(BuildList(GetDlgItem(hwndDlg,IDC_METALIST), IsDlgButtonChecked(hwndDlg, IDC_CHK_SRT) ? TRUE : FALSE)<=0)
+ {
+ if(MessageBox(hwndDlg,Translate("Either there is no MetaContact in the database (in this case you should first convert a contact into one)\n"
+ "or there is none that can host this contact.\n"
+ "Another solution could be to convert this contact into a new MetaContact.\n\nConvert this contact into a new MetaContact?"),
+ Translate("No suitable MetaContact found"),MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON1)==IDYES)
+ Meta_Convert((WPARAM)lParam,0);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY:
+ { // Free all allocated memory and return the focus to the CList
+ HWND clist = GetParent(hwndDlg);
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
+ EndDialog(hwndDlg,TRUE);
+ SetFocus(clist);
+ return TRUE;
+ }
+ }
+ return FALSE; // All other Message are not handled
+}
diff --git a/plugins/MetaContacts/edit.c b/plugins/MetaContacts/edit.c new file mode 100644 index 0000000000..9a5f55d920 --- /dev/null +++ b/plugins/MetaContacts/edit.c @@ -0,0 +1,585 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file edit.c
+*
+* Functions for the <b>'Edit'</b> Dialog.
+* Contains all the functions and all the structures
+* needed to display and control the <b>'Edit'</b> Dialog.
+*/
+#include "metacontacts.h"
+
+//! Holds the differents changes that have to made
+typedef struct tag_CHANGES {
+ HANDLE hMeta; //!< \c HANDLE of the MetaContact that is edited.
+ HANDLE hDefaultContact; //!< \c HANDLE of the new default contact
+ HANDLE hOfflineContact;
+ int num_deleted, //!< \c DWORD number of deleted contacts
+ num_contacts; //!< \c DWORD number of contacts
+ HANDLE hDeletedContacts[MAX_CONTACTS]; //!< \c HANDLEs of the subcontacts to be removed from this metacontact
+ HANDLE hContact[MAX_CONTACTS]; //!< \c HANDLEs of the subcontacts, in the order they should be in
+ int force_default;
+} CHANGES;
+
+CHANGES changes; //!< \c global CHANGES structure
+
+/** Fills the list of contacts
+*
+* @param chg : Structure holding all the change info (See CHANGES).
+*/
+void FillContactList(HWND hWndDlg, CHANGES *chg) {
+ HWND hList = GetDlgItem(hWndDlg, IDC_LST_CONTACTS);
+ char *proto, *field, buff[256];
+ int i;
+ LVITEM LvItem;
+ DBVARIANT dbv;
+ LVITEMW LvItemW; // for unicode nicks
+
+
+ SendMessage(hList,LVM_DELETEALLITEMS,0,0);
+
+ ZeroMemory(&LvItem, sizeof(LvItem));
+ LvItem.mask=LVIF_TEXT; // Text Style
+ LvItem.cchTextMax = 256; // Max size of test
+
+ ZeroMemory(&LvItemW, sizeof(LvItemW));
+ LvItemW.mask=LVIF_TEXT; // Text Style
+ LvItemW.cchTextMax = 256; // Max size of test
+
+ for(i = 0; i < chg->num_contacts; i++) {
+ LvItem.iItem = i;
+ LvItemW.iItem = i;
+
+ {
+
+ char *szCDN = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)chg->hContact[i], 0);
+
+ if(os_unicode_enabled) {
+ wchar_t *swzCDN = (wchar_t *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)chg->hContact[i], GCDNF_UNICODE),
+ *swzContactDisplayName;
+
+ LvItemW.iSubItem = 0; // clist display name
+
+ // detect if the clist provided unicode display name by comparing with non-unicode
+ if(szCDN && swzCDN && strncmp(szCDN, (char *)swzCDN, strlen(szCDN)) != 0 && wcslen(swzCDN) >= strlen(szCDN)) {
+ swzContactDisplayName = swzCDN;
+ } else {
+ // no? convert to unicode
+ if(szCDN) {
+ swzContactDisplayName = (wchar_t *) _alloca(sizeof(wchar_t) * (strlen(szCDN) + 1));
+ MultiByteToWideChar(CP_ACP, 0, (char *) szCDN, -1, swzContactDisplayName, (int)strlen((char *)szCDN) + 1);
+ } else {
+ swzContactDisplayName = TranslateW(L"(Unknown Contact)");
+ }
+ }
+
+ LvItemW.pszText = swzContactDisplayName;
+ SendMessageW(hList, LVM_INSERTITEMW, (WPARAM)0, (LPARAM)&LvItemW);
+ } else {
+ LvItem.iSubItem = 0; // clist display name
+ LvItem.pszText = szCDN;
+ SendMessage(hList, LVM_INSERTITEM, (WPARAM)0, (LPARAM)&LvItem);
+ }
+ }
+
+
+
+ LvItem.iSubItem = 1; // id
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)chg->hContact[i], 0);
+ if(proto) {
+ field = (char *)CallProtoService(proto,PS_GETCAPS,PFLAG_UNIQUEIDSETTING,0);
+
+ DBGetContactSetting(chg->hContact[i],proto,field,&dbv);
+ switch(dbv.type)
+ {
+ case DBVT_ASCIIZ:
+ sprintf(buff,"%s",dbv.pszVal);
+ break;
+ case DBVT_BYTE:
+ sprintf(buff,"%d",dbv.bVal);
+ break;
+ case DBVT_WORD:
+ sprintf(buff,"%d",dbv.wVal);
+ break;
+ case DBVT_DWORD:
+ sprintf(buff,"%d",(int)dbv.dVal);
+ break;
+ default:
+ //sprintf(buff,"");
+ buff[0] = 0;
+ }
+ DBFreeVariant(&dbv);
+
+ LvItem.pszText = buff;
+ SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); // Enter text to SubItems
+
+ LvItem.iSubItem = 2; // protocol
+ LvItem.pszText = proto;
+ SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); // Enter text to SubItems
+ } else {
+ LvItem.pszText = "Unknown";
+ SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); // Enter text to SubItems
+
+ LvItem.iSubItem = 2; // protocol
+ LvItem.pszText = "Unknown";
+ SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); // Enter text to SubItems
+ }
+ LvItem.iSubItem = 3; // Default (Yes/No)
+ LvItem.pszText = (chg->hContact[i] == chg->hDefaultContact ? Translate("Yes") : Translate("No"));
+ SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); // Enter text to SubItems
+
+ LvItem.iSubItem = 4; // Offline (Yes/No)
+ LvItem.pszText = (chg->hContact[i] == chg->hOfflineContact ? Translate("Yes") : Translate("No"));
+ SendMessage(hList,LVM_SETITEM,0,(LPARAM)&LvItem); // Enter text to SubItems
+ }
+}
+
+
+void SetListSelection(HWND hList, int sel) {
+ LVITEM LvItem;
+
+ ZeroMemory(&LvItem, sizeof(LvItem));
+ LvItem.iItem = sel;
+ LvItem.mask = LVIF_STATE;
+ LvItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
+ LvItem.state = LVIS_SELECTED|LVIS_FOCUSED;
+
+ SendMessage(hList, LVM_SETITEMSTATE, (WPARAM)sel, (LPARAM)&LvItem);
+
+}
+
+/** Scans the \c CHANGES and call the appropriate function for each change.
+*
+* @param chg : Structure holding all the change info (See CHANGES).
+*/
+void ApplyChanges(CHANGES *chg)
+{
+ HANDLE most_online;
+ int i;
+
+ // remove removed contacts
+ for(i = 0; i < chg->num_deleted; i++) {
+ Meta_Delete((WPARAM)chg->hDeletedContacts[i], 0);
+ if(chg->hDeletedContacts[i] == chg->hDefaultContact)
+ chg->hDefaultContact = 0;
+ if(chg->hDeletedContacts[i] == chg->hOfflineContact)
+ chg->hOfflineContact = 0;
+ }
+
+ // set contact positions
+ for(i = 0; i < chg->num_contacts; i++) {
+ if(Meta_GetContactNumber(chg->hContact[i]) != i)
+ Meta_SwapContacts(chg->hMeta, Meta_GetContactNumber(chg->hContact[i]), i);
+ }
+
+ NotifyEventHooks(hSubcontactsChanged, (WPARAM)chg->hMeta, (LPARAM)chg->hDefaultContact);
+
+ // set default
+ if(chg->hDefaultContact)
+ DBWriteContactSettingDword(chg->hMeta, META_PROTO, "Default", Meta_GetContactNumber(chg->hDefaultContact));
+ else
+ DBWriteContactSettingDword(chg->hMeta, META_PROTO, "Default", 0);
+ NotifyEventHooks(hEventDefaultChanged, (WPARAM)chg->hMeta, (LPARAM)chg->hDefaultContact);
+
+ // set offline
+ if(chg->hOfflineContact)
+ DBWriteContactSettingDword(chg->hMeta, META_PROTO, "OfflineSend", Meta_GetContactNumber(chg->hOfflineContact));
+ else
+ DBWriteContactSettingDword(chg->hMeta, META_PROTO, "OfflineSend", (DWORD)-1);
+
+ // fix nick
+ most_online = Meta_GetMostOnline(chg->hMeta);
+ Meta_CopyContactNick(chg->hMeta, most_online);
+
+ // fix status
+ Meta_FixStatus(chg->hMeta);
+
+ // fix avatar
+ most_online = Meta_GetMostOnlineSupporting(chg->hMeta, PFLAGNUM_4, PF4_AVATARS);
+ if(most_online) {
+ PROTO_AVATAR_INFORMATION AI;
+
+ AI.cbSize = sizeof(AI);
+ AI.hContact = chg->hMeta;
+ AI.format = PA_FORMAT_UNKNOWN;
+ strcpy(AI.filename, "X");
+
+ if((int)CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&AI) == GAIR_SUCCESS)
+ DBWriteContactSettingString(chg->hMeta, "ContactPhoto", "File",AI.filename);
+ }
+
+ if(MetaAPI_GetForceState((WPARAM)chg->hMeta, 0) != chg->force_default)
+ MetaAPI_ForceDefault((WPARAM)chg->hMeta, 0);
+}
+
+LRESULT ProcessCustomDraw (LPARAM lParam)
+{
+ LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
+
+ switch(lplvcd->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT : //Before the paint cycle begins
+ //request notifications for individual listview items
+ return CDRF_NOTIFYITEMDRAW;
+
+ case CDDS_ITEMPREPAINT: //Before an item is drawn
+ /*
+ if (((int)lplvcd->nmcd.dwItemSpec%2)==0)
+ {
+ //customize item appearance
+ //lplvcd->clrText = RGB(255,0,0);
+ lplvcd->clrTextBk = RGB(200,200,200);
+ }
+ else{
+ //lplvcd->clrText = RGB(0,0,255);
+ lplvcd->clrTextBk = RGB(255,255,255);
+ }
+ */
+ if(changes.hContact[(int)lplvcd->nmcd.dwItemSpec] == changes.hDefaultContact) {
+ lplvcd->clrText = RGB(255, 0, 0);
+ }
+ return CDRF_NEWFONT;
+ }
+
+ return 0;
+}
+
+/** Callback function for the <b>'Edit'</b> Dialog.
+*
+* All the UI is controlled here, from display to functionnalities.
+*
+* @param hwndDlg : \c HANDLE to the <b>'Edit'</b> \c Dialog.
+* @param uMsg : Specifies the message received by this dialog.
+* @param wParam : Specifies additional message-specific information.
+* @param lParam : Specifies additional message-specific information (handle of MetaContact to edit)
+*
+* @return \c TRUE if the dialog processed the message, \c FALSE if it did not.
+*/
+#define WMU_SETTITLE (WM_USER + 1)
+
+INT_PTR CALLBACK Meta_EditDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd;
+ char *str;
+ int sel, i;
+
+ switch(msg)
+ {
+ case WM_INITDIALOG:
+ {
+ // Font necessary for all controls created with CreateWindowsEx
+ //HFONT hfDefault = GetStockObject(DEFAULT_GUI_FONT);
+ //HWND combo = GetDlgItem(hwndDlg,IDC_DEFAULT);
+ int nb_contacts, default_contact_number, offline_contact_number;
+ LVCOLUMN LvCol;
+
+ TranslateDialogDefault( hwndDlg );
+
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx(I_EDIT));
+
+ // Disable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),FALSE);
+
+ // (from http://www.codeproject.com/listctrl/listview.asp)
+ // initialize list
+ hwnd = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ SendMessage(hwnd,LVM_SETEXTENDEDLISTVIEWSTYLE, 0,LVS_EX_FULLROWSELECT); // Set style
+
+ // Create list columns
+ ZeroMemory(&LvCol, sizeof(LvCol));
+ LvCol.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; // Type of mask
+
+ // Inserting Couloms as much as we want
+ LvCol.pszText=Translate("Contact"); // First Header Text
+ LvCol.cx=100; // width of column
+ SendMessage(hwnd,LVM_INSERTCOLUMN,0,(LPARAM)&LvCol); // Insert/Show the coloum
+
+ LvCol.pszText=Translate("Id"); // Next coloum
+ LvCol.cx=130; // width of column
+ SendMessage(hwnd,LVM_INSERTCOLUMN,1,(LPARAM)&LvCol); // ...
+ LvCol.pszText=Translate("Protocol"); //
+ LvCol.cx=100; // width of column
+ SendMessage(hwnd,LVM_INSERTCOLUMN,2,(LPARAM)&LvCol); //
+ LvCol.pszText=Translate("Default"); //
+ LvCol.cx=60; // width of column
+ SendMessage(hwnd,LVM_INSERTCOLUMN,3,(LPARAM)&LvCol); //
+ LvCol.pszText=Translate("Send Offline"); //
+ LvCol.cx=85; // width of column
+ SendMessage(hwnd,LVM_INSERTCOLUMN,4,(LPARAM)&LvCol); //
+
+ // disable buttons until a selection is made in the list
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_REM);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_SETDEFAULT);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_SETOFFLINE);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_UP);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_DOWN);
+ EnableWindow(hwnd, FALSE);
+
+ nb_contacts = DBGetContactSettingDword((HANDLE)lParam, META_PROTO, "NumContacts", 0);
+ default_contact_number = DBGetContactSettingDword((HANDLE)lParam, META_PROTO, "Default", (DWORD)-1);
+ offline_contact_number = DBGetContactSettingDword((HANDLE)lParam, META_PROTO, "OfflineSend", (DWORD)-1);
+
+ changes.hMeta = (HANDLE)lParam;
+ changes.num_contacts = nb_contacts;
+ changes.num_deleted = 0;
+ changes.hDefaultContact = Meta_GetContactHandle((HANDLE)lParam, default_contact_number);
+ changes.hOfflineContact = Meta_GetContactHandle((HANDLE)lParam, offline_contact_number);
+ for(i = 0; i < nb_contacts; i++)
+ changes.hContact[i] = Meta_GetContactHandle((HANDLE)lParam, i);
+ changes.force_default = MetaAPI_GetForceState((WPARAM)lParam, 0);
+
+ SendMessage(hwndDlg, WMU_SETTITLE, 0, lParam);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_FORCEDEFAULT, changes.force_default);
+
+ FillContactList(hwndDlg, &changes);
+ return TRUE;
+ }
+ case WMU_SETTITLE:
+ {
+
+ char *szCDN = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)lParam, 0);
+ if(os_unicode_enabled) {
+ wchar_t *swzCDN = (wchar_t *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)lParam, GCDNF_UNICODE),
+ *swzContactDisplayName;
+
+ // detect if the clist provided unicode display name by comparing with non-unicode
+ if(szCDN && swzCDN && strncmp(szCDN, (char *)swzCDN, strlen(szCDN)) != 0 && wcslen(swzCDN) >= strlen(szCDN)) {
+ swzContactDisplayName = swzCDN;
+ } else {
+ // no? convert to unicode
+ if(szCDN) {
+ swzContactDisplayName = (wchar_t *) _alloca(sizeof(wchar_t) * (strlen(szCDN) + 1));
+ MultiByteToWideChar(CP_ACP, 0, (char *) szCDN, -1, swzContactDisplayName, (int)strlen((char *)szCDN) + 1);
+ } else {
+ swzContactDisplayName = TranslateW(L"(Unknown Contact)");
+ }
+ }
+
+ SetWindowTextW(GetDlgItem(hwndDlg,IDC_ED_NAME), swzContactDisplayName);
+ } else {
+ SetWindowText(GetDlgItem(hwndDlg,IDC_ED_NAME), szCDN);
+ }
+ }
+ return TRUE;
+ case WM_NOTIFY: // the message that is being sent always
+ switch(LOWORD(wParam)) // hit control
+ {
+ case IDC_LST_CONTACTS: // did we hit our ListView contorl?
+ if(((LPNMHDR)lParam)->code == NM_CLICK) {
+ hwnd = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ sel=SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+ // enable buttons
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_REM);
+ EnableWindow(hwnd, sel!=-1);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_SETDEFAULT);
+ EnableWindow(hwnd, sel!=-1 && changes.hContact[sel] != changes.hDefaultContact);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_SETOFFLINE);
+ EnableWindow(hwnd, sel!=-1 && changes.hContact[sel] != changes.hOfflineContact);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_UP);
+ EnableWindow(hwnd, (sel > 0));
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_DOWN);
+ EnableWindow(hwnd, (sel != -1) && (sel < changes.num_contacts - 1));
+/*
+ // custom draw stuff - change colour of listview things - doesn't affect selection :(
+ } else if(((LPNMHDR)lParam)->code == NM_CUSTOMDRAW) {
+ SetWindowLong(hwndDlg, DWL_MSGRESULT, (LONG)ProcessCustomDraw(lParam));
+ return TRUE;
+*/
+ }
+ break;
+ }
+ break;
+ case WM_COMMAND:
+ switch(HIWORD(wParam))
+ {
+ case BN_CLICKED: // A button ('Remove', 'Ok', 'Cancel' or 'Apply', normally) has been clicked
+ switch(LOWORD(wParam))
+ {
+ case IDC_VALIDATE: // Apply changes, if there is still one contact attached to the metacontact.
+ if(changes.num_contacts == 0) // Otherwise, delete the metacontact.
+ {
+ if(MessageBox(hwndDlg,Translate("You are going to remove all the contacts associated with this MetaContact.\nThis will delete the MetaContact.\n\nProceed Anyway?"),
+ Translate("Delete MetaContact?"),MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON1)!=IDYES)
+ return TRUE;
+ else
+ {
+ Meta_Delete((WPARAM)changes.hMeta,(LPARAM)NULL);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ }
+ ApplyChanges(&changes);
+
+ // Disable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),FALSE);
+ break;
+ case IDOK:
+ if(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_VALIDATE)))
+ { // If there are changes that could be made,
+ if(changes.num_contacts == 0) // do the work that would have be done if
+ { // the button 'Apply' has been clicked.
+ if(MessageBox(hwndDlg,Translate("You are going to remove all the contacts associated with this MetaContact.\nThis will delete the MetaContact.\n\nProceed Anyway?"),
+ Translate("Delete MetaContact?"),MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON1)!=IDYES)
+ {
+ return TRUE;
+ } else {
+ Meta_Delete((WPARAM)changes.hMeta,(LPARAM)NULL);
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+ }
+ ApplyChanges(&changes);
+ }
+ EndDialog(hwndDlg, IDOK);
+ return TRUE;
+ case IDCANCEL: // Simply close the dialog
+ EndDialog(hwndDlg, IDCANCEL);
+ return TRUE;
+ case IDC_BTN_SETDEFAULT:
+ hwnd = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ sel=SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+ InvalidateRect(hwnd, 0, TRUE);
+ changes.hDefaultContact = changes.hContact[sel];
+ SendMessage(hwndDlg, WMU_SETTITLE, 0, (LPARAM)changes.hContact[sel]);
+
+ FillContactList(hwndDlg, &changes);
+ SetListSelection(hwnd, sel);
+ // Disable set default button
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_SETDEFAULT),FALSE);
+ // Enable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),TRUE);
+
+ // repaint list
+ return TRUE;
+ case IDC_BTN_SETOFFLINE:
+ hwnd = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ sel=SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+ InvalidateRect(hwnd, 0, TRUE);
+ changes.hOfflineContact = changes.hContact[sel];
+
+ FillContactList(hwndDlg, &changes);
+ SetListSelection(hwnd, sel);
+ // Disable set offline button
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_SETOFFLINE),FALSE);
+ // Enable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),TRUE);
+
+ // repaint list
+ return TRUE;
+ case IDC_BTN_REM:
+ hwnd = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ sel=SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+ changes.num_contacts--;
+ changes.hDeletedContacts[changes.num_deleted++] = changes.hContact[sel];
+ if(changes.hDefaultContact == changes.hContact[sel]) {
+ if(changes.num_contacts > 0) {
+ changes.hDefaultContact = changes.hContact[0];
+ str = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)changes.hDefaultContact, 0);
+ SetWindowText(GetDlgItem(hwndDlg,IDC_ED_DEFAULT),str);
+ } else {
+ changes.hDefaultContact = 0;
+ SetWindowText(GetDlgItem(hwndDlg,IDC_ED_DEFAULT),"None");
+ }
+
+ }
+
+ for(i = sel; i < changes.num_contacts; i++)
+ changes.hContact[i] = changes.hContact[i + 1];
+ FillContactList(hwndDlg, &changes);
+ // disable buttons
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_REM);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_SETDEFAULT);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_SETOFFLINE);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_UP);
+ EnableWindow(hwnd, FALSE);
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_DOWN);
+ EnableWindow(hwnd, FALSE);
+ // Enable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),TRUE);
+ return TRUE;
+ case IDC_BTN_UP:
+ hwnd = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ sel=SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+
+ {
+ HANDLE temp = changes.hContact[sel];
+ changes.hContact[sel] = changes.hContact[sel - 1];
+ changes.hContact[sel - 1] = temp;
+ }
+ FillContactList(hwndDlg, &changes);
+ sel--;
+ SetListSelection(hwnd, sel);
+
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_UP);
+ EnableWindow(hwnd, (sel > 0));
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_DOWN);
+ EnableWindow(hwnd, (sel < changes.num_contacts - 1));
+ // Enable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),TRUE);
+ return TRUE;
+ case IDC_BTN_DOWN:
+ hwnd = GetDlgItem(hwndDlg, IDC_LST_CONTACTS);
+ sel=SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_FOCUSED|LVNI_SELECTED); // return item selected
+
+ {
+ HANDLE temp = changes.hContact[sel];
+ changes.hContact[sel] = changes.hContact[sel + 1];
+ changes.hContact[sel + 1] = temp;
+ }
+ FillContactList(hwndDlg, &changes);
+ sel++;
+ SetListSelection(hwnd, sel);
+
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_UP);
+ EnableWindow(hwnd, (sel > 0));
+ hwnd = GetDlgItem(hwndDlg, IDC_BTN_DOWN);
+ EnableWindow(hwnd, (sel < changes.num_contacts - 1));
+ // Enable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),TRUE);
+ return TRUE;
+ case IDC_CHK_FORCEDEFAULT:
+ changes.force_default = IsDlgButtonChecked(hwndDlg, IDC_CHK_FORCEDEFAULT);
+ // Enable the 'Apply' button.
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VALIDATE),TRUE);
+ return TRUE;
+ }
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+
+ case WM_DESTROY:
+ ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
+ EndDialog(hwndDlg, IDCANCEL);
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/plugins/MetaContacts/icons.c b/plugins/MetaContacts/icons.c new file mode 100644 index 0000000000..f10739ca0b --- /dev/null +++ b/plugins/MetaContacts/icons.c @@ -0,0 +1,101 @@ +#include "metacontacts.h"
+
+HANDLE hIcoLibIconsChanged = NULL;
+
+
+typedef struct {
+ char* szDescr;
+ char* szName;
+ int defIconID;
+} IconStruct;
+
+static IconStruct iconList[] = {
+ { "Toggle Off", "mc_off", IDI_MCMENUOFF },
+ { "Toggle On", "mc_on", IDI_MCMENU },
+ { "Convert to MetaContact", "mc_convert", IDI_MCCONVERT },
+ { "Add to Existing", "mc_add", IDI_MCADD },
+ { "Edit", "mc_edit", IDI_MCEDIT },
+ { "Set to Default", "mc_default", IDI_MCSETDEFAULT },
+ { "Remove", "mc_remove", IDI_MCREMOVE },
+};
+
+
+HICON LoadIconEx(IconIndex i) {
+ HICON hIcon;
+
+ if (hIcoLibIconsChanged)
+ hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)iconList[(int)i].szName);
+ else
+ hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(iconList[(int)i].defIconID), IMAGE_ICON, 0, 0, 0);
+
+ return hIcon;
+}
+
+
+void ReleaseIconEx(HICON hIcon) {
+ if (hIcoLibIconsChanged)
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ else
+ DestroyIcon(hIcon);
+}
+
+int ReloadIcons(WPARAM wParam, LPARAM lParam) {
+ // fix menu icons
+ CLISTMENUITEM menu = {0};
+
+ menu.cbSize = sizeof(menu);
+ menu.flags = CMIM_ICON;
+
+ menu.hIcon = LoadIconEx(Meta_IsEnabled() ? I_MENUOFF : I_MENU);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuOnOff, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_CONVERT);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_ADD);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_EDIT);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuEdit, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_SETDEFAULT);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ menu.hIcon = LoadIconEx(I_REMOVE);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDelete, (LPARAM)&menu);
+ ReleaseIconEx(menu.hIcon);
+
+ return 0;
+}
+
+void InitIcons(void) {
+ SKINICONDESC sid = {0};
+ char path[MAX_PATH];
+ int i;
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.pszSection = META_PROTO;
+ sid.pszDefaultFile = path;
+ GetModuleFileName(hInstance, path, sizeof(path));
+
+ for (i = 0; i < sizeof(iconList) / sizeof(IconStruct); ++i)
+ {
+ sid.pszDescription = Translate(iconList[i].szDescr);
+ sid.pszName = iconList[i].szName;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+ hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, ReloadIcons);
+
+ ReloadIcons(0, 0);
+}
+
+void DeinitIcons(void) {
+ if (hIcoLibIconsChanged) UnhookEvent(hIcoLibIconsChanged);
+}
diff --git a/plugins/MetaContacts/icons.h b/plugins/MetaContacts/icons.h new file mode 100644 index 0000000000..c77b1b02fc --- /dev/null +++ b/plugins/MetaContacts/icons.h @@ -0,0 +1,6 @@ +#ifndef _ICONS_INC
+#define _ICONS_INC
+
+#include "metacontacts.h"
+
+#endif
diff --git a/plugins/MetaContacts/mcmenu.ico b/plugins/MetaContacts/mcmenu.ico Binary files differnew file mode 100644 index 0000000000..b28455c554 --- /dev/null +++ b/plugins/MetaContacts/mcmenu.ico diff --git a/plugins/MetaContacts/mcmenuof.ico b/plugins/MetaContacts/mcmenuof.ico Binary files differnew file mode 100644 index 0000000000..72749e1c70 --- /dev/null +++ b/plugins/MetaContacts/mcmenuof.ico diff --git a/plugins/MetaContacts/mcmenuoff2.ico b/plugins/MetaContacts/mcmenuoff2.ico Binary files differnew file mode 100644 index 0000000000..5b3444abb0 --- /dev/null +++ b/plugins/MetaContacts/mcmenuoff2.ico diff --git a/plugins/MetaContacts/meta_add.ico b/plugins/MetaContacts/meta_add.ico Binary files differnew file mode 100644 index 0000000000..e3907099d9 --- /dev/null +++ b/plugins/MetaContacts/meta_add.ico diff --git a/plugins/MetaContacts/meta_api.c b/plugins/MetaContacts/meta_api.c new file mode 100644 index 0000000000..bf3aed5d2f --- /dev/null +++ b/plugins/MetaContacts/meta_api.c @@ -0,0 +1,245 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au)
+
+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.
+*/
+
+/** @file meta_api.c
+*
+* API functions needed to handle MetaContacts.
+* Centralizes functions called by other plugins.
+*/
+
+#include "metacontacts.h"
+
+//get the handle for a contact's parent metacontact
+//wParam=(HANDLE)hSubContact
+//lParam=0
+//returns a handle to the parent metacontact, or null if this contact is not a subcontact
+INT_PTR MetaAPI_GetMeta(WPARAM wParam, LPARAM lParam) {
+ return (int)(HANDLE)DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Handle", 0);
+}
+
+//gets the handle for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the default contact, or null on failure
+INT_PTR MetaAPI_GetDefault(WPARAM wParam, LPARAM lParam) {
+ DWORD default_contact_number = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Default", -1);
+ if(default_contact_number != -1) {
+ return (int)Meta_GetContactHandle((HANDLE)wParam, default_contact_number);
+ }
+ return 0;
+}
+
+//gets the contact number for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD contact number, or -1 on failure
+INT_PTR MetaAPI_GetDefaultNum(WPARAM wParam, LPARAM lParam) {
+ return DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Default", -1);
+}
+
+//gets the handle for the 'most online' contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the 'most online' contact
+INT_PTR MetaAPI_GetMostOnline(WPARAM wParam, LPARAM lParam) {
+ return (int)Meta_GetMostOnline((HANDLE)wParam);
+}
+
+//gets the number of subcontacts for a metacontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD representing the number of subcontacts for the given metacontact
+INT_PTR MetaAPI_GetNumContacts(WPARAM wParam, LPARAM lParam) {
+ DWORD num_contacts = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "NumContacts", -1);
+ return num_contacts;
+}
+
+//gets the handle of a subcontact, using the subcontact's number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns a handle to the specified subcontact
+INT_PTR MetaAPI_GetContact(WPARAM wParam, LPARAM lParam) {
+ return (int)Meta_GetContactHandle((HANDLE)wParam, (DWORD)lParam);
+}
+
+//sets the default contact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+INT_PTR MetaAPI_SetDefaultContactNum(WPARAM wParam, LPARAM lParam) {
+ DWORD num_contacts = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "NumContacts", -1);
+ if(num_contacts == -1)
+ return 1;
+ if((DWORD)lParam >= num_contacts || (DWORD)lParam < 0)
+ return 1;
+ if(DBWriteContactSettingDword((HANDLE)wParam, META_PROTO, "Default", (DWORD)lParam))
+ return 1;
+
+ NotifyEventHooks(hEventDefaultChanged, wParam, (LPARAM)Meta_GetContactHandle((HANDLE)wParam, (int)lParam));
+ return 0;
+}
+
+//sets the default contact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success
+INT_PTR MetaAPI_SetDefaultContact(WPARAM wParam, LPARAM lParam) {
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword((HANDLE)lParam, META_PROTO, "Handle", 0);
+ DWORD contact_number = Meta_GetContactNumber((HANDLE)lParam);
+ if(contact_number == -1 || !hMeta || hMeta != (HANDLE)wParam)
+ return 1;
+ if(DBWriteContactSettingDword(hMeta, META_PROTO, "Default", contact_number))
+ return 1;
+
+ NotifyEventHooks(hEventDefaultChanged, wParam, lParam);
+ return 0;
+}
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+INT_PTR MetaAPI_ForceSendContactNum(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = Meta_GetContactHandle((HANDLE)wParam, (int)lParam);
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword(hContact, META_PROTO, "Handle", 0);
+ if(!hContact || !hMeta || hMeta != (HANDLE)wParam || DBGetContactSettingByte(hMeta, META_PROTO, "ForceDefault", 0))
+ return 1;
+
+ DBWriteContactSettingDword(hMeta, META_PROTO, "ForceSend", (DWORD)hContact);
+
+ NotifyEventHooks(hEventForceSend, wParam, (LPARAM)hContact);
+ return 0;
+}
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success (will fail if 'force default' is in effect)
+INT_PTR MetaAPI_ForceSendContact(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)lParam;
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword(hContact, META_PROTO, "Handle", 0);
+ if(!hContact || !hMeta || hMeta != (HANDLE)wParam || DBGetContactSettingByte(hMeta, META_PROTO, "ForceDefault", 0))
+ return 1;
+
+ DBWriteContactSettingDword(hMeta, META_PROTO, "ForceSend", (DWORD)hContact);
+
+ NotifyEventHooks(hEventForceSend, wParam, lParam);
+ return 0;
+}
+
+//'unforces' the metacontact to send using a specific subcontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 0 on success (will fail if 'force default' is in effect)
+INT_PTR MetaAPI_UnforceSendContact(WPARAM wParam, LPARAM lParam) {
+ if(DBGetContactSettingByte((HANDLE)wParam, META_PROTO, "ForceDefault", 0))
+ return 1;
+
+ DBWriteContactSettingDword((HANDLE)wParam, META_PROTO, "ForceSend", 0);
+
+ NotifyEventHooks(hEventUnforceSend, wParam, lParam);
+ return 0;
+}
+
+
+//'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact
+// overrides 'force send' above, and will even force use of offline contacts
+// will send ME_MC_FORCESEND event
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 1(true) or 0(false) representing new state of 'force default'
+INT_PTR MetaAPI_ForceDefault(WPARAM wParam, LPARAM lParam) {
+ // forward to menu function
+ Meta_ForceDefault(wParam, lParam);
+ return DBGetContactSettingByte((HANDLE)wParam, META_PROTO, "ForceDefault", 0);
+}
+
+// method to get state of 'force' for a metacontact
+// wParam=(HANDLE)hMetaContact
+// lParam= (DWORD)&contact_number or NULL
+// if lparam supplied, the contact_number of the contatct 'in force' will be copied to the address it points to,
+// or if none is in force, the value (DWORD)-1 will be copied
+// (v0.8.0.8+ returns 1 if 'force default' is true with *lParam == default contact number, else returns 0 with *lParam as above)
+INT_PTR MetaAPI_GetForceState(WPARAM wParam, LPARAM lParam) {
+ HANDLE hMeta = (HANDLE)wParam;
+ HANDLE hContact;
+
+ if(!hMeta) return 0;
+
+ if(DBGetContactSettingByte(hMeta, META_PROTO, "ForceDefault", 0)) {
+ if(lParam) *(DWORD *)lParam = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Default", -1);
+ return 1;
+ }
+
+ hContact = (HANDLE)DBGetContactSettingDword(hMeta, META_PROTO, "ForceSend", 0);
+
+ if(!hContact) {
+ if(lParam) *(DWORD *)lParam = -1;
+ } else {
+ if(lParam) *(DWORD *)lParam = (DWORD)Meta_GetContactNumber(hContact);
+ }
+
+ return 0;
+}
+
+// method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :)
+// wParam=lParam=0
+INT_PTR MetaAPI_GetProtoName(WPARAM wParam, LPARAM lParam) {
+ return (int)META_PROTO;
+}
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=0
+// convert a given contact into a metacontact
+INT_PTR MetaAPI_ConvertToMeta(WPARAM wParam, LPARAM lParam) {
+ return Meta_Convert(wParam, lParam);
+}
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=(HANDLE)hMeta
+// add an existing contact to a metacontact
+INT_PTR MetaAPI_AddToMeta(WPARAM wParam, LPARAM lParam) {
+ return Meta_Assign((HANDLE)wParam, (HANDLE)lParam, FALSE);
+}
+
+// added 0.9.5.0 (22/3/05)
+// wParam=0
+// lParam=(HANDLE)hContact
+// remove a contact from a metacontact
+INT_PTR MetaAPI_RemoveFromMeta(WPARAM wParam, LPARAM lParam) {
+ // notice we switch args - to keep the API function consistent with the others
+ return Meta_Delete((WPARAM)lParam, (LPARAM)wParam);
+}
+
+// added 0.9.13.2 (6/10/05)
+// wParam=(BOOL)disable
+// lParam=0
+// enable/disable the 'hidden group hack' - for clists that support subcontact hiding using 'IsSubcontact' setting
+// should be called once in your 'onmodulesloaded' event handler
+
+BOOL meta_group_hack_disabled = FALSE; // this global flag is used in utils 'SetGroup' function
+
+INT_PTR MetaAPI_DisableHiddenGroup(WPARAM wParam, LPARAM lParam) {
+ meta_group_hack_disabled = (BOOL)wParam;
+ return 0;
+}
diff --git a/plugins/MetaContacts/meta_convert.ico b/plugins/MetaContacts/meta_convert.ico Binary files differnew file mode 100644 index 0000000000..747d9d1d18 --- /dev/null +++ b/plugins/MetaContacts/meta_convert.ico diff --git a/plugins/MetaContacts/meta_edit.ico b/plugins/MetaContacts/meta_edit.ico Binary files differnew file mode 100644 index 0000000000..2992671618 --- /dev/null +++ b/plugins/MetaContacts/meta_edit.ico diff --git a/plugins/MetaContacts/meta_main.c b/plugins/MetaContacts/meta_main.c new file mode 100644 index 0000000000..eea5e0666e --- /dev/null +++ b/plugins/MetaContacts/meta_main.c @@ -0,0 +1,270 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file meta_main.c
+*
+* Functions used by Miranda to launch the plugin.
+* Centralizes functions needed by Miranda to get
+* information about the plugin and to initialize it
+* and to dispose of it properly.
+*/
+
+/*! \mainpage MetaContacts plugin
+ * \image html ulp.gif
+ * \section desc Description
+ * This library is a plugin for Miranda IM.\n
+ * It allows the user to group several contacts from different
+ * protocols (such as AIM or ICQ) into one unique metacontact.\n
+ *
+ * \section principle How does it work ?
+ * Only one protocol will be used at a time (the default protocol).\n
+ * This protocol is referenced in the proper field of the MetaContact
+ * section in the Database.
+ *
+ * \subsection send Emission of messages
+ * The plugin will search through the Database to get the default protocol
+ * (i.e. the protocol used to communicate with),\n and then call the Send function
+ * provided by this protocol.
+ *
+ * \subsection recv Reception of messages
+ * When a contact is converted to a metacontact, or when it is added to an existing
+ * metacontact, it gets a pseudo protocol \n (named "MetaContacts") in the protocol chain.\n
+ * Usually, when a message is received, all the protocols in the chain get this message,
+ * the real protocol (for example ICQ) at the end.\n But here, the message will be intercepted
+ * by the MetaContact protocol, which will inhibit the further reception.\n The message will
+ * then be redirected to the MetaContact, that will display it normally.
+ *
+ * \subsection handling Handling MetaContacts
+ * There are four functionnality for handling MetaContacts :
+ * \li Convert a contact to a MetaContact.
+ * \li Add a contact to an existing MetaContact.
+ * \li Edit a MetaContact.
+ * \li Delete a MetaContact.
+ *
+ * They all are accessible via the context-menu displayed when a right click has occured,
+ * but not at the same time : The 2 first will appear when the menu concerns a simple contact.\n
+ * whereas the 2 last are only accessible from a MetaContact.\n
+ * Those functions are self-explanatory, and a MessageBox is shown before any modification, so, for
+ * further information, take a look at the Dialogs shown when they are called.\n
+ *
+ * \section cvats Caveats
+ * Several functionnalities have not yet been developped :
+ * \li Assigning contacts by Drag'n'Drop
+ * \li Updating dynamically the status of the MetaContact
+ * \li Merging history of all the contacts attached to MetaContact
+ * \li Handling Files and URLs as well as Messages
+ * \li and some other little functionnalities...
+ *
+ * Some of those functionnalities will not be developped due to the architecture
+ * of Miranda (the 2 first, for example)
+ *
+ * \section mail Contact
+ * For any comment, suggestion or question, send a mail to shaalj@free.fr.\n
+ * This code is provided as-is, and I cannot be held responsible for any harm
+ * done to your database by this plugin.\n
+ * Test it first on a fake database before using it normally.
+ */
+
+#include "metacontacts.h"
+
+// Use VersionNo.h to set the version number, and ensure resource file is not open
+#include "version.h"
+
+struct MM_INTERFACE mmi;
+BOOL os_unicode_enabled = FALSE;
+int hLangpack;
+
+//! Information gathered by Miranda, displayed in the plugin pane of the Option Dialog
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME, // altered here and on file listing, so as not to match original
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ 0,
+ 0,
+ { 0x4c4a27cf, 0x5e64, 0x4242, { 0xa3, 0x32, 0xb9, 0x8b, 0x8, 0x24, 0x3e, 0x89 } } // {4C4A27CF-5E64-4242-A332-B98B08243E89}
+};
+
+HINSTANCE hInstance; //!< Global reference to the application
+PLUGINLINK *pluginLink; //!< Link between Miranda and this plugin
+
+/** Called by Miranda to get the information associated to this plugin.
+* It only returns the PLUGININFO structure, without any test on the version
+* @param mirandaVersion The version of the application calling this function
+*/
+__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ if ( mirandaVersion < PLUGIN_MAKE_VERSION( 0, 8, 0, 0 )) {
+ MessageBox( NULL, _T("The MetaContacts cannot be loaded. It requires Miranda IM 0.8.0.0 or later."), _T("Miranda"), MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST );
+ return NULL;
+ }
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_METACONTACTS, MIID_LAST};
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+/** DLL entry point
+* Required to store the instance handle
+*/
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInstance=hinstDLL;
+ DisableThreadLibraryCalls(hInstance);
+ return TRUE;
+}
+
+/** Prepare the plugin to stop
+* Called by Miranda when it will exit or when the plugin gets deselected
+*/
+__declspec(dllexport)int Unload(void)
+{
+ // see also meta_services.c, Meta_PreShutdown
+ Meta_CloseHandles();
+ //MessageBox(0, "Unload complete", "MC", MB_OK);
+ return 0;
+}
+
+BOOL IsUnicodeOS()
+{
+ OSVERSIONINFOW os;
+ memset(&os, 0, sizeof(OSVERSIONINFOW));
+ os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+ return (GetVersionExW(&os) != 0);
+}
+
+/** Initializes the services provided and the link to those needed
+* Called when the plugin is loaded into Miranda
+*/
+int __declspec(dllexport)Load(PLUGINLINK *link)
+{
+ PROTOCOLDESCRIPTOR pd;
+ DBVARIANT dbv;
+
+ pluginLink=link;
+
+ mir_getMMI(&mmi);
+ mir_getLP(&pluginInfo);
+
+ os_unicode_enabled = IsUnicodeOS();
+
+ if(ServiceExists(MS_DB_SETSETTINGRESIDENT)) { // 0.6+
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(META_PROTO "/Status"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(META_PROTO "/IdleTS"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(META_PROTO "/ContactCountCheck"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(META_PROTO "/Handle"));
+ CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(META_PROTO "/WindowOpen"));
+ }
+
+ //set all contacts to 'offline', and initialize subcontact counter for db consistency check
+ {
+ HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0);
+ char *proto;
+ while(hContact != NULL) {
+ //proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if(!DBGetContactSetting(hContact, "Protocol", "p", &dbv)) {
+ proto = dbv.pszVal;
+ if (proto && !lstrcmp( META_PROTO, proto)) {
+ DBWriteContactSettingWord(hContact, META_PROTO, "Status", ID_STATUS_OFFLINE);
+ DBWriteContactSettingDword(hContact, META_PROTO, "IdleTS", 0);
+ DBWriteContactSettingByte(hContact, META_PROTO, "ContactCountCheck", 0);
+
+ // restore any saved defaults that might have remained if miranda was closed or crashed while a convo was happening
+ if(DBGetContactSettingDword(hContact, META_PROTO, "SavedDefault", (DWORD)-1) != (DWORD)-1) {
+ DBWriteContactSettingDword(hContact, META_PROTO, "Default", DBGetContactSettingDword(hContact, META_PROTO, "SavedDefault", 0));
+ DBWriteContactSettingDword(hContact, META_PROTO, "SavedDefault", (DWORD)-1);
+ }
+
+ }
+ DBFreeVariant(&dbv);
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ }
+
+ Meta_ReadOptions(&options);
+
+
+ // sets subcontact handles to metacontacts, and metacontact handles to subcontacts
+ // (since these handles are not necessarily the same from run to run of miranda)
+
+ // also verifies that subcontacts: have metacontacts, and that contact numbers are reasonable,
+ // that metacontacts: have the correct number of subcontacts, and have reasonable defaults
+ if(Meta_SetHandles()) {
+ // error - db corruption
+ if(!DBGetContactSettingByte(0, META_PROTO, "DisabledMessageShown", 0)) {
+ MessageBox(0, Translate("Error - Database corruption.\nPlugin disabled."), Translate("MetaContacts"), MB_OK | MB_ICONERROR);
+ DBWriteContactSettingByte(0, META_PROTO, "DisabledMessageShown", 1);
+ }
+ //Meta_HideMetaContacts(TRUE);
+ return 1;
+ }
+
+ DBDeleteContactSetting(0, META_PROTO, "DisabledMessageShown");
+
+ // add our modules to the KnownModules list
+ {
+ DBVARIANT dbv;
+ if (DBGetContactSetting(NULL, "KnownModules", META_PROTO, &dbv))
+ DBWriteContactSettingString(NULL, "KnownModules", META_PROTO, META_PROTO);
+ else
+ DBFreeVariant(&dbv);
+ }
+
+ ZeroMemory(&pd,sizeof(pd));
+ pd.cbSize=PROTOCOLDESCRIPTOR_V3_SIZE;//sizeof(pd);
+
+ pd.szName=META_FILTER;
+ pd.type=PROTOTYPE_FILTER;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+
+ ZeroMemory(&pd,sizeof(pd));
+ pd.cbSize=PROTOCOLDESCRIPTOR_V3_SIZE;//sizeof(pd);
+
+ pd.szName=META_PROTO;
+ pd.type = PROTOTYPE_PROTOCOL;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+
+ // further db setup done in modules loaded (nick [protocol string required] & clist display name)
+
+ Meta_InitServices();
+
+ // moved to 'modules loaded' event handler (in meta_services.c) because we need to
+ // check protocol for jabber hack, and the proto modules must be loaded
+ //Meta_HideLinkedContactsAndSetHandles();
+
+ if(ServiceExists(MS_MSG_GETWINDOWAPI)) {
+ message_window_api_enabled = TRUE;
+ }
+
+ // for clist_meta_mw - write hidden group name to DB
+ DBWriteContactSettingString(0, META_PROTO, "HiddenGroupName", META_HIDDEN_GROUP);
+
+ return 0;
+}
diff --git a/plugins/MetaContacts/meta_menu.c b/plugins/MetaContacts/meta_menu.c new file mode 100644 index 0000000000..36caabffa7 --- /dev/null +++ b/plugins/MetaContacts/meta_menu.c @@ -0,0 +1,562 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file meta_menu.c
+*
+* Functions needed to handle MetaContacts.
+* Centralizes functions called when the user chooses
+* an option integrated in the context-menu of the \c CList.
+*/
+
+#include "metacontacts.h"
+
+/** Convert the contact chosen into a MetaContact.
+*
+* Create a new MetaContact, remove the selected contact from the \c CList
+* and attach it to the MetaContact.
+*
+* @param wParam : \c HANDLE to the contact that has been chosen.
+* @param lParam : Allways set to 0.
+*/
+INT_PTR Meta_Convert(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hMetaContact;
+ DBVARIANT dbv;
+ char *group = 0;//, *proto;
+
+ // Get some information about the selected contact.
+// proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ if(!DBGetContactSettingStringUtf((HANDLE)wParam,"CList","Group",&dbv)) {
+ group = _strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ // Create a new metacontact
+ hMetaContact = (HANDLE)CallService(MS_DB_CONTACT_ADD,0,0);
+
+ // Add the info for the metacontact
+ if(hMetaContact)
+ {
+
+ DBWriteContactSettingDword(hMetaContact,META_PROTO,META_ID,nextMetaID);
+ DBWriteContactSettingDword(hMetaContact,META_PROTO,"NumContacts",0);
+ DBWriteContactSettingDword(NULL,META_PROTO,"NextMetaID",++nextMetaID);
+
+ // Add the MetaContact protocol to the new meta contact
+ CallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hMetaContact, ( LPARAM )META_PROTO );
+
+ if(group) {
+ if(ServiceExists(MS_DB_CONTACT_GETSETTING_STR))
+ DBWriteContactSettingStringUtf(hMetaContact,"CList","Group",group);
+ else
+ DBWriteContactSettingString(hMetaContact,"CList","Group",group);
+ }
+
+ // Assign the contact to the MetaContact just created (and make default).
+ if(!Meta_Assign((HANDLE)wParam,hMetaContact,TRUE)) {
+ MessageBox(0,Translate("There was a problem in assigning the contact to the MetaContact"),Translate("Error"),MB_ICONEXCLAMATION);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hMetaContact, 0);
+ return 0;
+ }
+
+ // hide the contact if clist groups disabled (shouldn't create one anyway since menus disabled)
+ if(!Meta_IsEnabled())
+ DBWriteContactSettingByte(hMetaContact, "CList", "Hidden", 1);
+
+ }
+
+ // Update the graphics
+ CallService(MS_CLUI_SORTLIST,0,0);
+
+ free(group);
+ return (int)hMetaContact;
+}
+
+/** Display the <b>'Add to'</b> Dialog
+*
+* Present a dialog in which the user can choose to which MetaContact this
+* contact will be added
+*
+* @param wParam : \c HANDLE to the contact that has been chosen.
+* @param lParam : Allways set to 0.
+*/
+INT_PTR Meta_AddTo(WPARAM wParam, LPARAM lParam)
+{
+ HWND clui = (HWND)CallService(MS_CLUI_GETHWND,0,0);
+ DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_METASELECT),clui,&Meta_SelectDialogProc,(LPARAM)wParam);
+ return 0;
+}
+
+/** Display the <b>'Edit'</b> Dialog
+*
+* Present a dialog in which the user can edit some properties of the MetaContact.
+*
+* @param wParam : \c HANDLE to the MetaContact to be edited.
+* @param lParam : Allways set to 0.
+*/
+INT_PTR Meta_Edit(WPARAM wParam,LPARAM lParam)
+{
+ HWND clui = (HWND)CallService(MS_CLUI_GETHWND,0,0);
+ DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_METAEDIT),clui,Meta_EditDialogProc,(LPARAM)wParam);
+ return 0;
+}
+
+/* DB/Contact/WriteSetting service
+Change the value of, or create a new value with, a named setting for a specific
+contact in the database to the given value
+ wParam=(WPARAM)(HANDLE)hContact
+ lParam=(LPARAM)(DBCONTACTWRITESETTING*)&dbcws
+hContact should have been returned by find*contact or addcontact
+Returns 0 on success or nonzero if hContact was invalid
+Note that DBCONTACTGETSETTING takes a pointer to a DBVARIANT, whereas
+DBCONTACTWRITESETTING contains a DBVARIANT.
+Because this is such a common function there are some short helper function at
+the bottom of this header that use it.
+Triggers a db/contact/settingchanged event just before it returns.
+*/
+//typedef struct {
+// const char *szModule; // pointer to name of the module that wrote the
+// // setting to get
+// const char *szSetting; // pointer to name of the setting to get
+// DBVARIANT value; // variant containing the value to set
+//} DBCONTACTWRITESETTING;
+//#define MS_DB_CONTACT_WRITESETTING "DB/Contact/WriteSetting"
+
+void Meta_RemoveContactNumber(HANDLE hMeta, int number) {
+ int i, num_contacts, default_contact;
+ HANDLE hContact;//, handle;
+
+ char buffer[512], buffer2[512];
+
+ num_contacts = DBGetContactSettingDword(hMeta, META_PROTO, "NumContacts", 0);
+ default_contact = DBGetContactSettingDword(hMeta, META_PROTO, "Default", -1);
+ if(number >= 0 && number < num_contacts) {
+
+ // get the handle
+ hContact = Meta_GetContactHandle(hMeta, number);
+
+ // make sure this contact thinks it's part of this metacontact
+ if((HANDLE)DBGetContactSettingDword(hContact,META_PROTO,"Handle", 0) == hMeta) {
+
+ // remove link to meta contact
+ DBDeleteContactSetting(hContact,META_PROTO,"IsSubcontact");
+ DBDeleteContactSetting(hContact,META_PROTO,META_LINK);
+ DBDeleteContactSetting(hContact,META_PROTO,"Handle");
+ DBDeleteContactSetting(hContact,META_PROTO,"ContactNumber");
+ // unhide - must be done after removing link (see meta_services.c:Meta_ChangeStatus)
+ Meta_RestoreGroup(hContact);
+ DBDeleteContactSetting(hContact,META_PROTO,"OldCListGroup");
+ //CallService(MS_PROTO_REMOVEFROMCONTACT,(WPARAM)hContact,(LPARAM)META_PROTO);
+ CallService(MS_PROTO_REMOVEFROMCONTACT,(WPARAM)hContact,(LPARAM)META_FILTER);
+ // stop ignoring, if we were
+ if(options.suppress_status)
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+ }
+
+ // remove history from metacontact
+ //Meta_RemoveHistory(hMeta, hContact);
+
+ // each contact from 'number' upwards will be moved down one
+ // and the last one will be deleted
+ for(i = number + 1; i < num_contacts; i++) {
+ Meta_SwapContacts(hMeta, i, i-1);
+ }
+
+ // remove the last one
+ strcpy(buffer, "Protocol");
+ strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+ strcpy(buffer, "Status");
+ strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+ strcpy(buffer, "Handle");
+ strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+ strcpy(buffer, "StatusString");
+ strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+ strcpy(buffer, "Login");
+ strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+ strcpy(buffer, "Nick");
+ strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+ strcpy(buffer, "CListName");
+ strcat(buffer, _itoa((num_contacts - 1), buffer2, 10));
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+
+ // if the default contact was equal to or greater than 'number', decrement it (and deal with ends)
+ if(default_contact >= number) {
+ default_contact--;
+ if(default_contact < 0)
+ default_contact = 0;
+
+ DBWriteContactSettingDword(hMeta, META_PROTO, "Default", (DWORD)default_contact);
+ NotifyEventHooks(hEventDefaultChanged, (WPARAM)hMeta, (LPARAM)Meta_GetContactHandle(hMeta, default_contact));
+ }
+ num_contacts--;
+ DBWriteContactSettingDword(hMeta, META_PROTO, "NumContacts", (DWORD)num_contacts);
+
+ // fix nick
+ hContact = Meta_GetMostOnline(hMeta);
+ Meta_CopyContactNick(hMeta, hContact);
+
+ // fix status
+ Meta_FixStatus(hMeta);
+
+ // fix avatar
+ hContact = Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_4, PF4_AVATARS);
+ if(hContact) {
+ PROTO_AVATAR_INFORMATION AI;
+
+ AI.cbSize = sizeof(AI);
+ AI.hContact = hMeta;
+ AI.format = PA_FORMAT_UNKNOWN;
+ strcpy(AI.filename, "X");
+
+ if((int)CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&AI) == GAIR_SUCCESS)
+ DBWriteContactSettingString(hMeta, "ContactPhoto", "File",AI.filename);
+ }
+ }
+}
+
+/** Delete a MetaContact from the database
+*
+* Delete a MetaContact and remove all the information
+* concerning this MetaContact in the contact linked to it.
+*
+* @param wParam : \c HANDLE to the MetaContact to be deleted, or to the subcontact to be removed from the MetaContact
+* @param lParam : \c BOOL flag indicating whether to ask 'are you sure' when deleting a MetaContact
+*/
+INT_PTR Meta_Delete(WPARAM wParam,LPARAM lParam)
+{
+ DWORD metaID;
+ HANDLE hContact;
+
+ if((metaID=DBGetContactSettingDword((HANDLE)wParam,META_PROTO,META_ID,(DWORD)-1))!=(DWORD)-1)
+ {// The wParam is a metacontact
+ if(!lParam) { // check from recursion - see second half of this function
+ if(MessageBox((HWND)CallService(MS_CLUI_GETHWND,0,0),Translate("This will remove the MetaContact permanently.\n\nProceed Anyway?"),
+ Translate("Are you sure?"),MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2)!=IDYES)
+ {
+ return 0;
+ }
+ }
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact)
+ { // Scans the database to get all the contacts that have been previously linked to this MetaContact
+ if(DBGetContactSettingDword(hContact,META_PROTO,META_LINK,(DWORD)-1)==metaID)
+ { // This contact is assigned to the MetaContact that will be deleted, clear the "MetaContacts" information
+ DBDeleteContactSetting(hContact,META_PROTO,"IsSubcontact");
+ DBDeleteContactSetting(hContact,META_PROTO,META_LINK);
+ DBDeleteContactSetting(hContact,META_PROTO,"Handle");
+ DBDeleteContactSetting(hContact,META_PROTO,"ContactNumber");
+ // unhide - must be done after removing link (see meta_services.c:Meta_ChangeStatus)
+ Meta_RestoreGroup(hContact);
+ DBDeleteContactSetting(hContact,META_PROTO,"OldCListGroup");
+
+ CallService(MS_PROTO_REMOVEFROMCONTACT,(WPARAM)hContact,(LPARAM)META_FILTER);
+ // stop ignoring, if we were
+ if(options.suppress_status)
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+ //DBDeleteContactSetting((HANDLE)wParam, META_PROTO, META_ID);
+ //DBDeleteContactSetting((HANDLE)wParam, META_PROTO, "NumContacts");
+ //CallService(MS_PROTO_REMOVEFROMCONTACT,wParam,(LPARAM)META_PROTO);
+ NotifyEventHooks(hSubcontactsChanged, (WPARAM)wParam, 0);
+ CallService(MS_DB_CONTACT_DELETE,wParam,0);
+ }
+ else
+ {// The wParam is a simple contact
+ //if(lParam == 0)
+ // return 1; // The function has been called by the menu of a simple contact. Should not happen.
+ //else
+ {// The function has been called by the edit dialog
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Handle", 0);
+
+
+ DWORD num_contacts = DBGetContactSettingDword(hMeta, META_PROTO, "NumContacts", -1);
+
+ if(num_contacts == 1) {
+ if(MessageBox(0,Translate("You are going to remove all the contacts associated with this MetaContact.\nThis will delete the MetaContact.\n\nProceed Anyway?"),
+ Translate("Delete MetaContact?"),MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON1)==IDYES)
+ {
+ // recurse - once
+ Meta_Delete((WPARAM)hMeta,(LPARAM)1);
+ }
+ return 0;
+ }
+
+ Meta_RemoveContactNumber(hMeta, DBGetContactSettingDword((HANDLE)wParam,META_PROTO,"ContactNumber", -1));
+
+ CallService(MS_PROTO_REMOVEFROMCONTACT,(WPARAM)wParam,(LPARAM)META_FILTER);
+ }
+ }
+ return 0;
+}
+
+/** Set contact as MetaContact default
+*
+* Set the given contact to be the default one for the metacontact to which it is linked.
+*
+* @param wParam : \c HANDLE to the MetaContact to be set as default
+* @param lParam : \c HWND to the clist window
+ (This means the function has been called via the contact menu).
+*/
+INT_PTR Meta_Default(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hMeta;
+
+ if((hMeta = (HANDLE)DBGetContactSettingDword((HANDLE)wParam,META_PROTO,"Handle",0)) != 0)
+ { // the wParam is a subcontact
+ DBWriteContactSettingDword(hMeta, META_PROTO, "Default", (DWORD)Meta_GetContactNumber((HANDLE)wParam));
+ NotifyEventHooks(hEventDefaultChanged, (WPARAM)hMeta, (LPARAM)(HANDLE)wParam);
+ }
+ return 0;
+}
+
+/** Set/unset (i.e. toggle) contact to force use of default contact
+*
+* Set the given contact to be the default one for the metacontact to which it is linked.
+*
+* @param wParam : \c HANDLE to the MetaContact to be set as default
+* @param lParam : \c HWND to the clist window
+ (This means the function has been called via the contact menu).
+*/
+INT_PTR Meta_ForceDefault(WPARAM wParam,LPARAM lParam)
+{
+ if(DBGetContactSettingDword((HANDLE)wParam,META_PROTO, META_ID, (DWORD)-1) != (DWORD)-1)
+ { // the wParam is a MetaContact
+
+ BOOL current = DBGetContactSettingByte((HANDLE)wParam, META_PROTO, "ForceDefault", 0);
+ current = !current;
+ DBWriteContactSettingByte((HANDLE)wParam, META_PROTO, "ForceDefault", (BYTE)current);
+
+ DBWriteContactSettingDword((HANDLE)wParam, META_PROTO, "ForceSend", 0);
+
+ if(current) NotifyEventHooks(hEventForceSend, wParam, (LPARAM)Meta_GetContactHandle((HANDLE)wParam, DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Default", -1)));
+ else NotifyEventHooks(hEventUnforceSend, wParam, 0);
+ }
+ return 0;
+}
+
+INT_PTR MenuFunc0(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 0);}
+INT_PTR MenuFunc1(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 1);}
+INT_PTR MenuFunc2(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 2);}
+INT_PTR MenuFunc3(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 3);}
+INT_PTR MenuFunc4(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 4);}
+INT_PTR MenuFunc5(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 5);}
+INT_PTR MenuFunc6(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 6);}
+INT_PTR MenuFunc7(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 7);}
+INT_PTR MenuFunc8(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 8);}
+INT_PTR MenuFunc9(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 9);}
+INT_PTR MenuFunc10(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 10);}
+INT_PTR MenuFunc11(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 11);}
+INT_PTR MenuFunc12(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 12);}
+INT_PTR MenuFunc13(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 13);}
+INT_PTR MenuFunc14(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 14);}
+INT_PTR MenuFunc15(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 15);}
+INT_PTR MenuFunc16(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 16);}
+INT_PTR MenuFunc17(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 17);}
+INT_PTR MenuFunc18(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 18);}
+INT_PTR MenuFunc19(WPARAM wParam, LPARAM lParam) {return TranslateMenuFunc((HANDLE)wParam, 19);}
+
+HANDLE hMenuContact[MAX_CONTACTS];
+
+INT_PTR TranslateMenuFunc(HANDLE hMeta, int contact_number) {
+ return Meta_ContactMenuFunc((WPARAM)hMeta, (LPARAM) contact_number);
+}
+
+/** Called when the context-menu of a contact is about to be displayed
+*
+* This will test which of the 4 menu item should be displayed, depending
+* on which contact triggered the event
+*
+* @param wParam : \c HANDLE to the contact that triggered the event
+* @param lParam : Always set to 0;
+*/
+int Meta_ModifyMenu(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+ DBVARIANT dbv;
+ HANDLE hContact;
+ char *proto;
+ char buf[512], buffer2[512];
+ int i, iconIndex;
+ WORD status;
+
+ mi.flags = CMIM_FLAGS;
+ mi.cbSize = sizeof(CLISTMENUITEM);
+
+ if(DBGetContactSettingDword((HANDLE)wParam,META_PROTO,META_ID,-1) != (DWORD)-1)
+ {
+ int num_contacts, i;
+
+ // save the mouse pos in case they open a subcontact menu
+ GetCursorPos(&menuMousePoint);
+
+ // This is a MetaContact, show the edit, force default, and the delete menu, and hide the others
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuEdit, (LPARAM)&mi);
+ //mi.flags |= CMIM_NAME;
+ //if(DBGetContactSettingByte((HANDLE)wParam, META_PROTO, "ForceDefault", 0))
+ // mi.pszName = Translate("Unforce Default");
+ //else
+ // mi.pszName = Translate("Force Default");
+ //CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuForceDefault, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | CMIM_NAME | CMIF_HIDDEN; // we don't need delete - already in contact menu
+ mi.pszName = Translate("Delete MetaContact");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDelete, (LPARAM)&mi);
+
+
+ //show subcontact menu items
+ num_contacts = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "NumContacts", 0);
+ for(i = 0; i < MAX_CONTACTS; i++) {
+ if(i < num_contacts) {
+ hContact = Meta_GetContactHandle((HANDLE)wParam, i);
+ proto = _strdup((char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0));
+
+ if(!proto)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE);
+
+ if(options.menu_contact_label == DNT_UID) {
+ strcpy(buf, "Login");
+ strcat(buf, _itoa(i, buffer2, 10));
+
+ DBGetContactSetting((HANDLE)wParam,META_PROTO,buf,&dbv);
+ switch(dbv.type)
+ {
+ case DBVT_ASCIIZ:
+ mir_snprintf(buf,512,"%s",dbv.pszVal);
+ break;
+ case DBVT_BYTE:
+ mir_snprintf(buf,512,"%d",dbv.bVal);
+ break;
+ case DBVT_WORD:
+ mir_snprintf(buf,512,"%d",dbv.wVal);
+ break;
+ case DBVT_DWORD:
+ mir_snprintf(buf,512,"%d",dbv.dVal);
+ break;
+ default:
+ buf[0] = 0;
+ }
+ DBFreeVariant(&dbv);
+ mi.pszName = buf;
+ mi.flags = 0;
+ } else {
+ char *name = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0);
+ char *wname = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_UNICODE);
+
+ if(wname && strncmp(name, wname, strlen(name)) != 0) {
+ mi.pszName = wname;
+ mi.flags = CMIF_UNICODE;
+ }
+ else {
+ mi.pszName = name;
+ mi.flags = 0;
+ }
+ }
+
+ mi.flags |= CMIM_FLAGS | CMIM_NAME | CMIM_ICON;
+
+ //mi.hIcon = LoadSkinnedProtoIcon(proto, status);
+ iconIndex = (int)CallService(MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0);
+ mi.hIcon = ImageList_GetIcon((HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0), iconIndex, 0);;
+
+ free(proto);
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuContact[i], (LPARAM)&mi);
+ DestroyIcon(mi.hIcon);
+ //CallService(MS_SKIN2_RELEASEICON, (WPARAM)mi.hIcon, 0);
+ } else {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuContact[i], (LPARAM)&mi);
+ }
+ }
+
+ // show hide nudge menu item
+#define MS_NUDGE_SHOWMENU "NudgeShowMenu"
+// wParam = char *szProto
+// lParam = BOOL show
+ {
+ char serviceFunc[256];
+ hContact = Meta_GetMostOnline((HANDLE)wParam);
+ mir_snprintf(serviceFunc, 256, "%s/SendNudge", (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0));
+ CallService(MS_NUDGE_SHOWMENU, (WPARAM)META_PROTO, (LPARAM)ServiceExists(serviceFunc));
+ }
+ }
+ else
+ {// This is a simple contact
+ if(!Meta_IsEnabled())
+ {
+ // groups disabled - all meta menu options hidden
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDelete, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuEdit, (LPARAM)&mi);
+ for(i = 0; i < MAX_CONTACTS; i++) {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuContact[i], (LPARAM)&mi);
+ }
+
+ } else if(DBGetContactSettingDword((HANDLE)wParam,META_PROTO,META_LINK,(DWORD)-1)!=(DWORD)-1) {
+ // The contact is affected to a metacontact.
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ mi.flags |= CMIM_NAME;
+ mi.pszName = (char *)Translate("Remove from MetaContact");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDelete, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuEdit, (LPARAM)&mi);
+ for(i = 0; i < MAX_CONTACTS; i++) {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuContact[i], (LPARAM)&mi);
+ }
+ } else {
+ // The contact is neutral
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuAdd, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuConvert, (LPARAM)&mi);
+ mi.flags |= CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuEdit, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDelete, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDefault, (LPARAM)&mi);
+ for(i = 0; i < MAX_CONTACTS; i++) {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuContact[i], (LPARAM)&mi);
+ }
+ }
+ }
+ return 0;
+}
+
+
+
diff --git a/plugins/MetaContacts/meta_options.c b/plugins/MetaContacts/meta_options.c new file mode 100644 index 0000000000..6fd6aa47e5 --- /dev/null +++ b/plugins/MetaContacts/meta_options.c @@ -0,0 +1,640 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file meta_menu.c
+*
+* Functions needed to handle MetaContacts.
+* Centralizes functions called when the user chooses
+* an option integrated in the context-menu of the \c CList.
+*/
+
+#include "metacontacts.h"
+
+MetaOptions options;
+MetaOptions options_changes;
+
+INT_PTR CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hw;
+ char buff[512];
+
+ switch ( msg ) {
+ case WM_INITDIALOG: {
+ TranslateDialogDefault( hwndDlg );
+ options_changes = options;
+
+ CheckDlgButton(hwndDlg, IDC_CHK_SETDEFAULTRECV, options_changes.set_default_on_recv ? TRUE : FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_TEMPDEFAULT);
+ EnableWindow(hw, options_changes.set_default_on_recv);
+ CheckDlgButton(hwndDlg, IDC_CHK_TEMPDEFAULT, options_changes.temp_default ? TRUE : FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_ALWAYSUSEDEFAULT, options_changes.always_use_default ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_SUPPRESSSTATUS, options_changes.suppress_status ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_SUPPRESSPROTO, options_changes.suppress_proto ? TRUE : FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_RAD_UID, options_changes.menu_contact_label == DNT_UID);
+ CheckDlgButton(hwndDlg, IDC_RAD_DID, options_changes.menu_contact_label == DNT_DID);
+
+ CheckDlgButton(hwndDlg, IDC_RAD_MSG, options_changes.menu_function == FT_MSG);
+ CheckDlgButton(hwndDlg, IDC_RAD_MENU, options_changes.menu_function == FT_MENU);
+ CheckDlgButton(hwndDlg, IDC_RAD_INFO, options_changes.menu_function == FT_INFO);
+
+ CheckDlgButton(hwndDlg, IDC_RAD_NICK, options_changes.clist_contact_name == CNNT_NICK);
+ CheckDlgButton(hwndDlg, IDC_RAD_NAME, options_changes.clist_contact_name == CNNT_DISPLAYNAME);
+ CheckDlgButton(hwndDlg, IDC_CHK_LOCKHANDLE, options_changes.lockHandle ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_SUBWINDOW, options_changes.subcontact_windows ? TRUE : FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_METAHISTORY, options_changes.metahistory ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_SUBHISTORY, options_changes.subhistory ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_COPYDATA, options_changes.copydata ? TRUE : FALSE);
+
+ if(!options_changes.subcontact_windows) {
+ hw = GetDlgItem(hwndDlg, IDC_CHK_METAHISTORY);
+ EnableWindow(hw, FALSE);
+ } else {
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUBHISTORY);
+ EnableWindow(hw, FALSE);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_CHK_COPYHISTORY, options_changes.copy_subcontact_history ? TRUE : FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_DAYS);
+ _itoa(options_changes.days_history, buff, 10);
+ SetWindowText(hw, buff);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_CHK_SETDEFAULTRECV:
+ options_changes.set_default_on_recv = IsDlgButtonChecked(hwndDlg, IDC_CHK_SETDEFAULTRECV);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_TEMPDEFAULT);
+ EnableWindow(hw, options_changes.set_default_on_recv);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_TEMPDEFAULT:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_TEMPDEFAULT);
+ options_changes.temp_default = IsDlgButtonChecked(hwndDlg, IDC_CHK_TEMPDEFAULT);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_ALWAYSUSEDEFAULT:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_ALWAYSUSEDEFAULT);
+ options_changes.always_use_default = IsDlgButtonChecked(hwndDlg, IDC_CHK_ALWAYSUSEDEFAULT);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_SUPPRESSSTATUS:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUPPRESSSTATUS);
+ options_changes.suppress_status = IsDlgButtonChecked(hwndDlg, IDC_CHK_SUPPRESSSTATUS);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_SUPPRESSPROTO:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUPPRESSPROTO);
+ options_changes.suppress_proto = IsDlgButtonChecked(hwndDlg, IDC_CHK_SUPPRESSPROTO);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_COPYHISTORY:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_COPYHISTORY);
+ options_changes.copy_subcontact_history = IsDlgButtonChecked(hwndDlg, IDC_CHK_COPYHISTORY);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_METAHISTORY:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_METAHISTORY);
+ options_changes.metahistory = IsDlgButtonChecked(hwndDlg, IDC_CHK_METAHISTORY);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_SUBHISTORY:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUBHISTORY);
+ options_changes.subhistory = IsDlgButtonChecked(hwndDlg, IDC_CHK_SUBHISTORY);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_COPYDATA:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_COPYDATA);
+ options_changes.copydata = IsDlgButtonChecked(hwndDlg, IDC_CHK_COPYDATA);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_RAD_UID:
+ hw = GetDlgItem(hwndDlg, IDC_RAD_UID);
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_UID)) {
+ options_changes.menu_contact_label = DNT_UID;
+ CheckDlgButton(hwndDlg, IDC_RAD_DID, FALSE);
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_RAD_DID:
+ hw = GetDlgItem(hwndDlg, IDC_RAD_DID);
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_DID)) {
+ options_changes.menu_contact_label = DNT_DID;
+ CheckDlgButton(hwndDlg, IDC_RAD_UID, FALSE);
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_RAD_MSG:
+ hw = GetDlgItem(hwndDlg, IDC_RAD_MSG);
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_MSG)) {
+ options_changes.menu_function = FT_MSG;
+ CheckDlgButton(hwndDlg, IDC_RAD_MENU, FALSE);
+ CheckDlgButton(hwndDlg, IDC_RAD_INFO, FALSE);
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_RAD_MENU:
+ hw = GetDlgItem(hwndDlg, IDC_RAD_MENU);
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_MENU)) {
+ options_changes.menu_function = FT_MENU;
+ CheckDlgButton(hwndDlg, IDC_RAD_MSG, FALSE);
+ CheckDlgButton(hwndDlg, IDC_RAD_INFO, FALSE);
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_RAD_INFO:
+ hw = GetDlgItem(hwndDlg, IDC_RAD_INFO);
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_INFO)) {
+ options_changes.menu_function = FT_INFO;
+ CheckDlgButton(hwndDlg, IDC_RAD_MSG, FALSE);
+ CheckDlgButton(hwndDlg, IDC_RAD_MENU, FALSE);
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_RAD_NICK:
+ hw = GetDlgItem(hwndDlg, IDC_RAD_NICK);
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_NICK)) {
+ options_changes.clist_contact_name = CNNT_NICK;
+ CheckDlgButton(hwndDlg, IDC_RAD_NAME, FALSE);
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_RAD_NAME:
+ hw = GetDlgItem(hwndDlg, IDC_RAD_NAME);
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_NAME)) {
+ options_changes.clist_contact_name = CNNT_DISPLAYNAME;
+ CheckDlgButton(hwndDlg, IDC_RAD_NICK, FALSE);
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_SUBWINDOW:
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUBWINDOW);
+ options_changes.subcontact_windows = IsDlgButtonChecked(hwndDlg, IDC_CHK_SUBWINDOW);
+
+ if(options_changes.subcontact_windows) {
+ hw = GetDlgItem(hwndDlg, IDC_CHK_METAHISTORY);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUBHISTORY);
+ CheckDlgButton(hwndDlg, IDC_CHK_SUBHISTORY, TRUE);
+ EnableWindow(hw, FALSE);
+ options_changes.subhistory = TRUE;
+ } else {
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUBHISTORY);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_METAHISTORY);
+ CheckDlgButton(hwndDlg, IDC_CHK_METAHISTORY, TRUE);
+ EnableWindow(hw, FALSE);
+ options_changes.metahistory = TRUE;
+ }
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_CHK_LOCKHANDLE:
+ options_changes.lockHandle = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOCKHANDLE);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ }
+ } else if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus()) {
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == PSN_APPLY ) {
+ hw = GetDlgItem(hwndDlg, IDC_ED_DAYS);
+ GetWindowText(hw, buff, 512);
+ if(strlen(buff) > 0)
+ options_changes.days_history = atoi(buff);
+
+ options = options_changes;
+ Meta_WriteOptions(&options);
+
+ Meta_SuppressStatus(options.suppress_status);
+ Meta_SetAllNicks();
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+int Meta_WriteOptions(MetaOptions *opt) {
+ DBWriteContactSettingByte(NULL, META_PROTO, "SetDefaultOnRecv", (BYTE)(opt->set_default_on_recv ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "TempDefault", (BYTE)(opt->temp_default ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "AlwaysUseDefault", (BYTE)(opt->always_use_default ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "SuppressStatus", (BYTE)(opt->suppress_status ? 1 : 0));
+ DBWriteContactSettingWord(NULL, META_PROTO, "MenuContactLabel", (WORD)opt->menu_contact_label);
+ DBWriteContactSettingWord(NULL, META_PROTO, "MenuContactFunction", (WORD)opt->menu_function);
+ DBWriteContactSettingWord(NULL, META_PROTO, "CListContactName", (WORD)opt->clist_contact_name);
+ DBWriteContactSettingByte(NULL, META_PROTO, "SuppressProto", (BYTE)(opt->suppress_proto ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "CopyHistory", (BYTE)(opt->copy_subcontact_history ? 1 : 0));
+ DBWriteContactSettingDword(NULL, META_PROTO, "DaysHistory", (DWORD)(opt->days_history));
+ DBWriteContactSettingDword(NULL, META_PROTO, "SetStatusFromOfflineDelay", (DWORD)(opt->set_status_from_offline_delay));
+ DBWriteContactSettingByte(NULL, META_PROTO, "SubcontactWindows", (BYTE)(opt->subcontact_windows ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "CopyData", (BYTE)(opt->copydata ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "LockHandle", (BYTE)(opt->lockHandle ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "MetaMessageIcon", (BYTE)(opt->flash_meta_message_icon ? 1 : 0));
+ DBWriteContactSettingByte(NULL, META_PROTO, "CopyUserInfo", (BYTE)(opt->copy_userinfo ? 1 : 0));
+
+ if(!opt->subcontact_windows)
+ DBWriteContactSettingByte(NULL, META_PROTO, "MetaHistory", 1);
+ else
+ DBWriteContactSettingByte(NULL, META_PROTO, "MetaHistory", (BYTE)(opt->metahistory ? 1 : 0));
+
+ if(opt->subcontact_windows)
+ DBWriteContactSettingByte(NULL, META_PROTO, "SubcontactHistory", 1);
+ else
+ DBWriteContactSettingByte(NULL, META_PROTO, "SubcontactHistory", (BYTE)(opt->subhistory ? 1 : 0));
+ return 0;
+
+ DBWriteContactSettingByte(NULL, META_PROTO, "UseProtoRecv", (BYTE)(opt->use_proto_recv ? 1 : 0));
+}
+
+int Meta_ReadOptions(MetaOptions *opt) {
+ opt->set_default_on_recv = (DBGetContactSettingByte(NULL, META_PROTO, "SetDefaultOnRecv", 1) == 1 ? TRUE : FALSE);
+ opt->temp_default = (DBGetContactSettingByte(NULL, META_PROTO, "TempDefault", 0) == 1 ? TRUE : FALSE);
+ opt->always_use_default = (DBGetContactSettingByte(NULL, META_PROTO, "AlwaysUseDefault", 0) == 1 ? TRUE : FALSE);
+ opt->suppress_status = (DBGetContactSettingByte(NULL, META_PROTO, "SuppressStatus", 1) == 1 ? TRUE : FALSE);
+ opt->menu_contact_label = (int)DBGetContactSettingWord(NULL, META_PROTO, "MenuContactLabel", DNT_UID);
+ opt->menu_function = (int)DBGetContactSettingWord(NULL, META_PROTO, "MenuContactFunction", FT_MENU);
+ opt->clist_contact_name = (int)DBGetContactSettingWord(NULL, META_PROTO, "CListContactName", CNNT_NICK);
+ opt->suppress_proto = (DBGetContactSettingByte(NULL, META_PROTO, "SuppressProto", 0) == 1 ? TRUE : FALSE);
+ opt->copy_subcontact_history = (DBGetContactSettingByte(NULL, META_PROTO, "CopyHistory", 1) == 1 ? TRUE : FALSE);
+ opt->days_history = (int)DBGetContactSettingDword(NULL, META_PROTO, "DaysHistory", 14);
+ opt->set_status_from_offline_delay = (int)DBGetContactSettingDword(NULL, META_PROTO, "SetStatusFromOfflineDelay", DEFAULT_SET_STATUS_SLEEP_TIME);
+ opt->subcontact_windows = (DBGetContactSettingByte(NULL, META_PROTO, "SubcontactWindows", 0) == 1 ? TRUE : FALSE);
+ opt->copydata = (DBGetContactSettingByte(NULL, META_PROTO, "CopyData", 1) == 1 ? TRUE : FALSE);
+ opt->lockHandle = (DBGetContactSettingByte(NULL, META_PROTO, "LockHandle", 0) == 1 ? TRUE : FALSE);
+ opt->flash_meta_message_icon = (DBGetContactSettingByte(NULL, META_PROTO, "MetaMessageIcon", 1) == 1 ? TRUE : FALSE);
+ opt->copy_userinfo = (DBGetContactSettingByte(NULL, META_PROTO, "CopyUserInfo", 1) == 1 ? TRUE : FALSE);
+
+ if(!opt->subcontact_windows)
+ opt->metahistory = TRUE;
+ else
+ opt->metahistory = (DBGetContactSettingByte(NULL, META_PROTO, "MetaHistory", 1) == 1 ? TRUE : FALSE);
+
+ if(opt->subcontact_windows)
+ opt->subhistory = TRUE;
+ else
+ opt->subhistory = (DBGetContactSettingByte(NULL, META_PROTO, "SubcontactHistory", 1) == 1 ? TRUE : FALSE);
+
+ opt->use_proto_recv = (DBGetContactSettingByte(NULL, META_PROTO, "UseProtoRecv", 1) == 1 ? TRUE : FALSE);
+ return 0;
+}
+
+/*
+#define ID_STATUS_OFFLINE 40071 ->8
+#define ID_STATUS_ONLINE 40072 ->0
+#define ID_STATUS_AWAY 40073 ->4
+#define ID_STATUS_DND 40074 ->7
+#define ID_STATUS_NA 40075 ->6
+#define ID_STATUS_OCCUPIED 40076 ->5
+#define ID_STATUS_FREECHAT 40077 ->1
+#define ID_STATUS_INVISIBLE 40078 ->0
+#define ID_STATUS_ONTHEPHONE 40079 ->2
+#define ID_STATUS_OUTTOLUNCH 40080 ->3
+*/
+
+int GetDefaultPrio(int status) {
+ switch( status ) {
+ case ID_STATUS_OFFLINE: return 8;
+ case ID_STATUS_AWAY: return 4;
+ case ID_STATUS_DND: return 7;
+ case ID_STATUS_NA: return 6;
+ case ID_STATUS_OCCUPIED: return 5;
+ case ID_STATUS_FREECHAT: return 1;
+ case ID_STATUS_ONTHEPHONE: return 2;
+ case ID_STATUS_OUTTOLUNCH: return 3;
+ }
+
+ return 0;
+}
+
+typedef struct {
+ int prio[10]; // priority for each status
+ BOOL def[10]; // use default for this one?
+} ProtoStatusPrio;
+
+ProtoStatusPrio *priorities = 0;
+
+int GetRealPriority(char *proto, int status) {
+ char szSetting[256];
+ if(!proto) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", status);
+ return DBGetContactSettingWord(0, META_PROTO, szSetting, GetDefaultPrio(status));
+ } else {
+ int prio;
+ mir_snprintf(szSetting, 256, "ProtoPrio_%s%d", proto, status);
+ prio = DBGetContactSettingWord(0, META_PROTO, szSetting, 0xFFFF);
+ if(prio == 0xFFFF) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", status);
+ return DBGetContactSettingWord(0, META_PROTO, szSetting, GetDefaultPrio(status));
+ } else
+ return prio;
+ }
+ return 0xFFFF;
+}
+
+void ReadPriorities() {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ char szSetting[256];
+ ProtoStatusPrio * current;
+ int i, j;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ current = priorities = (ProtoStatusPrio *)malloc((num_protocols + 1) * sizeof(ProtoStatusPrio));
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", i);
+ current->def[i - ID_STATUS_OFFLINE] = TRUE;
+ current->prio[i - ID_STATUS_OFFLINE] = DBGetContactSettingWord(0, META_PROTO, szSetting, GetDefaultPrio(i));
+ }
+ for(i = 0; i < num_protocols; i++) {
+ current = priorities + (i + 1);
+ for(j = ID_STATUS_OFFLINE; j <= ID_STATUS_OUTTOLUNCH; j++) {
+ mir_snprintf(szSetting, 256, "ProtoPrio_%s%d", pppDesc[i]->szName, j);
+ current->prio[j - ID_STATUS_OFFLINE] = DBGetContactSettingWord(0, META_PROTO, szSetting, 0xFFFF);
+ current->def[j - ID_STATUS_OFFLINE] = (current->prio[j - ID_STATUS_OFFLINE] == 0xFFFF);
+ }
+ }
+}
+
+void WritePriorities() {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ char szSetting[256];
+ ProtoStatusPrio * current = priorities;
+ int i, j;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ mir_snprintf(szSetting, 256, "DefaultPrio_%d", i);
+ if(current->prio[i - ID_STATUS_OFFLINE] != GetDefaultPrio(i))
+ DBWriteContactSettingWord(0, META_PROTO, szSetting, (WORD)current->prio[i - ID_STATUS_OFFLINE]);
+ else
+ DBDeleteContactSetting(0, META_PROTO, szSetting);
+ }
+ for(i = 0; i < num_protocols; i++) {
+ current = priorities + (i + 1);
+ for(j = ID_STATUS_OFFLINE; j <= ID_STATUS_OUTTOLUNCH; j++) {
+ mir_snprintf(szSetting, 256, "ProtoPrio_%s%d", pppDesc[i]->szName, j);
+ if(!current->def[j - ID_STATUS_OFFLINE])
+ DBWriteContactSettingWord(0, META_PROTO, szSetting, (WORD)current->prio[j - ID_STATUS_OFFLINE]);
+ else
+ DBDeleteContactSetting(0, META_PROTO, szSetting);
+ }
+ }
+}
+
+int GetIsDefault(int proto_index, int status) {
+ return (priorities + (proto_index + 1))->def[status - ID_STATUS_OFFLINE];
+}
+
+BOOL GetPriority(int proto_index, int status) {
+ ProtoStatusPrio * current;
+ if(proto_index == -1) {
+ current = priorities;
+ return current->prio[status - ID_STATUS_OFFLINE];
+ } else {
+ current = priorities + (proto_index + 1);
+ if(current->def[status - ID_STATUS_OFFLINE]) {
+ current = priorities;
+ }
+ return current->prio[status - ID_STATUS_OFFLINE];
+ }
+ return 0xFFFF;
+}
+
+void SetPriority(int proto_index, int status, BOOL def, int prio) {
+ ProtoStatusPrio * current;
+ if(prio < 0) prio = 0;
+ if(prio > 500) prio = 500;
+ if(proto_index == -1) {
+ current = priorities;
+ current->prio[status - ID_STATUS_OFFLINE] = prio;
+ } else {
+ current = priorities + (proto_index + 1);
+ current->def[status - ID_STATUS_OFFLINE] = def;
+ if(!def) {
+ current->prio[status - ID_STATUS_OFFLINE] = prio;
+ }
+ }
+}
+
+void ResetPriorities() {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ ProtoStatusPrio * current;
+ int i, j;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ current = priorities;
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ current->def[i - ID_STATUS_OFFLINE] = TRUE;
+ current->prio[i - ID_STATUS_OFFLINE] = GetDefaultPrio(i);
+ }
+ for(i = 0; i < num_protocols; i++) {
+ current = priorities + (i + 1);
+ for(j = ID_STATUS_OFFLINE; j <= ID_STATUS_OUTTOLUNCH; j++) {
+ current->def[j - ID_STATUS_OFFLINE] = TRUE;
+ }
+ }
+}
+
+#define WMU_FILLSTATUSCMB (WM_USER + 0x100)
+#define WMU_FILLPRIODATA (WM_USER + 0x101)
+
+INT_PTR CALLBACK DlgProcOptsPriorities(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hw;
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault( hwndDlg );
+ SendMessage(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), UDM_SETRANGE, 0, (LPARAM)MAKELONG(500, 0));
+ ReadPriorities();
+ {
+ int num_protocols;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ int i, index;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+ hw = GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL);
+ index = SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)Translate("<default>"));
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, -1);
+ for(i = 0; i < num_protocols; i++) {
+ if(pppDesc[i]->type == PROTOTYPE_PROTOCOL) {
+ if(strcmp(pppDesc[i]->szName, META_PROTO) != 0) {
+ index = SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)pppDesc[i]->szName);
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, i);
+ }
+ }
+ }
+
+ SendMessage(hw, CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLSTATUSCMB, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ }
+ return FALSE;
+ case WMU_FILLPRIODATA:
+ {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int status = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETITEMDATA, (WPARAM)sel, 0);
+ SetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, GetPriority(index, status), FALSE);
+ if(index == -1) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), TRUE);
+ CheckDlgButton(hwndDlg, IDC_CHK_DEFAULT, TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_DEFAULT), FALSE);
+ } else {
+ if(GetIsDefault(index, status)) {
+ CheckDlgButton(hwndDlg, IDC_CHK_DEFAULT, TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), FALSE);
+ } else {
+ CheckDlgButton(hwndDlg, IDC_CHK_DEFAULT, FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), TRUE);
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_DEFAULT), TRUE);
+ }
+ }
+ }
+ }
+ return TRUE;
+ case WMU_FILLSTATUSCMB:
+ {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ HWND hw = GetDlgItem(hwndDlg, IDC_CMB_STATUS);
+ SendMessage(hw, CB_RESETCONTENT, 0, 0);
+ if(index == -1) {
+ int i;
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ index = SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)(char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, i, 0));
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, i);
+ }
+ } else {
+ int num_protocols, caps, i;
+ PROTOCOLDESCRIPTOR **pppDesc;
+ CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc);
+
+ caps = CallProtoService(pppDesc[index]->szName, PS_GETCAPS, PFLAGNUM_2, 0);
+
+ for(i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if(caps & Proto_Status2Flag(i)) {
+ index = SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)(char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, i, 0));
+ SendMessage(hw, CB_SETITEMDATA, (WPARAM)index, i);
+ }
+ }
+ }
+ SendMessage(hw, CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ }
+ }
+ return TRUE;
+ case WM_COMMAND:
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_CHK_DEFAULT:
+ {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ BOOL checked = IsDlgButtonChecked(hwndDlg, IDC_CHK_DEFAULT);
+ int status = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETITEMDATA, (WPARAM)sel, 0);
+ if(checked) {
+ SetPriority(index, status, TRUE, 0);
+ SetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, GetPriority(index, status), FALSE);
+ } else {
+ SetPriority(index, status, FALSE, GetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, 0, FALSE));
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ED_PRIORITY), !checked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SP_PRIORITY), !checked);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ }
+ break;
+ case IDC_BTN_RESET:
+ ResetPriorities();
+ SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_SETCURSEL, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLSTATUSCMB, 0, 0);
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ }
+ }
+ if ( HIWORD( wParam ) == EN_CHANGE && LOWORD(wParam) == IDC_ED_PRIORITY && ( HWND )lParam == GetFocus()) {
+ int sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int index = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_PROTOCOL), CB_GETITEMDATA, (WPARAM)sel, 0);
+ sel = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ int status = SendMessage(GetDlgItem(hwndDlg, IDC_CMB_STATUS), CB_GETITEMDATA, (WPARAM)sel, 0);
+ int prio = GetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, 0, FALSE);
+ SetPriority(index, status, FALSE, prio);
+ if(prio != GetPriority(index, status))
+ SetDlgItemInt(hwndDlg, IDC_ED_PRIORITY, GetPriority(index, status), FALSE);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ }
+ if ( HIWORD( wParam ) == CBN_SELCHANGE) {
+ switch( LOWORD( wParam )) {
+ case IDC_CMB_STATUS:
+ SendMessage(hwndDlg, WMU_FILLPRIODATA, 0, 0);
+ break;
+ case IDC_CMB_PROTOCOL:
+ SendMessage(hwndDlg, WMU_FILLSTATUSCMB, 0, 0);
+ break;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == PSN_APPLY ) {
+ WritePriorities();
+ return TRUE;
+ }
+ break;
+ case WM_DESTROY:
+ free(priorities);
+ priorities = 0;
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/plugins/MetaContacts/meta_remove2.ico b/plugins/MetaContacts/meta_remove2.ico Binary files differnew file mode 100644 index 0000000000..ecfe29e6bf --- /dev/null +++ b/plugins/MetaContacts/meta_remove2.ico diff --git a/plugins/MetaContacts/meta_services.c b/plugins/MetaContacts/meta_services.c new file mode 100644 index 0000000000..bbf9177132 --- /dev/null +++ b/plugins/MetaContacts/meta_services.c @@ -0,0 +1,2106 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file meta_services.c
+*
+* Functions specific to the protocol part of the plugin.
+* Centralizes all the functions called by Miranda to make
+* the plugin work as a protocol.
+*/
+
+#include "metacontacts.h"
+
+#define NB_SERVICES 62 //!< Number of services registered in Miranda (see Meta_CloseHandles()).
+#define NB_HOOKS 17 //!< Number of hooks set up (see Meta_CloseHandles()).
+
+#define PREF_METANODB 0x2000 //!< Flag to indicate message should not be added to db by filter when sending
+
+char *pendingACK = 0; //!< Name of the protocol in which an ACK is about to come.
+
+int previousMode, //!< Previous status of the MetaContacts Protocol
+ mcStatus; //!< Current status of the MetaContacts Protocol
+
+HANDLE hServices[NB_SERVICES] = {0}, //!< list of all the services registered (see Meta_CloseHandles()).
+hHooks[NB_HOOKS] = {0}; //!< list of all hooks set up (see Meta_CloseHandles()).
+
+HANDLE *hNudgeEvents = 0;
+int iNudgeProtos = 0;
+
+HANDLE hMenuConvert, //!< \c HANDLE to the convert menu item.
+ hMenuAdd, //!< \c HANDLE to the add to menu item.
+ hMenuEdit, //!< \c HANDLE to the edit menu item.
+ hMenuDelete, //!< \c HANDLE to the delete menu item.
+ hMenuDefault, //!< \c HANDLE to the delete menu item.
+ hMenuForceDefault; //!< \c HANDLE to the delete menu item.
+
+HANDLE hMenuOnOff; //!< \c HANDLE to the enable/disable menu item.
+
+HANDLE hEventDefaultChanged, //!< \c HANDLE to the 'default changed' event
+ hEventForceSend, //!< \c HANDLE to the 'force send' event
+ hEventUnforceSend, //!< \c HANDLE to the 'unforce send' event
+ hSubcontactsChanged, //!< \c HANDLE to the 'contacts changed' event
+ hEventNudge;
+
+
+DWORD nextMetaID; //!< Global variable specifying the ID value the next MetaContact will have.
+
+BOOL message_window_api_enabled = FALSE; //!< Global variable specifying whether the message window api ver 0.0.0.1+ is available
+
+// stuff for mw_clist extra icon
+int proto_count = 0;
+HANDLE hExtraImage[MAX_PROTOCOLS * 2]; // online and offline icons
+char proto_names[MAX_PROTOCOLS * 128];
+HANDLE hProtoIcons[MAX_PROTOCOLS * 2]; // online and offline icons
+
+UINT_PTR setStatusTimerId = 0;
+BOOL firstSetOnline = TRUE; // see Meta_SetStatus function
+
+/** Get the capabilities of the "MetaContacts" protocol.
+*
+* @param wParam : equals to one of the following values :\n
+ <tt> PFLAGNUM_1 | PFLAGNUM_2 | PFLAGNUM_3 | PFLAGNUM_4 | PFLAG_UNIQUEIDTEXT | PFLAG_MAXLENOFMESSAGE | PFLAG_UNIQUEIDSETTING </tt>.
+* @param lParam : Allways set to 0.
+*
+* @return Depending on the \c WPARAM.
+*/
+INT_PTR Meta_GetCaps(WPARAM wParam,LPARAM lParam)
+{
+ int ret = 0;
+ switch (wParam) {
+ case PFLAGNUM_1:
+ //ret = PF1_IM | PF1_URL | PF1_FILE | PF1_MODEMSG | PF1_AUTHREQ | PF1_ADDED;
+ //ret = PF1_IMSEND | PF1_URLSEND | PF1_FILESEND | PF1_MODEMSGSEND;
+ ret = PF1_IM | PF1_CHAT | PF1_FILESEND | PF1_MODEMSGRECV | PF1_NUMERICUSERID;
+ break;
+ case PFLAGNUM_2:
+ if(!options.suppress_proto) {
+ ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND
+ | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ }
+ //ret = PF2_ONLINE;
+ break;
+ case PFLAGNUM_3:
+ //ret = PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND;
+ ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND
+ | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ break;
+ case PFLAGNUM_4:
+ //ret = PF4_FORCEAUTH;
+ ret = PF4_SUPPORTTYPING | PF4_AVATARS;
+ break;
+ case PFLAGNUM_5:
+ ret = PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND
+ | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE;
+ break;
+ case PFLAG_UNIQUEIDTEXT:
+ ret = (INT_PTR) Translate("Meta ID");
+ break;
+ case PFLAG_MAXLENOFMESSAGE:
+ ret = 2000;
+ break;
+ case PFLAG_UNIQUEIDSETTING:
+ ret = (INT_PTR) META_ID;
+ break;
+ }
+ return ret;
+}
+
+/** Copy the name of the protocole into lParam
+* @param wParam : max size of the name
+* @param lParam : reference to a char *, which will hold the name
+*/
+INT_PTR Meta_GetName(WPARAM wParam,LPARAM lParam)
+{
+ char *name = (char *)Translate(META_PROTO);
+ size_t size = min(strlen(name),wParam-1); // copy only the first size bytes.
+ if(strncpy((char *)lParam,name,size)==NULL)
+ return 1;
+ ((char *)lParam)[size]='\0';
+ return 0;
+}
+
+/** Loads the icon corresponding to the status
+* Called by the CList when the status changes.
+* @param wParam : one of the following values : \n
+ <tt>PLI_PROTOCOL | PLI_ONLINE | PLI_OFFLINE</tt>
+* @return an \c HICON in which the icon has been loaded.
+*/
+INT_PTR Meta_LoadIcon(WPARAM wParam,LPARAM lParam)
+{
+ UINT id;
+ switch (wParam & 0xFFFF)
+ {
+ case PLI_PROTOCOL:
+ id = IDI_MCMENU;
+ break;
+ case PLI_ONLINE:
+ id = IDI_MCMENU;
+ break;
+ case PLI_OFFLINE:
+ id = IDI_MCMENU;
+ break;
+ default:
+ return 0;
+ }
+
+ return (INT_PTR) LoadImage(hInstance, MAKEINTRESOURCE(id), IMAGE_ICON,
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON),
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0);
+
+}
+
+
+//static DWORD CALLBACK SetStatusThread( LPVOID param )
+void CALLBACK SetStatusThread(HWND hWnd, UINT msg, UINT_PTR id, DWORD dw)
+{
+
+ previousMode = mcStatus;
+
+ //Sleep(options.set_status_from_offline_delay);
+
+ mcStatus = (int)ID_STATUS_ONLINE;
+ ProtoBroadcastAck(META_PROTO,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS, (HANDLE)previousMode, mcStatus);
+
+ //return 0;
+ KillTimer(0, setStatusTimerId);
+}
+
+/** Changes the status and notifies everybody
+* @param wParam : The new mode
+* @param lParam : Allways set to 0.
+*/
+INT_PTR Meta_SetStatus(WPARAM wParam,LPARAM lParam)
+{
+ // firstSetOnline starts out true - used to delay metacontact's 'onlineness' to prevent double status notifications on startup
+ if(mcStatus == ID_STATUS_OFFLINE && firstSetOnline) {
+ // causes crash on exit if miranda is closed in under options.set_status_from_offline milliseconds!
+ //CloseHandle( CreateThread( NULL, 0, SetStatusThread, (void *)wParam, 0, 0 ));
+ setStatusTimerId = SetTimer(0, 0, options.set_status_from_offline_delay, SetStatusThread);
+ firstSetOnline = FALSE;
+ } else {
+ previousMode = mcStatus;
+ mcStatus = (int)wParam;
+ ProtoBroadcastAck(META_PROTO,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS, (HANDLE)previousMode, mcStatus);
+ }
+ return 0;
+}
+
+/** Returns the current status
+*/
+INT_PTR Meta_GetStatus(WPARAM wParam,LPARAM lParam)
+{
+ return mcStatus;
+}
+
+//////////////////////////////////////////////////////////
+/// Copied from MSN plugin - sent acks need to be from different thread :(
+//////////////////////////////////////////////////////////
+typedef struct tag_TFakeAckParams
+{
+ HANDLE hEvent;
+ HANDLE hContact;
+ LONG id;
+ char msg[512];
+} TFakeAckParams;
+
+/*
+static DWORD CALLBACK sttFakeAckSuccess( LPVOID param )
+{
+ TFakeAckParams *tParam = ( TFakeAckParams* )param;
+ WaitForSingleObject( tParam->hEvent, INFINITE );
+
+ Sleep( 100 );
+ ProtoBroadcastAck(META_PROTO, tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, ( HANDLE )tParam->id, 0 );
+
+ CloseHandle( tParam->hEvent );
+ free(tParam);
+ return 0;
+}
+*/
+
+static DWORD CALLBACK sttFakeAckFail( LPVOID param )
+{
+ TFakeAckParams *tParam = ( TFakeAckParams* )param;
+ WaitForSingleObject( tParam->hEvent, INFINITE );
+
+ Sleep( 100 );
+ ProtoBroadcastAck(META_PROTO, tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, ( HANDLE )tParam->id, (WPARAM)tParam->msg );
+
+ CloseHandle( tParam->hEvent );
+ mir_free(tParam);
+ return 0;
+}
+
+/** Filter messages sent by subcontacts
+*
+* When groups are disabled, add an event to the DB for the metacontact to maintain history
+*
+* @param wParam : index of the protocol in the protocol chain.
+* @param lParam : \c CCSDATA structure holding all the information about the message.
+*
+* @return 0 on success, 1 otherwise.
+*/
+
+INT_PTR MetaFilter_SendMessage(WPARAM wParam,LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ HANDLE hMeta;
+
+ if((hMeta = (HANDLE)DBGetContactSettingDword(ccs->hContact,META_PROTO, "Handle", (DWORD)0)) == (DWORD)0) {
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam); // Can't find the MetaID of the metacontact linked to
+ }
+
+ // if subcontact sending, add db event to keep metacontact history correct
+ if(options.metahistory && !(ccs->wParam & PREF_METANODB)) {
+
+ // reject "file As Message" messages
+ if(strlen((char *)ccs->lParam) > 5 && strncmp((char *)ccs->lParam, "<%fAM", 5) == 0)
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam); // continue processing
+
+ // reject "data As Message" messages
+ if(strlen((char *)ccs->lParam) > 5 && strncmp((char *)ccs->lParam, "<%dAM", 5) == 0)
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam); // continue processing
+
+ // reject "OTR" messages
+ if(strlen((char *)ccs->lParam) > 5 && strncmp((char *)ccs->lParam, "?OTR", 4) == 0)
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam); // continue processing
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = META_PROTO;
+ dbei.flags = DBEF_SENT;
+ dbei.timestamp = time(NULL);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ if(ccs->wParam & PREF_RTL) dbei.flags |= DBEF_RTL;
+ if(ccs->wParam & PREF_UTF) dbei.flags |= DBEF_UTF;
+ dbei.cbBlob = (DWORD)strlen((char *)ccs->lParam) + 1;
+ if ( ccs->wParam & PREF_UNICODE )
+ dbei.cbBlob *= ( sizeof( wchar_t )+1 );
+ dbei.pBlob = (PBYTE)ccs->lParam;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM) hMeta, (LPARAM)&dbei);
+ }
+
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+}
+
+INT_PTR Meta_SendNudge(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hMeta = (HANDLE)wParam,
+ hSubContact = Meta_GetMostOnline(hMeta);
+
+ char servicefunction[ 100 ];
+ char *protoName = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hSubContact, 0);
+ sprintf(servicefunction, "%s/SendNudge", protoName);
+
+ return CallService(servicefunction, (WPARAM)hSubContact, lParam);
+
+ //return CallService("NUDGE/Send", (WPARAM)hSubContact, lParam);
+}
+
+/////////////////////////////////////////////////////////////////
+
+/** Send a message to the protocol specific network.
+*
+* Call the function specific to the protocol that belongs
+* to the contact chosen to send the message.
+*
+* @param wParam : index of the protocol in the protocol chain.
+* @param lParam : \c CCSDATA structure holding all the information abour rhe message.
+*
+* @return 0 on success, 1 otherwise.
+*/
+INT_PTR Meta_SendMessage(WPARAM wParam,LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+ DWORD default_contact_number;
+
+
+ if((default_contact_number = DBGetContactSettingDword(ccs->hContact,META_PROTO,"Default",(DWORD)-1)) == (DWORD)-1)
+ {
+ // This is a simple contact, let through the stack of protocols
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return CallService(MS_PROTO_CHAINSEND, wParam, lParam);
+ }
+ else
+ {
+ char szServiceName[100];
+ HANDLE most_online;
+
+ most_online = Meta_GetMostOnline(ccs->hContact);
+ //DBEVENTINFO dbei;
+
+ if(!most_online) {
+ DWORD dwThreadId;
+ HANDLE hEvent;
+ TFakeAckParams *tfap;
+
+ // send failure to notify user of reason
+ hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+
+ tfap = (TFakeAckParams *)mir_alloc(sizeof(TFakeAckParams));
+ tfap->hContact = ccs->hContact;
+ tfap->hEvent = hEvent;
+ tfap->id = 10;
+ strcpy(tfap->msg, Translate("No online contacts found."));
+
+ CloseHandle( CreateThread( NULL, 0, sttFakeAckFail, tfap, 0, &dwThreadId ));
+ SetEvent( hEvent );
+
+ return 10;
+ }
+
+ Meta_CopyContactNick(ccs->hContact, most_online);
+
+ ccs->hContact = most_online;
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+ Meta_SetNick(proto); // (no matter what was there before)
+
+ // don't bypass filters etc
+ strncpy(szServiceName, PSS_MESSAGE, sizeof(szServiceName));
+
+ if(ccs->wParam & PREF_UNICODE) {
+ char szTemp[100];
+ _snprintf(szTemp, sizeof(szTemp), "%s%sW", proto, PSS_MESSAGE);
+ if (ServiceExists(szTemp))
+ strncpy(szServiceName, PSS_MESSAGE "W", sizeof(szServiceName));
+ }
+
+ if(options.subhistory && !(ccs->wParam & PREF_METANODB)) {
+ // add sent event to subcontact
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ dbei.flags = DBEF_SENT;
+ dbei.timestamp = time(NULL);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ if(ccs->wParam & PREF_RTL) dbei.flags |= DBEF_RTL;
+ if(ccs->wParam & PREF_UTF) dbei.flags |= DBEF_UTF;
+ dbei.cbBlob = (DWORD)strlen((char *)ccs->lParam) + 1;
+ if ( ccs->wParam & PREF_UNICODE )
+ dbei.cbBlob *= ( sizeof( wchar_t )+1 );
+ dbei.pBlob = (PBYTE)ccs->lParam;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM)&dbei);
+ }
+
+ // prevent send filter from adding another copy of this send event to the db
+ ccs->wParam |= PREF_METANODB;
+
+ return CallContactService(ccs->hContact, szServiceName, ccs->wParam, ccs->lParam);
+ }
+}
+
+/** Transmit a message received by a contact.
+*
+* Forward the message received by a contact linked to a MetaContact
+* to that MetaContact and inhibit the further reception of this message
+* by the standard protocol of the contact.
+*
+* @param wParam : index of the protocol in the protocol chain.
+* @param lParam : \c CCSDATA structure holding all the information about the message.
+*
+* @return 0 on success, 1 otherwise.
+*/
+INT_PTR MetaFilter_RecvMessage(WPARAM wParam,LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam;
+ HANDLE hMeta;
+
+ if((hMeta = (HANDLE)DBGetContactSettingDword(ccs->hContact,META_PROTO, "Handle", (DWORD)0)) == (DWORD)0) {
+ CallService(MS_PROTO_CHAINRECV, wParam, (LPARAM)ccs); // Can't find the MetaID of the metacontact linked to
+ // this contact, let through the protocol chain
+ return 0;
+ }
+
+ if(options.set_default_on_recv) {
+ if(options.temp_default && DBGetContactSettingDword(hMeta, META_PROTO, "SavedDefault", (DWORD)-1) == (DWORD)-1)
+ DBWriteContactSettingDword(hMeta, META_PROTO, "SavedDefault", DBGetContactSettingDword(hMeta, META_PROTO, "Default", 0));
+ DBWriteContactSettingDword(hMeta, META_PROTO, "Default", DBGetContactSettingDword(ccs->hContact, META_PROTO, "ContactNumber", 0));
+ NotifyEventHooks(hEventDefaultChanged, (WPARAM)hMeta, (LPARAM)ccs->hContact); // nick set in event handler
+ }
+
+ // if meta disabled (now message api) or window open (message api), or using subcontact windows,
+ // let through but add db event for metacontact history
+ if(!Meta_IsEnabled()
+ || DBGetContactSettingByte(ccs->hContact, META_PROTO, "WindowOpen", 0) == 1
+ || options.subcontact_windows)
+ {
+
+ // add a clist event, so that e.g. there is an icon flashing
+ // (only add it when message api available, 'cause then we can remove the event when the message window is opened)
+ if(message_window_api_enabled
+ && DBGetContactSettingByte(ccs->hContact, META_PROTO, "WindowOpen", 0) == 0
+ && DBGetContactSettingByte(hMeta, META_PROTO, "WindowOpen", 0) == 0
+ && options.flash_meta_message_icon)
+ {
+ CLISTEVENT cle;
+ char toolTip[256], *contactName;
+ ZeroMemory(&cle, sizeof(cle));
+
+ cle.cbSize = sizeof(cle);
+ cle.hContact = hMeta;
+ cle.hDbEvent = ccs->hContact; // use subcontact handle as key - then we can remove all events if the subcontact window is opened
+ cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+ cle.pszService = "MetaContacts/CListMessageEvent";
+ contactName = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hMeta, 0);
+ _snprintf(toolTip, sizeof(toolTip), Translate("Message from %s"), contactName);
+ cle.pszTooltip = toolTip;
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle);
+ }
+
+ if(options.metahistory) {
+
+ BOOL added = FALSE;
+
+ // should be able to do this, but some protos mess with the memory
+ if(options.use_proto_recv)
+ {
+ // use the subcontact's protocol 'recv' service to add the meta's history (AIMOSCAR removes HTML here!) if possible
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ if(proto) {
+ char service[256];
+ HANDLE hSub = ccs->hContact;
+ DWORD flags = pre->flags;
+ mir_snprintf(service, 256, "%s%s", proto, PSR_MESSAGE);
+ ccs->hContact = hMeta;
+ pre->flags |= (DBGetContactSettingByte(hMeta, META_PROTO, "WindowOpen", 0) ? 0 : PREF_CREATEREAD);
+ if(ServiceExists(service) && !CallService(service, 0, (LPARAM)ccs))
+ added = TRUE;
+ ccs->hContact = hSub;
+ pre->flags = flags;
+ }
+ }
+
+ if(!added) {
+ // otherwise add raw db event
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = META_PROTO;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = (DBGetContactSettingByte(hMeta, META_PROTO, "WindowOpen", 0) ? 0 : DBEF_READ);
+ if(pre->flags & PREF_RTL) dbei.flags |= DBEF_RTL;
+ if(pre->flags & PREF_UTF) dbei.flags |= DBEF_UTF;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = (DWORD)strlen(pre->szMessage) + 1;
+ if ( pre->flags & PREF_UNICODE ) {
+ dbei.cbBlob *= ( sizeof( wchar_t )+1 );
+ }
+ dbei.pBlob = (PBYTE) pre->szMessage;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM) hMeta, (LPARAM)&dbei);
+ }
+ }
+
+ CallService(MS_PROTO_CHAINRECV, wParam, (LPARAM)ccs);
+ return 0;
+ } // else:
+
+ /*
+ // add event to subcontact history (would do it in meta_recvmessage, but here we have the hcontact)
+ // should be able to use the method below, except some protos can mess with the memory
+ if(options.subhistory) {
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = (DBGetContactSettingByte(ccs->hContact, META_PROTO, "WindowOpen", 0) ? 0 : DBEF_READ);
+ if(pre->flags & PREF_RTL) dbei.flags |= DBEF_RTL;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = strlen(pre->szMessage) + 1;
+ if ( pre->flags & PREF_UNICODE )
+ dbei.cbBlob *= ( sizeof( wchar_t )+1 );
+ dbei.pBlob = (PBYTE) pre->szMessage;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM)&dbei);
+ }
+ */
+
+
+ {
+ HANDLE hSub = ccs->hContact;
+ ccs->hContact = hMeta; // Forward to the associated MetaContact.
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)ccs);
+ ccs->hContact = hSub;
+ }
+
+ if(options.subhistory && !(ccs->wParam & PREF_METANODB)) {
+ // allow event pass through and thereby be added to subcontact history
+ pre->flags |= (DBGetContactSettingByte(ccs->hContact, META_PROTO, "WindowOpen", 0) ? 0 : PREF_CREATEREAD);
+ CallService(MS_PROTO_CHAINRECV, wParam, (LPARAM)ccs); // pass through as normal
+ return 0;
+ }
+
+ return 1; // Stop further processing.
+}
+
+/** Receive a message for a MetaContact
+*
+* @return 0
+*/
+INT_PTR Meta_RecvMessage(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *) ccs->lParam;
+
+ char *proto;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ccs->hContact, 0);
+
+ // contact is not a meta proto contact - just leave it
+ if(!proto || strcmp(proto, META_PROTO)) {
+ return 0;
+ }
+
+ if(options.use_proto_recv)
+ {
+ // use the subcontact's protocol to add the db if possible (AIMOSCAR removes HTML here!)
+ HANDLE most_online = Meta_GetMostOnline(ccs->hContact);
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+ if(proto) {
+ char service[256];
+ mir_snprintf(service, 256, "%s%s", proto, PSR_MESSAGE);
+ if (CallService(service, wParam, lParam) != CALLSERVICE_NOTFOUND)
+ return 0;
+ }
+ }
+
+
+ // otherwise, add event to db directly
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = META_PROTO;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = (pre->flags & PREF_CREATEREAD ? DBEF_READ : 0);
+ if(pre->flags & PREF_RTL) dbei.flags |= DBEF_RTL;
+ if(pre->flags & PREF_UTF) dbei.flags |= DBEF_UTF;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = (DWORD)strlen(pre->szMessage) + 1;
+ if ( pre->flags & PREF_UNICODE )
+ dbei.cbBlob *= ( sizeof( wchar_t )+1 );
+ dbei.pBlob = (PBYTE) pre->szMessage;
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM)&dbei);
+
+ return 0;
+}
+
+
+
+/** Called when an ACK is received.
+*
+* Retransmit the ACK sent by a simple contact so that it
+* looks like it was the MetaContact that sends the ACK.
+*
+* @param wParam : Allways set to 0.
+* @param lParam : Reference to a ACKDATA that contains
+ information about the ACK.
+* @return 0 on success, 1 otherwise.
+*/
+int Meta_HandleACK(WPARAM wParam, LPARAM lParam)
+{
+ ACKDATA *ack = (ACKDATA*) lParam;
+ HANDLE hUser;
+
+ if(ack->hContact == 0 || (hUser = (HANDLE)DBGetContactSettingDword(ack->hContact,META_PROTO,"Handle",0)) == 0)
+ return 0; // Can't find the MetaID, let through the protocol chain
+
+
+ if(!strcmp(ack->szModule, META_PROTO)) {
+ return 0; // don't rebroadcast our own acks
+ }
+
+ // if it's for something we don't support, ignore
+ if(ack->type != ACKTYPE_MESSAGE && ack->type != ACKTYPE_CHAT && ack->type != ACKTYPE_FILE && ack->type != ACKTYPE_AWAYMSG
+ && ack->type != ACKTYPE_AVATAR && ack->type != ACKTYPE_GETINFO)
+
+ {
+ return 0;
+ }
+
+ // change the hContact in the avatar info struct, if it's the avatar we're using - else drop it
+ if(ack->type == ACKTYPE_AVATAR) {
+ if(ack->result == ACKRESULT_SUCCESS || ack->result == ACKRESULT_FAILED || ack->result == ACKRESULT_STATUS) {
+ HANDLE most_online;
+ DBVARIANT dbv;
+
+ // change avatar if the most online supporting avatars changes, or if we don't have one
+ most_online = Meta_GetMostOnlineSupporting(hUser, PFLAGNUM_4, PF4_AVATARS);
+ //if(AI.hContact == 0 || AI.hContact != most_online) {
+ if(ack->hContact == 0 || ack->hContact != most_online) {
+ return 0;
+ }
+
+ //if(!DBGetContactSetting(AI.hContact, "ContactPhoto", "File", &dbv)) {
+ if(!DBGetContactSetting(ack->hContact, "ContactPhoto", "File", &dbv)) {
+ DBWriteContactSettingString(hUser, "ContactPhoto", "File", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ if(ack->hProcess) {
+ PROTO_AVATAR_INFORMATION AI;
+ memcpy(&AI, (PROTO_AVATAR_INFORMATION *)ack->hProcess, sizeof(PROTO_AVATAR_INFORMATION));
+ if(AI.hContact)
+ AI.hContact = hUser;
+
+ return ProtoBroadcastAck(META_PROTO,hUser,ack->type,ack->result, (HANDLE)&AI, ack->lParam);
+ } else
+ return ProtoBroadcastAck(META_PROTO,hUser,ack->type,ack->result, 0, ack->lParam);
+ }
+ }
+
+ return ProtoBroadcastAck(META_PROTO,hUser,ack->type,ack->result,ack->hProcess,ack->lParam);
+}
+
+// hiding contacts on "CList/UseGroups" setting changed can cause a crash - do it in a seperate thread during idle time
+static DWORD sttHideContacts( BOOL param )
+{
+ Meta_HideMetaContacts((int)param);
+ return 0;
+}
+
+/** Call whenever a contact changes one of its settings (for example, the status)
+**
+* @param wParam \c HANDLE to the contact that has change of its setting.
+* @param lParam Reference to a structure that contains the setting that has changed (not used)
+*/
+int Meta_SettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *dcws = (DBCONTACTWRITESETTING *)lParam;
+ char buffer[512], buffer2[512];
+ int contact_number;
+ HANDLE hMeta, most_online;
+
+
+ // hide metacontacts when groups disabled
+ if(wParam == 0
+ && ((strcmp(dcws->szModule, "CList") == 0 && strcmp(dcws->szSetting, "UseGroups") == 0)
+ || (strcmp(dcws->szModule, META_PROTO) == 0 && strcmp(dcws->szSetting, "Enabled") == 0)))
+ {
+ sttHideContacts(!Meta_IsEnabled());
+ return 0;
+ }
+
+ if(wParam == 0
+ && strcmp(dcws->szModule, "Import") == 0 && strcmp(dcws->szSetting, "Completed") == 0)
+ {
+ // import process has just been run...call startup routines...
+ Meta_SetHandles();
+ {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ int meta_id;
+ while ( hContact != NULL ) {
+ if((meta_id = DBGetContactSettingDword(hContact,META_PROTO,META_ID,(DWORD)-1))!=(DWORD)-1) {
+ Meta_CopyData(hContact);
+ }
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ }
+
+ Meta_HideLinkedContacts();
+ Meta_SuppressStatus(options.suppress_status);
+ }
+
+ if(wParam == 0
+ && strcmp(dcws->szModule, "CListGroups") == 0 && dcws->value.type != DBVT_DELETED && strcmp(dcws->value.pszVal, META_HIDDEN_GROUP) == 0)
+ {
+ // someone is creating our hidden group!!
+
+ }
+
+ // from here on, we're just interested in contact settings
+ if(wParam == 0) return 0;
+
+ if((hMeta=(HANDLE)DBGetContactSettingDword((HANDLE)wParam,META_PROTO,"Handle",0))!=0
+ && CallService(MS_DB_CONTACT_IS, (WPARAM)hMeta, 0)) // just to be safe
+
+ { // This contact is attached to a MetaContact.
+
+ contact_number = Meta_GetContactNumber((HANDLE)wParam);
+ if(contact_number == -1) return 0; // exit - db corruption
+
+ if(!meta_group_hack_disabled && !strcmp(dcws->szModule, "CList") && !strcmp(dcws->szSetting, "Group") &&
+ Meta_IsEnabled() && DBGetContactSettingByte((HANDLE)wParam, META_PROTO, "Hidden", 0) == 0 && !Miranda_Terminated()) {
+ if((dcws->value.type == DBVT_ASCIIZ || dcws->value.type == DBVT_UTF8) && !Meta_IsHiddenGroup(dcws->value.pszVal)) {
+ // subcontact group reassigned - copy to saved group
+ MyDBWriteContactSetting((HANDLE)wParam, META_PROTO, "OldCListGroup", &dcws->value);
+ DBWriteContactSettingString((HANDLE)wParam, "CList", "Group", META_HIDDEN_GROUP);
+ } else if(dcws->value.type == DBVT_DELETED) {
+ DBDeleteContactSetting((HANDLE)wParam, META_PROTO, "OldCListGroup");
+ DBWriteContactSettingString((HANDLE)wParam, "CList", "Group", META_HIDDEN_GROUP);
+ }
+ } else
+
+ // copy IP
+ if(!strcmp(dcws->szSetting, "IP")) {
+ if(dcws->value.type == DBVT_DWORD)
+ DBWriteContactSettingDword(hMeta, META_PROTO, "IP", dcws->value.dVal);
+ else
+ DBDeleteContactSetting(hMeta, META_PROTO, "IP");
+ } else
+
+ // copy RealIP
+ if(!strcmp(dcws->szSetting, "RealIP")) {
+ if(dcws->value.type == DBVT_DWORD)
+ DBWriteContactSettingDword(hMeta, META_PROTO, "RealIP", dcws->value.dVal);
+ else
+ DBDeleteContactSetting(hMeta, META_PROTO, "RealIP");
+
+ } else
+ // copy ListeningTo
+ if(!strcmp(dcws->szSetting, "ListeningTo")) {
+ switch(dcws->value.type) {
+ case DBVT_ASCIIZ:
+ DBWriteContactSettingString(hMeta, META_PROTO, "ListeningTo", dcws->value.pszVal);
+ break;
+ case DBVT_UTF8:
+ DBWriteContactSettingStringUtf(hMeta, META_PROTO, "ListeningTo", dcws->value.pszVal);
+ break;
+ case DBVT_WCHAR:
+ DBWriteContactSettingWString(hMeta, META_PROTO, "ListeningTo", dcws->value.pwszVal);
+ break;
+ case DBVT_DELETED:
+ DBDeleteContactSetting(hMeta, META_PROTO, "ListeningTo");
+ break;
+ }
+ } else
+
+ if(!strcmp(dcws->szSetting, "Nick") && !dcws->value.type == DBVT_DELETED) {
+ DBVARIANT dbv;
+ HANDLE most_online;
+
+ // subcontact nick has changed - update metacontact
+ strcpy(buffer, "Nick");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ MyDBWriteContactSetting(hMeta, META_PROTO, buffer, &dcws->value);
+
+ if(MyDBGetContactSetting((HANDLE)wParam, "CList", "MyHandle", &dbv)) {
+ strcpy(buffer, "CListName");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ MyDBWriteContactSetting(hMeta, META_PROTO, buffer, &dcws->value);
+ } else {
+ DBFreeVariant(&dbv);
+ }
+
+ // copy nick to metacontact, if it's the most online
+ most_online = Meta_GetMostOnline(hMeta);
+ Meta_CopyContactNick(hMeta, most_online);
+
+ return 0;
+ } else
+
+ if(!strcmp(dcws->szSetting, "IdleTS")) {
+ if(dcws->value.type == DBVT_DWORD)
+ DBWriteContactSettingDword(hMeta, META_PROTO, "IdleTS", dcws->value.dVal);
+ else if(dcws->value.type == DBVT_DELETED)
+ DBWriteContactSettingDword(hMeta, META_PROTO, "IdleTS", 0);
+ } else
+
+ if(!strcmp(dcws->szSetting, "LogonTS")) {
+ if(dcws->value.type == DBVT_DWORD)
+ DBWriteContactSettingDword(hMeta, META_PROTO, "LogonTS", dcws->value.dVal);
+ else if(dcws->value.type == DBVT_DELETED)
+ DBWriteContactSettingDword(hMeta, META_PROTO, "LogonTS", 0);
+ } else
+
+ if(!strcmp(dcws->szModule, "CList") && !strcmp(dcws->szSetting, "MyHandle")) {
+ HANDLE most_online;
+
+ if(dcws->value.type == DBVT_DELETED) {
+ DBVARIANT dbv;
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ strcpy(buffer, "CListName");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ if(proto && !MyDBGetContactSetting((HANDLE)wParam, proto, "Nick", &dbv)) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buffer, &dbv);
+ DBFreeVariant(&dbv);
+ } else {
+ DBDeleteContactSetting(hMeta, META_PROTO, buffer);
+ }
+ } else {
+ // subcontact clist displayname has changed - update metacontact
+ strcpy(buffer, "CListName");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+
+ MyDBWriteContactSetting(hMeta, META_PROTO, buffer, &dcws->value);
+ }
+
+ // copy nick to metacontact, if it's the most online
+ most_online = Meta_GetMostOnline(hMeta);
+ Meta_CopyContactNick(hMeta, most_online);
+
+ return 0;
+ } else
+
+ if(!strcmp(dcws->szSetting, "Status") && !dcws->value.type == DBVT_DELETED) {
+ // subcontact changing status
+
+ // update subcontact status setting
+ strcpy(buffer, "Status");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ DBWriteContactSettingWord(hMeta, META_PROTO, buffer, dcws->value.wVal);
+ strcpy(buffer, "StatusString");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ Meta_GetStatusString(dcws->value.wVal, buffer2, 512);
+ DBWriteContactSettingString(hMeta, META_PROTO, buffer, buffer2);
+
+ // if the contact was forced, unforce it (which updates status)
+ if((HANDLE)DBGetContactSettingDword(hMeta, META_PROTO, "ForceSend", 0) == (HANDLE)wParam) {
+ MetaAPI_UnforceSendContact((WPARAM)hMeta, 0);
+ } else {
+ // set status to that of most online contact
+ most_online = Meta_GetMostOnline(hMeta);
+ Meta_CopyContactNick(hMeta, most_online);
+
+ Meta_FixStatus(hMeta);
+
+ Meta_CopyData(hMeta);
+ }
+
+ // most online contact with avatar support might have changed - update avatar
+ most_online = Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_4, PF4_AVATARS);
+ if(most_online) {
+ PROTO_AVATAR_INFORMATION AI;
+
+ AI.cbSize = sizeof(AI);
+ AI.hContact = hMeta;
+ AI.format = PA_FORMAT_UNKNOWN;
+ strcpy(AI.filename, "X");
+
+ if((int)CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&AI) == GAIR_SUCCESS)
+ DBWriteContactSettingString(hMeta, "ContactPhoto", "File",AI.filename);
+ }
+ } else
+
+ if(strcmp(dcws->szSetting, "XStatusId") == 0 || strcmp(dcws->szSetting, "XStatusMsg") == 0 || strcmp(dcws->szSetting, "XStatusName") == 0 || strcmp(dcws->szSetting, "StatusMsg") == 0) {
+ Meta_CopyData(hMeta);
+ } else
+
+ if(strcmp(dcws->szSetting, "MirVer") == 0) {
+ Meta_CopyData(hMeta);
+ } else
+
+ if(!meta_group_hack_disabled && !strcmp(dcws->szModule, "CList") && !strcmp(dcws->szSetting, "Hidden")) {
+ if((dcws->value.type == DBVT_DELETED || DBGetContactSettingByte((HANDLE)wParam, "CList", "Hidden", 0) == 0)
+ && DBGetContactSettingByte((HANDLE)wParam, META_PROTO, "Hidden", 0) == 1)
+ {
+ // a subcontact we hid (e.g. jabber) has been unhidden - hide it again :(
+ DBWriteContactSettingByte((HANDLE)wParam, "CList", "Hidden", 1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int Meta_ContactDeleted(WPARAM wParam, LPARAM lParam) {
+ HANDLE hMeta;
+
+ // is a subcontact - update meta contact
+ hMeta = (HANDLE)DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "Handle", 0);
+ if(hMeta) {
+ Meta_RemoveContactNumber(hMeta, DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "ContactNumber", -1));
+ NotifyEventHooks(hSubcontactsChanged, (WPARAM)hMeta, 0);
+ return 0;
+ } else {
+ // not a subcontact - is it a metacontact?
+ int num_contacts = DBGetContactSettingDword((HANDLE)wParam, META_PROTO, "NumContacts", 0);
+ int i;
+ HANDLE hContact;
+
+ if(num_contacts) NotifyEventHooks(hSubcontactsChanged, (WPARAM)wParam, 0);
+
+ // remove & restore all subcontacts
+ for(i = 0; i < num_contacts; i++) {
+ hContact = Meta_GetContactHandle((HANDLE)wParam, i);
+
+ if(hContact && (HANDLE)DBGetContactSettingDword(hContact, META_PROTO, "Handle", 0) == (HANDLE)wParam) {
+ if(DBGetContactSettingByte(hContact, META_PROTO, "IsSubcontact", 0) == 1)
+ DBDeleteContactSetting(hContact,META_PROTO,"IsSubcontact");
+ DBDeleteContactSetting(hContact,META_PROTO,META_LINK);
+ DBDeleteContactSetting(hContact,META_PROTO,"Handle");
+ DBDeleteContactSetting(hContact,META_PROTO,"ContactNumber");
+ Meta_RestoreGroup(hContact);
+ DBDeleteContactSetting(hContact,META_PROTO,"OldCListGroup");
+
+ CallService(MS_PROTO_REMOVEFROMCONTACT, (WPARAM)hContact, (LPARAM)META_FILTER);
+ // stop ignoring, if we were
+ if(options.suppress_status)
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+ }
+ }
+ return 0;
+ }
+
+
+ return 0;
+}
+
+/** Call when we want to send a user is typing message
+*
+* @param wParam \c HANDLE to the contact that we are typing to
+* @param lParam either PROTOTYPE_SELFTYPING_ON or PROTOTYPE_SELFTYPING_OFF
+*/
+INT_PTR Meta_UserIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ char *proto;
+ char buff[512];
+
+ if(DBGetContactSettingDword((HANDLE)wParam,META_PROTO,META_ID,(DWORD)-1) == (DWORD)-1)
+ {
+ // This is a simple contact, let through the stack of protocols
+ return 0;
+ }
+ else
+ {
+ // forward to sending protocol, if supported
+
+ HANDLE most_online = Meta_GetMostOnline((HANDLE)wParam);
+ Meta_CopyContactNick((HANDLE)wParam, most_online);
+
+ if(!most_online) return 0;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+ if(proto) {
+ strncpy(buff, proto, 512);
+ strncpy(buff + strlen(proto), PSS_USERISTYPING, 512 - strlen(proto));
+
+ if(ServiceExists(buff)) {
+ CallService(buff, (WPARAM)most_online, (LPARAM)lParam);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** Call when we want to receive a user is typing message
+*
+* @param wParam \c HANDLE to the contact that is typing or not
+* @param lParam either PROTOTYPE_SELFTYPING_ON or PROTOTYPE_SELFTYPING_OFF
+*/
+int Meta_ContactIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hMeta;
+
+ if((hMeta = (HANDLE)DBGetContactSettingDword((HANDLE)wParam,META_PROTO,"Handle",(DWORD)0)) != 0
+ // check metacontacts enabled
+ && Meta_IsEnabled()
+ )
+ { // This contact is attached to a MetaContact.
+ if(!options.subcontact_windows) { // we don't want clicking on the clist notification icon to open the metacontact message window
+
+ // try to remove any clist events we added for subcontact
+ CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1);
+
+ CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hMeta, lParam);
+
+ // stop processing of event
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/** Called when user info is about to be shown
+*
+* Returns 1 to stop event processing and opens page for metacontact default contact (returning 1 to stop it doesn't work!)
+*
+*/
+int Meta_UserInfo(WPARAM wParam, LPARAM lParam)
+{
+ DWORD default_contact_number = DBGetContactSettingDword((HANDLE)lParam, META_PROTO, "Default", (DWORD)-1);
+
+ if(default_contact_number == -1) // not a meta contact
+ return 0;
+
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)Meta_GetContactHandle((HANDLE)lParam, default_contact_number), 0);
+
+ return 1;
+}
+
+// handle message window api ver 0.0.0.1+ events - record window open/close status for subcontacts, so we know whether to
+// let received messages through and add db history to metacontact, or vice versa
+int Meta_MessageWindowEvent(WPARAM wParam, LPARAM lParam) {
+ MessageWindowEventData *mwed = (MessageWindowEventData *)lParam;
+ HANDLE hMeta = 0;
+
+ message_window_api_enabled = TRUE;
+
+ if((hMeta = (HANDLE)DBGetContactSettingDword(mwed->hContact, META_PROTO, "Handle", 0)) != 0
+ || DBGetContactSettingDword(mwed->hContact, META_PROTO, META_ID, (DWORD)-1) != (DWORD)-1)
+ {
+ // contact is subcontact of metacontact, or an actual metacontact - record whether window is open or closed
+ if(mwed->uType == MSG_WINDOW_EVT_OPEN || mwed->uType == MSG_WINDOW_EVT_OPENING) {
+ DBWriteContactSettingByte(mwed->hContact, META_PROTO, "WindowOpen", 1);
+
+ if(hMeta) { // subcontact window opened - remove clist events we added for metacontact
+ while(!CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hMeta, (LPARAM)mwed->hContact));
+ }
+ } else if(mwed->uType == MSG_WINDOW_EVT_CLOSE || mwed->uType == MSG_WINDOW_EVT_CLOSING) {
+ DBWriteContactSettingByte(mwed->hContact, META_PROTO, "WindowOpen", 0);
+ if(!hMeta) { // hMeta is 0 for metacontact (sorry)
+ DWORD saved_def;
+
+ MetaAPI_UnforceSendContact((WPARAM)mwed->hContact, 0);
+
+ // restore saved default contact
+ if(options.set_default_on_recv) {
+ saved_def = DBGetContactSettingDword(mwed->hContact, META_PROTO, "SavedDefault", -1);
+ if(options.temp_default && saved_def != (DWORD)-1) {
+ DBWriteContactSettingDword(mwed->hContact, META_PROTO, "Default", saved_def);
+ DBWriteContactSettingDword(mwed->hContact, META_PROTO, "SavedDefault", (DWORD)-1);
+ NotifyEventHooks(hEventDefaultChanged, (WPARAM)mwed->hContact, (LPARAM)Meta_GetContactHandle(hMeta, saved_def)); // nick set in event handler
+ }
+ }
+ }
+ }
+
+ }
+
+ return 0;
+}
+/*
+int Meta_LoadIcons(WPARAM wParam, LPARAM lParam) {
+ PROTOCOLDESCRIPTOR **protos;
+
+ //MessageBox(0, "LoadIcons", "Event", MB_OK);
+
+ if(ServiceExists(MS_CLIST_EXTRA_ADD_ICON)) {
+ int index = 0, i;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&proto_count,(LPARAM)&protos);
+ for(i = 0; i < proto_count && i < MAX_PROTOCOLS; i++) {
+ if(protos[i]->type!=PROTOTYPE_PROTOCOL || CallProtoService(protos[i]->szName,PS_GETCAPS,PFLAGNUM_2,0)==0)
+ continue;
+
+ strncpy(proto_names + (index * 128), protos[i]->szName, 128);
+ hProtoIcons[index * 2] = LoadSkinnedProtoIcon(protos[i]->szName,ID_STATUS_ONLINE);
+ hProtoIcons[index * 2 + 1] = LoadSkinnedProtoIcon(protos[i]->szName,ID_STATUS_OFFLINE);
+ hExtraImage[index * 2] = 0;
+ hExtraImage[index * 2 + 1] = 0;
+
+ //sprintf(buff, "Added icon (hIcon = %d, hImage = %d) for protocol %s.", hProtoIcons[index], hExtraImage[index], protos[i]->szName);
+ //MessageBox(0, buff, "Added Extra Icon", MB_OK);
+
+ index++;
+ }
+ proto_count = index;
+
+ //Meta_CListMW_ExtraIconsRebuild(0, 0);
+
+ }
+
+
+ return 0;
+}
+
+int Meta_CListMW_ExtraIconsRebuild(WPARAM wParam, LPARAM lParam) {
+ int i;
+
+ //MessageBox(0, "IconsRebuild", "Event", MB_OK);
+ Meta_LoadIcons(0, 0);
+
+ if(ServiceExists(MS_CLIST_EXTRA_ADD_ICON)) {
+ for(i = 0; i < proto_count; i++) {
+ hExtraImage[i * 2] = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)hProtoIcons[i * 2], 0);
+ hExtraImage[i * 2 + 1] = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)hProtoIcons[i * 2 + 1], 0);
+ }
+ }
+
+ return 0;
+}
+
+int Meta_CListMW_ExtraIconsApply(WPARAM wParam, LPARAM lParam) {
+
+ //MessageBox(0, "IconsApply", "Event", MB_OK);
+
+ if(DBGetContactSettingDword((HANDLE)wParam, META_PROTO, META_ID, (DWORD)-1) != (DWORD)-1) {
+ if(ServiceExists(MS_CLIST_EXTRA_SET_ICON)) {
+ IconExtraColumn iec;
+ HANDLE most_online_im = Meta_GetMostOnline((HANDLE)wParam);
+ int i;
+
+ if(most_online_im) {
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online_im, 0);
+ if(proto) {
+ WORD status = DBGetContactSettingWord(most_online_im, proto, "Status", ID_STATUS_OFFLINE);
+ iec.cbSize = sizeof(iec);
+ for(i = 0; i < proto_count; i++) {
+ if(!strcmp((proto_names + i * 128), proto)) {
+ if(hExtraImage[i * 2 + (status == ID_STATUS_OFFLINE ? 1 : 0)]) {
+ iec.hImage = hExtraImage[i * 2 + (status == ID_STATUS_OFFLINE ? 1 : 0)];
+ iec.ColumnType = EXTRA_ICON_ADV2;
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)wParam, (LPARAM)&iec);
+ iec.ColumnType = EXTRA_ICON_PROTO;
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)wParam, (LPARAM)&iec);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+*/
+int Meta_ClistDoubleClicked(WPARAM wParam, LPARAM lParam) {
+
+ if(DBGetContactSettingDword((HANDLE)wParam,META_PROTO,"Default",(WORD)-1) == (WORD)-1)
+ {
+ // This is a simple contact
+ return 0;
+ }
+ else
+ {
+ // -1 indicates no specific capability but respect 'ForceDefault'
+ HANDLE most_online = Meta_GetMostOnlineSupporting((HANDLE)wParam, PFLAGNUM_1, -1);
+ //DBEVENTINFO dbei;
+ char *proto;
+ char buffer[512];
+ int caps;
+
+ if(!most_online)
+ return 0;
+
+ if(options.subcontact_windows) {
+ if(lParam) {
+ // contact from incoming message in lParam via (at this point) clist message event
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)lParam, 0);
+ } else {
+ // simulate double click on most_online contact and stop event processing
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)most_online, 0);
+ }
+ return 1;
+ } else {
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+
+ if(proto) {
+ strcpy(buffer, proto);
+ strcat(buffer, PS_GETCAPS);
+
+ // get the contacts messaging capabilities
+ caps = CallService(buffer, (WPARAM)PFLAGNUM_1, 0);
+
+ if((caps & PF1_IMSEND) || (caps & PF1_CHAT) || (proto && strcmp(proto, "IRC") == 0))
+ // let event process normally
+ return 0;
+ else {
+ // simulate double click on most_online contact and stop event processing
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)most_online, 0);
+ return 1;
+ }
+ } else
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+INT_PTR Meta_ClistMessageEventClicked(WPARAM wParam, LPARAM lParam) {
+
+ HANDLE hContact = ((CLISTEVENT *)lParam)->hContact;
+
+ // hdbevent contains the id of the subcontact
+ return Meta_ClistDoubleClicked((WPARAM)hContact, (LPARAM)((CLISTEVENT *)lParam)->hDbEvent);
+}
+
+
+int NudgeRecieved(WPARAM wParam, LPARAM lParam) {
+ /*
+ // already being forwarded by someone
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword((HANDLE)wParam,META_PROTO, "Handle", (DWORD)0);
+ if(hMeta)
+ NotifyEventHooks(hEventNudge, (WPARAM)hMeta, 0);
+ */
+ return 0;
+}
+
+/** Called when all the plugin are loaded into Miranda.
+*
+* Initializes the 4 menus present in the context-menu
+* and the initial value of nextMetaID
+*/
+int Meta_ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM menu = {0};
+ char buffer[512], buffer2[512], buffer3[512];
+ int i;
+
+ if(ServiceExists(MS_MSG_GETWINDOWAPI)) {
+ message_window_api_enabled = TRUE;
+ }
+
+ if(ServiceExists(MS_UPDATE_REGISTER)) {
+ // register with updater
+ Update update = {0};
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion);
+ update.cpbVersion = (int)strlen((char *)update.pbVersion);
+ update.szBetaChangelogURL = "https://server.scottellis.com.au/wsvn/mim_plugs/metacontacts/?op=log&rev=0&sc=0&isdir=1";
+
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szBetaUpdateURL = "http://www.scottellis.com.au/miranda_plugins/MetaContacts.zip";
+ update.szBetaVersionURL = "http://www.scottellis.com.au/miranda_plugins/ver_MetaContacts.html";
+ update.pbBetaVersionPrefix = (BYTE *)"MetaContacts Plugin, version ";
+
+ update.cpbBetaVersionPrefix = (int)strlen((char *)update.pbBetaVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+
+ // disable group hack for older nicer versions without the fix
+ if(ServiceExists(MS_CLUI_GETVERSION)) {
+ char *version = (char *)CallService(MS_CLUI_GETVERSION, 0, 0);
+ if(version && strlen(version) >= strlen("CList Nicer+") && strncmp(version, "CList Nicer+", strlen("CList Nicer+")) == 0)
+ meta_group_hack_disabled = TRUE;
+ }
+
+ // for database editor++ ver 3+
+ if(ServiceExists("DBEditorpp/RegisterSingleModule"))
+ CallService("DBEditorpp/RegisterSingleModule",(WPARAM)META_PROTO,0);
+
+
+ hHooks[11] = (HANDLE)HookEvent(ME_CLIST_PREBUILDCONTACTMENU, Meta_ModifyMenu);
+ hHooks[12] = (HANDLE)HookEvent(ME_CLIST_DOUBLECLICKED, Meta_ClistDoubleClicked );
+ //hHooks[13] = (HANDLE)HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, Meta_CListMW_ExtraIconsRebuild);
+ //hHooks[14] = (HANDLE)HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, Meta_CListMW_ExtraIconsApply);
+
+ // icons are erased on this event...
+ // (BUT, the me_clist_extra_list_rebuild is send FIRST...so, we ignore this one...)
+ hHooks[15] = 0;//(HANDLE)HookEvent(ME_SKIN_ICONSCHANGED, Meta_LoadIcons);
+
+ menu.cbSize=sizeof(menu);
+ menu.flags = CMIM_ALL;
+
+ // main menu item
+ menu.pszName = "Toggle MetaContacts Off";
+ menu.pszService = "MetaContacts/OnOff";
+ menu.position = 500010000;
+ hMenuOnOff = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&menu);
+
+ // contact menu items
+ menu.position = -200010;
+ menu.pszName = "Convert to MetaContact";
+ menu.pszService = "MetaContacts/Convert";
+ hMenuConvert = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+ menu.position = -200009;
+ menu.pszName = "Add to existing MetaContact...";
+ menu.pszService = "MetaContacts/AddTo";
+ hMenuAdd = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ menu.position = -200010;
+ menu.pszName = "Edit MetaContact...";
+ menu.pszService = "MetaContacts/Edit";
+ hMenuEdit = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+ menu.position = -200009;
+ menu.pszName = "Set as MetaContact default";
+ menu.pszService = "MetaContacts/Default";
+ hMenuDefault = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+ menu.position = -200008;
+ menu.pszName = "Delete MetaContact";
+ menu.pszService = "MetaContacts/Delete";
+ hMenuDelete = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+ //menu.pszName = "Force Default";
+ //menu.pszService = "MetaContacts/ForceDefault";
+ //hMenuForceDefault = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ menu.flags |= CMIF_HIDDEN;
+ menu.pszContactOwner = META_PROTO;
+
+ menu.position = -99000;
+ for(i = 0; i < MAX_CONTACTS; i++) {
+ menu.position--;
+ strcpy(buffer3, (char *)Translate("Context"));
+ strcat(buffer3, _itoa(i, buffer2, 10));
+ menu.pszName = buffer3;
+
+ strcpy(buffer, "MetaContacts/MenuFunc");
+ strcat(buffer, _itoa(i, buffer2, 10));
+ menu.pszService= buffer;
+
+ hMenuContact[i] = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+ }
+
+ nextMetaID = DBGetContactSettingDword(NULL,META_PROTO,"NextMetaID",(DWORD)0);
+
+ // attemp to subsume userinfo...(returning 1 does not prevent dialog - so disabled)
+ //hHooks[] = (HANDLE)HookEvent(ME_USERINFO_INITIALISE, Meta_UserInfo);
+
+ // loop and copy data from subcontacts
+ if(options.copydata) {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ int meta_id;
+ while ( hContact != NULL ) {
+ if((meta_id = DBGetContactSettingDword(hContact,META_PROTO,META_ID,(DWORD)-1))!=(DWORD)-1) {
+ Meta_CopyData(hContact);
+ }
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ }
+
+ Meta_HideLinkedContacts();
+
+ InitIcons();
+
+ if(!Meta_IsEnabled())
+ {
+ // modify main menu item
+ menu.flags = CMIM_NAME;
+ menu.pszName = "Toggle MetaContacts On";
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuOnOff, (LPARAM)&menu);
+
+ Meta_HideMetaContacts(TRUE);
+ } else {
+ Meta_SuppressStatus(options.suppress_status);
+ }
+
+ // hook srmm window close/open events - message api ver 0.0.0.1+
+ hHooks[16] = (HANDLE)HookEvent(ME_MSG_WINDOWEVENT, Meta_MessageWindowEvent);
+ if(hHooks[16]) // message api available
+ message_window_api_enabled = TRUE;
+
+ // hook protocol nudge events to forward to subcontacts
+ {
+ int i, numberOfProtocols,ret;
+ char str[MAXMODULELABELLENGTH + 10];
+ HANDLE hNudgeEvent = NULL;
+ PROTOCOLDESCRIPTOR ** ppProtocolDescriptors;
+ ret = CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM) &numberOfProtocols,(LPARAM)&ppProtocolDescriptors);
+ if(ret == 0)
+ {
+ for(i = 0; i < numberOfProtocols ; i++)
+ {
+ if(ppProtocolDescriptors[i]->type == PROTOTYPE_PROTOCOL)
+ {
+ if(strcmp(ppProtocolDescriptors[i]->szName, META_PROTO)) {
+ sprintf(str,"%s/Nudge",ppProtocolDescriptors[i]->szName);
+ hNudgeEvent = HookEvent(str, NudgeRecieved);
+ if(hNudgeEvent != NULL) {
+ ++iNudgeProtos;
+ hNudgeEvents = realloc(hNudgeEvents, sizeof(HANDLE) * iNudgeProtos);
+ hNudgeEvents[iNudgeProtos - 1] = hNudgeEvent;
+ }
+ }
+ }
+ }
+
+ }
+ }
+ return 0;
+}
+
+static VOID CALLBACK sttMenuThread( PVOID param )
+{
+ HMENU hMenu;
+ TPMPARAMS tpmp;
+ BOOL menuRet;
+
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)param, 0);
+
+ ZeroMemory(&tpmp, sizeof(tpmp));
+ tpmp.cbSize = sizeof(tpmp);
+
+ menuRet = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, menuMousePoint.x, menuMousePoint.y, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), &tpmp);
+
+ CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(menuRet), MPCF_CONTACTMENU), (LPARAM)param);
+
+ DestroyMenu(hMenu);
+}
+
+INT_PTR Meta_ContactMenuFunc(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact;
+ hContact = Meta_GetContactHandle((HANDLE)wParam, (int)lParam);
+
+ if(options.menu_function == FT_MSG) {
+ // open message window if protocol supports message sending or chat, else simulate double click
+
+ int caps;
+ char *proto;
+ char buffer[512];
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if(proto) {
+ strcpy(buffer, proto);
+ strcat(buffer, PS_GETCAPS);
+
+ caps = CallService(buffer, (WPARAM)PFLAGNUM_1, 0);
+
+ if((caps & PF1_IMSEND) || (caps & PF1_CHAT) || (proto && strcmp(proto, "IRC") == 0)) {
+ // set default contact for sending/status and open message window
+ DBWriteContactSettingDword((HANDLE)wParam, META_PROTO, "Default", (DWORD)(int)lParam);
+ NotifyEventHooks(hEventDefaultChanged, wParam, (LPARAM)hContact);
+ CallService(MS_MSG_SENDMESSAGE, wParam, 0);
+ } else
+ // protocol does not support messaging - simulate double click
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContact, 0);
+ } else
+ // protocol does not support messaging - simulate double click
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContact, 0);
+
+ } else if(options.menu_function == FT_MENU) {
+ // show contact's context menu
+ CallFunctionAsync(sttMenuThread, hContact);
+ } else if(options.menu_function == FT_INFO) {
+ // show user info for subcontact
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0);
+ }
+
+ return 0;
+}
+
+////////////////////
+// file transfer support - mostly not required, since subcontacts do the receiving
+////////////////////
+/*
+INT_PTR Meta_FileResume(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+
+ if(DBGetContactSetting(ccs->hContact,META_PROTO,"Default",&dbv))
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 1;
+ }
+ else
+ {
+ HANDLE most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_1, PF1_FILERESUME);
+ //DBEVENTINFO dbei;
+ char szServiceName[100];
+
+ DBFreeVariant(&dbv);
+
+ if(!most_online)
+ return 0;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+
+ ccs->hContact = most_online;
+ Meta_SetNick(proto);
+
+ _snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PS_FILERESUME);
+ if (ServiceExists(szServiceName)) {
+ strncpy(szServiceName, PS_FILERESUME, sizeof(szServiceName));
+ return (int)(CallContactService(ccs->hContact, szServiceName, ccs->wParam, ccs->lParam));
+ }
+ }
+ return 1; // fail
+}
+
+INT_PTR Meta_FileAllow(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+
+ if(DBGetContactSetting(ccs->hContact,META_PROTO,"Default",&dbv))
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 0;
+ }
+ else
+ {
+ HANDLE most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_1, PF1_FILE);
+ char szServiceName[100];
+
+ DBFreeVariant(&dbv);
+
+ if(!most_online)
+ return 0;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+
+ ccs->hContact = most_online;
+ Meta_SetNick(proto);
+
+ _snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PSS_FILEALLOW);
+ if (ServiceExists(szServiceName)) {
+ strncpy(szServiceName, PSS_FILEALLOW, sizeof(szServiceName));
+ return (int)(CallContactService(ccs->hContact, szServiceName, ccs->wParam, ccs->lParam));
+ }
+ }
+ return 0; // fail
+}
+
+INT_PTR Meta_FileDeny(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+
+ if(DBGetContactSetting(ccs->hContact,META_PROTO,"Default",&dbv))
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 1;
+ }
+ else
+ {
+ HANDLE most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_1, PF1_FILE);
+ //DBEVENTINFO dbei;
+ char szServiceName[100];
+
+ DBFreeVariant(&dbv);
+
+ if(!most_online)
+ return 1;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+
+ ccs->hContact = most_online;
+ Meta_SetNick(proto);
+
+ _snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PSS_FILEDENY);
+ if (ServiceExists(szServiceName)) {
+ strncpy(szServiceName, PSS_FILEDENY, sizeof(szServiceName));
+ return (int)(CallContactService(ccs->hContact, szServiceName, ccs->wParam, ccs->lParam));
+ }
+ }
+ return 1; // fail
+}
+
+INT_PTR Meta_FileRecv(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+
+ if(DBGetContactSetting(ccs->hContact,META_PROTO,"Default",&dbv))
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 0;
+ }
+ else
+ {
+ HANDLE most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_1, PF1_FILE);
+ //DBEVENTINFO dbei;
+ char szServiceName[100];
+
+ DBFreeVariant(&dbv);
+
+ if(!most_online)
+ return 0;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+
+ ccs->hContact = most_online;
+ Meta_SetNick(proto);
+
+ _snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PSR_FILE);
+ if (ServiceExists(szServiceName)) {
+ strncpy(szServiceName, PSR_FILE, sizeof(szServiceName));
+ return (int)(CallContactService(ccs->hContact, szServiceName, ccs->wParam, ccs->lParam));
+ }
+ }
+
+ return 0;
+}
+
+int Meta_FileCancel(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+
+ if(DBGetContactSetting(ccs->hContact,META_PROTO,"Default",&dbv))
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 0;
+ }
+ else
+ {
+ HANDLE most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_1, PF1_FILE);
+ //DBEVENTINFO dbei;
+ char szServiceName[100];
+
+ DBFreeVariant(&dbv);
+
+ if(!most_online)
+ return 0;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+
+ ccs->hContact = most_online;
+ Meta_SetNick(proto);
+
+ _snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PSS_FILECANCEL);
+ if (ServiceExists(szServiceName)) {
+ strncpy(szServiceName, PSS_FILECANCEL, sizeof(szServiceName));
+ return (int)(CallContactService(ccs->hContact, szServiceName, ccs->wParam, ccs->lParam));
+ }
+ }
+ return 0;
+}
+*/
+
+INT_PTR Meta_FileSend(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+ DWORD default_contact_number;
+
+ if((default_contact_number = DBGetContactSettingDword(ccs->hContact,META_PROTO,"Default",(DWORD)-1)) == (DWORD)-1)
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ //PUShowMessage("meta has no default", SM_NOTIFY);
+ return 0;
+ }
+ else
+ {
+ HANDLE most_online;
+ //DBEVENTINFO dbei;
+ //char szServiceName[100];
+
+ most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_1, PF1_FILESEND);
+
+ if(!most_online) {
+ //PUShowMessage("no most online for ft", SM_NOTIFY);
+ return 0;
+ }
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+ //Meta_CopyContactNick(ccs->hContact, most_online, proto);
+
+ if(proto) {
+ //ccs->hContact = most_online;
+ //Meta_SetNick(proto);
+
+ // don't check for existence of service - 'accounts' based protos don't have them!
+ //_snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PSS_FILE);
+ //if (ServiceExists(szServiceName)) {
+ // PUShowMessage("sending to subcontact", SM_NOTIFY);
+ return (int)(CallContactService(most_online, PSS_FILE, ccs->wParam, ccs->lParam));
+ //} else
+ // PUShowMessage("no service", SM_NOTIFY);
+ } //else
+ //PUShowMessage("no proto for subcontact", SM_NOTIFY);
+ }
+ return 0; // fail
+}
+
+INT_PTR Meta_GetAwayMsg(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+ DWORD default_contact_number;
+
+ if((default_contact_number = DBGetContactSettingDword(ccs->hContact,META_PROTO,"Default",(DWORD)-1)) == (DWORD)-1)
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 0;
+ }
+ else
+ {
+ HANDLE most_online;
+
+ most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_1, PF1_MODEMSGRECV);
+
+ if(!most_online)
+ return 0;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+ if(!proto) return 0;
+
+ //Meta_CopyContactNick(ccs->hContact, most_online, proto);
+
+ ccs->hContact = most_online;
+ //Meta_SetNick(proto);
+
+ return (int)(CallContactService(ccs->hContact, PSS_GETAWAYMSG, ccs->wParam, ccs->lParam));
+ }
+ return 0; // fail
+}
+
+INT_PTR Meta_GetAvatarInfo(WPARAM wParam, LPARAM lParam) {
+ PROTO_AVATAR_INFORMATION *AI = (PROTO_AVATAR_INFORMATION *) lParam;
+ char *proto = 0;
+ DWORD default_contact_number;
+
+ if((default_contact_number = DBGetContactSettingDword(AI->hContact,META_PROTO,"Default",(DWORD)-1)) == (DWORD)-1)
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 0;
+ }
+ else
+ {
+ HANDLE hSub, hMeta;
+ char szServiceName[100];
+ int result;
+
+ hMeta = AI->hContact;
+ hSub = Meta_GetMostOnlineSupporting(AI->hContact, PFLAGNUM_4, PF4_AVATARS);
+
+ if(!hSub)
+ return GAIR_NOAVATAR;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hSub, 0);
+ if(!proto) return GAIR_NOAVATAR;
+
+ AI->hContact = hSub;
+
+ mir_snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PS_GETAVATARINFO);
+ result = CallService(szServiceName, wParam, lParam);
+ AI->hContact = hMeta;
+ if (result != CALLSERVICE_NOTFOUND) return result;
+ }
+ return GAIR_NOAVATAR; // fail
+}
+
+INT_PTR Meta_GetInfo(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ char *proto = 0;
+ DWORD default_contact_number;
+
+ if((default_contact_number = DBGetContactSettingDword(ccs->hContact,META_PROTO,"Default",(DWORD)-1)) == (DWORD)-1)
+ {
+ // This is a simple contact
+ // (this should normally not happen, since linked contacts do not appear on the list.)
+ return 0;
+ }
+ else
+ {
+ HANDLE most_online;
+ PROTO_AVATAR_INFORMATION AI;
+ char szServiceName[100];
+
+ most_online = Meta_GetMostOnlineSupporting(ccs->hContact, PFLAGNUM_4, PF4_AVATARS);
+
+ if(!most_online)
+ return 0;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+ if(!proto) return 0;
+
+ AI.cbSize = sizeof(AI);
+ AI.hContact = ccs->hContact;
+ AI.format = PA_FORMAT_UNKNOWN;
+ strcpy(AI.filename, "X");
+ if((int)CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&AI) == GAIR_SUCCESS)
+ DBWriteContactSettingString(ccs->hContact, "ContactPhoto", "File",AI.filename);
+
+ most_online = Meta_GetMostOnline(ccs->hContact);
+ Meta_CopyContactNick(ccs->hContact, most_online);
+
+ if(!most_online)
+ return 0;
+
+ //Meta_CopyContactNick(ccs->hContact, most_online, proto);
+
+ ccs->hContact = most_online;
+ //Meta_SetNick(proto);
+
+ _snprintf(szServiceName, sizeof(szServiceName), "%s%s", proto, PSS_GETINFO);
+ if (ServiceExists(szServiceName)) {
+ strncpy(szServiceName, PSS_GETINFO, sizeof(szServiceName));
+ return (int)(CallContactService(ccs->hContact, szServiceName, ccs->wParam, ccs->lParam));
+ }
+ }
+ return 0; // fail
+}
+
+int Meta_OptInit(WPARAM wParam, LPARAM lParam) {
+ OPTIONSDIALOGPAGE odp;
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = -790000000;
+ odp.hInstance = hInstance;
+ odp.flags = ODPF_BOLDGROUPS;
+
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS);
+ odp.pszTitle = "MetaContacts";
+ odp.pszGroup = "Contact List";
+ odp.pszTab = "General";
+ odp.pfnDlgProc = DlgProcOpts;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_PRIORITIES);
+ odp.pszTitle = "MetaContacts";
+ odp.pszGroup = "Contact List";
+ odp.pszTab = "Priorities";
+ odp.pfnDlgProc = DlgProcOptsPriorities;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_HISTORY);
+ odp.pszTitle = "MetaContacts";
+ odp.pszGroup = "Contact List";
+ odp.pszTab = "History";
+ odp.pfnDlgProc = DlgProcOpts;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+ return 0;
+}
+
+int Meta_CallMostOnline(WPARAM wParam, LPARAM lParam) {
+ HANDLE most_online_im = Meta_GetMostOnline((HANDLE)wParam);
+
+ // fix nick
+ Meta_CopyContactNick((HANDLE)wParam, most_online_im);
+
+ // fix status
+ Meta_FixStatus((HANDLE)wParam);
+
+ // copy all other data
+ Meta_CopyData((HANDLE) wParam);
+
+ return 0;
+}
+
+
+INT_PTR Meta_OnOff(WPARAM wParam, LPARAM lParam) {
+ CLISTMENUITEM menu;
+ menu.cbSize = sizeof(CLISTMENUITEM);
+ // just write to db - the rest is handled in the Meta_SettingChanged function
+ if(DBGetContactSettingByte(0, META_PROTO, "Enabled", 1)) {
+ DBWriteContactSettingByte(0, META_PROTO, "Enabled", 0);
+ // modify main menu item
+ menu.flags = CMIM_NAME | CMIM_ICON;
+ menu.hIcon = LoadIconEx(I_MENU);
+ menu.pszName = "Toggle MetaContacts On";
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuOnOff, (LPARAM)&menu);
+ } else {
+ DBWriteContactSettingByte(0, META_PROTO, "Enabled", 1);
+ // modify main menu item
+ menu.flags = CMIM_NAME | CMIM_ICON;
+ menu.hIcon = LoadIconEx(I_MENUOFF);
+ menu.pszName = "Toggle MetaContacts Off";
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuOnOff, (LPARAM)&menu);
+ }
+ ReleaseIconEx(menu.hIcon);
+
+ return 0;
+}
+
+
+int Meta_PreShutdown(WPARAM wParam, LPARAM lParam) {
+ //MessageBox(0, "Preshutdown called", "MC", MB_OK);
+ Meta_SetStatus((WPARAM)ID_STATUS_OFFLINE, 0);
+ Meta_UnhideLinkedContacts();
+ Meta_SuppressStatus(FALSE);
+ //MessageBox(0, "Status is OFFLINE", "MC", MB_OK);
+ //MessageBox(0, "Preshutdown complete", "MC", MB_OK);
+
+ if(setStatusTimerId) KillTimer(0, setStatusTimerId);
+
+ return 0;
+}
+
+int Meta_OkToExit(WPARAM wParam, LPARAM lParam) {
+ Meta_SetStatus((WPARAM)ID_STATUS_OFFLINE, 0);
+ return 0;
+}
+
+int Meta_OnIdleChanged(WPARAM wParam, LPARAM lParam) {
+ return 0;
+}
+
+/** Initializes all services provided by the plugin
+*
+* Creates every function and hooks the event desired.
+*/
+void Meta_InitServices()
+{
+ int i;
+
+ previousMode = mcStatus = ID_STATUS_OFFLINE;
+
+ // set hooks pointers and services pointers to zero - in case we do not initialize them all correctly
+ for(i=0;i<NB_HOOKS;i++)
+ hHooks[i] = 0;
+ for(i=0;i<NB_SERVICES;i++)
+ hServices[i] = 0;
+
+ hServices[0] = CreateServiceFunction("MetaContacts/Convert",Meta_Convert);
+ hServices[1] = CreateServiceFunction("MetaContacts/AddTo",Meta_AddTo);
+ hServices[2] = CreateServiceFunction("MetaContacts/Edit",Meta_Edit);
+ hServices[3] = CreateServiceFunction("MetaContacts/Delete",Meta_Delete);
+ hServices[4] = CreateServiceFunction("MetaContacts/Default",Meta_Default);
+ hServices[5] = CreateServiceFunction("MetaContacts/ForceDefault",Meta_ForceDefault);
+
+ // hidden contact menu items...ho hum
+ hServices[6 + 0] = CreateServiceFunction("MetaContacts/MenuFunc0",MenuFunc0);
+ hServices[6 + 1] = CreateServiceFunction("MetaContacts/MenuFunc1",MenuFunc1);
+ hServices[6 + 2] = CreateServiceFunction("MetaContacts/MenuFunc2",MenuFunc2);
+ hServices[6 + 3] = CreateServiceFunction("MetaContacts/MenuFunc3",MenuFunc3);
+ hServices[6 + 4] = CreateServiceFunction("MetaContacts/MenuFunc4",MenuFunc4);
+ hServices[6 + 5] = CreateServiceFunction("MetaContacts/MenuFunc5",MenuFunc5);
+ hServices[6 + 6] = CreateServiceFunction("MetaContacts/MenuFunc6",MenuFunc6);
+ hServices[6 + 7] = CreateServiceFunction("MetaContacts/MenuFunc7",MenuFunc7);
+ hServices[6 + 8] = CreateServiceFunction("MetaContacts/MenuFunc8",MenuFunc8);
+ hServices[6 + 9] = CreateServiceFunction("MetaContacts/MenuFunc9",MenuFunc9);
+ hServices[6 + 10] = CreateServiceFunction("MetaContacts/MenuFunc10",MenuFunc10);
+ hServices[6 + 11] = CreateServiceFunction("MetaContacts/MenuFunc11",MenuFunc11);
+ hServices[6 + 12] = CreateServiceFunction("MetaContacts/MenuFunc12",MenuFunc12);
+ hServices[6 + 13] = CreateServiceFunction("MetaContacts/MenuFunc13",MenuFunc13);
+ hServices[6 + 14] = CreateServiceFunction("MetaContacts/MenuFunc14",MenuFunc14);
+ hServices[6 + 15] = CreateServiceFunction("MetaContacts/MenuFunc15",MenuFunc15);
+ hServices[6 + 16] = CreateServiceFunction("MetaContacts/MenuFunc16",MenuFunc16);
+ hServices[6 + 17] = CreateServiceFunction("MetaContacts/MenuFunc17",MenuFunc17);
+ hServices[6 + 18] = CreateServiceFunction("MetaContacts/MenuFunc18",MenuFunc18);
+ hServices[6 + 19] = CreateServiceFunction("MetaContacts/MenuFunc19",MenuFunc19);
+
+ hServices[26] = CreateProtoServiceFunction(META_PROTO,PS_GETCAPS,Meta_GetCaps);
+ hServices[27] = CreateProtoServiceFunction(META_PROTO,PS_GETNAME,Meta_GetName);
+ hServices[28] = CreateProtoServiceFunction(META_PROTO,PS_LOADICON,Meta_LoadIcon);
+
+ hServices[29] = CreateProtoServiceFunction(META_PROTO,PS_SETSTATUS,Meta_SetStatus);
+
+ hServices[30] = CreateProtoServiceFunction(META_PROTO,PS_GETSTATUS,Meta_GetStatus);
+ hServices[31] = CreateProtoServiceFunction(META_PROTO,PSS_MESSAGE,Meta_SendMessage);
+ hServices[32] = CreateProtoServiceFunction(META_PROTO,PSS_MESSAGE"W",Meta_SendMessage); // unicode send (same send func as above line, checks for PREF_UNICODE)
+
+ hServices[33] = CreateProtoServiceFunction(META_PROTO,PSS_USERISTYPING,Meta_UserIsTyping );
+
+ hServices[34] = CreateProtoServiceFunction(META_PROTO,PSR_MESSAGE,Meta_RecvMessage);
+
+ // file recv is done by subcontacts
+ //hServices[] = CreateProtoServiceFunction(META_PROTO,PS_FILERESUME,Meta_FileResume);
+ //hServices[] = CreateProtoServiceFunction(META_PROTO,PSS_FILEALLOW,Meta_FileAllow);
+ //hServices[] = CreateProtoServiceFunction(META_PROTO,PSS_FILEDENY,Meta_FileDeny);
+ //hServices[] = CreateProtoServiceFunction(META_PROTO,PSS_FILECANCEL,Meta_FileCancel);
+ //hServices[] = CreateProtoServiceFunction(META_PROTO,PSR_FILE,Meta_FileRecv);
+ hServices[35] = CreateProtoServiceFunction(META_PROTO,PSS_FILE,Meta_FileSend);
+
+ hServices[36] = CreateProtoServiceFunction(META_PROTO,PSS_GETAWAYMSG,Meta_GetAwayMsg);
+
+ hServices[37] = CreateProtoServiceFunction(META_PROTO,PS_GETAVATARINFO,Meta_GetAvatarInfo);
+
+ hServices[38] = CreateProtoServiceFunction(META_PROTO,PSS_GETINFO,Meta_GetInfo);
+
+ hServices[39] = CreateProtoServiceFunction(META_FILTER,PSR_MESSAGE,MetaFilter_RecvMessage);
+ hServices[40] = CreateProtoServiceFunction(META_FILTER,PSS_MESSAGE,MetaFilter_SendMessage);
+ hServices[41] = CreateProtoServiceFunction(META_FILTER,PSS_MESSAGE"W",MetaFilter_SendMessage);
+
+ // API services and events
+
+ hServices[42] = CreateServiceFunction(MS_MC_GETMETACONTACT, MetaAPI_GetMeta);
+ hServices[43] = CreateServiceFunction(MS_MC_GETDEFAULTCONTACT, MetaAPI_GetDefault);
+ hServices[44] = CreateServiceFunction(MS_MC_GETDEFAULTCONTACTNUM, MetaAPI_GetDefaultNum);
+ hServices[45] = CreateServiceFunction(MS_MC_GETMOSTONLINECONTACT, MetaAPI_GetMostOnline);
+ hServices[46] = CreateServiceFunction(MS_MC_GETNUMCONTACTS, MetaAPI_GetNumContacts);
+ hServices[47] = CreateServiceFunction(MS_MC_GETSUBCONTACT, MetaAPI_GetContact);
+ hServices[48] = CreateServiceFunction(MS_MC_SETDEFAULTCONTACTNUM, MetaAPI_SetDefaultContactNum);
+ hServices[49] = CreateServiceFunction(MS_MC_SETDEFAULTCONTACT, MetaAPI_SetDefaultContact);
+ hServices[50] = CreateServiceFunction(MS_MC_FORCESENDCONTACTNUM, MetaAPI_ForceSendContactNum);
+ hServices[51] = CreateServiceFunction(MS_MC_FORCESENDCONTACT, MetaAPI_ForceSendContact);
+ hServices[52] = CreateServiceFunction(MS_MC_UNFORCESENDCONTACT, MetaAPI_UnforceSendContact);
+ hServices[53] = CreateServiceFunction(MS_MC_GETPROTOCOLNAME, MetaAPI_GetProtoName);
+ hServices[54] = CreateServiceFunction(MS_MC_GETFORCESTATE, MetaAPI_GetForceState);
+
+ hServices[55] = CreateServiceFunction(MS_MC_CONVERTTOMETA, MetaAPI_ConvertToMeta);
+ hServices[56] = CreateServiceFunction(MS_MC_ADDTOMETA, MetaAPI_AddToMeta);
+ hServices[57] = CreateServiceFunction(MS_MC_REMOVEFROMMETA, MetaAPI_RemoveFromMeta);
+
+ hServices[58] = CreateServiceFunction(MS_MC_DISABLEHIDDENGROUP, MetaAPI_DisableHiddenGroup);
+
+ hServices[59] = CreateServiceFunction("MetaContacts/OnOff", Meta_OnOff);
+ hServices[60] = CreateServiceFunction("MetaContacts/CListMessageEvent", Meta_ClistMessageEventClicked);
+
+ hServices[61] = CreateProtoServiceFunction(META_PROTO, "/SendNudge", Meta_SendNudge);
+
+ // create our hookable events
+ hEventDefaultChanged = CreateHookableEvent(ME_MC_DEFAULTTCHANGED);
+ hEventForceSend = CreateHookableEvent(ME_MC_FORCESEND);
+ hEventUnforceSend = CreateHookableEvent(ME_MC_UNFORCESEND);
+ hSubcontactsChanged = CreateHookableEvent(ME_MC_SUBCONTACTSCHANGED);
+
+ // hook other module events we need
+ hHooks[0] = (HANDLE)HookEvent(ME_PROTO_ACK, Meta_HandleACK);
+ hHooks[1] = (HANDLE)HookEvent(ME_DB_CONTACT_SETTINGCHANGED, Meta_SettingChanged);
+ hHooks[2] = (HANDLE)HookEvent(ME_SYSTEM_MODULESLOADED, Meta_ModulesLoaded);
+ hHooks[3] = (HANDLE)HookEvent(ME_PROTO_CONTACTISTYPING, Meta_ContactIsTyping);
+ hHooks[4] = (HANDLE)HookEvent(ME_DB_CONTACT_DELETED, Meta_ContactDeleted);
+ hHooks[5] = (HANDLE)HookEvent(ME_OPT_INITIALISE, Meta_OptInit );
+
+ hHooks[6] = (HANDLE)HookEvent(ME_SYSTEM_PRESHUTDOWN, Meta_PreShutdown);
+ hHooks[7] = (HANDLE)HookEvent(ME_SYSTEM_OKTOEXIT, Meta_OkToExit);
+
+ // hook our own events, used to call Meta_GetMostOnline which sets nick for metacontact
+ hHooks[8] = (HANDLE)HookEvent(ME_MC_DEFAULTTCHANGED, Meta_CallMostOnline );
+ hHooks[9] = (HANDLE)HookEvent(ME_MC_FORCESEND, Meta_CallMostOnline );
+ hHooks[10] = (HANDLE)HookEvent(ME_MC_UNFORCESEND, Meta_CallMostOnline );
+
+ /// more hooks in modules loaded event handler - for services that are not created
+
+ //hHooks[] = (HANDLE)HookEvent(ME_IDLE_CHANGED, Meta_OnIdleChanged); // what can we do with idle?
+
+ // redirect nudge events
+ hEventNudge = CreateHookableEvent(META_PROTO "/Nudge");
+}
+
+//! Unregister all hooks and services from Miranda
+void Meta_CloseHandles()
+{
+ int i;
+
+ for(i=0;i<iNudgeProtos;i++) // Idem for the hooks.
+ {
+ UnhookEvent(hNudgeEvents[i]);
+ }
+ free(hNudgeEvents);
+ iNudgeProtos = 0;
+
+ for(i=0;i<NB_HOOKS;i++) // Idem for the hooks.
+ if(hHooks[i]) UnhookEvent(hHooks[i]);
+
+ if(ServiceExists(MS_CLIST_EXTRA_ADD_ICON)) {
+ proto_count = 0;
+ }
+
+ // destroy our hookable events
+ DestroyHookableEvent(hEventDefaultChanged);
+ DestroyHookableEvent(hEventForceSend);
+ DestroyHookableEvent(hEventUnforceSend);
+ DestroyHookableEvent(hSubcontactsChanged);
+ DestroyHookableEvent(hEventNudge);
+
+ // lets leave them, hey? (why?)
+ for(i=0;i<NB_SERVICES;i++) // Scan each 'HANDLE' and Destroy the service attached to it.
+ if(hServices[i]) DestroyServiceFunction(hServices[i]);
+
+ DeinitIcons();
+}
diff --git a/plugins/MetaContacts/meta_set_as_default.ico b/plugins/MetaContacts/meta_set_as_default.ico Binary files differnew file mode 100644 index 0000000000..1792f9b23c --- /dev/null +++ b/plugins/MetaContacts/meta_set_as_default.ico diff --git a/plugins/MetaContacts/meta_utils.c b/plugins/MetaContacts/meta_utils.c new file mode 100644 index 0000000000..38a9e69f6c --- /dev/null +++ b/plugins/MetaContacts/meta_utils.c @@ -0,0 +1,1717 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file meta_utils.c
+*
+* Diverses functions useful in different places.
+*/
+
+#include "metacontacts.h"
+
+HANDLE invisiGroup;
+POINT menuMousePoint;
+
+INT_PTR MyDBWriteContactSetting(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) {
+ DBCONTACTWRITESETTING dcws;
+ dcws.szModule = szModule;
+ dcws.szSetting = szSetting;
+ dcws.value = *dbv;
+ return CallService(MS_DB_CONTACT_WRITESETTING, (WPARAM)hContact, (LPARAM)&dcws);
+}
+
+INT_PTR MyDBGetContactSetting(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) {
+ static BOOL strsvc, strsvcset = FALSE;
+ memset(dbv, 0, sizeof(DBVARIANT));
+
+ if(!strsvcset) {strsvc = ServiceExists(MS_DB_CONTACT_GETSETTING_STR); strsvcset = TRUE;}
+
+ // preserve unicode strings - this service should return other data types unchanged
+ if(strsvc) return DBGetContactSettingW(hContact, szModule, szSetting, dbv);
+
+ return DBGetContactSetting(hContact, szModule, szSetting, dbv);
+}
+
+int Meta_EqualDBV(DBVARIANT *dbv, DBVARIANT *id) {
+ DWORD res = 1;
+ int i;
+ if(dbv->type == id->type)
+ { // If the id parameter and the value returned by the DBGetContactSetting
+ // are the same, this is the correct HANDLE, return it.
+ switch(dbv->type)
+ {
+ case DBVT_DELETED:
+ return 1;
+ case DBVT_BYTE:
+ if(dbv->bVal == id->bVal)
+ return 1;
+ case DBVT_WORD:
+ if(dbv->wVal == id->wVal)
+ return 1;
+ case DBVT_DWORD:
+ if(dbv->dVal == id->dVal)
+ return 1;
+ break;
+ case DBVT_ASCIIZ:
+ case DBVT_UTF8:
+ if(!strcmp(dbv->pszVal,id->pszVal))
+ return 1;
+ case DBVT_WCHAR:
+ if(!wcscmp(dbv->pwszVal,id->pwszVal))
+ return 1;
+ case DBVT_BLOB:
+ if(dbv->cpbVal == id->cpbVal)
+ {
+ for(i=dbv->cpbVal;res && i<=0;i--)
+ res = (dbv->pbVal[i] == id->pbVal[i]);
+ if(res)
+ {
+ return 1;
+ }
+ }
+ break;
+ } // end switch
+ } // end if(dbv.type == id.type)
+
+ return 0;
+}
+
+/** Retrieve a \c HANDLE from a protocol and an identifier
+*
+* @param protocol : Name of the protocol
+* @param id : Unique field identifiying the contact searched
+*
+* @return a \c HANDLE to the specified contact or \c NULL
+ if no contact has been found.
+*/
+HANDLE Meta_GetHandle(const char *protocol, DBVARIANT *id)
+{
+ char *field;
+ DBVARIANT dbv;
+ HANDLE hUser;
+ DWORD i,res = 1;
+ // Get the field identifying the contact in the database.
+ char str[MAXMODULELABELLENGTH];
+ strcpy(str,protocol);
+ strcat(str,PS_GETCAPS);
+ if(!ServiceExists(str))
+ return NULL;
+
+ field = (char *)CallProtoService(protocol,PS_GETCAPS,PFLAG_UNIQUEIDSETTING,0);
+ hUser = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hUser)
+ { // Scan the database and retrieve the field for each contact
+ if(!DBGetContactSetting(hUser,protocol,field,&dbv))
+ {
+ if(dbv.type == id->type)
+ { // If the id parameter and the value returned by the DBGetContactSetting
+ // are the same, this is the correct HANDLE, return it.
+ switch(dbv.type)
+ {
+ case DBVT_DELETED:
+ break;
+ case DBVT_BYTE:
+ if(dbv.bVal == id->bVal)
+ return hUser;
+ break;
+ case DBVT_WORD:
+ if(dbv.wVal == id->wVal)
+ return hUser;
+ break;
+ case DBVT_DWORD:
+ if(dbv.dVal == id->dVal)
+ return hUser;
+ break;
+ case DBVT_ASCIIZ:
+ case DBVT_UTF8:
+ if(!strcmp(dbv.pszVal,id->pszVal))
+ {
+ DBFreeVariant(&dbv);
+ return hUser;
+ }
+ else
+ {
+ DBFreeVariant(&dbv);
+ break;
+ }
+ case DBVT_WCHAR:
+ if(!wcscmp(dbv.pwszVal,id->pwszVal))
+ {
+ DBFreeVariant(&dbv);
+ return hUser;
+ }
+ else
+ {
+ DBFreeVariant(&dbv);
+ break;
+ }
+ case DBVT_BLOB:
+ if(dbv.cpbVal == id->cpbVal)
+ {
+ for(i=dbv.cpbVal;res && i<=0;i--)
+ res = (dbv.pbVal[i] == id->pbVal[i]);
+ if(res)
+ {
+ DBFreeVariant(&dbv);
+ return hUser;
+ }
+ }
+ DBFreeVariant(&dbv);
+ break;
+ } // end switch
+ } else
+ DBFreeVariant(&dbv);
+ } // end if(!DBGetContactSetting(hUser,protocol,field,&dbv))
+ // This contact wasn't the good one, go to the next.
+ hUser = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hUser,0);
+ } // end while
+ return NULL;
+}
+
+/** Update the MetaContact login, depending on the protocol desired
+*
+* The login of the "MetaContacts" protocol will be copied from the login
+* of the specified protocol.
+*
+* @param proto : The name of the protocol used to get the login that will be
+* affected to the "MetaContacts" protocol.
+*
+* @return O on success, 1 otherwise.
+*/
+int Meta_SetNick(char *proto)
+{
+ CONTACTINFO ci;
+ ci.cbSize = sizeof(CONTACTINFO);
+ ci.dwFlag = CNF_DISPLAY;
+ ci.hContact = NULL;
+ ci.szProto = proto;
+ if(CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci))
+ return 1;
+ switch(ci.type)
+ {
+ case CNFT_BYTE:
+ if(DBWriteContactSettingByte(NULL,META_PROTO,"Nick",ci.bVal))
+ return 1;
+ break;
+ case CNFT_WORD:
+ if(DBWriteContactSettingWord(NULL,META_PROTO,"Nick",ci.wVal))
+ return 1;
+ break;
+ case CNFT_DWORD:
+ if(DBWriteContactSettingDword(NULL,META_PROTO,"Nick",ci.dVal))
+ return 1;
+ break;
+ case CNFT_ASCIIZ:
+ if(DBWriteContactSettingString(NULL,META_PROTO,"Nick",ci.pszVal))
+ return 1;
+ mir_free(ci.pszVal);
+ break;
+ default:
+ if(DBWriteContactSettingString(NULL,META_PROTO,"Nick",(char *)Translate("Sender")))
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+/** Assign a contact (src) to a metacontact (dest)
+*
+* @param src \c HANDLE to a contact that should be assigned
+* @param dest \c HANDLE to a metacontact that will host the contact
+* @param set_as_default \c bool flag to indicate whether the new contact becomes the default
+*
+* @return TRUE on success, FALSE otherwise
+*/
+BOOL Meta_Assign(HANDLE src, HANDLE dest, BOOL set_as_default)
+{
+ DBCONTACTWRITESETTING cws;
+ DWORD metaID;
+ char *proto,
+ *field;
+ DWORD num_contacts;
+ char buffer[512], buffer2[512];
+ WORD status;
+ HANDLE most_online;
+
+ if((metaID=DBGetContactSettingDword(dest,META_PROTO,META_ID,(DWORD)-1))==-1) {
+ MessageBox(0, Translate("Could not get MetaContact id"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+ if((num_contacts=DBGetContactSettingDword(dest,META_PROTO,"NumContacts",(DWORD)-1))==-1) {
+ MessageBox(0, Translate("Could not retreive MetaContact contact count"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+ if(!(proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)src,0))) {
+ MessageBox(0, Translate("Could not retreive contact protocol"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // Get the login of the subcontact
+ field = (char *)CallProtoService(proto,PS_GETCAPS,PFLAG_UNIQUEIDSETTING,0);
+ if(DBGetContactSetting(src,proto,field,&cws.value)) {
+ MessageBox(0, Translate("Could not get unique id of contact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // Check that is is 'on the list'
+ if(DBGetContactSettingByte(src, "CList", "NotOnList", 0) == 1) {
+ MessageBox(0, Translate("Contact is 'Not on List' - please add the contact to your contact list before assigning."), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ DBFreeVariant(&cws.value);
+ return FALSE;
+ }
+
+ num_contacts++;
+ if(num_contacts >= MAX_CONTACTS) {
+ MessageBox(0, Translate("MetaContact is full"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ DBFreeVariant(&cws.value);
+ return FALSE;
+ }
+
+ // write the contact's protocol
+ strcpy(buffer, "Protocol");
+ strcat(buffer, _itoa((int)(num_contacts -1), buffer2, 10));
+
+ if(DBWriteContactSettingString(dest, META_PROTO, buffer, proto)) {
+ MessageBox(0, Translate("Could not write contact protocol to MetaContact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ DBFreeVariant(&cws.value);
+ return FALSE;
+ }
+
+ // write the login
+ strcpy(buffer, "Login");
+ strcat(buffer, _itoa((int)(num_contacts - 1), buffer2, 10));
+
+ cws.szModule=META_PROTO;
+ cws.szSetting=buffer;
+
+ if(CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)dest,(LPARAM)&cws)) {
+ MessageBox(0, Translate("Could not write unique id of contact to MetaContact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ DBFreeVariant(&cws.value);
+ return FALSE;
+ }
+
+ DBFreeVariant(&cws.value);
+
+ // If we can get the nickname of the subcontact...
+ if(!DBGetContactSetting(src,proto,"Nick",&cws.value)) {
+ // write the nickname
+ strcpy(buffer, "Nick");
+ strcat(buffer, _itoa((int)(num_contacts - 1), buffer2, 10));
+
+ cws.szModule=META_PROTO;
+ cws.szSetting=buffer;
+
+ if(CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)dest,(LPARAM)&cws)) {
+ MessageBox(0, Translate("Could not write nickname of contact to MetaContact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ DBFreeVariant(&cws.value);
+ }
+
+ {
+ // Get the displayname of the subcontact
+ char *name = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)src, 0);
+ wchar_t *wname = (wchar_t *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)src, GCDNF_UNICODE);
+
+ // write the display name
+ strcpy(buffer, "CListName");
+ strcat(buffer, _itoa((int)(num_contacts - 1), buffer2, 10));
+
+ if(wname && strncmp(name, (char *)wname, strlen(name)) != 0) {
+ DBWriteContactSettingWString(dest, META_PROTO, buffer, wname);
+ } else
+ DBWriteContactSettingString(dest, META_PROTO, buffer, name);
+
+ // Get the status
+ if(!proto)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = DBGetContactSettingWord(src, proto, "Status", ID_STATUS_OFFLINE);
+ }
+
+ // write the status
+ strcpy(buffer, "Status");
+ strcat(buffer, _itoa((int)(num_contacts - 1), buffer2, 10));
+ if(DBWriteContactSettingWord(dest, META_PROTO, buffer, status)) {
+ MessageBox(0, Translate("Could not write contact status to MetaContact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // write the handle
+ strcpy(buffer, "Handle");
+ strcat(buffer, _itoa((int)(num_contacts - 1), buffer2, 10));
+ if(DBWriteContactSettingDword(dest, META_PROTO, buffer, (DWORD)src)) {
+ MessageBox(0, Translate("Could not write contact handle to MetaContact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // write status string
+ strcpy(buffer, "StatusString");
+ strcat(buffer, _itoa((int)(num_contacts - 1), buffer2, 10));
+ Meta_GetStatusString(status, buffer2, 512);
+ if(DBWriteContactSettingString(dest, META_PROTO, buffer, buffer2)) {
+ MessageBox(0, Translate("Could not write contact status string to MetaContact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // Add the MetaContactFilter module to the old contact to intercept messages and forward to the new
+ // metacontact
+ if( !CallService( MS_PROTO_ISPROTOONCONTACT, (WPARAM)src, ( LPARAM )META_FILTER ))
+ CallService( MS_PROTO_ADDTOCONTACT, (WPARAM)src, ( LPARAM )META_FILTER );
+
+ // Write the link in the contact
+ if(DBWriteContactSettingDword(src,META_PROTO,META_LINK,metaID)) {
+ MessageBox(0, Translate("Could not write MetaContact id to contact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // Write the contact number in the contact
+ if(DBWriteContactSettingDword(src,META_PROTO,"ContactNumber",(DWORD)(num_contacts - 1))) {
+ MessageBox(0, Translate("Could not write MetaContact contact number to contact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // Write the handle in the contact
+ if(DBWriteContactSettingDword(src,META_PROTO,"Handle",(DWORD)dest)) {
+ MessageBox(0, Translate("Could not write MetaContact contact number to contact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ // update count of contacts
+ if(DBWriteContactSettingDword(dest,META_PROTO,"NumContacts",num_contacts)) {
+ MessageBox(0, Translate("Could not write contact count to MetaContact"), Translate("Assignment Error"), MB_OK | MB_ICONWARNING);
+ return FALSE;
+ }
+
+ if(set_as_default) {
+ DBWriteContactSettingDword(dest, META_PROTO, "Default", (WORD)(num_contacts - 1));
+ NotifyEventHooks(hEventDefaultChanged, (WPARAM)dest, (LPARAM)src);
+ }
+
+ DBWriteContactSettingByte(src, META_PROTO, "IsSubcontact", 1);
+ // set nick to most online contact that can message
+ most_online = Meta_GetMostOnline(dest);
+ Meta_CopyContactNick(dest, most_online);
+
+ // set status to that of most online contact
+ Meta_FixStatus(dest);
+
+ // if the new contact is the most online contact with avatar support, get avatar info
+ most_online = Meta_GetMostOnlineSupporting(dest, PFLAGNUM_4, PF4_AVATARS);
+ if(most_online == src) {
+ PROTO_AVATAR_INFORMATION AI;
+
+ AI.cbSize = sizeof(AI);
+ AI.hContact = dest;
+ AI.format = PA_FORMAT_UNKNOWN;
+ strcpy(AI.filename, "X");
+
+ if((int)CallProtoService(META_PROTO, PS_GETAVATARINFO, 0, (LPARAM)&AI) == GAIR_SUCCESS)
+ DBWriteContactSettingString(dest, "ContactPhoto", "File",AI.filename);
+ }
+
+ // Hide the contact
+ Meta_SetGroup(src);
+
+ // copy history
+ if(options.copy_subcontact_history)
+ copyHistory(src, dest);
+
+ // Ignore status if the option is on
+ if(options.suppress_status)
+ CallService(MS_IGNORE_IGNORE, (WPARAM)src, (WPARAM)IGNOREEVENT_USERONLINE);
+
+ // copy other data
+ Meta_CopyData(dest);
+
+ NotifyEventHooks(hSubcontactsChanged, (WPARAM)dest, 0);
+ return TRUE;
+}
+
+
+/**
+* Convenience method - get most online contact supporting messaging
+*
+*/
+HANDLE Meta_GetMostOnline(HANDLE hMeta) {
+ return Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_1, PF1_IM);
+}
+/** Get the 'most online' contact for a meta contact (according to above order) which supports the specified
+* protocol service, and copies nick from that contact
+*
+* @param hMeta \c HANDLE to a metacontact
+*
+* @return \c HANDLE to a contact
+*/
+
+HANDLE Meta_GetMostOnlineSupporting(HANDLE hMeta, int pflagnum, unsigned long capability) {
+ int most_online_status = ID_STATUS_OFFLINE;
+ HANDLE most_online_contact = NULL, hContact;
+ int i, status, default_contact_number, num_contacts;
+ unsigned long caps = 0;
+ char *proto, *most_online_proto;
+
+ // you can't get more online than having the default contact ONLINE - so check that first
+ if((default_contact_number = DBGetContactSettingDword(hMeta,META_PROTO,"Default",(DWORD)-1)) == (DWORD)-1)
+ {
+ // This is a simple contact - return NULL to signify error.
+ // (this should normally not happen, since all meta contacts have a default contact)
+ return NULL;
+ }
+
+ // if the default is beyond the end of the list (eek!) return null
+ if(default_contact_number >= (num_contacts = DBGetContactSettingDword(hMeta, META_PROTO, "NumContacts", 0)))
+ return NULL;
+
+ most_online_contact = Meta_GetContactHandle(hMeta, default_contact_number);
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online_contact, 0);
+ caps = proto ? CallProtoService(proto, PS_GETCAPS, (WPARAM)pflagnum, 0) : 0;
+ if(proto && strcmp(proto, "IRC") == 0) caps |= PF1_IM;
+ // we are forced to do use default for sending - '-1' capability indicates no specific capability, but respect 'Force Default'
+ if(proto && DBGetContactSettingByte(hMeta, META_PROTO, "ForceDefault", 0) && capability != 0 && (capability == -1 || (caps & capability) == capability)) // capability is 0 when we're working out status
+ return most_online_contact;
+
+ // a subcontact is being temporarily 'forced' to do sending
+ if((most_online_contact = (HANDLE)DBGetContactSettingDword(hMeta, META_PROTO, "ForceSend", 0))) {
+ caps = proto ? CallProtoService(proto, PS_GETCAPS, (WPARAM)pflagnum, 0) : 0;
+ if(proto && strcmp(proto, "IRC") == 0) caps |= PF1_IM;
+ if(proto && (caps & capability) == capability && capability != 0) // capability is 0 when we're working out status
+ return most_online_contact;
+ }
+
+ most_online_contact = Meta_GetContactHandle(hMeta, default_contact_number);
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online_contact, 0);
+ if(proto && CallProtoService(proto, PS_GETSTATUS, 0, 0) >= ID_STATUS_ONLINE) {
+ caps = proto ? CallProtoService(proto, PS_GETCAPS, (WPARAM)pflagnum, 0) : 0;
+ if(proto && strcmp(proto, "IRC") == 0) caps |= PF1_IM;
+ if(proto && (capability == -1 || (caps & capability) == capability)) {
+ most_online_status = DBGetContactSettingWord(most_online_contact, proto, "Status", ID_STATUS_OFFLINE);
+
+ // if our default is not offline, and option to use default is set - return default
+ // and also if our default is online, return it
+ if(most_online_status == ID_STATUS_ONLINE || (most_online_status != ID_STATUS_OFFLINE && options.always_use_default)) {
+ return most_online_contact;
+ }
+ } else
+ most_online_status = ID_STATUS_OFFLINE;
+ } else
+ most_online_status = ID_STATUS_OFFLINE;
+
+ most_online_proto = proto;
+ // otherwise, check all the subcontacts for the one closest to the ONLINE state which supports the required capability
+ for(i = 0; i < num_contacts; i++) {
+ if(i == default_contact_number) // already checked that (i.e. initial value of most_online_contact and most_online_status are those of the default contact)
+ continue;
+
+ hContact = Meta_GetContactHandle(hMeta, i);
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if(!proto || CallProtoService(proto, PS_GETSTATUS, 0, 0) < ID_STATUS_ONLINE) // proto offline or connecting
+ continue;
+
+ caps = proto ? CallProtoService(proto, PS_GETCAPS, (WPARAM)pflagnum, 0) : 0;
+ if(proto && strcmp(proto, "IRC") == 0) caps |= PF1_IM;
+ if(proto && (capability == -1 || (caps & capability) == capability)) {
+
+ status = DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE);
+
+ if(status == ID_STATUS_ONLINE) {
+ most_online_contact = hContact;
+ most_online_proto = proto;
+ return most_online_contact;
+ } else if(status <= ID_STATUS_OFFLINE) // status below ID_STATUS_OFFLINE is a connecting status
+ continue;
+ else {
+ if(GetRealPriority(proto, status) < GetRealPriority(most_online_proto, most_online_status)) {
+ most_online_status = status;
+ most_online_contact = hContact;
+ most_online_proto = proto;
+ }
+ }
+ }
+ }
+
+ // no online contacts? if we're trying to message, use 'send offline' contact
+ if(most_online_status == ID_STATUS_OFFLINE && capability == PF1_IM) {
+ HANDLE hOffline = Meta_GetContactHandle(hMeta, DBGetContactSettingDword(hMeta, META_PROTO, "OfflineSend", (DWORD)-1));
+ if(hOffline)
+ most_online_contact = hOffline;
+ }
+
+ return most_online_contact;
+}
+
+int Meta_GetContactNumber(HANDLE hContact) {
+ return DBGetContactSettingDword(hContact, META_PROTO, "ContactNumber", -1);
+}
+
+BOOL dbv_same(DBVARIANT *dbv1, DBVARIANT *dbv2) {
+ if(dbv1->type != dbv2->type) return FALSE;
+
+ switch(dbv1->type) {
+ case DBVT_BYTE:
+ return dbv1->bVal == dbv2->bVal;
+ case DBVT_WORD:
+ return dbv1->wVal == dbv2->wVal;
+ case DBVT_DWORD:
+ return dbv1->dVal == dbv2->dVal;
+ case DBVT_ASCIIZ:
+ return !strcmp(dbv1->pszVal, dbv2->pszVal);
+ case DBVT_BLOB:
+ return (dbv1->cpbVal == dbv2->cpbVal && !memcmp(dbv1->pbVal, dbv2->pbVal, dbv1->cpbVal));
+ break;
+ default:
+ return FALSE;
+ }
+}
+
+ void copy_settings_array(HANDLE hMeta, char *module, const char *settings[], int num_settings) {
+ int num_contacts = DBGetContactSettingDword(hMeta, META_PROTO, "NumContacts", (DWORD)-1),
+ default_contact = DBGetContactSettingDword(hMeta, META_PROTO, "Default", (DWORD)-1),
+ most_online = Meta_GetContactNumber(Meta_GetMostOnline(hMeta));
+
+ HANDLE hContact;
+ int i, j;
+ char *used_mod;
+
+ DBVARIANT dbv1, dbv2;
+ BOOL free, got_val, bDataWritten;
+
+ BOOL use_default = FALSE;
+ int source_contact = (use_default ? default_contact : most_online);
+
+ if(source_contact < 0 || source_contact >= num_contacts) return;
+
+ for(i = 0; i < num_settings; i++) {
+ bDataWritten = FALSE;
+ for(j = 0; j < num_contacts && !bDataWritten; j++) {
+ // do source (most online) first
+ if(j == 0)
+ hContact = Meta_GetContactHandle(hMeta, source_contact);
+ else if(j <= source_contact)
+ hContact = Meta_GetContactHandle(hMeta, j - 1);
+ else
+ hContact = Meta_GetContactHandle(hMeta, j);
+
+ if(hContact) {
+ if(!module) {
+ used_mod = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if(!used_mod) continue; // next contact
+ } else
+ used_mod = module;
+
+ if(j == 0 && strcmp(settings[i], "MirVer") == 0) { //Always reset MirVer
+ DBDeleteContactSetting(hMeta, (module ? used_mod : META_PROTO), settings[i]);
+ }
+
+ got_val = !MyDBGetContactSetting(hContact, used_mod, settings[i], &dbv2);
+ if(got_val) {
+ free = !MyDBGetContactSetting(hMeta, (module ? used_mod : META_PROTO), settings[i], &dbv1);
+
+ if(strcmp(settings[i], "MirVer") == 0) {
+ if(DBGetContactSettingWord(hContact, used_mod, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) {
+ if(!free || (dbv1.pszVal == NULL || strcmp(dbv1.pszVal, "") == 0 || strlen(dbv1.pszVal) < 2)) {
+ MyDBWriteContactSetting(hMeta, (module ? used_mod : META_PROTO), settings[i], &dbv2);
+ bDataWritten = TRUE; //only break if found something to copy
+ }
+ }
+
+ } else {
+ if(!free || !dbv_same(&dbv1, &dbv2)) {
+ MyDBWriteContactSetting(hMeta, (module ? used_mod : META_PROTO), settings[i], &dbv2);
+ if(dbv2.type == DBVT_ASCIIZ || dbv2.type == DBVT_UTF8) {
+ if(dbv2.pszVal != NULL && strcmp(dbv2.pszVal, "") != 0)
+ bDataWritten = TRUE; //only break if found something to copy
+ } else if(dbv2.type == DBVT_WCHAR) {
+ if(dbv2.pwszVal != 0 && wcscmp(dbv2.pwszVal, L"") != 0)
+ bDataWritten = TRUE; //only break if found something to copy
+ } else
+ bDataWritten = TRUE; //only break if found something to copy
+ }
+ else
+ bDataWritten = TRUE;
+
+ }
+ DBFreeVariant(&dbv2);
+ if(free)DBFreeVariant(&dbv1);
+ }
+ }
+ }
+ }
+}
+
+const char *ProtoSettings[25] =
+ {"BirthDay", "BirthMonth", "BirthYear", "Age", "Cell", "Cellular", "Homepage", "email", "Email", "e-mail",
+ "FirstName", "MiddleName", "LastName", "Title", "Timezone", "Gender", "MirVer", "ApparentMode", "IdleTS", "LogonTS", "IP", "RealIP",
+ "Auth", "ListeningTo", "Country"};
+const char *UserInfoSettings[71] =
+ {"NickName", "FirstName", "MiddleName", "LastName", "Title", "Timezone", "Gender", "DOBd", "DOBm", "DOBy",
+ "Mye-mail0", "Mye-mail1", "MyPhone0", "MyPhone1", "MyNotes", "PersonalWWW",
+ "HomePhone", "HomeFax", "HomeMobile", "HomeStreet", "HomeCity", "HomeState", "HomeZip", "HomeCountry",
+ "WorkPhone", "WorkFax", "WorkMobile", "WorkStreet", "WorkCity", "WorkState", "WorkZip", "WorkCountry", "Company", "Department", "Position",
+ "Occupation", "Cellular", "Cell", "Phone", "Notes",
+
+ "e-mail", "e-mail0", "e-mail1", "Homepage", "MaritalStatus",
+ "CompanyCellular", "CompanyCity", "CompanyState", "CompanyStreet", "CompanyCountry", "Companye-mail",
+ "CompanyHomepage", "CompanyDepartment", "CompanyOccupation", "CompanyPosition", "CompanyZip",
+
+ "OriginCity", "OriginState", "OriginStreet", "OriginCountry", "OriginZip",
+ "City", "State", "Street", "Country", "Zip",
+
+ "Language1", "Language2", "Language3", "Partner", "Gender"};
+const char *ContactPhotoSettings[5] =
+ {"File","Backup","Format","ImageHash","RFile"};
+const char *MBirthdaySettings[3] =
+ { "BirthDay", "BirthMonth", "BirthYear"};
+
+// special handling for status message
+// copy from first subcontact with any of these values that has the same status as the most online contact
+// proto:
+// clist: "StatusMsg"
+void CopyStatusData(HANDLE hMeta) {
+ int num_contacts = DBGetContactSettingDword(hMeta, META_PROTO, "NumContacts", (DWORD)-1),
+ most_online = Meta_GetContactNumber(Meta_GetMostOnline(hMeta));
+ WORD status = DBGetContactSettingWord(hMeta, META_PROTO, "Status", ID_STATUS_OFFLINE);
+ HANDLE hContact;
+ DBVARIANT dbv;
+ char *proto;
+ BOOL bDoneStatus = FALSE, bDoneXStatus = FALSE;
+ int i;
+
+ for(i = 0; i < num_contacts; i++) {
+ if(i == 0)
+ hContact = Meta_GetContactHandle(hMeta, most_online);
+ else if(i <= most_online)
+ hContact = Meta_GetContactHandle(hMeta, i - 1);
+ else
+ hContact = Meta_GetContactHandle(hMeta, i);
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if(proto && DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE) == status) {
+ if(!bDoneStatus && !MyDBGetContactSetting(hContact, "CList", "StatusMsg", &dbv)) {
+ MyDBWriteContactSetting(hMeta, "CList", "StatusMsg", &dbv);
+ DBFreeVariant(&dbv);
+ bDoneStatus = TRUE;
+ }
+ if((!bDoneXStatus) && (!MyDBGetContactSetting(hContact, proto, "XStatusId", &dbv)) && dbv.type != DBVT_DELETED) {
+ DBWriteContactSettingString(hMeta, META_PROTO, "XStatusProto", proto);
+ MyDBWriteContactSetting(hMeta, META_PROTO, "XStatusId", &dbv);
+
+ DBFreeVariant(&dbv);
+ if(!MyDBGetContactSetting(hContact, proto, "XStatusMsg", &dbv)) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, "XStatusMsg", &dbv);
+ DBFreeVariant(&dbv);
+ }
+ if(!MyDBGetContactSetting(hContact, proto, "XStatusName", &dbv)) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, "XStatusName", &dbv);
+ DBFreeVariant(&dbv);
+ }
+ bDoneXStatus = TRUE;
+ }
+ }
+
+ if(bDoneStatus && bDoneXStatus) break;
+ }
+
+ if(!bDoneStatus) DBDeleteContactSetting(hMeta, "CList", "StatusMsg");
+ if(!bDoneXStatus) {
+ DBDeleteContactSetting(hMeta, META_PROTO, "XStatusId");
+ DBDeleteContactSetting(hMeta, META_PROTO, "XStatusMsg");
+ DBDeleteContactSetting(hMeta, META_PROTO, "XStatusName");
+ }
+}
+
+void Meta_CopyData(HANDLE hMeta) {
+ if(options.copydata) {
+ CopyStatusData(hMeta);
+
+ copy_settings_array(hMeta, 0, ProtoSettings, 25);
+ copy_settings_array(hMeta, "mBirthday", UserInfoSettings, 3);
+ copy_settings_array(hMeta, "ContactPhoto", ContactPhotoSettings, 5);
+
+ if(options.copy_userinfo)
+ copy_settings_array(hMeta, "UserInfo", UserInfoSettings, 71);
+ }
+}
+
+
+HANDLE Meta_GetContactHandle(HANDLE hMeta, int contact_number) {
+ char buffer[512], buffer2[512];
+ int num_contacts = DBGetContactSettingDword(hMeta, META_PROTO, "NumContacts", 0);
+
+ if(contact_number >= num_contacts || contact_number < 0) return 0;
+
+ strcpy(buffer, "Handle");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ return (HANDLE)DBGetContactSettingDword(hMeta, META_PROTO, buffer, 0);
+
+}
+
+int Meta_SetHandles(void) {
+ DWORD meta_id, num_contacts, contact_number;
+ HANDLE hContact2, hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ), hNextContact;
+ char buffer[512], buffer2[512];
+ char nick_buffer[128];
+ BOOL found;
+
+ while ( hContact != NULL ) {
+ if((meta_id = DBGetContactSettingDword(hContact,META_PROTO,META_LINK,(DWORD)-1))!=(DWORD)-1) {
+ // is a subcontact
+
+ // get nick for debug messages
+ strcpy(nick_buffer, "meta_id: ");
+ strcat(nick_buffer, _itoa(meta_id, buffer2, 10));
+
+ contact_number = DBGetContactSettingDword(hContact, META_PROTO, "ContactNumber", (DWORD)-1);
+ strcat(nick_buffer, ", contact num: ");
+ strcat(nick_buffer, _itoa(contact_number, buffer2, 10));
+
+ if(contact_number < 0) {
+ // problem!
+ MessageBox(0, "Subcontact contact number < 0 - deleting MetaContact", nick_buffer, MB_OK | MB_ICONERROR);
+ //CallService(MS_DB_CONTACT_DELETE, (WPARMA)hContact, 0);
+ hNextContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ Meta_Delete((WPARAM)hContact, (LPARAM)1);
+ hContact = hNextContact;
+ continue;
+ //return 1;
+ }
+
+ // ensure the window open flag is not present
+ DBDeleteContactSetting(hContact, META_PROTO, "WindowOpen");
+
+
+ // find metacontact
+ found = FALSE;
+ hContact2 = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+
+ while ( hContact2 != NULL ) {
+ if(DBGetContactSettingDword(hContact2,META_PROTO,META_ID,(DWORD)-1) == meta_id) {
+ found = TRUE;
+
+ // set handle
+ DBWriteContactSettingDword(hContact, META_PROTO, "Handle", (DWORD)hContact2);
+
+ // increment contact counter (cleared in Load function)
+ DBWriteContactSettingByte(hContact2, META_PROTO, "ContactCountCheck",
+ (unsigned char)(DBGetContactSettingByte(hContact2, META_PROTO, "ContactCountCheck", 0) + 1));
+
+ num_contacts = DBGetContactSettingDword(hContact2, META_PROTO, "NumContacts", (DWORD)-1);
+ if(contact_number >= 0 && contact_number < num_contacts) {
+ // set metacontact's handle to us
+ strcpy(buffer, "Handle");
+ strcat(buffer, _itoa((int)contact_number, buffer2, 10));
+ DBWriteContactSettingDword(hContact2, META_PROTO, buffer, (DWORD)hContact);
+ } else {
+ char buff[256];
+ // problem - contact number is greater than meta's number of contacts
+ sprintf(buff, "Subcontact contact number (%d) > meta num contacts (%d) - deleting MetaContact", (int)contact_number, (int)num_contacts);
+ MessageBox(0, buff, nick_buffer, MB_OK | MB_ICONERROR);
+ //CallService(MS_DB_CONTACT_DELETE, (WPARMA)hContact, 0);
+ hNextContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ Meta_Delete((WPARAM)hContact, (LPARAM)1);
+ hContact = hNextContact;
+ continue;
+ //return 1;
+ }
+ }
+
+ hContact2 = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact2, 0 );
+ }
+
+ if(!found) {
+ // problem - subcontact's meta not found
+ MessageBox(0, "Subcontact's MetaContact not found - deleting MetaContact data", nick_buffer, MB_OK | MB_ICONERROR);
+
+ // delete meta data
+ DBDeleteContactSetting(hContact,META_PROTO,"IsSubcontact");
+ DBDeleteContactSetting(hContact,META_PROTO,META_LINK);
+ DBDeleteContactSetting(hContact,META_PROTO,"Handle");
+ DBDeleteContactSetting(hContact,META_PROTO,"ContactNumber");
+ Meta_RestoreGroup(hContact);
+ DBDeleteContactSetting(hContact,META_PROTO,"OldCListGroup");
+
+ CallService(MS_PROTO_REMOVEFROMCONTACT, (WPARAM)hContact, (LPARAM)META_FILTER);
+ // stop ignoring, if we were
+ if(options.suppress_status)
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+
+ } else {
+ if(!DBGetContactSettingByte(hContact, META_PROTO, "IsSubcontact", 0))
+ DBWriteContactSettingByte(hContact, META_PROTO, "IsSubcontact", 1);
+ }
+
+ } else
+ DBDeleteContactSetting(hContact, META_PROTO, "Handle");
+
+ if((meta_id = DBGetContactSettingDword(hContact,META_PROTO,META_ID,(DWORD)-1))!=(DWORD)-1) {
+ // is a metacontact
+
+ // get nick for debug messages
+ strcpy(nick_buffer, "meta_id: ");
+ strcat(nick_buffer, _itoa(meta_id, buffer2, 10));
+
+ // ensure the window open flag is not present
+ DBDeleteContactSetting(hContact, META_PROTO, "WindowOpen");
+
+ // ensure default is reasonable
+ contact_number = DBGetContactSettingDword(hContact, META_PROTO, "Default", -1);
+ num_contacts = DBGetContactSettingDword(hContact, META_PROTO, "NumContacts", (DWORD)-1);
+
+ if(num_contacts < 0) {
+ // problem
+ MessageBox(0, "MetaContact number of contacts < 0 - deleting MetaContact", nick_buffer, MB_OK | MB_ICONERROR);
+ //CallService(MS_DB_CONTACT_DELETE, (WPARMA)hContact, 0);
+ hNextContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ Meta_Delete((WPARAM)hContact, (LPARAM)1);
+ hContact = hNextContact;
+ continue;
+ //return 1;
+ }
+
+ if(contact_number < 0 || contact_number >= num_contacts) {
+ // problem
+ MessageBox(0, "MetaContact default contact number out of range - deleting MetaContact", nick_buffer, MB_OK | MB_ICONERROR);
+ hNextContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ Meta_Delete((WPARAM)hContact, (LPARAM)1);
+ hContact = hNextContact;
+ //CallService(MS_DB_CONTACT_DELETE, (WPARMA)hContact, 0);
+ continue;
+ //return 1;
+ }
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ // loop through one more time - check contact counts match
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL ) {
+ if((meta_id = DBGetContactSettingDword(hContact,META_PROTO,META_ID,(DWORD)-1))!=(DWORD)-1) {
+ // get nick for debug messages
+ strcpy(nick_buffer, Translate("MetaId: "));
+ strcat(nick_buffer, _itoa(meta_id, buffer2, 10));
+
+ num_contacts = DBGetContactSettingByte(hContact, META_PROTO, "ContactCountCheck", -2);
+ if(num_contacts != (DWORD)DBGetContactSettingDword(hContact, META_PROTO, "NumContacts", (DWORD)-1)) {
+ // mismatch
+ //if(MessageBox(0, Translate("MetaContact corrupted - the number of subcontacts is incorrect.\nDelete MetaContact?"), nick_buffer, MB_YESNO | MB_ICONERROR) == IDYES) {
+ // Meta_Delete((WPARAM)hContact, (LPARAM)1); // second param prevents confirm dialog
+ //} else
+ // return 1;
+ hNextContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ MessageBox(0, Translate("MetaContact corrupted - the number of subcontacts is incorrect.\nDeleting MetaContact."), nick_buffer, MB_OK | MB_ICONERROR);
+ Meta_Delete((WPARAM)hContact, (LPARAM)1);
+ hContact = hNextContact;
+ continue;
+ }
+ }
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ return 0;
+}
+
+/** Hide all contacts linked to any meta contact, and set handle links
+*
+* Additionally, set all sub contacts and metacontacts to offline so that status notifications are always sent
+*
+* and ensure metafilter in place
+*/
+int Meta_HideLinkedContacts(void) {
+ DBVARIANT dbv, dbv2;
+ DWORD meta_id, num_contacts, contact_number;
+ WORD status;
+ char buffer[512], buffer2[512];
+ char *proto, *group_name;
+ int hGroup = 1;
+
+ HANDLE hContact2, hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+
+ // ensure the hidden group does not exist (how this occurs i wonder but there have been reports!)
+ // (sometimes protocol server side groups are to blame - msn and icq)
+ if(!meta_group_hack_disabled) do {
+ group_name = (char *)CallService(MS_CLIST_GROUPGETNAME, (WPARAM)hGroup, 0);
+ if(group_name && !strcmp(group_name, META_HIDDEN_GROUP)) {
+ // disabled because it shows a message box
+ //CallService(MS_CLIST_GROUPDELETE, (WPARAM)hGroup, 0);
+ MessageBox(0, Translate("The 'MetaContacts Hidden Group' has been added to your contact list.\n"
+ "This is most likely due to server-side contact information. To fix this, so that\n"
+ "MetaContacts continues to function correctly, you should:\n"
+ " - disable MetaContacts using the 'Toggle MetaContacts Off' main menu item\n"
+ " - move all contacts out of this group\n"
+ " - synchronize your contacts with the server\n"
+ " - re-enable MetaContacts"), Translate("MetaContacts Warning"), MB_ICONWARNING | MB_OK);
+ break;
+ }
+ hGroup++;
+ } while(group_name);
+
+
+ while ( hContact != NULL ) {
+ if((meta_id = DBGetContactSettingDword(hContact,META_PROTO,META_LINK,(DWORD)-1))!=(DWORD)-1) {
+ // is a subcontact
+
+ // * ensure filter present
+ if( !CallService( MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, ( LPARAM )META_FILTER ))
+ CallService( MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, ( LPARAM )META_FILTER );
+
+
+ // get contact number
+ contact_number = DBGetContactSettingDword(hContact, META_PROTO, "ContactNumber", (DWORD)-1);
+
+ // prepare to update metacontact record of subcontat status
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ // save old group and move to invisible group (i.e. non-existent group)
+ Meta_SetGroup(hContact);
+
+ // find metacontact
+ hContact2 = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+
+ while ( hContact2 != NULL ) {
+ if(DBGetContactSettingDword(hContact2,META_PROTO,META_ID,(DWORD)-1) == meta_id) {
+ num_contacts = DBGetContactSettingDword(hContact2, META_PROTO, "NumContacts", (DWORD)-1);
+ if(contact_number >= 0 && contact_number < num_contacts) {
+
+ if(!proto)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE);
+
+ // update metacontact's record of status for this contact
+ strcpy(buffer, "Status");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ DBWriteContactSettingWord(hContact2, META_PROTO, buffer, status);
+
+ // update metacontact's record of nick for this contact
+ if(proto && !DBGetContactSetting(hContact, proto, "Nick", &dbv)) {
+ strcpy(buffer, "Nick");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ MyDBWriteContactSetting(hContact2, META_PROTO, buffer, &dbv);
+
+ strcpy(buffer, "CListName");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ if(DBGetContactSetting(hContact, "CList", "MyHandle", &dbv2)) {
+ MyDBWriteContactSetting(hContact2, META_PROTO, buffer, &dbv);
+ } else {
+ MyDBWriteContactSetting(hContact2, META_PROTO, buffer, &dbv2);
+ DBFreeVariant(&dbv2);
+ }
+
+ DBFreeVariant(&dbv);
+ } else {
+ if(!DBGetContactSetting(hContact, "CList", "MyHandle", &dbv)) {
+ strcpy(buffer, "CListName");
+ strcat(buffer, _itoa(contact_number, buffer2, 10));
+ MyDBWriteContactSetting(hContact2, META_PROTO, buffer, &dbv);
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+ }
+
+ hContact2 = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact2, 0 );
+ }
+
+ if(options.suppress_status)
+ CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ // do metacontacts after handles set properly above
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL ) {
+ if(DBGetContactSettingDword(hContact,META_PROTO,META_ID,(DWORD)-1)!=(DWORD)-1) {
+ // is a meta contact
+ HANDLE hMostOnline = Meta_GetMostOnline(hContact); // set nick
+ Meta_CopyContactNick(hContact, hMostOnline);
+
+ Meta_FixStatus(hContact);
+
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ CallService(MS_CLUI_SORTLIST, 0, 0);
+ return 0;
+}
+
+/** Unhide all contacts linked to any meta contact
+*
+*/
+int Meta_UnhideLinkedContacts(void) {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+
+ while ( hContact != NULL ) {
+ if(DBGetContactSettingDword(hContact,META_PROTO,META_LINK,(DWORD)-1)!=(DWORD)-1) {
+ // has a link - unhide it
+ // restore old group
+ Meta_RestoreGroup(hContact);
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ if(!CallService(MS_SYSTEM_TERMINATED, 0, 0))
+ CallService(MS_CLUI_SORTLIST, 0, 0);
+ return 0;
+}
+
+int Meta_HideMetaContacts(int hide) {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+
+ // set status suppression
+ if(hide) Meta_SuppressStatus(FALSE);
+ else Meta_SuppressStatus(options.suppress_status);
+
+ while ( hContact != NULL ) {
+ if(DBGetContactSettingDword(hContact,META_PROTO,META_ID,(DWORD)-1)!=(DWORD)-1) {
+ // is a meta contact
+
+ if(hide)
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);
+ else
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+
+ } else if(DBGetContactSettingDword(hContact,META_PROTO,META_LINK,(DWORD)-1)!=(DWORD)-1) {
+ // when metacontacts are hidden, show subcontacts, and vice versa
+ if(hide) {
+ Meta_RestoreGroup(hContact);
+ } else {
+ Meta_SetGroup(hContact);
+ }
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ if(!CallService(MS_SYSTEM_TERMINATED, 0, 0))
+ CallService(MS_CLUI_SORTLIST, 0, 0);
+ return 0;
+}
+
+void Meta_RestoreGroup(HANDLE hContact) {
+
+ if(meta_group_hack_disabled) return; // clist has called api function to disable group hack - yay!
+
+ // the existence of this service means that clist_meta_mw is active and will do the hiding for us
+ if(ServiceExists(MS_CLUI_METASUPPORT)) return;
+
+ // show it anyway - users are reporting contacts removed from meta remain 'hidden'
+ // possible suspect - server side groups cause hidden group hack to fail, users hide contacts via clist->delete->hide option
+ DBDeleteContactSetting(hContact, META_PROTO, "Hidden");
+
+ if(DBGetContactSettingByte(hContact, META_PROTO, "Hidden", 0) == 1)
+ {
+ // if we hid it, unhide it
+ DBDeleteContactSetting(hContact, META_PROTO, "Hidden");
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+ } else {
+ DBCONTACTWRITESETTING cws;
+
+ if(!DBGetContactSetting(hContact, META_PROTO, "OldCListGroup", &cws.value)) {
+
+ if((cws.value.type == DBVT_ASCIIZ || cws.value.type == DBVT_UTF8) && !strcmp(cws.value.pszVal, META_HIDDEN_GROUP)) {
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ } else {
+ int hGroup = 1;
+ char *name = 0;
+ BOOL found = FALSE;
+ do {
+ name = (char *)CallService(MS_CLIST_GROUPGETNAME, (WPARAM)hGroup, 0);
+ if(name && !strcmp(name, cws.value.pszVal)) {
+ found = TRUE;
+ break;
+ }
+ hGroup++;
+ } while(name);
+
+ if(found) {
+ cws.szModule = "CList";
+ cws.szSetting = "Group";
+ CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws);
+ } else {
+ //DBDeleteContactSetting(hContact, "CList", "Group");
+ // put back into metacontact's group
+ DBVARIANT dbv;
+ HANDLE hMeta = (HANDLE)DBGetContactSettingDword(hContact, META_PROTO, "Handle", 0);
+ if(hMeta && !MyDBGetContactSetting(hMeta, "CList", "Group", &dbv)) {
+ MyDBWriteContactSetting(hContact, "CList", "Group", &dbv);
+ DBFreeVariant(&dbv);
+ } else
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ }
+ }
+ DBFreeVariant(&cws.value);
+ }
+ DBDeleteContactSetting(hContact, META_PROTO, "OldCListGroup");
+
+ if(!DBGetContactSetting(hContact, "CList", "Group", &cws.value)) {
+ if((cws.value.type == DBVT_ASCIIZ || cws.value.type == DBVT_UTF8) && !strcmp(cws.value.pszVal, META_HIDDEN_GROUP)) {
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ }
+ DBFreeVariant(&cws.value);
+ }
+ }
+
+ // show it anyway - users are reporting contacts removed from meta remain 'hidden'
+ // possible suspect - server side groups cause hidden group hack to fail, users hide contacts via clist->delete->hide option
+ DBDeleteContactSetting(hContact, "CList", "Hidden");
+}
+
+void Meta_SetGroup(HANDLE hContact) {
+ char *proto, *uid;
+
+ if(meta_group_hack_disabled) return; // clist has called api function to disable group hack - yay!
+
+ // the existence of this service means that clist_meta_mw is active and will do the hiding for us
+ if(ServiceExists(MS_CLUI_METASUPPORT)) return;
+
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (proto)
+ uid = (char *)CallProtoService(proto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+
+ if(proto && uid && (INT_PTR)uid != CALLSERVICE_NOTFOUND && !strcmp(JABBER_UNIQUE_ID_SETTING, uid)) {
+ // if it's a jabber contact, hide it, and record the fact that it was us who did
+ DBWriteContactSettingByte(hContact, META_PROTO, "Hidden", 1);
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);
+ } else {
+ DBCONTACTWRITESETTING cws;
+ // save old group and move to invisible group (i.e. non-existent group)
+ if(!MyDBGetContactSetting(hContact, "CList", "Group", &cws.value)) {
+ if((cws.value.type == DBVT_ASCIIZ || cws.value.type == DBVT_UTF8) && !strcmp(cws.value.pszVal, META_HIDDEN_GROUP)) {
+ // it's already in the group (shouldn't be - but maybe a crash)
+ } else {
+ cws.szModule = META_PROTO;
+ cws.szSetting = "OldCListGroup";
+ CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws);
+ }
+ DBFreeVariant(&cws.value);
+ } else
+ DBDeleteContactSetting(hContact, META_PROTO, "OldCListGroup");
+
+ DBWriteContactSettingString(hContact, "CList", "Group", META_HIDDEN_GROUP);
+ }
+}
+
+void Meta_GetStatusString(int status, char *buf, size_t size) {
+ switch(status) {
+ case ID_STATUS_OFFLINE:
+ strncpy(buf, Translate("Offline"), size);
+ break;
+ case ID_STATUS_ONLINE:
+ strncpy(buf, Translate("Online"), size);
+ break;
+ case ID_STATUS_AWAY:
+ strncpy(buf, Translate("Away"), size);
+ break;
+ case ID_STATUS_DND:
+ strncpy(buf, Translate("DND"), size);
+ break;
+ case ID_STATUS_NA:
+ strncpy(buf, Translate("N/A"), size);
+ break;
+ case ID_STATUS_OCCUPIED:
+ strncpy(buf, Translate("Occupied"), size);
+ break;
+ case ID_STATUS_FREECHAT:
+ strncpy(buf, Translate("Free to Chat"), size);
+ break;
+ case ID_STATUS_INVISIBLE:
+ strncpy(buf, Translate("Invisible"), size);
+ break;
+ case ID_STATUS_ONTHEPHONE:
+ strncpy(buf, Translate("On the Phone"), size);
+ break;
+ case ID_STATUS_OUTTOLUNCH:
+ strncpy(buf, Translate("Out to Lunch"), size);
+ break;
+ case ID_STATUS_IDLE:
+ strncpy(buf, Translate("IDLE"), size);
+ break;
+ default:
+ strncpy(buf, Translate("Unknown"), size);
+ break;
+ }
+}
+
+int Meta_SuppressStatus(BOOL suppress) {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+
+ while ( hContact != NULL ) {
+ if(DBGetContactSettingDword(hContact,META_PROTO,META_LINK,(DWORD)-1)!=(DWORD)-1) {
+ // is a subcontact
+ if(suppress)
+ CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+ else
+ CallService(MS_IGNORE_UNIGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ return 0;
+}
+
+int Meta_CopyContactNick(HANDLE hMeta, HANDLE hContact) {
+ DBVARIANT dbv, dbv_proto;
+ char *proto;
+
+ if(options.lockHandle) {
+ hContact = Meta_GetContactHandle(hMeta, 0);
+ }
+
+ if(!hContact) return 1;
+
+ //proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ // read proto direct from db, since we do this on load and other proto plugins may not be loaded yet
+ if(!DBGetContactSetting(hContact, "Protocol", "p", &dbv_proto)) {
+
+ proto = dbv_proto.pszVal;
+ if(options.clist_contact_name == CNNT_NICK && proto) {
+ if(!MyDBGetContactSetting(hContact, proto, "Nick", &dbv)) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, "Nick", &dbv);
+ DBFreeVariant(&dbv);
+ //CallService(MS_CLIST_INVALIDATEDISPLAYNAME, (WPARAM)hMeta, 0);
+ //CallService(MS_CLUI_CONTACTRENAMED, (WPARAM)hMeta, 0);
+ DBFreeVariant(&dbv_proto);
+ return 0;
+ }
+ } else if(options.clist_contact_name == CNNT_DISPLAYNAME) {
+ char *name = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0);
+ wchar_t *wname = (wchar_t *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_UNICODE);
+
+ if(name && strcmp(name, Translate("(Unknown Contact)")) != 0) {
+ if(wname && strncmp(name, (char *)wname, strlen(name)) != 0) {
+ DBVARIANT dbv;
+ dbv.pwszVal = wname;
+ dbv.type = DBVT_WCHAR;
+
+ MyDBWriteContactSetting(hMeta, META_PROTO, "Nick", &dbv);
+ } else
+ DBWriteContactSettingString(hMeta, META_PROTO, "Nick", name);
+ //CallService(MS_CLIST_INVALIDATEDISPLAYNAME, (WPARAM)hMeta, 0);
+ //CallService(MS_CLUI_CONTACTRENAMED, (WPARAM)hMeta, 0);
+ DBFreeVariant(&dbv_proto);
+ return 0;
+ }
+ }
+ DBFreeVariant(&dbv_proto);
+ }
+ return 1;
+}
+
+int Meta_SetAllNicks() {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ), most_online;
+
+ while ( hContact != NULL ) {
+ if(DBGetContactSettingDword(hContact,META_PROTO,META_ID,(DWORD)-1)!=(DWORD)-1) {
+ most_online = Meta_GetMostOnline(hContact);
+ Meta_CopyContactNick(hContact, most_online);
+ Meta_FixStatus(hContact);
+ Meta_CopyData(hContact);
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ return 0;
+}
+
+int Meta_IsHiddenGroup(const char *group_name) {
+ if(group_name && !strcmp(group_name, META_HIDDEN_GROUP)) return 1;
+
+ return 0;
+}
+
+int Meta_SwapContacts(HANDLE hMeta, DWORD contact_number1, DWORD contact_number2) {
+ DBVARIANT dbv1, dbv2;
+
+ HANDLE hContact1 = Meta_GetContactHandle(hMeta, contact_number1),
+ hContact2 = Meta_GetContactHandle(hMeta, contact_number2);
+ char buff1[512], buff12[512], buff2[512], buff22[512];
+ BOOL ok1, ok2;
+
+ // swap the protocol
+ strcpy(buff1, "Protocol");
+ strcat(buff1, _itoa(contact_number1, buff12, 10));
+ strcpy(buff2, "Protocol");
+ strcat(buff2, _itoa(contact_number2, buff22, 10));
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff1, &dbv1);
+ ok2 = !MyDBGetContactSetting(hMeta, META_PROTO, buff2, &dbv2);
+ if(ok1) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff2, &dbv1);
+ DBFreeVariant(&dbv1);
+ }
+ if(ok2) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff1, &dbv2);
+ DBFreeVariant(&dbv2);
+ }
+
+ // swap the status
+ strcpy(buff1, "Status");
+ strcat(buff1, _itoa(contact_number1, buff12, 10));
+ strcpy(buff2, "Status");
+ strcat(buff2, _itoa(contact_number2, buff22, 10));
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff1, &dbv1);
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff2, &dbv2);
+ if(ok1) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff2, &dbv1);
+ DBFreeVariant(&dbv1);
+ }
+ if(ok2) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff1, &dbv2);
+ DBFreeVariant(&dbv2);
+ }
+
+ // swap the status string
+ strcpy(buff1, "StatusString");
+ strcat(buff1, _itoa(contact_number1, buff12, 10));
+ strcpy(buff2, "StatusString");
+ strcat(buff2, _itoa(contact_number2, buff22, 10));
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff1, &dbv1);
+ ok2 = !MyDBGetContactSetting(hMeta, META_PROTO, buff2, &dbv2);
+ if(ok1) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff2, &dbv1);
+ DBFreeVariant(&dbv1);
+ }
+ if(ok2) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff1, &dbv2);
+ DBFreeVariant(&dbv2);
+ }
+
+ // swap the login
+ strcpy(buff1, "Login");
+ strcat(buff1, _itoa(contact_number1, buff12, 10));
+ strcpy(buff2, "Login");
+ strcat(buff2, _itoa(contact_number2, buff22, 10));
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff1, &dbv1);
+ ok2 = !MyDBGetContactSetting(hMeta, META_PROTO, buff2, &dbv2);
+ if(ok1) {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff2);
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff2, &dbv1);
+ DBFreeVariant(&dbv1);
+ }
+ if(ok2) {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff1);
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff1, &dbv2);
+ DBFreeVariant(&dbv2);
+ }
+
+ // swap the nick
+ strcpy(buff1, "Nick");
+ strcat(buff1, _itoa(contact_number1, buff12, 10));
+ strcpy(buff2, "Nick");
+ strcat(buff2, _itoa(contact_number2, buff22, 10));
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff1, &dbv1);
+ ok2 = !MyDBGetContactSetting(hMeta, META_PROTO, buff2, &dbv2);
+ if(ok1) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff2, &dbv1);
+ DBFreeVariant(&dbv1);
+ } else {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff2);
+ }
+ if(ok2) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff1, &dbv2);
+ DBFreeVariant(&dbv2);
+ } else {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff1);
+ }
+
+ // swap the clist name
+ strcpy(buff1, "CListName");
+ strcat(buff1, _itoa(contact_number1, buff12, 10));
+ strcpy(buff2, "CListName");
+ strcat(buff2, _itoa(contact_number2, buff22, 10));
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff1, &dbv1);
+ ok2 = !MyDBGetContactSetting(hMeta, META_PROTO, buff2, &dbv2);
+ if(ok1) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff2, &dbv1);
+ DBFreeVariant(&dbv1);
+ } else {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff2);
+ }
+ if(ok2) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff1, &dbv2);
+ DBFreeVariant(&dbv2);
+ } else {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff1);
+ }
+
+ // swap the handle
+ strcpy(buff1, "Handle");
+ strcat(buff1, _itoa(contact_number1, buff12, 10));
+ strcpy(buff2, "Handle");
+ strcat(buff2, _itoa(contact_number2, buff22, 10));
+ ok1 = !MyDBGetContactSetting(hMeta, META_PROTO, buff1, &dbv1);
+ ok2 = !MyDBGetContactSetting(hMeta, META_PROTO, buff2, &dbv2);
+ if(ok1) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff2, &dbv1);
+ DBFreeVariant(&dbv1);
+ } else {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff2);
+ }
+ if(ok2) {
+ MyDBWriteContactSetting(hMeta, META_PROTO, buff1, &dbv2);
+ DBFreeVariant(&dbv2);
+ } else {
+ DBDeleteContactSetting(hMeta, META_PROTO, buff1);
+ }
+
+ // finally, inform the contacts of their change in position
+ DBWriteContactSettingDword(hContact1, META_PROTO, "ContactNumber", (DWORD)contact_number2);
+ DBWriteContactSettingDword(hContact2, META_PROTO, "ContactNumber", (DWORD)contact_number1);
+
+ return 0;
+}
+
+INT_PTR CALLBACK DlgProcNull(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ HWND prog = GetDlgItem(hwndDlg, IDC_PROG);
+
+ TranslateDialogDefault( hwndDlg );
+
+ SendMessage(prog, PBM_SETPOS, 0, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+// function to copy history from one contact to another - courtesy JdGordon (thx)
+void copyHistory(HANDLE hContactFrom,HANDLE hContactTo)
+{
+ HANDLE hDbEvent;
+ DBEVENTINFO dbei;
+ //char *id;
+ //DWORD id_length;
+ //DWORD oldBlobSize;
+ DWORD time_now = time(0);
+ DWORD earliest_time = time_now - options.days_history * 24 * 60 * 60;
+ BYTE *buffer = 0;
+ HWND progress_dialog, prog;
+
+ if (!hContactFrom || !hContactTo) return;
+
+ //id = Meta_GetUniqueIdentifier(hContactFrom, &id_length);
+ //if(!id) return;
+
+ progress_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_COPYPROGRESS), 0, DlgProcNull);
+ ShowWindow(progress_dialog, SW_SHOW);
+
+ prog = GetDlgItem(progress_dialog, IDC_PROG);
+
+ //CallService(MS_DB_SETSAFETYMODE, (WPARAM)FALSE, 0);
+ for (hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST,(WPARAM)hContactFrom, 0);
+ hDbEvent;
+ hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0))
+ {
+ // get the event
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+
+ if((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == -1)
+ break;
+
+ buffer = mir_realloc(buffer, dbei.cbBlob);// + id_length);
+ dbei.pBlob = buffer;
+
+ if (CallService(MS_DB_EVENT_GET,(WPARAM)hDbEvent,(LPARAM)&dbei))
+ break;
+
+ // i.e. optoins.days_history == 0;
+ if(time_now == earliest_time) earliest_time = dbei.timestamp;
+
+ if(dbei.timestamp < earliest_time)
+ continue;
+
+ if(dbei.eventType != EVENTTYPE_MESSAGE && dbei.eventType != EVENTTYPE_FILE && dbei.eventType != EVENTTYPE_URL)
+ continue;
+
+ if(time_now > earliest_time) { // just in case!
+ SendMessage(prog, PBM_SETPOS, (WPARAM)(int)(100.0 * (dbei.timestamp - earliest_time) / (time_now - earliest_time)), 0);
+ UpdateWindow(progress_dialog);
+ }
+
+ dbei.szModule = META_PROTO;
+ //oldBlobSize = dbei.cbBlob;
+ //dbei.cbBlob = oldBlobSize + id_length;
+ dbei.flags &= ~DBEF_FIRST;
+ //memcpy(dbei.pBlob + oldBlobSize, id, id_length);
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hContactTo, (LPARAM)&dbei);
+ }
+ //CallService(MS_DB_SETSAFETYMODE, (WPARAM)TRUE, 0);
+
+ DestroyWindow(progress_dialog);
+ if(buffer) mir_free(buffer);
+ //mir_free(id);
+}
+
+/*
+void Meta_RemoveHistory(HANDLE hContactRemoveFrom, HANDLE hContactSource) {
+ HANDLE hDbEvent;
+ DBEVENTINFO dbei = { 0 };
+ char *id;
+ DWORD id_length;
+ BYTE *buffer = 0;
+ DWORD time_now = time(0), earliest_time = time_now;
+ HWND progress_dialog, prog;
+
+ if (!hContactRemoveFrom || !hContactSource) return;
+
+ id = Meta_GetUniqueIdentifier(hContactSource, &id_length);
+ if(!id) return;
+
+ progress_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DELPROGRESS), 0, DlgProcNull);
+ ShowWindow(progress_dialog, SW_SHOW);
+
+ prog = GetDlgItem(progress_dialog, IDC_PROG);
+
+ //CallService(MS_DB_SETSAFETYMODE, (WPARAM)FALSE, 0);
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST,(WPARAM)hContactRemoveFrom, 0);
+ while (hDbEvent)
+ {
+ // get the event
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+
+ if((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == -1) {
+ break;
+ }
+
+ buffer = mir_realloc(buffer, dbei.cbBlob + id_length);
+ dbei.pBlob = buffer;
+
+ if (CallService(MS_DB_EVENT_GET,(WPARAM)hDbEvent,(LPARAM)&dbei)) break;
+
+ if(dbei.timestamp < earliest_time)
+ earliest_time = dbei.timestamp;
+
+ if(dbei.eventType != EVENTTYPE_MESSAGE && dbei.eventType != EVENTTYPE_FILE && dbei.eventType != EVENTTYPE_URL) {
+ hDbEvent=(HANDLE)CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0);
+ continue;
+ }
+
+ if(dbei.cbBlob >= id_length && strncmp((char *)(dbei.pBlob + dbei.cbBlob - id_length), id, id_length - 1) == 0) {
+ // event is tagged with source contact id - remove
+ HANDLE hDbEventNext;
+
+ if(time_now > earliest_time) { // just in case
+ SendMessage(prog, PBM_SETPOS, (WPARAM)(int)(100.0 * (dbei.timestamp - earliest_time) / (time_now - earliest_time)), 0);
+ UpdateWindow(progress_dialog);
+ }
+
+ hDbEventNext = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0);
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)hContactRemoveFrom, (LPARAM)hDbEvent);
+ hDbEvent = hDbEventNext;
+ continue;
+ }
+
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0);
+ }
+ //CallService(MS_DB_SETSAFETYMODE, (WPARAM)TRUE, 0);
+
+ DestroyWindow(progress_dialog);
+ if(buffer) mir_free(buffer);
+ mir_free(id);
+}
+
+char *Meta_GetUniqueIdentifier(HANDLE hContact, DWORD *pused) {
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ char *field;
+ char *id;
+ char buff[256];
+ DWORD used;
+ DBVARIANT dbv;
+
+ id = (char *)mir_alloc(256);
+
+ if(!proto) return 0;
+
+ strncpy(id, proto, 127);
+ strcat(id, "*"); // seperate proto & proto id with asterisk to make one long comparable string
+
+ used = strlen(id);
+
+ field = (char *)CallProtoService(proto,PS_GETCAPS,PFLAG_UNIQUEIDSETTING,0);
+ if(!field) return 0;
+
+ DBGetContactSetting(hContact,proto,field,&dbv);
+ switch(dbv.type)
+ {
+ case DBVT_ASCIIZ:
+ sprintf(buff,"%s",dbv.pszVal);
+ break;
+ case DBVT_BYTE:
+ sprintf(buff,"%d",dbv.bVal);
+ break;
+ case DBVT_WORD:
+ sprintf(buff,"%d",dbv.wVal);
+ break;
+ case DBVT_DWORD:
+ sprintf(buff,"%d",dbv.dVal);
+ break;
+ default:
+ sprintf(buff,"bugger this");
+ }
+ DBFreeVariant(&dbv);
+
+ strncpy(id + used, buff, 256 - used);
+ if(used) {
+ *pused = (DWORD)(used + strlen(buff) + 1);
+ if(*pused > 256) *pused = 256;
+ }
+
+ return id;
+}
+*/
+void Meta_FixStatus(HANDLE hMeta) {
+ HANDLE most_online = Meta_GetMostOnlineSupporting(hMeta, PFLAGNUM_1, 0);
+ if(most_online) {
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)most_online, 0);
+ if(proto) {
+ WORD status = (WORD)DBGetContactSettingWord(most_online, proto, "Status", (WORD)ID_STATUS_OFFLINE);
+ DBWriteContactSettingWord(hMeta, META_PROTO, "Status", status);
+ } else
+ DBWriteContactSettingWord(hMeta, META_PROTO, "Status", (WORD)ID_STATUS_OFFLINE);
+ } else
+ DBWriteContactSettingWord(hMeta, META_PROTO, "Status", (WORD)ID_STATUS_OFFLINE);
+
+ // trigger setting changed in mw_clist to reset extra icons
+ if(ServiceExists(MS_CLIST_EXTRA_SET_ICON)) {
+ DBWriteContactSettingString(hMeta, "DummyModule", "e-mail", "blah");
+ //DBDeleteContactSetting(hMeta, "DummyModule", "e-mail"); // causes 'empty settings group' error in dbtool
+ }
+
+}
+
+INT_PTR Meta_IsEnabled() {
+ return DBGetContactSettingByte(0, META_PROTO, "Enabled", 1) && (meta_group_hack_disabled || DBGetContactSettingByte(NULL, "CList", "UseGroups", 1));
+}
+
+
+
diff --git a/plugins/MetaContacts/metacontacts.h b/plugins/MetaContacts/metacontacts.h new file mode 100644 index 0000000000..790fb9a6a4 --- /dev/null +++ b/plugins/MetaContacts/metacontacts.h @@ -0,0 +1,269 @@ +/*
+MetaContacts Plugin for Miranda IM.
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+
+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.
+*/
+
+/** @file metacontacts.h
+*
+* Header declaring functions that are accessed in multiple files.
+*/
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+#define _WIN32_WINNT 0x0400
+#define _WIN32_IE 0x0300
+
+#define MIRANDA_VER 0x0A00
+
+#include <m_stdhdr.h>
+
+#include <windows.h>
+#include <commctrl.h>
+#include <string.h>
+#include <time.h>
+#include "resource.h"
+
+#include "m_metacontacts.h"
+
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_skin.h>
+#include <m_langpack.h>
+#include <m_protomod.h>
+#include <m_database.h>
+#include <m_system.h>
+#include <m_protocols.h>
+#include <m_userinfo.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_ignore.h>
+#include <m_clc.h>
+#include <m_contacts.h>
+#include <m_message.h>
+#include <m_ignore.h>
+#include <m_icolib.h>
+#include <m_langpack.h>
+#include <m_popup.h>
+#include <m_cluiframes.h>
+#include "m_updater.h"
+
+#define META_PROTO "MetaContacts"
+#define META_FILTER "MetaContactsFilter"
+#define META_ID "MetaID"
+#define META_FILTER_ID "MetaFilterID"
+#define META_LINK "MetaLink"
+
+#define META_HIDDEN_GROUP "MetaContacts Hidden Group"
+#define MAX_CONTACTS 20
+
+// I can't think of a way around this - mental block
+
+INT_PTR TranslateMenuFunc(HANDLE hContact, int i);
+extern HANDLE hMenuContact[MAX_CONTACTS];
+
+INT_PTR MenuFunc0(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc1(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc2(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc3(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc4(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc5(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc6(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc7(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc8(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc9(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc10(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc11(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc12(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc13(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc14(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc15(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc16(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc17(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc18(WPARAM wParam, LPARAM lParam);
+INT_PTR MenuFunc19(WPARAM wParam, LPARAM lParam);
+
+extern HINSTANCE hInstance;
+extern PLUGININFOEX pluginInfo;
+
+// contact menu items
+extern HANDLE hMenuConvert,
+ hMenuAdd,
+ hMenuEdit,
+ hMenuDelete,
+ hMenuDefault,
+ hMenuForceDefault;
+
+// main menu item
+extern HANDLE hMenuOnOff;
+
+extern DWORD nextMetaID;
+extern int mcStatus;
+
+INT_PTR Meta_Convert(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_AddTo(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_Edit(WPARAM wParam,LPARAM lParam);
+void Meta_RemoveContactNumber(HANDLE hMeta, int number);
+INT_PTR Meta_Delete(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_Default(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_ForceDefault(WPARAM wParam,LPARAM lParam);
+
+INT_PTR Meta_IsEnabled();
+
+int Meta_EqualDBV(DBVARIANT *dbv, DBVARIANT *id);
+int Meta_ModifyMenu(WPARAM wParam,LPARAM lParam);
+BOOL Meta_Assign(HANDLE src, HANDLE dest, BOOL set_as_default);
+HANDLE Meta_GetHandle(const char *protocol, DBVARIANT *id);
+int Meta_SetNick(char *proto);
+HANDLE Meta_GetMostOnline(HANDLE hMeta);
+HANDLE Meta_GetMostOnlineSupporting(HANDLE hMeta, int pflagnum, unsigned long capability);
+int Meta_HideLinkedContacts(void);
+int Meta_SetHandles(void);
+int Meta_UnhideLinkedContacts(void);
+int Meta_GetContactNumber(HANDLE hContact);
+HANDLE Meta_GetContactHandle(HANDLE hMeta, int contact_number);
+void Meta_GetStatusString(int status, char *buf, size_t size);
+void Meta_RestoreGroup(HANDLE hContact);
+void Meta_SetGroup(HANDLE hContact);
+int Meta_HideMetaContacts(int hide);
+int Meta_SuppressStatus(int suppress);
+int Meta_CopyContactNick(HANDLE hMeta, HANDLE hContact);
+void Meta_CopyData(HANDLE hMeta);
+int Meta_SetAllNicks();
+int Meta_IsHiddenGroup(const char *group_name);
+int Meta_SwapContacts(HANDLE hMeta, DWORD contact_number1, DWORD contact_number2);
+// function to copy history from one contact to another - courtesy JdGordon with mods (thx)
+void copyHistory(HANDLE hContactFrom,HANDLE hContactTo);
+// inverse
+//void Meta_RemoveHistory(HANDLE hContactRemoveFrom, HANDLE hContactSource);
+void Meta_FixStatus(HANDLE hMeta);
+
+char *Meta_GetUniqueIdentifier(HANDLE hContact, DWORD *pused);
+
+INT_PTR Meta_GetCaps(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_GetName(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_LoadIcon(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_SetStatus(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_GetStatus(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_SendMessage(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_RecvMessage(WPARAM wParam,LPARAM lParam);
+INT_PTR Meta_ContactMenuFunc(WPARAM wParam, LPARAM lParam);
+
+INT_PTR CALLBACK Meta_SelectDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK Meta_EditDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+void Meta_InitServices();
+void Meta_CloseHandles();
+
+enum MenuDisplayNameType {DNT_UID = 0, DNT_DID = 1};
+enum MenuFunctionType {FT_MSG = 0, FT_MENU = 1, FT_INFO = 2};
+enum CListDisplayNameType {CNNT_NICK = 0, CNNT_DISPLAYNAME = 1};
+
+typedef struct tag_MetaOptions {
+ BOOL set_default_on_recv;
+ BOOL always_use_default;
+ BOOL suppress_status;
+ int menu_contact_label;
+ int clist_contact_name;
+ int menu_function;
+ BOOL suppress_proto;
+ BOOL copy_subcontact_history;
+ int days_history;
+ int set_status_from_offline_delay;
+ BOOL subcontact_windows;
+ BOOL metahistory;
+ BOOL subhistory;
+ BOOL copydata;
+ BOOL lockHandle;
+ BOOL temp_default;
+ BOOL flash_meta_message_icon;
+ BOOL copy_userinfo;
+ BOOL use_proto_recv;
+} MetaOptions;
+
+extern MetaOptions options;
+
+INT_PTR CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcOptsPriorities(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+int Meta_WriteOptions(MetaOptions *opt);
+int Meta_ReadOptions(MetaOptions *opt);
+
+int GetDefaufaultPrio(int status);
+int GetRealPriority(char *proto, int status);
+
+// API function headers
+INT_PTR MetaAPI_GetMeta(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_GetDefault(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_GetDefaultNum(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_GetMostOnline(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_GetNumContacts(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_GetContact(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_SetDefaultContactNum(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_SetDefaultContact(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_ForceSendContactNum(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_ForceSendContact(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_UnforceSendContact(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_ForceDefault(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_GetForceState(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_GetProtoName(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_ConvertToMeta(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_AddToMeta(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_RemoveFromMeta(WPARAM wParam, LPARAM lParam);
+INT_PTR MetaAPI_DisableHiddenGroup(WPARAM wParam, LPARAM lParam);
+
+// extended db get/write setting functions, that handle unicode
+INT_PTR MyDBWriteContactSetting(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
+INT_PTR MyDBGetContactSetting(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv);
+
+// IcoLib support
+void InitIcons(void);
+void DeinitIcons(void);
+
+typedef enum {I_MENUOFF, I_MENU, I_CONVERT, I_ADD, I_EDIT, I_SETDEFAULT, I_REMOVE} IconIndex;
+HICON LoadIconEx(IconIndex i);
+void ReleaseIconEx(HICON hIcon);
+
+extern HANDLE hEventDefaultChanged, hEventForceSend, hEventUnforceSend, hSubcontactsChanged;
+
+extern POINT menuMousePoint;
+
+extern BOOL message_window_api_enabled;
+
+#define MAX_PROTOCOLS 20
+extern int proto_count;
+extern char proto_names[MAX_PROTOCOLS * 128];
+
+// used for the 'jabber' hack - i.e. hide contacts instead of moving them to the hidden group
+#define JABBER_UNIQUE_ID_SETTING "jid"
+
+// delay setting status from offline - to help reduce innapropriate status notification popups
+#define DEFAULT_SET_STATUS_SLEEP_TIME 15000 // milliseconds
+
+// service from clist_meta_mw, existence means we don't need to hide subcontacts (woohoo - thanks FYR)
+#define MS_CLUI_METASUPPORT "CLUI/MetaContactSupport"
+
+extern BOOL meta_group_hack_disabled;
+
+#ifndef MS_CLUI_GETVERSION
+#define MS_CLUI_GETVERSION "CLUI/GetVersion"
+
+
+extern BOOL os_unicode_enabled;
+
+#endif
diff --git a/plugins/MetaContacts/resource.h b/plugins/MetaContacts/resource.h new file mode 100644 index 0000000000..fe813d2ccf --- /dev/null +++ b/plugins/MetaContacts/resource.h @@ -0,0 +1,76 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MetaContacts.rc
+//
+#define IDC_BTN_REM 3
+#define IDD_METASELECT 101
+#define IDI_MCMENU 103
+#define IDD_METAEDIT 108
+#define IDD_OPTIONS 109
+#define IDD_COPYPROGRESS 110
+#define IDD_DELPROGRESS 111
+#define IDI_MCMENUOFF 116
+#define IDI_MCEDIT 118
+#define IDI_MCREMOVE 119
+#define IDI_MCCONVERT 120
+#define IDI_MCADD 121
+#define IDI_MCSETDEFAULT 122
+#define IDD_PRIORITIES 123
+#define IDD_HISTORY 124
+#define IDC_METALIST 1002
+#define IDC_ONLYAVAIL 1005
+#define IDC_DEFAULT 1008
+#define IDC_NAME 1009
+#define IDC_FRAME 1013
+#define IDC_VALIDATE 1014
+#define IDC_CHK_SETDEFAULTRECV 1016
+#define IDC_CHK_ALWAYSUSEDEFAULT 1017
+#define IDC_CHECK1 1018
+#define IDC_CHK_SUPPRESSSTATUS 1018
+#define IDC_CHK_FORCEDEFAULT 1018
+#define IDC_CHK_SRT 1018
+#define IDC_CHK_DEFAULT 1018
+#define IDC_RAD_UID 1019
+#define IDC_RAD_DID 1020
+#define IDC_RAD_MSG 1021
+#define IDC_RAD_MENU 1022
+#define IDC_RAD_INFO 1023
+#define IDC_RAD_NICK 1024
+#define IDC_RAD_NAME 1025
+#define IDC_LST_CONTACTS 1026
+#define IDC_CHK_SUPPRESSPROTO 1026
+#define IDC_BTN_SETDEFAULT 1027
+#define IDC_CHK_COPYHISTORY 1027
+#define IDC_BTN_UP 1028
+#define IDC_BTN_DOWN 1029
+#define IDC_ED_NAME 1030
+#define IDC_ED_DEFAULT 1031
+#define IDC_BTN_SETDEFAULT2 1031
+#define IDC_BTN_SETOFFLINE 1031
+#define IDC_ED_DAYS 1033
+#define IDC_PROG 1034
+#define IDC_CHK_SUBWINDOW 1035
+#define IDC_CHK_METAHISTORY 1036
+#define IDC_CHK_SUBHISTORY 1037
+#define IDC_CHK_COPYDATA 1038
+#define IDC_CHK_LOCKHANDLE 1039
+#define IDC_CHK_TEMPDEFAULT 1040
+#define IDC_ED_PRIORITY 1042
+#define IDC_SP_PRIORITY 1043
+#define IDC_CMB_STATUS 1044
+#define IDC_BUTTON2 1048
+#define IDC_BTN_RESET 1048
+#define IDC_CMB_PROTOCOL 1062
+
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 125
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1049
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/MetaContacts/resource.rc b/plugins/MetaContacts/resource.rc new file mode 100644 index 0000000000..5557199080 --- /dev/null +++ b/plugins/MetaContacts/resource.rc @@ -0,0 +1,6 @@ +
+// this makes our dependencies work better
+#include "version.h"
+
+#include "MetaContacts.rc"
+#include "version.rc"
diff --git a/plugins/MetaContacts/version.h b/plugins/MetaContacts/version.h new file mode 100644 index 0000000000..5c5bf65b3e --- /dev/null +++ b/plugins/MetaContacts/version.h @@ -0,0 +1,27 @@ +// Set the version number here - it will affect the version resource and the version field of the pluginInfo structure
+// (Be careful that you don't have the resource file open when you change this and rebuild, otherwise the changes may not
+// take effect within the version resource)
+
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 14
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 13
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __FILEVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+#define __STRINGIFY(x) #x
+#define __VERSION_STRING __STRINGIFY(__FILEVERSION_STRING_DOTS)
+
+#define __DESC "Merges contacts from the same or different protocols into one"
+#define __AUTHOR "J. Schaal & S. Ellis"
+#define __AUTHOREMAIL "mail@scottellis.com.au"
+#define __COPYRIGHT "© 2005,2006 Scott Ellis"
+#define __AUTHORWEB "http://www.scottellis.com.au"
+
+#ifdef _UNICODE
+#define __PLUGIN_NAME "MetaContacts Plugin (Unicode)"
+#else
+#define __PLUGIN_NAME "MetaContacts Plugin"
+#endif
+#define __FILENAME "MetaContacts.dll"
+
diff --git a/plugins/MetaContacts/version.rc b/plugins/MetaContacts/version.rc new file mode 100644 index 0000000000..0bb7a49488 --- /dev/null +++ b/plugins/MetaContacts/version.rc @@ -0,0 +1,33 @@ +
+#include <windows.h>
+#include "version.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __FILEVERSION_STRING
+ PRODUCTVERSION __FILEVERSION_STRING
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Author", __AUTHOR
+ VALUE "FileDescription", __DESC
+ VALUE "InternalName", __PLUGIN_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ VALUE "OriginalFilename", __FILENAME
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
|