From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/ContactsPlus/contacts.cpp | 31 + plugins/ContactsPlus/contacts.dsp | 171 +++++ plugins/ContactsPlus/contacts.dsw | 29 + plugins/ContactsPlus/contacts.h | 79 +++ plugins/ContactsPlus/contacts.rc | 191 ++++++ plugins/ContactsPlus/contacts.sln | 36 ++ plugins/ContactsPlus/contacts.vcxproj | 578 +++++++++++++++++ plugins/ContactsPlus/contacts.vcxproj.filters | 56 ++ plugins/ContactsPlus/langpack_contacts.txt | 33 + plugins/ContactsPlus/main.cpp | 363 +++++++++++ plugins/ContactsPlus/readme_contacts.txt | 158 +++++ plugins/ContactsPlus/receive.cpp | 522 +++++++++++++++ plugins/ContactsPlus/receive.h | 65 ++ plugins/ContactsPlus/res/SendContacts.ico | Bin 0 -> 2606 bytes plugins/ContactsPlus/resource.h | 44 ++ plugins/ContactsPlus/send.cpp | 609 ++++++++++++++++++ plugins/ContactsPlus/send.h | 110 ++++ plugins/ContactsPlus/utils.cpp | 876 ++++++++++++++++++++++++++ plugins/ContactsPlus/utils.h | 91 +++ 19 files changed, 4042 insertions(+) create mode 100644 plugins/ContactsPlus/contacts.cpp create mode 100644 plugins/ContactsPlus/contacts.dsp create mode 100644 plugins/ContactsPlus/contacts.dsw create mode 100644 plugins/ContactsPlus/contacts.h create mode 100644 plugins/ContactsPlus/contacts.rc create mode 100644 plugins/ContactsPlus/contacts.sln create mode 100644 plugins/ContactsPlus/contacts.vcxproj create mode 100644 plugins/ContactsPlus/contacts.vcxproj.filters create mode 100644 plugins/ContactsPlus/langpack_contacts.txt create mode 100644 plugins/ContactsPlus/main.cpp create mode 100644 plugins/ContactsPlus/readme_contacts.txt create mode 100644 plugins/ContactsPlus/receive.cpp create mode 100644 plugins/ContactsPlus/receive.h create mode 100644 plugins/ContactsPlus/res/SendContacts.ico create mode 100644 plugins/ContactsPlus/resource.h create mode 100644 plugins/ContactsPlus/send.cpp create mode 100644 plugins/ContactsPlus/send.h create mode 100644 plugins/ContactsPlus/utils.cpp create mode 100644 plugins/ContactsPlus/utils.h (limited to 'plugins/ContactsPlus') diff --git a/plugins/ContactsPlus/contacts.cpp b/plugins/ContactsPlus/contacts.cpp new file mode 100644 index 0000000000..a7ba2cdfbb --- /dev/null +++ b/plugins/ContactsPlus/contacts.cpp @@ -0,0 +1,31 @@ +// -------------------------------------------------------------------------- +// Contacts+ for Miranda Instant Messenger +// _______________________________________ +// +// Copyright © 2002 Dominus Procellarum +// Copyright © 2004-2008 Joe Kucera +// +// 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. +// +// ----------------------------------------------------------------------------- + +#include "contacts.h" + + +bool WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + hInst = hinstDLL; + return TRUE; +} diff --git a/plugins/ContactsPlus/contacts.dsp b/plugins/ContactsPlus/contacts.dsp new file mode 100644 index 0000000000..29adec3bd8 --- /dev/null +++ b/plugins/ContactsPlus/contacts.dsp @@ -0,0 +1,171 @@ +# Microsoft Developer Studio Project File - Name="contacts" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=contacts - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "contacts.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "contacts.mak" CFG="contacts - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "contacts - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "contacts - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "contacts - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CONTACTS_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\include" /I "..\ExternalAPI" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CONTACTS_EXPORTS" /Yu"contacts.h" /FD /c +# SUBTRACT CPP /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x405 /d "NDEBUG" +# ADD RSC /l 0x405 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /map /machine:I386 /ALIGN:4096 /ignore:4108 +# SUBTRACT LINK32 /pdb:none /debug + +!ELSEIF "$(CFG)" == "contacts - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CONTACTS_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\ExternalAPI" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CONTACTS_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x405 /d "_DEBUG" +# ADD RSC /l 0x405 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "contacts - Win32 Release" +# Name "contacts - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\contacts.cpp + +!IF "$(CFG)" == "contacts - Win32 Release" + +# ADD CPP /Yc + +!ELSEIF "$(CFG)" == "contacts - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\main.cpp + +!IF "$(CFG)" == "contacts - Win32 Release" + +# ADD CPP /Yu + +!ELSEIF "$(CFG)" == "contacts - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\receive.cpp +# End Source File +# Begin Source File + +SOURCE=.\send.cpp +# End Source File +# Begin Source File + +SOURCE=.\utils.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\contacts.h +# End Source File +# Begin Source File + +SOURCE=.\receive.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\send.h +# End Source File +# Begin Source File + +SOURCE=.\utils.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\contacts.rc +# End Source File +# Begin Source File + +SOURCE=.\res\SendContacts.ico +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/ContactsPlus/contacts.dsw b/plugins/ContactsPlus/contacts.dsw new file mode 100644 index 0000000000..de931e6c9f --- /dev/null +++ b/plugins/ContactsPlus/contacts.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "contacts"=".\contacts.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/ContactsPlus/contacts.h b/plugins/ContactsPlus/contacts.h new file mode 100644 index 0000000000..73123a4c62 --- /dev/null +++ b/plugins/ContactsPlus/contacts.h @@ -0,0 +1,79 @@ +// --------------------------------------------------------------------------- +// Contacts+ for Miranda Instant Messenger +// _______________________________________ +// +// Copyright © 2002 Dominus Procellarum +// Copyright © 2004-2008 Joe Kucera +// +// 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. +// +// --------------------------------------------------------------------------- + +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//!!this is fake - this plugin maintains backward compatibility internally +#define MIRANDA_VER 0x800 + +#include "newpluginapi.h" +#include "m_system.h" +#include "m_protocols.h" +#include "m_protosvc.h" +#include "m_database.h" +#include "m_utils.h" +#include "m_langpack.h" +#include "m_skin.h" +#include "m_clist.h" +#include "m_clc.h" +#include "m_clui.h" +#include "m_addcontact.h" +#include "m_history.h" +#include "m_userinfo.h" +#include "m_button.h" +#include "m_contacts.h" +#include "m_message.h" +#include "statusmodes.h" +#include "win2k.h" + +#include "resource.h" + +#include "m_updater.h" + +#include "utils.h" +#include "send.h" +#include "receive.h" + +#define MODULENAME "SendReceiveContacts" + + +#define MS_CONTACTS_SEND "ContactsTransfer/SendContacts" +#define MS_CONTACTS_RECEIVE "ContactsTransfer/ReceiveContacts" + +// Global Variables +extern int g_UnicodeCore; +extern int g_NewProtoAPI; +extern int g_SendAckSupported; +extern int g_Utf8EventsSupported; diff --git a/plugins/ContactsPlus/contacts.rc b/plugins/ContactsPlus/contacts.rc new file mode 100644 index 0000000000..3edfca49c4 --- /dev/null +++ b/plugins/ContactsPlus/contacts.rc @@ -0,0 +1,191 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SEND DIALOGEX 0, 0, 308, 242 +STYLE DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Send contacts" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_PROTOCOL,"Button",BS_OWNERDRAW | WS_TABSTOP,5,7, + 12,12 + LTEXT "",IDC_NAME,19,7,118,9,SS_NOPREFIX | SS_CENTERIMAGE + CONTROL "&A",IDC_ADD,"MButtonClass",WS_TABSTOP,231,5,16,14, + 0x18000000L + CONTROL "6",IDC_USERMENU,"MButtonClass",WS_TABSTOP,249,5,16,14, + 0x18000000L + CONTROL "&D",IDC_DETAILS,"MButtonClass",WS_TABSTOP,267,5,16,14, + 0x18000000L + CONTROL "&H",IDC_HISTORY,"MButtonClass",WS_TABSTOP,285,5,16,14, + 0x18000000L + CONTROL "Choose contacts to be send:",IDC_STATIC,"Static", + SS_SIMPLE | WS_GROUP,5,20,300,10,WS_EX_TRANSPARENT + DEFPUSHBUTTON "&Send",IDOK,195,220,50,14 + PUSHBUTTON "Cancel",IDCANCEL,249,220,50,14 + CONTROL "",IDC_LIST,"CListControl",WS_TABSTOP | 0x3da,5,30,298, + 185,WS_EX_CLIENTEDGE + PUSHBUTTON "&Select All",ID_SELECTALL,5,220,50,14 +END + +IDD_RECEIVE DIALOGEX 0, 0, 320, 225 +STYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU | WS_THICKFRAME +CAPTION "Received contacts" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_PROTOCOL,"Button",BS_OWNERDRAW | WS_TABSTOP,5,7, + 12,12 + LTEXT "",IDC_NAME,19,7,118,9,SS_NOPREFIX | SS_CENTERIMAGE + CONTROL "&A",IDC_ADD,"MButtonClass",WS_TABSTOP,243,5,16,14, + 0x18000000L + CONTROL "6",IDC_USERMENU,"MButtonClass",WS_TABSTOP,261,5,16,14, + 0x18000000L + CONTROL "&D",IDC_DETAILS,"MButtonClass",WS_TABSTOP,279,5,16,14, + 0x18000000L + CONTROL "&H",IDC_HISTORY,"MButtonClass",WS_TABSTOP,297,5,16,14, + 0x18000000L + CONTROL "",IDC_CONTACTS,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | + WS_BORDER | WS_TABSTOP,5,22,310,178 + CONTROL "Add to &group:",IDC_ENABLEGROUPS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,205,80,12 + COMBOBOX IDC_GROUPS,90,205,72,140,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP | 0x8000 + PUSHBUTTON "&Add",IDOK,169,204,46,14,WS_DISABLED + PUSHBUTTON "&Details",IDDETAILS,215,204,46,14,WS_DISABLED + PUSHBUTTON "Close",IDCANCEL,261,204,52,14 +END + +IDD_MSGSENDERROR DIALOGEX 0, 0, 187, 97 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Contacts send error" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "An error has occured. The protocol reported the following error:", + IDC_STATIC,5,5,177,28 + DEFPUSHBUTTON "Try again",IDOK,22,78,63,14 + PUSHBUTTON "Cancel",IDCANCEL,104,78,61,14 + EDITTEXT IDC_ERRORTEXT,5,37,177,35,ES_MULTILINE | ES_READONLY | + WS_VSCROLL +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO MOVEABLE PURE +BEGIN + IDD_SEND, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 300 + TOPMARGIN, 7 + BOTTOMMARGIN, 235 + END + + IDD_RECEIVE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 313 + TOPMARGIN, 7 + BOTTOMMARGIN, 218 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_CONTACTMENU MENUEX DISCARDABLE +BEGIN + POPUP "Popup", 0,MFT_STRING,MFS_ENABLED + BEGIN + MENUITEM "Add to List", 111,MFT_STRING,MFS_ENABLED + MENUITEM "User Details", 113,MFT_STRING, + MFS_ENABLED | MFS_UNCHECKED | MFS_UNHILITE | MFS_DEFAULT + MENUITEM MFT_SEPARATOR + MENUITEM "Send Message", 112,MFT_STRING,MFS_ENABLED + END +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,5,2,0 + PRODUCTVERSION 0,8,0,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Requires Miranda 0.3+; Recommended Miranda 0.4+\0" + VALUE "CompanyName", "Jokusoftware, Dusk Horizon\0" + VALUE "FileDescription", "Send/Receive Contacts plugin for Miranda (Unicode 2in1)\0" + VALUE "FileVersion", "1, 5, 2, 0\0" + VALUE "InternalName", "contacts+\0" + VALUE "LegalCopyright", "Copyright (C) 2004-2008 Jokusoftware, Original code (C) 2002 Dominus Procellarum\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "contacts.dll\0" + VALUE "ProductName", "Send/Receive Contacts plugin for Miranda\0" + VALUE "ProductVersion", "0, 8, 0, 0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_CONTACTS ICON DISCARDABLE "res\\SendContacts.ico" +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// diff --git a/plugins/ContactsPlus/contacts.sln b/plugins/ContactsPlus/contacts.sln new file mode 100644 index 0000000000..573e39f319 --- /dev/null +++ b/plugins/ContactsPlus/contacts.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "contacts", "contacts.vcxproj", "{3E2FEAB1-3749-A6E4-A81E-54853C5B194E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Unicode|Win32 = Debug Unicode|Win32 + Debug Unicode|x64 = Debug Unicode|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release Unicode|Win32 = Release Unicode|Win32 + Release Unicode|x64 = Release Unicode|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Debug Unicode|x64.ActiveCfg = Debug Unicode|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Debug|Win32.Build.0 = Debug|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Debug|x64.ActiveCfg = Debug|x64 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Debug|x64.Build.0 = Debug|x64 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Release Unicode|Win32.Build.0 = Release Unicode|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Release Unicode|x64.ActiveCfg = Release Unicode|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Release|Win32.ActiveCfg = Release|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Release|Win32.Build.0 = Release|Win32 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Release|x64.ActiveCfg = Release|x64 + {3E2FEAB1-3749-A6E4-A81E-54853C5B194E}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/ContactsPlus/contacts.vcxproj b/plugins/ContactsPlus/contacts.vcxproj new file mode 100644 index 0000000000..0effcb9218 --- /dev/null +++ b/plugins/ContactsPlus/contacts.vcxproj @@ -0,0 +1,578 @@ + + + + + Debug Unicode + Win32 + + + Debug Unicode + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release Unicode + Win32 + + + Release Unicode + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + + + DynamicLibrary + false + MultiByte + true + + + DynamicLibrary + false + MultiByte + true + + + DynamicLibrary + false + MultiByte + + + + + + + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + + + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + + + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + + + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + + + false + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + + + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + + + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + + + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + + + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + + + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + + + + MultiThreadedDLL + OnlyExplicitInline + true + true + Full + true + Level3 + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + Use + contacts.h + Size + true + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\contacts.tlb + true + Win32 + + + 0x0405 + NDEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + false + Console + /ALIGN:4096 /ignore:4108 + comctl32.lib;%(AdditionalDependencies) + true + true + $(IntDir)$(TargetName).lib + UseLinkTimeCodeGeneration + + + + + MultiThreadedDLL + OnlyExplicitInline + true + true + Full + true + Level3 + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + Use + contacts.h + Size + true + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\contacts.tlb + true + + + 0x0405 + NDEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + false + Console + /ALIGN:4096 /ignore:4108 + comctl32.lib;%(AdditionalDependencies) + true + true + $(IntDir)$(TargetName).lib + UseLinkTimeCodeGeneration + + + + + MultiThreadedDLL + OnlyExplicitInline + true + true + Full + true + Level3 + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + Use + contacts.h + Size + true + false + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\contacts.tlb + true + Win32 + + + 0x0405 + NDEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + Console + /ALIGN:4096 /ignore:4108 + comctl32.lib;%(AdditionalDependencies) + true + true + $(IntDir)$(TargetName).lib + UseLinkTimeCodeGeneration + true + + + + + MultiThreadedDLL + OnlyExplicitInline + true + true + Full + true + Level3 + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + Use + contacts.h + Size + true + false + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\contacts.tlb + true + + + 0x0405 + NDEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + Console + /ALIGN:4096 /ignore:4108 + comctl32.lib;%(AdditionalDependencies) + true + true + $(IntDir)$(TargetName).lib + UseLinkTimeCodeGeneration + true + + + + + MultiThreadedDLL + OnlyExplicitInline + true + true + Full + true + Level3 + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + Use + contacts.h + Size + true + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\contacts.tlb + true + + + 0x0405 + NDEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + false + Console + $(IntDir)$(TargetName).lib + /ALIGN:4096 /ignore:4108 + comctl32.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + true + UseLinkTimeCodeGeneration + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + EditAndContinue + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + false + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\contacts.tlb + true + Win32 + + + 0x0405 + _DEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + true + Console + comctl32.lib;%(AdditionalDependencies) + $(IntDir)$(TargetName).lib + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + ProgramDatabase + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + false + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\contacts.tlb + true + + + 0x0405 + _DEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + true + Console + comctl32.lib;%(AdditionalDependencies) + $(IntDir)$(TargetName).lib + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + EditAndContinue + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + false + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\contacts.tlb + true + Win32 + + + 0x0405 + _DEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + true + Console + comctl32.lib;%(AdditionalDependencies) + $(IntDir)$(TargetName).lib + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + ProgramDatabase + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + false + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\contacts.tlb + true + + + 0x0405 + _DEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + true + Console + comctl32.lib;%(AdditionalDependencies) + $(IntDir)$(TargetName).lib + + + + + MultiThreadedDebug + Default + false + Disabled + true + Level3 + ProgramDatabase + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;CONTACTS_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\contacts.tlb + true + + + 0x0405 + _DEBUG;%(PreprocessorDefinitions) + + + true + + + true + true + true + Console + $(IntDir)$(TargetName).lib + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Create + Create + Create + Create + Create + contacts.h + contacts.h + contacts.h + contacts.h + contacts.h + + + Use + Use + Use + Use + Use + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/ContactsPlus/contacts.vcxproj.filters b/plugins/ContactsPlus/contacts.vcxproj.filters new file mode 100644 index 0000000000..8270d92a72 --- /dev/null +++ b/plugins/ContactsPlus/contacts.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {c0e9ea51-8fc0-4db3-a0d9-491b3e4fecde} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {05b2429f-b6fd-4862-97a2-f5686ee35703} + h;hpp;hxx;hm;inl + + + {56ec564b-af99-40f8-ae70-af5307bdc3f5} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/plugins/ContactsPlus/langpack_contacts.txt b/plugins/ContactsPlus/langpack_contacts.txt new file mode 100644 index 0000000000..13341fc88a --- /dev/null +++ b/plugins/ContactsPlus/langpack_contacts.txt @@ -0,0 +1,33 @@ +;[Incoming Contacts] +;[Outgoing Contacts] +;[Contacts received from] +;[Contacts] +;[Error] + +; receive dlg +;[Contacts from] +;[Nick] +;[First Name] +;[Last Name] +;[Add to &group:] +;[&Add] +;[&Details] +;[Close] +;[Add to List] +;[User Details] +;[Send Message] + +;send dlg +;[Send Contacts to] +;[The contacts send timed out.] +;[Contacts transfer failed!] +;[The selected contact does not support receiving contacts.] +;[Choose contacts to be send:] +;[&Send] +;[Cancel] +;[Select All] + +;error dlg +;[An error has occured. The protocol reported the following error:] +;[Try again] +;[Cancel] \ No newline at end of file diff --git a/plugins/ContactsPlus/main.cpp b/plugins/ContactsPlus/main.cpp new file mode 100644 index 0000000000..7f167c84d0 --- /dev/null +++ b/plugins/ContactsPlus/main.cpp @@ -0,0 +1,363 @@ +// -------------------------------------------------------------------------- +// Contacts+ for Miranda Instant Messenger +// _______________________________________ +// +// Copyright © 2002 Dominus Procellarum +// Copyright © 2004-2008 Joe Kucera +// +// 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. +// +// ----------------------------------------------------------------------------- + +#include "contacts.h" + + +HINSTANCE hInst; + +PLUGINLINK *pluginLink; + +int g_NewProtoAPI = FALSE; + +int g_SendAckSupported = FALSE; +int g_Utf8EventsSupported = FALSE; + +HANDLE ghSendWindowList; +HANDLE ghRecvWindowList; +gAckList gaAckData; + +HANDLE hServiceSend; +HANDLE hServiceReceive; + +HANDLE hHookModulesLoaded = NULL; +HANDLE hHookDBEventAdded = NULL; +HANDLE hHookContactDeleted = NULL; +HANDLE hHookContactSettingChanged = NULL; +HANDLE hHookPreBuildContactMenu = NULL; + +HANDLE hContactMenuItem = NULL; + +int g_UnicodeCore; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), +#ifdef WIN64 + "Send/Receive Contacts+ (x64)", +#else + "Send/Receive Contacts+", +#endif + PLUGIN_MAKE_VERSION(1,5,2,0), + "Allows you to send and receive contacts", + "Joe Kucera, Todor Totev", + "jokusoftware@miranda-im.org", + "(C) 2004-2008 Joe Kucera, Original Code (C) 2002 Dominus Procellarum", + "http://addons.miranda-im.org/details.php?action=viewfile&id=1253", + 0, //no flags by default + 0, //doesn't replace anything built-in + {0x0324785E, 0x74CE, 0x4600, {0xB7, 0x81, 0x85, 0x17, 0x73, 0xB3, 0xEF, 0xC5 } } // {0324785E-74CE-4600-B781-851773B3EFC5} +}; + + +static int HookDBEventAdded(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + HANDLE hDbEvent = (HANDLE)lParam; + //process the event + DBEVENTINFO dbe = {0}; + + dbe.cbSize = sizeof(DBEVENTINFO); + //get event details + CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbe); + //check if we should process the event + if (dbe.flags & (DBEF_SENT|DBEF_READ) || dbe.eventType != EVENTTYPE_CONTACTS) return 0; + //get event contents + dbe.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0); + if (dbe.cbBlob != -1) + dbe.pBlob = (PBYTE)_alloca(dbe.cbBlob); + CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbe); + //play received sound + SkinPlaySound("RecvContacts"); + { //add event to the contact list + CLISTEVENT cle = {0}; + TCHAR caToolTip[128]; + + cle.cbSize = sizeof(cle); + cle.hContact = hContact; + cle.hDbEvent = hDbEvent; + cle.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CONTACTS)); + cle.pszService = MS_CONTACTS_RECEIVE; + + WCHAR tmp[MAX_PATH]; + _snprintfT(caToolTip, 64, "%s %s", SRCTranslateT("Contacts received from", tmp), (TCHAR*)GetContactDisplayNameT(hContact)); + + cle.ptszTooltip = caToolTip; + if (g_UnicodeCore) + cle.flags |= CLEF_UNICODE; + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); + } + return 0; //continue processing by other hooks +} + + +static void ProcessUnreadEvents(void) +{ + DBEVENTINFO dbei = {0}; + HANDLE hDbEvent,hContact; + + dbei.cbSize = sizeof(dbei); + + hContact = SRCFindFirstContact(); + while (hContact) + { + hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRSTUNREAD,(WPARAM)hContact,0); + + while (hDbEvent) + { + dbei.cbBlob=0; + CallService(MS_DB_EVENT_GET,(WPARAM)hDbEvent,(LPARAM)&dbei); + if (!(dbei.flags&(DBEF_SENT|DBEF_READ)) && dbei.eventType==EVENTTYPE_CONTACTS) + { //process the event + HookDBEventAdded((WPARAM)hContact, (LPARAM)hDbEvent); + } + hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0); + } + hContact = SRCFindNextContact(hContact); + } +} + + +static bool CheckContactsServiceSupport(const char* szProto) +{ + if (g_NewProtoAPI) + { // there is no way to determine if the service exists (only proto_interface call is supported by 0.8+) + if (SRCCallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_CONTACTSEND) + return true; + } + else + { // check the real send service (only 0.7.x and older) + char serstr[MAX_PATH+30]; + + strcpy(serstr, szProto); + strcat(serstr, PSS_CONTACTS); + if (ServiceExists(serstr)) + return true; + } + return false; +} + + +static int HookPreBuildContactMenu(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + char* szProto = GetContactProto(hContact); + int bVisible = FALSE; + + if (szProto && CheckContactsServiceSupport(szProto)) + { // known protocol, protocol supports contacts sending + // check the selected contact if it supports contacts receive + if (SRCCallProtoService(szProto, PS_GETCAPS, PFLAG_MAXCONTACTSPERPACKET, (LPARAM)hContact)) + bVisible = TRUE; + } + + { // update contact menu item's visibility + CLISTMENUITEM mi = {0}; + + mi.cbSize = sizeof(mi); + if (bVisible) + mi.flags = CMIM_FLAGS; + else + mi.flags = CMIM_FLAGS | CMIF_HIDDEN; + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuItem, (LPARAM)&mi); + } + + return 0; +} + + +static int HookModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + char* modules[2] = {0}; + WCHAR tmp[MAX_PATH]; + + modules[0] = MODULENAME; + CallService("DBEditorpp/RegisterModule",(WPARAM)modules,(LPARAM)1); + + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(mi); + mi.ptszName = SRCTranslateT("Contacts", tmp); + mi.position = -2000009990; //position in menu + mi.flags = CMIF_KEEPUNTRANSLATED; + if (g_UnicodeCore) + mi.flags |= CMIF_UNICODE; + mi.pszService = MS_CONTACTS_SEND; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CONTACTS)); + + hContactMenuItem = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi); + hHookPreBuildContactMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, HookPreBuildContactMenu); + + ghSendWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); // no need to destroy this + ghRecvWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); // no need to destroy this + +#ifndef WIN64 + //register for Update (the FL name is different...) + CallService(MS_UPDATE_REGISTERFL, 1253, (WPARAM)&pluginInfo); +#endif + + ProcessUnreadEvents(); + return 0; +} + + +static int HookContactSettingChanged(WPARAM wParam, LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; + char *szProto = GetContactProto((HANDLE)wParam); + + if (strcmpnull(cws->szModule,"CList") && strcmpnull(cws->szModule, szProto)) return 0; + + WindowList_Broadcast(ghSendWindowList,DM_UPDATETITLE,0,0); + WindowList_Broadcast(ghRecvWindowList,DM_UPDATETITLE,0,0); + + return 0; +} + + +static int HookContactDeleted(WPARAM wParam, LPARAM lParam) +{ // if our contact gets deleted close his window + HWND h = WindowList_Find(ghSendWindowList,(HANDLE)wParam); + + if (h) + { + SendMessageT(h,WM_CLOSE,0,0); + } + + while (h = WindowList_Find(ghRecvWindowList, (HANDLE)wParam)) + { // since we hack the window list - more windows for one contact, we need to close them all + SendMessageT(h, WM_CLOSE,0,0); + } + return 0; +} + + +static INT_PTR ServiceSendCommand(WPARAM wParam, LPARAM lParam) +{ + HWND hWnd; + //find window for hContact + hWnd = WindowList_Find(ghSendWindowList, (HANDLE)wParam); + + if (!hWnd) + CreateDialogParamT(hInst, MAKEINTRESOURCE(IDD_SEND), NULL, SendDlgProc, (LPARAM)(HANDLE)wParam); + else + { + SetForegroundWindow(hWnd); + SetFocus(hWnd); + } + return 0; +} + +static INT_PTR ServiceReceiveCommand(WPARAM wParam, LPARAM lParam) +{ + CLISTEVENT* pcle = (CLISTEVENT*)lParam; + + CreateDialogParamT(hInst, MAKEINTRESOURCE(IDD_RECEIVE), NULL, RecvDlgProc, (LPARAM)pcle); + + return 0; +} + + +static void* PrepareMirandaPluginInfo(DWORD mirandaVersion) +{ + if (!(mirandaVersion >= PLUGIN_MAKE_VERSION(0,4,0,0))) + pluginInfo.description = "Allows you to send and receive contacts; Please upgrade your Miranda IM to version 0.4 for better functionality."; + else + g_SendAckSupported = TRUE; + + if (mirandaVersion >= PLUGIN_MAKE_VERSION(0,7,0,0)) + g_Utf8EventsSupported = TRUE; + + if (mirandaVersion >= PLUGIN_MAKE_VERSION(0,8,0,8)) + g_NewProtoAPI = TRUE; + + if (mirandaVersion >= PLUGIN_MAKE_VERSION(0,3,3,0)) + { + // Are we running under Unicode Windows version ? + if ((GetVersion() & 0x80000000) == 0) + { + pluginInfo.flags = 1; // UNICODE_AWARE + } + return &pluginInfo; + } + return NULL; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + pluginInfo.cbSize = sizeof(PLUGININFOEX); + return (PLUGININFOEX*)PrepareMirandaPluginInfo(mirandaVersion); +} + +extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) +{ + pluginInfo.cbSize = sizeof(PLUGININFO); + return (PLUGININFO*)PrepareMirandaPluginInfo(mirandaVersion); +} + +static const MUUID interfaces[] = {MIID_SRCONTACTS, MIID_LAST}; +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +extern "C" __declspec(dllexport) int Load(PLUGINLINK *link) +{ + pluginLink = link; + InitCommonControls(); + InitI18N(); + + { // Are we running under unicode Miranda core ? + char szVer[MAX_PATH]; + + CallService(MS_SYSTEM_GETVERSIONTEXT, MAX_PATH, (LPARAM)szVer); + _strlwr(szVer); + g_UnicodeCore = (strstr(szVer, "unicode") != NULL); + } + //init hooks + hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, HookModulesLoaded); + hHookDBEventAdded = HookEvent(ME_DB_EVENT_ADDED, HookDBEventAdded); + hHookContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, HookContactDeleted); + hHookContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, HookContactSettingChanged); + //create services + hServiceSend = CreateServiceFunction(MS_CONTACTS_SEND, ServiceSendCommand); + hServiceReceive = CreateServiceFunction(MS_CONTACTS_RECEIVE, ServiceReceiveCommand); + //define event sounds + SkinAddNewSound("RecvContacts", LPGEN("Incoming Contacts"), "contacts.wav"); + SkinAddNewSound("SentContacts", LPGEN("Outgoing Contacts"), "ocontacts.wav"); + + return 0; +} + +extern "C" __declspec(dllexport) int Unload(void) +{ + UnhookEvent(hHookModulesLoaded); + UnhookEvent(hHookDBEventAdded); + UnhookEvent(hHookContactDeleted); + UnhookEvent(hHookContactSettingChanged); + UnhookEvent(hHookPreBuildContactMenu); + + DestroyServiceFunction(hServiceSend); + DestroyServiceFunction(hServiceReceive); + + return 0; +} diff --git a/plugins/ContactsPlus/readme_contacts.txt b/plugins/ContactsPlus/readme_contacts.txt new file mode 100644 index 0000000000..f3ae933be3 --- /dev/null +++ b/plugins/ContactsPlus/readme_contacts.txt @@ -0,0 +1,158 @@ +About +----- + +Send and receive contacts ui +Version 1.5.2.0 +by Joe Kucera aka Jokusoftware +Original Code by Todor Totev aka Dominus Procellarum +for use with Miranda IM 0.3.3+ +Best for Miranda IM 0.4+ + + +Description +----------- + +This plugin allows you to send and receive contacts. +It is protocol independent, although currently the only +protocol supporting contacts transfer is ICQ. + + +Installation +------------ + +For the contactsp.zip zip archive - + Extract contacts.dll to Miranda plugin folder - + usually this is C:\Program Files\Miranda\Plugins. + All other files are not mandatory and can go to Miranda folder. + + +Source +------ + +The source code for this plugin can be downloaded from Miranda IM +website http://addons.miranda-im.org. + + +License +------- + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. +2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. +3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. +4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +For more information, e-mail jokusoftware@miranda-im.org + + +Version history +--------------- +1.0.11.0 + initial release - working ui, but M is still crashing +1.0.12.0 + 20-may night build of M - underlying code is OK, so i can continue this plugin + remove inverse logic in MirandaPluginInfo() + removed #include "win2k.h" for cleaner build + attempt to show more user info on receive contacts +1.0.13.0 + cleaned main.cpp + added icon to dialogue windows +1.0.14.0 + Nick / UIN swapped upon showing received contacts /silly me/ + bigger size of nick string allowed to accomodate non-english nicks /cyrrilic letters requires 2 times more bytes/ + added icon for menu item +1.0.15.0 + list columns default size is more convinient + save restore window position / size +1.0.16.0 + receive dlg is resizable one /thanks to WTL there was virtually no code to write/ +1.0.17.0 + add button is enabled only when at least one item in the list view is checked-in +1.0.18.0 + more translate()-friendly + at last contacts are permanently added to DB +1.0.19.0 + receive window is now being put on top + lots of big-fixes +1.1.0.0 + source beautify + receive user iface and internal dependancies re-design + now only contacts which details are requested are being added to the DB + std::vector is used instead of std::deque for 10KB smaller dll + this should be the official release build + you can get detailed info about contacts being sent to you + more bug fixes +1.2.0.0 + bugfix - contacts are always being added outside any group /forget actually writing to the DB/ + sending contacts is now a Miranda service, accessible via m_contacts.h + implemented contactlist event, no more popup windows + NOTE: the langpack is modified, because my english is at least questionable and some items are now obsolete + +1.4.0.0 (New developer: Joe @ Whale, jokusoftware@miranda-im.org) + now fully protocol independent + made sending with full acknowledgement (needs miranda 0.3.4alpha) & improved Send Dialog + now sent contacts are added to history (can be viewed by e.g. History++) + improved Receive Dialog - added popup & some convenient functions, display more info (like ICQ) + many fixes +1.4.1.3 + fixed multipacket sending (if 15 contacts, do not try to send empty packet) + optimisations (reimplemented many structures, size cut by 20kB) + when contact gets deleted close his send window + redesigned Send dialog - more nice & effective (show only contacts of the same protocol + many more) + grouplist on receive dialog now gets updated +1.4.1.7 + redesigned and improved Received dialog (get rid of WTL & MFC) + empty groups in send dialog are hidden according to clui setting + fixed multi-packet error handling + fixed crashes on exit (thanks to Ghazan) + small fixes +1.4.1.8 + fixed received dialog not showed on some systems + other small fixes +1.4.2.0 + fixed memory leak on any event received (thx to Ghazan) + fixed other small memory leaks + popup menu on Received dialog gets translated now + added DBE3++ Known Modules support +1.5.0.0 + many internal optimisations + added Unicode 2in1 support + added support for Unicode ready DB contacts events + added Updater plug-in support +1.5.1.0 + added support for per-contact contacts API capabilities + improved compatibility with unicode database API + added support for new clist groups API + several internal fixes & improvements +1.5.2.0 + fixed possible crash during contacts send (with older Miranda IM) + fixed compatibility with the new Account API introduced in Miranda IM 0.8 + + +Translation +----------- + +Contacts plugin can be translated via the Miranda language files. +The required strings are provided in langpack_contacts.txt file. diff --git a/plugins/ContactsPlus/receive.cpp b/plugins/ContactsPlus/receive.cpp new file mode 100644 index 0000000000..24caf66a5a --- /dev/null +++ b/plugins/ContactsPlus/receive.cpp @@ -0,0 +1,522 @@ +// -------------------------------------------------------------------------- +// Contacts+ for Miranda Instant Messenger +// _______________________________________ +// +// Copyright © 2002 Dominus Procellarum +// Copyright © 2004-2008 Joe Kucera +// +// 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. +// +// ----------------------------------------------------------------------------- + +#include "contacts.h" + + +/* TRecvContactsData */ + +TReceivedItem* TRecvContactsData::AddReceivedItem() { + int iItem = cbReceived; + + cbReceived++; + maReceived = (TReceivedItem**)realloc(maReceived, cbReceived*sizeof(TReceivedItem*)); + maReceived[iItem] = new TReceivedItem(); + + return maReceived[iItem]; +} + + +static int RecvDlg_Resize(HWND hwndDlg,LPARAM lParam,UTILRESIZECONTROL *urc) +{ + switch (urc->wId) + { + case IDC_CONTACTS: + return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + break; + case IDOK: + case IDDETAILS: + case IDC_ENABLEGROUPS: + case IDC_GROUPS: + return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; + break; + case IDC_ADD: + case IDC_HISTORY: + case IDC_USERMENU: + case IDC_DETAILS: + return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP; + break; + case IDCANCEL: + return RD_ANCHORY_BOTTOM | RD_ANCHORX_RIGHT; + break; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; // default +} + + +static char* ListView_GetItemTextEx(HWND hLV, int iItem, int iSubItem) +{ + LVITEM lvi = {0}; + + lvi.mask = LVIF_TEXT; + lvi.iSubItem = iSubItem; + lvi.cchTextMax = 64; + lvi.pszText = (char*)malloc(lvi.cchTextMax); + while (SendMessageT(hLV, LVM_GETITEMTEXT, iItem, (LPARAM)&lvi) == lvi.cchTextMax - 1) + { // loop until the returned size is smaller than buffer size + SAFE_FREE((void**)&lvi.pszText); + lvi.cchTextMax += 64; + lvi.pszText = (char*)malloc(lvi.cchTextMax); + } + return lvi.pszText; +} + + +static void EnableGroupCombo(HWND hwndDlg) +{ + EnableDlgItem(hwndDlg, IDC_GROUPS, SendMessageT(GetDlgItem(hwndDlg, IDC_ENABLEGROUPS), BM_GETCHECK, 0, 0)); +} + + +static void RebuildGroupCombo(HWND hwndDlg) +{ + DBVARIANT dbv = {0}; + char caGroupId[33]; + int bHasGroups = !DBGetContactSettingT(NULL, "CListGroups", "0", &dbv); + HWND hGroupsCombo = GetDlgItem(hwndDlg, IDC_GROUPS); + + DBFreeVariant(&dbv); + if (bHasGroups) + { + int curs = SendMessageT(hGroupsCombo, CB_GETCURSEL, 0, 0); + TCHAR* curst; + + EnableDlgItem(hwndDlg, IDC_ENABLEGROUPS, TRUE); + EnableGroupCombo(hwndDlg); + + if (curs != CB_ERR) + { + curst = (char*)_alloca((SendMessageT(hGroupsCombo, CB_GETLBTEXTLEN, curs, 0) + 1) * sizeof(WCHAR)); + SendMessageT(hGroupsCombo, CB_GETLBTEXT, curs, (LPARAM)curst); + } + SendMessageT(hGroupsCombo, CB_RESETCONTENT, 0, 0); + + for (int groupId=0; ; groupId++) + { + itoa(groupId, caGroupId, 10); + TCHAR* szGroup = DBGetContactSettingStringT(NULL, "CListGroups", caGroupId, NULL); + int nPrefix = g_UnicodeCore ? sizeof(WCHAR) : sizeof(char); + if (!szGroup) break; + int nIndex = SendMessageT(hGroupsCombo, CB_ADDSTRING, 0, (LPARAM)szGroup + nPrefix); + SendMessageT(hGroupsCombo, CB_SETITEMDATA, nIndex, groupId+1); + SAFE_FREE((void**)&szGroup); + } + if (curs != CB_ERR) + SendMessageT(hGroupsCombo, CB_SELECTSTRING, -1, (LPARAM)curst); + else + SendMessageT(hGroupsCombo, CB_SETCURSEL, 0, 0); + } + else + { // no groups available + EnableDlgItem(hwndDlg, IDC_ENABLEGROUPS, FALSE); + EnableDlgItem(hwndDlg, IDC_GROUPS, FALSE); + } +} + + +static HANDLE CreateTemporaryContactForItem(HWND hwndDlg, TRecvContactsData* wndData, int iItem) +{ + char* caUIN = ListView_GetItemTextEx(GetDlgItem(hwndDlg, IDC_CONTACTS), iItem, 0); + char* szProto = GetContactProto(wndData->mhContact); + wndData->rhSearch = (HANDLE)SRCCallProtoService(szProto, PS_BASICSEARCH, 0, (LPARAM)caUIN); // find it + SAFE_FREE((void**)&wndData->haUin); + wndData->haUin = caUIN; + for (int j = 0; j < wndData->cbReceived; j++) + if (!strcmpnull(wndData->maReceived[j]->mcaUIN, caUIN)) + return (HANDLE)SRCCallProtoService(szProto, PS_ADDTOLISTBYEVENT, MAKEWPARAM(PALF_TEMPORARY, j), (LPARAM)wndData->mhDbEvent); + return NULL; +} + + +void RecvListView_AddColumn(HWND hList, int nWidth, const char* szTitle, int nTranslate, int nItem) { + LVCOLUMN col; + WCHAR tmp[MAX_PATH]; + + + col.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM; + col.fmt = LVCFMT_LEFT; + col.cx = nWidth; + if (nTranslate) { + col.pszText = SRCTranslateT(szTitle, tmp); + } + else { + if (!szTitle) szTitle = "UID"; + col.pszText = ansi_to_tchar(szTitle, CallService(MS_LANGPACK_GETCODEPAGE, 0, 0)); + } + col.iSubItem = nItem; + ListView_InsertColumnT(hList, nItem, &col); + if (!nTranslate) + SAFE_FREE((void**)&col.pszText); +} + + +INT_PTR CALLBACK RecvDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TRecvContactsData* wndData = (TRecvContactsData*)GetWindowLong(hwndDlg, DWLP_USER); + + switch (msg) + { + case WM_INITDIALOG: + { + CLISTEVENT* pcle = (CLISTEVENT*)lParam; /// got it + + TranslateDialogDefault(hwndDlg); + WindowList_Add(ghRecvWindowList, hwndDlg, pcle->hContact); + SendMessageT(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_CONTACTS))); + EnableDlgItem(hwndDlg, IDOK, FALSE); + EnableDlgItem(hwndDlg, IDDETAILS, FALSE); + wndData = new TRecvContactsData(pcle->hContact); + SetWindowLong(hwndDlg, DWLP_USER, (LONG)wndData); + wndData->mhDbEvent = pcle->hDbEvent; /// initialized, pcle not needed anymore + wndData->mhListIcon = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLORDDB|ILC_MASK, 0, 1); + wndData->mhPopup = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTACTMENU)); + CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)wndData->mhPopup, 0); + wndData->hHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_EVENTSENT); + + char *szProto = GetContactProto(wndData->mhContact); + + HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); + ListView_SetExtendedListViewStyle(hLV, LVS_EX_CHECKBOXES|LVS_EX_FULLROWSELECT); + // add columns + RecvListView_AddColumn(hLV, 120, (char*)SRCCallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDTEXT, 0), FALSE, 0); + RecvListView_AddColumn(hLV, 100, "Nick", TRUE, 1); + RecvListView_AddColumn(hLV, 100, "First Name", TRUE, 2); + RecvListView_AddColumn(hLV, 100, "Last Name", TRUE, 3); + + // fill in groups + SendMessageT(GetDlgItem(hwndDlg, IDC_ENABLEGROUPS), BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); + RebuildGroupCombo(hwndDlg); + + { // fill listview with received contacts + DBEVENTINFO dbe = {0}; + + dbe.cbSize = sizeof(DBEVENTINFO); + dbe.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)wndData->mhDbEvent, 0); + if (dbe.cbBlob != -1) // this marks an invalid hDbEvent - all smashed anyway... + dbe.pBlob = (PBYTE)_alloca(dbe.cbBlob); + CallService(MS_DB_EVENT_GET, (WPARAM)wndData->mhDbEvent, (LPARAM)&dbe); + char* pcBlob = (char*)dbe.pBlob; + char* pcEnd = (char*)dbe.pBlob + dbe.cbBlob; + + HICON hiProto = LoadContactProtoIcon(wndData->mhContact); + ImageList_AddIcon(wndData->mhListIcon, hiProto); + DestroyIcon(hiProto); // imagelist copied the resource + ListView_SetImageList(hLV, wndData->mhListIcon, LVSIL_SMALL); + LVITEM lvi = {0}; + lvi.iImage = 0; + lvi.mask = LVIF_TEXT | LVIF_IMAGE; + + for (int nItem = 0; ; nItem++) + { // Nick + int strsize = (int)strlennull(pcBlob); + TReceivedItem* pItem = wndData->AddReceivedItem(); + + if (dbe.flags & DBEF_UTF) + pItem->mcaNick = utf8_to_tchar((unsigned char*)pcBlob); + else + pItem->mcaNick = ansi_to_tchar(pcBlob); + pcBlob += strsize + 1; + // UIN + strsize = (int)strlennull(pcBlob); + pItem->mcaUIN = null_strdup(pcBlob); + pcBlob += strsize + 1; + // add to listview + lvi.iItem = nItem; + lvi.pszText = pItem->mcaUIN; + ListView_InsertItem(hLV, &lvi); // with image + ListView_SetItemTextT(hLV, nItem, 1, pItem->mcaNick); + // check for end of contacts + if (pcBlob >= pcEnd) + break; + } + } + // new dlg init + wndData->hIcons[0] = InitMButton(hwndDlg, IDC_ADD, MAKEINTRESOURCEA(IDI_ADDCONTACT), "Add Contact Permanently to List"); + wndData->hIcons[1] = InitMButton(hwndDlg, IDC_DETAILS, MAKEINTRESOURCEA(IDI_USERDETAILS), "View User's Details"); + wndData->hIcons[2] = InitMButton(hwndDlg, IDC_HISTORY, MAKEINTRESOURCEA(IDI_HISTORY), "View User's History"); + wndData->hIcons[3] = InitMButton(hwndDlg, IDC_USERMENU, MAKEINTRESOURCEA(IDI_DOWNARROW), "User Menu"); + + SendMessageT(hwndDlg,DM_UPDATETITLE,0,0); + // new dialog init done + Utils_RestoreWindowPosition(hwndDlg, NULL, MODULENAME, ""); + return TRUE; + } + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == IDC_CONTACTS) + { + switch (((LPNMHDR)lParam)->code) + { + case NM_DBLCLK: + { + HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); + if (ListView_GetSelectedCount(hLV) != 1) break; // if not clicking on item, bye + wndData->iPopupItem = ListView_GetNextItem(hLV, -1, LVNI_ALL|LVNI_SELECTED); + if (wndData->iPopupItem == -1) break; // if no item selected no user details available + return SendMessageT(hwndDlg, WM_COMMAND, ID_POPUP_USERDETAILS, 0); // show user details + } + case LVN_ITEMCHANGED: + { + LPNMLISTVIEW pNMLV = (LPNMLISTVIEW)lParam; + HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); // optimisation, for FOR-Cycle + bool bExistsCheckedItem = false; // there must be no checked items to disable "Add" button + + if (ListView_GetCheckState(hLV, pNMLV->iItem)) + { // the user has checked this item + bExistsCheckedItem = true; // enable "Add" button + } + else + { // loop thru items and check if at least one is checked + for (int i = 0; i < ListView_GetItemCount(hLV); i++) + if (ListView_GetCheckState(hLV, i)) + { // we found checked item, enable add, exit loop + bExistsCheckedItem = true; + break; + } + } + EnableDlgItem(hwndDlg, IDOK, bExistsCheckedItem); + EnableDlgItem(hwndDlg, IDDETAILS, ListView_GetSelectedCount(hLV) > 0); + break; + } + } + } + break; + + case WM_COMMAND: + { + if (!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)wndData->mhContact)) + break; + + switch(LOWORD(wParam)) + { + case IDOK: // "Add Selected" button click + { // for each selected item, find its index in the hDbEvent + // and after that add this item to the DB permanently + char* caUIN; + HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); + HWND hGroupsCombo = GetDlgItem(hwndDlg, IDC_GROUPS); + HWND hGroupsCheck = GetDlgItem(hwndDlg, IDC_ENABLEGROUPS); + int curs = SendMessageT(hGroupsCombo, CB_GETCURSEL, 0, 0); + TCHAR* caGroup = NULL; + int nGroupId = -1; + if (curs != CB_ERR && IsWindowEnabled(hGroupsCheck) && SendMessageT(hGroupsCheck, BM_GETCHECK, 0, 0)) + { //got groups, get the one selected in combo + TCHAR* caGroup = (TCHAR*)_alloca((SendMessageT(hGroupsCombo, CB_GETLBTEXTLEN, curs, 0) + 1) * sizeof(WCHAR)); + SendMessageT(hGroupsCombo, CB_GETLBTEXT, curs, (LPARAM)caGroup); + nGroupId = SendMessageT(hGroupsCombo, CB_GETITEMDATA, curs, 0); + } + + for (int i = 0; i < ListView_GetItemCount(hLV); i++) + if (ListView_GetCheckState(hLV, i)) + { // found checked contact item, add it + caUIN = ListView_GetItemTextEx(hLV, i, 0); + for (int j = 0; j < wndData->cbReceived; j++) // determine item index in packet + if (!strcmpnull(wndData->maReceived[j]->mcaUIN, caUIN)) + { + char* szProto = GetContactProto(wndData->mhContact); + HANDLE hContact = (HANDLE)SRCCallProtoService(szProto, PS_ADDTOLISTBYEVENT, MAKEWPARAM(0, j), (LPARAM)wndData->mhDbEvent); + if (hContact && caGroup) + { // use newest group API if available + if (ServiceExists(MS_CLIST_CONTACTCHANGEGROUP)) + CallService(MS_CLIST_CONTACTCHANGEGROUP, (WPARAM)hContact, (LPARAM)nGroupId); + else + DBWriteContactSettingStringT(hContact, "CList", "Group", caGroup); + } + break; + } + SAFE_FREE((void**)&caUIN); + } // move to next item + break; + } + case IDDETAILS: + { // for each selected item, find its index in the hDbEvent + // and after that add this item to the DB + // finally, request Details window for this hContact + HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); + for (int i = 0; i < ListView_GetItemCount(hLV); i++) + if (ListView_GetItemState(hLV, i, LVIS_SELECTED)) + { + HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, i); + if (hContact) + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0); + } + break; + } + case IDCANCEL: + { + SendMessageT(hwndDlg, WM_CLOSE, 0, 0); + break; + } + case IDC_ENABLEGROUPS: + { + EnableGroupCombo(hwndDlg); + break; + } + case IDC_GROUPS: + { // rebuild group list on popup + if (HIWORD(wParam) == CBN_DROPDOWN) + RebuildGroupCombo(hwndDlg); + break; + } + case ID_POPUP_ADDUSER: + { + HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, wndData->iPopupItem); + + if (hContact) + DialogAddContactExecute(hwndDlg, hContact); + break; + } + case ID_POPUP_USERDETAILS: + { + HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, wndData->iPopupItem); + + if (hContact) + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0 ); + break; + } + case ID_POPUP_SENDMESSAGE: + { + HANDLE hContact = CreateTemporaryContactForItem(hwndDlg, wndData, wndData->iPopupItem); + + if (hContact) + CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0); + break; + } + case IDC_USERMENU: + { + RECT rc; + HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)wndData->mhContact, 0); + GetWindowRect(GetDlgItem(hwndDlg,IDC_USERMENU), &rc); + TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + break; + } + case IDC_HISTORY: + CallService(MS_HISTORY_SHOWCONTACTHISTORY,(WPARAM)wndData->mhContact,0); + break; + case IDC_DETAILS: + CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)wndData->mhContact,0); + break; + case IDC_ADD: + DialogAddContactExecute(hwndDlg, wndData->mhContact); + break; + } + break; + } + case WM_CONTEXTMENU: + { + HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); + LVHITTESTINFO lvh; + RECT rt; + + wndData->iPopupItem = -1; + if ((HWND)wParam != hLV) break; // if not our ListView go away + lvh.pt.x = LOWORD(lParam); + lvh.pt.y = HIWORD(lParam); + if (GetWindowRect(hLV, &rt)==0) return FALSE; // ?? why this, some check ?? + ScreenToClient(hLV, &lvh.pt); // convert to ListView local coordinates + int ci = ListView_HitTest(hLV, &lvh); + if (ci==-1) break; // mouse is not over any item + wndData->iPopupItem = ci; + TrackPopupMenu(GetSubMenu(wndData->mhPopup, 0), TPM_LEFTALIGN|TPM_TOPALIGN, LOWORD(lParam), HIWORD(lParam), 0, hwndDlg, NULL); + break; + } + case HM_EVENTSENT: + { + ACKDATA *ack=(ACKDATA*)lParam; + if (ack->type!=ACKTYPE_SEARCH) break; // not search ack, go away + if (ack->hProcess!=wndData->rhSearch) break; //not our search, go away + if (ack->result==ACKRESULT_DATA) + { + HWND hLV = GetDlgItem(hwndDlg, IDC_CONTACTS); + PROTOSEARCHRESULT* psr = (PROTOSEARCHRESULT*)ack->lParam; + LVFINDINFO fi; + fi.flags = LVFI_STRING; + fi.psz = wndData->haUin; + int iLPos = ListView_FindItem(hLV, -1, &fi); + if (iLPos==-1) iLPos=0; +// ListView_SetItemText(hLV, iLPos, 0, psr->email); // not sent by ICQ, and currently unsupported either + if (strcmpnull(psr->nick, "") && psr->nick) ListView_SetItemText(hLV, iLPos, 1, psr->nick); + ListView_SetItemText(hLV, iLPos, 2, psr->firstName); + ListView_SetItemText(hLV, iLPos, 3, psr->lastName); + break; + } + SAFE_FREE((void**)&wndData->haUin); + break; + } + case WM_CLOSE: // user closed window, so destroy it + { + WindowList_Remove(ghRecvWindowList, hwndDlg); + DestroyWindow(hwndDlg); + break; + } + case WM_DESTROY: // last message received by this dialog, cleanup + { + CallService(MS_DB_EVENT_MARKREAD, (WPARAM)wndData->mhContact, (LPARAM)wndData->mhDbEvent); + Utils_SaveWindowPosition(hwndDlg, NULL, MODULENAME, ""); + ImageList_Destroy(wndData->mhListIcon); + UnhookEvent(wndData->hHook); + DestroyMenu(wndData->mhPopup); + for (int i=0; i < SIZEOF(wndData->hIcons); i++) + DestroyIcon(wndData->hIcons[i]); + delete wndData; // automatically calls destructor + break; + } + case WM_MEASUREITEM: + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + + case WM_DRAWITEM: + { + DrawProtocolIcon(hwndDlg, lParam, wndData->mhContact); + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + } + case WM_SIZE: + { // make the dlg resizeable + UTILRESIZEDIALOG urd = {0}; + + if (IsIconic(hwndDlg)) break; + urd.cbSize = sizeof(urd); + urd.hInstance = hInst; + urd.hwndDlg = hwndDlg; + urd.lParam = 0; // user-defined + urd.lpTemplate = MAKEINTRESOURCEA(IDD_RECEIVE); + urd.pfnResizer = RecvDlg_Resize; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd); + break; + } + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi=(MINMAXINFO*)lParam; + mmi->ptMinTrackSize.x = 480+2*GetSystemMetrics(SM_CXSIZEFRAME); + mmi->ptMinTrackSize.y = 130+2*GetSystemMetrics(SM_CYSIZEFRAME); + break; + } + case DM_UPDATETITLE: + { + UpdateDialogTitle(hwndDlg, wndData?wndData->mhContact:NULL, "Contacts from"); + if (wndData) + UpdateDialogAddButton(hwndDlg, wndData->mhContact); + break; + } + } + return FALSE; +} diff --git a/plugins/ContactsPlus/receive.h b/plugins/ContactsPlus/receive.h new file mode 100644 index 0000000000..fe35d94be6 --- /dev/null +++ b/plugins/ContactsPlus/receive.h @@ -0,0 +1,65 @@ +// --------------------------------------------------------------------------- +// Contacts+ for Miranda Instant Messenger +// _______________________________________ +// +// Copyright © 2002 Dominus Procellarum +// Copyright © 2004-2008 Joe Kucera +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// --------------------------------------------------------------------------- + +#ifndef __RECEIVE_H +#define __RECEIVE_H + + +#define HM_EVENTSENT (WM_USER+10) + +#define DM_UPDATETITLE (WM_USER+11) + +#define IDI_ADDCONTACT 210 +#define IDI_USERDETAILS 160 +#define IDI_HISTORY 174 +#define IDI_DOWNARROW 264 + +struct TReceivedItem { + char* mcaUIN; + TCHAR* mcaNick; + ~TReceivedItem() { SAFE_FREE((void**)&mcaUIN); SAFE_FREE((void**)&mcaNick); } + TReceivedItem() { mcaUIN = NULL; mcaNick = NULL; } +}; + +struct TRecvContactsData { + HANDLE mhDbEvent; // handle to recv DB event + HANDLE mhContact; // from whom we received this + HIMAGELIST mhListIcon;// icons for listview + HMENU mhPopup; // popup menu for listview + HANDLE hHook; // hook to event + HANDLE rhSearch; // handle to uin-search + char* haUin; + int iPopupItem; + TReceivedItem** maReceived;// received contacts + int cbReceived; + TReceivedItem* AddReceivedItem(); + HICON hIcons[4]; // icons for dialog + TRecvContactsData(HANDLE contact) { mhContact = contact; hHook = NULL; cbReceived = 0; maReceived = NULL; haUin = NULL; }; + ~TRecvContactsData() { if (cbReceived) { for(int i=0;inContacts = nContacts; + ackData->aContacts = (HANDLE*)malloc(nContacts*sizeof(HANDLE)); + memmove(ackData->aContacts, phContacts, nContacts*sizeof(HANDLE)); // copy the array of hContact for ack array + EnableDlgItem(hwndDlg, IDOK, FALSE); + EnableDlgItem(hwndDlg, IDC_LIST, FALSE); + + return TRUE; // Success +} + + +int TSendContactsData::SendContacts(HWND hwndDlg) { + char* szProto = GetContactProto(hContact); + int nMaxContacts = SRCCallProtoService(szProto, PS_GETCAPS, PFLAG_MAXCONTACTSPERPACKET, (LPARAM)hContact); + + if (!nMaxContacts) { + ShowErrorDlg(hwndDlg, "The selected contact does not support receiving contacts.", FALSE); + return FALSE; + } + // hook event - we want to receive protocol acknowledgements + HookProtoAck(hwndDlg); + + for (int j = 0; j < nContacts / nMaxContacts; j++ ) + { // send in packets, each of nMaxContacts contacts + if (!SendContactsPacket(hwndDlg, aContacts + j*nMaxContacts, nMaxContacts)) + return FALSE; + } + if (nContacts%nMaxContacts!=0) + { + if (!SendContactsPacket(hwndDlg, aContacts + nContacts/nMaxContacts*nMaxContacts, nContacts%nMaxContacts)) + return FALSE; + } + return TRUE; +} + + +/* Send Dialog Implementation */ + +static void ResetListOptions(HWND hwndList) +{ + COLORREF bgColour,fgColour; + + SendMessageT(hwndList,CLM_SETBKBITMAP,0,(LPARAM)(HBITMAP)NULL); + bgColour=GetSysColor(COLOR_WINDOW); + SendMessageT(hwndList,CLM_SETBKCOLOR,bgColour,0); + SendMessageT(hwndList,CLM_SETGREYOUTFLAGS,0,0); + SendMessageT(hwndList,CLM_SETLEFTMARGIN,4,0); + SendMessageT(hwndList,CLM_SETINDENT,10,0); + for(int i=0; i<=FONTID_MAX; i++) + { + fgColour=(COLORREF)SendMessageT(hwndList,CLM_GETTEXTCOLOR,i,0); + if(abs(GetRValue(fgColour)-GetRValue(bgColour))<10 && + abs(GetGValue(fgColour)-GetGValue(bgColour))<10 && + abs(GetBValue(fgColour)-GetBValue(bgColour))<10) + SendMessageT(hwndList,CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT)); + } +} + + +static HANDLE FindNextClistContact(HWND hList, HANDLE hContact, HANDLE *phItem) +{ + HANDLE hNextContact = SRCFindNextContact(hContact); + HANDLE hNextItem = NULL; + + while (hNextContact && !(hNextItem = (HANDLE)SendMessageT(hList, CLM_FINDCONTACT, (WPARAM)hNextContact,0))) + hNextContact = SRCFindNextContact(hNextContact); + + if (phItem) + *phItem = hNextItem; + + return hNextContact; +} + + +static HANDLE FindFirstClistContact(HWND hList, HANDLE *phItem) +{ + HANDLE hContact = SRCFindFirstContact(); + HANDLE hItem = (HANDLE)SendMessageT(hList, CLM_FINDCONTACT, (WPARAM)hContact, 0); + + if (hContact && !hItem) + return FindNextClistContact(hList, hContact, phItem); + + if (phItem) + *phItem = hItem; + + return hContact; +} + + +bool binListEvent = FALSE; + +static void SetAllContactChecks(HWND hwndList, HANDLE hReceiver) // doubtful name +{ + HANDLE hContact, hItem; + + if (binListEvent) return; + binListEvent = TRUE; + char* szProto = GetContactProto(hReceiver); + if (szProto == NULL) return; + + if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_HIDEEMPTYGROUPS && DBGetContactSettingByte(NULL, "CList", "HideEmptyGroups", SETTING_USEGROUPS_DEFAULT)) + SendMessageT(hwndList, CLM_SETHIDEEMPTYGROUPS, (WPARAM) TRUE, 0); + else + SendMessageT(hwndList, CLM_SETHIDEEMPTYGROUPS, (WPARAM) FALSE, 0); + + hContact = FindFirstClistContact(hwndList, &hItem); + while (hContact) + { + char* szProto2 = GetContactProto(hContact); + + if (strcmpnull(szProto, szProto2)) + { // different protocols or protocol undefined, remove contact, useless anyway + SendMessageT(hwndList, CLM_DELETEITEM, (WPARAM)hItem, 0); + } + else // otherwise uncheck + SendMessageT(hwndList, CLM_SETCHECKMARK,(WPARAM)hItem, 0); + + hContact = FindNextClistContact(hwndList, hContact, &hItem); + } + + binListEvent = FALSE; +} + + +INT_PTR CALLBACK SendDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TSendContactsData* wndData = (TSendContactsData*)GetWindowLong(hwndDlg, DWLP_USER); + + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + SendMessageT(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_CONTACTS))); + ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST)); + SetAllContactChecks(GetDlgItem(hwndDlg,IDC_LIST), (HANDLE)lParam); + WindowList_Add(ghSendWindowList, hwndDlg, (HANDLE)lParam); + wndData = new TSendContactsData((HANDLE)lParam); + SetWindowLong(hwndDlg, DWLP_USER, (LONG)wndData); + // new dlg init + wndData->hIcons[0] = InitMButton(hwndDlg, IDC_ADD, MAKEINTRESOURCEA(IDI_ADDCONTACT), "Add Contact Permanently to List"); + wndData->hIcons[1] = InitMButton(hwndDlg, IDC_DETAILS, MAKEINTRESOURCEA(IDI_USERDETAILS), "View User's Details"); + wndData->hIcons[2] = InitMButton(hwndDlg, IDC_HISTORY, MAKEINTRESOURCEA(IDI_HISTORY), "View User's History"); + wndData->hIcons[3] = InitMButton(hwndDlg, IDC_USERMENU, MAKEINTRESOURCEA(IDI_DOWNARROW), "User Menu"); + + SendMessageT(hwndDlg,DM_UPDATETITLE,0,0); + // new dialog init done + return TRUE; + } + + case WM_SETFOCUS: + SetFocus(GetDlgItem(hwndDlg,IDC_LIST)); + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == IDC_LIST) + { + switch (((LPNMHDR)lParam)->code) + { + case CLN_NEWCONTACT: + case CLN_LISTREBUILT: // rebuild list + if (wndData) SetAllContactChecks(GetDlgItem(hwndDlg,IDC_LIST), wndData->hContact); + case CLN_OPTIONSCHANGED: + ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST)); + break; + } + } + break; + + case WM_TIMER: + if (wParam == TIMERID_MSGSEND) + { + if (!g_SendAckSupported) + { // old Miranda has this ack unimplemented, we need to send it by ourselves + ACKDATA ack = {0}; + + ack.cbSize = sizeof(ACKDATA); + ack.type = ACKTYPE_CONTACTS; + ack.result = ACKRESULT_SUCCESS; + ack.hContact = wndData->hContact; + while (wndData->uacklist.Count) + { // the uack gets empty after processing all messages :) + ack.hProcess = wndData->uacklist.Items[0]; + SendMessageT(hwndDlg, HM_EVENTSENT, NULL, (WPARAM)&ack); // this removes the ack from our array + } + break; + } + KillTimer(hwndDlg,wParam); + wndData->ShowErrorDlg(hwndDlg, "The contacts send timed out.", TRUE); + } + break; + + case DM_ERRORDECIDED: + { + EnableWindow(hwndDlg,TRUE); + wndData->hError = NULL; + switch(wParam) + { + case MSGERROR_CANCEL: + { + wndData->UnhookProtoAck(); + if (wndData->uacklist.Count) + { + for (int i=0; iuacklist.Count; i++) + { + delete gaAckData.Remove(wndData->uacklist.Items[i]); // remove our ackdata & release structure + } + SAFE_FREE((void**)&wndData->uacklist.Items); + wndData->uacklist.Count = 0; + } + EnableDlgItem(hwndDlg,IDOK,TRUE); + EnableDlgItem(hwndDlg,IDC_LIST,TRUE); + ShowWindow(hwndDlg,SW_SHOWNORMAL); + SetFocus(GetDlgItem(hwndDlg,IDC_LIST)); + break; + } + case MSGERROR_DONE: + // contacts were delivered succesfully after timeout + SetFocus(GetDlgItem(hwndDlg,IDC_LIST)); + wndData->UnhookProtoAck(); + break; + + case MSGERROR_RETRY:// resend timeouted packets + + for (int i=0; iuacklist.Count; i++) + { + TAckData* lla = gaAckData.Remove(wndData->uacklist.Items[i]); + HANDLE hProcc = (HANDLE)SRCCallContactService(wndData->hContact, PSS_CONTACTS, MAKEWPARAM(0, lla->nContacts), (LPARAM)lla->aContacts); + + if (!hProcc) // if fatal do not include + { + wndData->uacklist.Remove(wndData->uacklist.Items[i]); + delete lla; // release the structure + continue; + } + else + { // update process code + wndData->uacklist.Items[i] = hProcc; + gaAckData.Add(hProcc, lla); + } + }// collect TAckData for our window, resend + break; + } + break; + } + + case WM_COMMAND: + { + if(!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)wndData->hContact)) + break; + + switch(LOWORD(wParam)) + { + case IDOK: + { + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDOK))) break; + HANDLE hContact, hItem; + wndData->ClearContacts(); // do not include contacts twice + + HWND hList = GetDlgItem(hwndDlg, IDC_LIST); + hContact = FindFirstClistContact(hList, &hItem); + while (hContact) + { + if (SendMessageT(hList, CLM_GETCHECKMARK, (WPARAM)hItem, 0)) + { // build list of contacts to send + wndData->AddContact(hContact); + } + hContact = FindNextClistContact(hList, hContact, &hItem); + } + /* send contacts */ + if (!wndData->SendContacts(hwndDlg)) + break; + + if (g_SendAckSupported) + SetTimer(hwndDlg,TIMERID_MSGSEND,DBGetContactSettingDword(NULL,"SRMsg","MessageTimeout",TIMEOUT_MSGSEND),NULL); + else + SetTimer(hwndDlg,TIMERID_MSGSEND,1000,NULL); // wait one second - if no error occures + + break; + } + case IDCANCEL: + { + DestroyWindow(hwndDlg); + break; + } + case ID_SELECTALL: + { // select all contacts + HANDLE hContact, hItem; + HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST); + + hContact = FindFirstClistContact(hwndList, &hItem); + while (hContact) { + SendMessageT(hwndList,CLM_SETCHECKMARK,(WPARAM)hItem, 1); + hContact = FindNextClistContact(hwndList, hContact, &hItem); + }; + break; + } + case IDC_USERMENU: + { + RECT rc; + HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,(WPARAM)wndData->hContact,0); + + GetWindowRect(GetDlgItem(hwndDlg,IDC_USERMENU),&rc); + TrackPopupMenu(hMenu,0,rc.left,rc.bottom,0,hwndDlg,NULL); + DestroyMenu(hMenu); + break; + } + case IDC_HISTORY: + CallService(MS_HISTORY_SHOWCONTACTHISTORY,(WPARAM)wndData->hContact,0); + break; + + case IDC_DETAILS: + CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)wndData->hContact,0); + break; + + case IDC_ADD: + DialogAddContactExecute(hwndDlg, wndData->hContact); + break; + } + break; + } + case HM_EVENTSENT: + { + ACKDATA *ack=(ACKDATA*)lParam; + DBEVENTINFO dbei={0}; + + if (ack->type != ACKTYPE_CONTACTS) break; + + TAckData* ackData = gaAckData.Get(ack->hProcess); + + if (ackData == NULL) break; // on unknown hprocc go away + + if (ackData->hContact != ack->hContact) break; // this is not ours, strange + + if (ack->result == ACKRESULT_FAILED) + { // some process failed, show error dialog + KillTimer(hwndDlg, TIMERID_MSGSEND); + wndData->ShowErrorDlg(hwndDlg, (char *)ack->lParam, TRUE); + // ackData get used in error handling, released there + break; + } + + dbei.cbSize = sizeof(dbei); + dbei.szModule = GetContactProto(ackData->hContact); + dbei.eventType = EVENTTYPE_CONTACTS; + dbei.flags = DBEF_SENT; + if (g_UnicodeCore && g_Utf8EventsSupported) + dbei.flags |= DBEF_UTF; + dbei.timestamp = time(NULL); + //make blob + TCTSend* maSend = (TCTSend*)_alloca(ackData->nContacts*sizeof(TCTSend)); + ZeroMemory(maSend, ackData->nContacts*sizeof(TCTSend)); + dbei.cbBlob=0; + char* pBlob; + int i; + for (i=0; inContacts; i++) + { // prepare data & count size + if (g_UnicodeCore && g_Utf8EventsSupported) + maSend[i].mcaNick = make_utf8_string((WCHAR*)GetContactDisplayNameT(ackData->aContacts[i])); + else + maSend[i].mcaNick = (unsigned char*)null_strdup((char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)ackData->aContacts[i], 0)); + maSend[i].mcaUIN = GetContactUID(ackData->aContacts[i], FALSE); + dbei.cbBlob += (DWORD)strlennull(maSend[i].mcaUIN) + (DWORD)strlennull((char*)maSend[i].mcaNick) + 2; + } + dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob); + for (i=0, pBlob=(char*)dbei.pBlob; i < ackData->nContacts; i++) + { + strcpy(pBlob, (char*)maSend[i].mcaNick); + pBlob += strlennull(pBlob) + 1; + strcpy(pBlob, maSend[i].mcaUIN); + pBlob += strlennull(pBlob) + 1; + } + CallService(MS_DB_EVENT_ADD, (WPARAM)ackData->hContact,(LPARAM)&dbei); + gaAckData.Remove(ack->hProcess); // do not release here, still needed + wndData->uacklist.Remove(ack->hProcess); // packet confirmed + for (i=0; inContacts; i++) + { + SAFE_FREE((void**)&maSend[i].mcaUIN); + SAFE_FREE((void**)&maSend[i].mcaNick); + } + delete ackData; // all done, release structure + if (!wndData->uacklist.Count) + { + SkinPlaySound("SentContacts"); + KillTimer(hwndDlg, TIMERID_MSGSEND); + + if (wndData->hError) + SendMessageT(wndData->hError, DM_ERRORDECIDED, MSGERROR_DONE, 0); + + SendMessageT(hwndDlg, WM_CLOSE, 0, 0); // all packets confirmed, close the dialog + } + break; + } + + case WM_CLOSE: + { + wndData->UnhookProtoAck(); + DestroyWindow(hwndDlg); + break; + } + case WM_DESTROY: + { + int i; + for (i = 0; i < SIZEOF(wndData->hIcons); i++) + DestroyIcon(wndData->hIcons[i]); + WindowList_Remove(ghSendWindowList, hwndDlg); + delete wndData; + break; + } + case WM_MEASUREITEM: + return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); + + case WM_DRAWITEM: + { + DrawProtocolIcon(hwndDlg, lParam, wndData->hContact); + return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); + } + case DM_UPDATETITLE: + { + UpdateDialogTitle(hwndDlg, wndData?wndData->hContact:NULL, "Send Contacts to"); + if (wndData) + UpdateDialogAddButton(hwndDlg, wndData->hContact); + break; + } + } + + return FALSE; +} + + +// Error Dialog + +INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + RECT rc, rcParent; + + TranslateDialogDefault(hwndDlg); + + if (lParam) + { + WCHAR tmp[MAX_PATH]; + + SetDlgItemTextT(hwndDlg, IDC_ERRORTEXT, SRCTranslateT((char*)lParam, tmp)); + } + GetWindowRect(hwndDlg, &rc); + GetWindowRect(GetParent(hwndDlg), &rcParent); + SetWindowPos(hwndDlg, 0, + (rcParent.left+rcParent.right-(rc.right-rc.left))/2, + (rcParent.top+rcParent.bottom-(rc.bottom-rc.top))/2, + 0, 0, SWP_NOZORDER|SWP_NOSIZE); + } + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDOK: + SendMessageT(GetParent(hwndDlg), DM_ERRORDECIDED, MSGERROR_RETRY, 0); + DestroyWindow(hwndDlg); + break; + + case IDCANCEL: + SendMessageT(GetParent(hwndDlg), DM_ERRORDECIDED, MSGERROR_CANCEL, 0); + DestroyWindow(hwndDlg); + break; + } + break; + case DM_ERRORDECIDED: + if (wParam!=MSGERROR_DONE) break; + SendMessageT(GetParent(hwndDlg), DM_ERRORDECIDED, MSGERROR_DONE, 0); + DestroyWindow(hwndDlg); + break; + } + + return FALSE; +} diff --git a/plugins/ContactsPlus/send.h b/plugins/ContactsPlus/send.h new file mode 100644 index 0000000000..c8580a4eb1 --- /dev/null +++ b/plugins/ContactsPlus/send.h @@ -0,0 +1,110 @@ +// --------------------------------------------------------------------------- +// Contacts+ for Miranda Instant Messenger +// _______________________________________ +// +// Copyright © 2002 Dominus Procellarum +// Copyright © 2004-2008 Joe Kucera +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// --------------------------------------------------------------------------- + +#ifndef __SEND_H +#define __SEND_H + + +#define TIMERID_MSGSEND 1024 +#define TIMEOUT_MSGSEND 9000 //ms +#define HM_EVENTSENT (WM_USER+10) +#define DM_ERRORDECIDED (WM_USER+18) +#define DM_UPDATETITLE (WM_USER+11) +#define MSGERROR_CANCEL 0 +#define MSGERROR_RETRY 1 +#define MSGERROR_DONE 2 + +#define IDI_ADDCONTACT 210 +#define IDI_USERDETAILS 160 +#define IDI_HISTORY 174 +#define IDI_DOWNARROW 264 + +struct TSendProcessList { + int Count; + HANDLE* Items; + CRITICAL_SECTION lock; + void Add(HANDLE hProcc); + void Remove(HANDLE hProcc); + TSendProcessList(); + ~TSendProcessList(); +}; + +struct TSendContactsData { // hope uack is released automaticly, static property + HANDLE hHook; // hook to event + void HookProtoAck(HWND hwndDlg); + void UnhookProtoAck(); + HANDLE* aContacts; // contacts to be sent + int nContacts; // now many UIDs shall we send? + void ClearContacts(); + void AddContact(HANDLE hContact); + HANDLE hContact; // to whom shall we send? + TSendProcessList uacklist;// ackdata - necessary for errorbox + HWND hError; // handle of error box, if any + void ShowErrorDlg(HWND hwndDlg, char* szMsg, bool bAllowRetry); + int SendContactsPacket(HWND hwndDlg, HANDLE *phContacts, int nContacts); + int SendContacts(HWND hwndDlg); + HICON hIcons[4]; // icons for dialog + TSendContactsData(HANDLE contact); + ~TSendContactsData(); +}; + +struct TAckData { + HANDLE hContact; // to whom was it sent + HANDLE* aContacts; // obj + int nContacts; // how many + TAckData(HANDLE contact) { hContact = contact; aContacts = NULL; nContacts = 0;}; + ~TAckData() { if (nContacts) SAFE_FREE((void**)&aContacts); } +}; + +typedef TAckData* PAckData; + +struct TCTSend { + char* mcaUIN; + unsigned char* mcaNick; +}; + +struct gAckItem { // some shit here + HANDLE hProcc; + PAckData ackData; + gAckItem(HANDLE procC, PAckData aData) { ackData=aData; hProcc=procC; }; + ~gAckItem() { /*delete ackData;*/ }; +}; + +struct gAckList { + gAckItem** Items; + int Count; + TAckData* Get(HANDLE hProcc) { for (int i=0; ihProcc==hProcc) { return Items[i]->ackData; }; return NULL; }; + TAckData* Add(HANDLE hProcc, TAckData* ackData) { Items=(gAckItem**)realloc(Items, (Count+1)*sizeof(gAckItem*)); Items[Count]=new gAckItem(hProcc, ackData); Count++; return ackData; }; + TAckData* Remove(HANDLE hProcc) { for (int i=0; ihProcc==hProcc) { TAckData* data=Items[i]->ackData; delete Items[i]; memmove(Items+i, Items+i+1, (Count-i-1)*sizeof(gAckItem*)); Count--; return data; }; return NULL; }; + gAckList() { Count = 0; Items = NULL; } + ~gAckList() { if (Count) { for (int i=0; ihwndItem==GetDlgItem(hwndDlg, IDC_PROTOCOL)) + { + HICON hIcon = LoadContactProtoIcon(hContact); + if (hIcon) + { + DrawIconEx(dis->hDC,dis->rcItem.left,dis->rcItem.top,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL); + DestroyIcon(hIcon); + } + } +} + + +void UpdateDialogTitle(HWND hwndDlg, HANDLE hContact, char* pszTitleStart) +{ + TCHAR newtitle[512]; + WCHAR str[MAX_PATH]; + TCHAR *oldTitle; + TCHAR *szStatus; + char *szProto; + + if (hContact) + { + szProto = GetContactProto(hContact); + if (szProto) + { + TCHAR *uid = GetContactUID(hContact, TRUE); + TCHAR *contactName = GetContactDisplayNameT(hContact); + + oldTitle = GetDlgItemTextT(hwndDlg, IDC_NAME); + + if (strcmpT(uid?uid:contactName, oldTitle)) + SetDlgItemTextT(hwndDlg, IDC_NAME, uid?uid:contactName); + + szStatus = MirandaStatusToStringT(szProto==NULL ? ID_STATUS_OFFLINE:DBGetContactSettingWord(hContact,szProto,"Status",ID_STATUS_OFFLINE)); + _snprintfT(newtitle, 256, "%s %s (%s)", SRCTranslateT(pszTitleStart, str), contactName, szStatus); + + SAFE_FREE((void**)&uid); + SAFE_FREE((void**)&oldTitle); + } + else + strncpyT(newtitle, SRCTranslateT(pszTitleStart, str), 256); + } + else + strncpyT(newtitle, SRCTranslateT(pszTitleStart, str), 256); + + oldTitle = GetWindowTextT(hwndDlg); + + if (strcmpT(newtitle, oldTitle)) + SetWindowTextT(hwndDlg, newtitle); + + SAFE_FREE((void**)&oldTitle); +} + + +void UpdateDialogAddButton(HWND hwndDlg, HANDLE hContact) +{ + int bVisible = DBGetContactSettingByte(hContact,"CList","NotOnList",0); + + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), bVisible?SW_SHOW:SW_HIDE); +} + + +HICON InitMButton(HWND hDlg, int idButton, LPCSTR szIcon, char* szTip) +{ + HWND hButton = GetDlgItem(hDlg, idButton); + HICON hIcon = (HICON)LoadImage(GetModuleHandle(NULL),szIcon,IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0); + + SendMessageT(hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + SendMessageT(hButton, BUTTONSETASFLATBTN, 0, 0); + SendMessageT(hButton, BUTTONADDTOOLTIP, (WPARAM)Translate(szTip), 0); + + return hIcon; +} + + +HICON LoadContactProtoIcon(HANDLE hContact) +{ + char* szProto = GetContactProto(hContact); + if (szProto) + return (HICON)SRCCallProtoService(szProto, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0); + return NULL; +} + + +void EnableDlgItem(HWND hwndDlg, UINT control, int state) +{ + EnableWindow(GetDlgItem(hwndDlg, control), state); +} + + +LRESULT SendMessageT(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + if (g_UnicodeCore) + return SendMessageW(hWnd, Msg, wParam, lParam); + else + return SendMessageA(hWnd, Msg, wParam, lParam); +} + +TCHAR* GetWindowTextT(HWND hWnd) +{ + if (g_UnicodeCore) + { + int len = GetWindowTextLengthW(hWnd) + 1; + WCHAR* txt = (WCHAR*)malloc(len * sizeof(WCHAR)); + if (txt) { + txt[0] = 0; + GetWindowTextW(hWnd, txt, len); + } + return (TCHAR*)txt; + } + else + { + int len = GetWindowTextLengthA(hWnd) + 1; + char* txt = (char*)malloc(len * sizeof(char)); + if (txt) { + txt[0] = 0; + GetWindowTextA(hWnd, txt, len); + } + return (TCHAR*)txt; + } +} + +BOOL SetWindowTextT(HWND hWnd, TCHAR* lpString) +{ + if (g_UnicodeCore) + return SetWindowTextW(hWnd, (WCHAR*)lpString); + else + return SetWindowTextA(hWnd, lpString); +} + +TCHAR* GetDlgItemTextT(HWND hDlg, int nIDDlgItem) +{ + return GetWindowTextT(GetDlgItem(hDlg, nIDDlgItem)); +} + +BOOL SetDlgItemTextT(HWND hDlg, int nIDDlgItem, TCHAR* lpString) +{ + return SetWindowTextT(GetDlgItem(hDlg, nIDDlgItem), lpString); +} + +HWND CreateDialogParamT(HINSTANCE hInstance, const char* szTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +{ + if (g_UnicodeCore) + return CreateDialogParamW(hInstance, (LPCWSTR)szTemplate, hWndParent, lpDialogFunc, dwInitParam); + else + return CreateDialogParamA(hInstance, szTemplate, hWndParent, lpDialogFunc, dwInitParam); +} + +int ListView_InsertColumnT(HWND hwnd, int iCol, const LPLVCOLUMN pcol) +{ + return SendMessageT(hwnd, g_UnicodeCore ? LVM_INSERTCOLUMNW : LVM_INSERTCOLUMNA, (WPARAM)iCol, (LPARAM)pcol); +} + +void ListView_SetItemTextT(HWND hwnd, int i, int iSubItem, TCHAR* pszText) +{ + LV_ITEM lvi = {0}; + + lvi.iSubItem = iSubItem; + lvi.pszText = pszText; + SendMessageT(hwnd, g_UnicodeCore ? LVM_SETITEMTEXTW : LVM_SETITEMTEXTA, (WPARAM)i, (LPARAM)&lvi); +} + + + +size_t __fastcall strlenT(const TCHAR *string) +{ + if (string) + { + if (g_UnicodeCore) + return wcslen((WCHAR*)string); + else + return strlen((char*)string); + } + return 0; +} + +TCHAR* __fastcall strdupT(const TCHAR *string) +{ + if (string) + { + if (g_UnicodeCore) + return (TCHAR*)wcsdup((WCHAR*)string); + else + return (TCHAR*)strdup((char*)string); + } + return NULL; +} + +int __fastcall strcmpT(const TCHAR *string1, const TCHAR *string2) +{ + if (!string1 || !string2) return 1; + + if (g_UnicodeCore) + return wcscmp((WCHAR*)string1, (WCHAR*)string2); + else + return strcmp((char*)string1, (char*)string2); +} + +TCHAR* __fastcall strcpyT(TCHAR* dest, const TCHAR* src) +{ + if (src) + { + if (g_UnicodeCore) + return (TCHAR*)wcscpy((WCHAR*)dest, (WCHAR*)src); + else + return (TCHAR*)strcpy((char*)dest, (char*)src); + } + return dest; +} + +TCHAR* __fastcall strncpyT(TCHAR* dest, const TCHAR* src, size_t len) +{ + if (src) + { + if (g_UnicodeCore) + return (TCHAR*)wcsncpy((WCHAR*)dest, (WCHAR*)src, len); + else + return (TCHAR*)strncpy((char*)dest, (char*)src, len); + } + return dest; +} + +TCHAR* __fastcall strcatT(TCHAR* dest, const TCHAR* src) +{ + if (src) + { + if (g_UnicodeCore) + return (TCHAR*)wcscat((WCHAR*)dest, (WCHAR*)src); + else + return (TCHAR*)strcat((char*)dest, (char*)src); + } + return dest; +} + +int _snprintfT(TCHAR *buffer, size_t count, const char* fmt, ...) +{ + va_list va; + int len; + + va_start(va, fmt); + if (g_UnicodeCore) + { + TCHAR* wfmt = ansi_to_tchar(fmt); + + len = _vsnwprintf((WCHAR*)buffer, count-1, (WCHAR*)wfmt, va); + ((WCHAR*)buffer)[count-1] = 0; + SAFE_FREE((void**)&wfmt); + } + else + { + len = _vsnprintf((char*)buffer, count-1, fmt, va); + ((char*)buffer)[count-1] = 0; + } + va_end(va); + return len; +} + +TCHAR* __fastcall SRCTranslateT(const char* src, const WCHAR* unibuf) +{ // this takes Ascii strings only!!! + char* szRes = NULL; + + if (!strlennull(src)) + { // for the case of empty strings + return ""; + } + + if (g_UnicodeCore) + { // we give WCHAR + WCHAR *unicode; + int wchars, err; + + wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, + (int)strlennull(src), NULL, 0); + + if (wchars == 0) return NULL; // Failure + + unicode = (WCHAR*)unibuf; + if (!unicode) + unicode = (WCHAR*)malloc((wchars + 1) * sizeof(WCHAR)); + + unicode[wchars] = 0; + + err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, + (int)strlennull(src), unicode, wchars); + if (err != wchars) return NULL; // Failure + + return (TCHAR*)TranslateW(unicode); + } + else + return (TCHAR*)Translate(src); +} + +static BOOL bHasCP_UTF8 = FALSE; + + +void InitI18N(void) +{ + CPINFO CPInfo; + + + bHasCP_UTF8 = GetCPInfo(CP_UTF8, &CPInfo); +} + + +// Scans a string encoded in UTF-8 to verify that it contains +// only valid sequences. It will return 1 if the string contains +// only legitimate encoding sequences; otherwise it will return 0; +// From 'Secure Programming Cookbook', John Viega & Matt Messier, 2003 +int UTF8_IsValid(const unsigned char* pszInput) +{ + int nb, i; + const unsigned char* c = pszInput; + + if (!pszInput) return 0; + + for (c = pszInput; *c; c += (nb + 1)) + { + if (!(*c & 0x80)) + nb = 0; + else if ((*c & 0xc0) == 0x80) return 0; + else if ((*c & 0xe0) == 0xc0) nb = 1; + else if ((*c & 0xf0) == 0xe0) nb = 2; + else if ((*c & 0xf8) == 0xf0) nb = 3; + else if ((*c & 0xfc) == 0xf8) nb = 4; + else if ((*c & 0xfe) == 0xfc) nb = 5; + + for (i = 1; i<=nb; i++) // we this forward, do not cross end of string + if ((*(c + i) & 0xc0) != 0x80) + return 0; + } + + return 1; +} + + +/* + * The following UTF8 routines are + * + * Copyright (C) 2001 Peter Harris + * Copyright (C) 2001 Edmund Grimley Evans + * + * under a GPL license + * + * -------------------------------------------------------------- + * Convert a string between UTF-8 and the locale's charset. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * + * If the locale's charset is not set explicitly then it is + * obtained using nl_langinfo(CODESET), where available, the + * environment variable CHARSET, or assumed to be US-ASCII. + * + * Return value of conversion functions: + * + * -1 : memory allocation failed + * 0 : data was converted exactly + * 1 : valid data was converted approximately (using '?') + * 2 : input was invalid (but still converted, using '#') + * 3 : unknown encoding (but still converted, using '?') + */ + + + +/* + * Convert a string between UTF-8 and the locale's charset. + */ +unsigned char *make_utf8_string(const wchar_t *unicode) +{ + int size = 0; + int index = 0; + int out_index = 0; + unsigned char* out; + unsigned short c; + + if (!unicode) return NULL; + + /* first calculate the size of the target string */ + c = unicode[index++]; + while (c) + { + if (c < 0x0080) + size += 1; + else if (c < 0x0800) + size += 2; + else + size += 3; + c = unicode[index++]; + } + + out = (unsigned char*)malloc(size + 1); + if (out == NULL) + return NULL; + index = 0; + + c = unicode[index++]; + while (c) + { + if (c < 0x080) + { + out[out_index++] = (unsigned char)c; + } + else if (c < 0x800) + { + out[out_index++] = 0xc0 | (c >> 6); + out[out_index++] = 0x80 | (c & 0x3f); + } + else + { + out[out_index++] = 0xe0 | (c >> 12); + out[out_index++] = 0x80 | ((c >> 6) & 0x3f); + out[out_index++] = 0x80 | (c & 0x3f); + } + c = unicode[index++]; + } + out[out_index] = 0x00; + + return out; +} + + + +WCHAR *make_unicode_string(const unsigned char *utf8) +{ + int size = 0, index = 0, out_index = 0; + wchar_t *out; + unsigned char c; + + if (!utf8) return NULL; + + /* first calculate the size of the target string */ + c = utf8[index++]; + while (c) + { + if ((c & 0x80) == 0) + { + index += 0; + } + else if ((c & 0xe0) == 0xe0) + { + index += 2; + } + else + { + index += 1; + } + size += 1; + c = utf8[index++]; + } + + out = (wchar_t*)malloc((size + 1) * sizeof(wchar_t)); + if (out == NULL) + return NULL; + index = 0; + + c = utf8[index++]; + while (c) + { + if((c & 0x80) == 0) + { + out[out_index++] = c; + } + else if((c & 0xe0) == 0xe0) + { + out[out_index] = (c & 0x1F) << 12; + c = utf8[index++]; + out[out_index] |= (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } + else + { + out[out_index] = (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } + c = utf8[index++]; + } + out[out_index] = 0; + + return out; +} + + +// Returns 0 on error, 1 on success +static int utf8_decode(const unsigned char *from, char **to) +{ + int nResult = 0; + +// _ASSERTE(!(*to)); // You passed a non-zero pointer, make sure it doesnt point to unfreed memory + + // Validate the string + if (!UTF8_IsValid(from)) + return 0; + + // Use the native conversion routines when available + if (bHasCP_UTF8) + { + WCHAR *wszTemp = NULL; + int inlen = (int)strlennull((char*)from); + + wszTemp = (WCHAR *)_alloca(sizeof(WCHAR) * (inlen + 1)); + + // Convert the UTF-8 string to UCS + if (MultiByteToWideChar(CP_UTF8, 0, (char*)from, -1, wszTemp, inlen + 1)) + { + // Convert the UCS string to local ANSI codepage + *to = (char*)malloc(inlen+1); + if (WideCharToMultiByte(CP_ACP, 0, wszTemp, -1, *to, inlen+1, NULL, NULL)) + { + nResult = 1; + } + else + { + SAFE_FREE((void**)to); + } + } + } + else + { + wchar_t *unicode; + int chars; + int err; + + unicode = make_unicode_string(from); + if (unicode == NULL) + { +// fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n"); + return 0; + } + + chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); + + if(chars == 0) + { +// fprintf(stderr, "Unicode translation error %d\n", GetLastError()); + SAFE_FREE((void**)&unicode); + return 0; + } + + *to = (char*)malloc((chars + 1)*sizeof(unsigned char)); + if(*to == NULL) + { +// fprintf(stderr, "Out of memory processing string to local charset\n"); + SAFE_FREE((void**)&unicode); + return 0; + } + + err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL); + if (err != chars) + { +// fprintf(stderr, "Unicode translation error %d\n", GetLastError()); + SAFE_FREE((void**)&unicode); + SAFE_FREE((void**)to); + return 0; + } + + SAFE_FREE((void**)&unicode); + + nResult = 1; + } + + return nResult; +} + + + +TCHAR* ansi_to_tchar(const char* src, int codepage) +{ + if (g_UnicodeCore) + { + WCHAR *unicode; + int wchars, err; + + wchars = MultiByteToWideChar(codepage, MB_PRECOMPOSED, src, (int)strlennull(src), NULL, 0); + + if (wchars == 0) return NULL; // Failure + + unicode = (WCHAR*)malloc((wchars + 1) * sizeof(WCHAR)); + unicode[wchars] = 0; + + err = MultiByteToWideChar(codepage, MB_PRECOMPOSED, src, (int)strlennull(src), unicode, wchars); + if (err != wchars) + { + SAFE_FREE((void**)&unicode); + return NULL; // Failure + } + + return (TCHAR*)unicode; + } + else + return strdupT((TCHAR*)src); +} + +char* tchar_to_ansi(const TCHAR* src) +{ + if (g_UnicodeCore) + { + char *ansi; + int chars; + int err; + + chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, (WCHAR*)src, -1, NULL, 0, NULL, NULL); + + if (chars == 0) return NULL; // Failure + + ansi = (char*)malloc((chars + 1)*sizeof(char)); + if (ansi == NULL) return NULL; // Failure + + err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, (WCHAR*)src, -1, ansi, chars, NULL, NULL); + if (err != chars) + { + SAFE_FREE((void**)&ansi); + return NULL; + } + return ansi; + } + else + return (char*)strdupT(src); +} + +TCHAR* utf8_to_tchar(const unsigned char* utf) +{ + if (g_UnicodeCore) + return (TCHAR*)make_unicode_string(utf); + else + { + char* szAnsi = NULL; + + if (utf8_decode(utf, &szAnsi)) + return (TCHAR*)szAnsi; + else + return NULL; // Failure + } +} \ No newline at end of file diff --git a/plugins/ContactsPlus/utils.h b/plugins/ContactsPlus/utils.h new file mode 100644 index 0000000000..2b9af014b7 --- /dev/null +++ b/plugins/ContactsPlus/utils.h @@ -0,0 +1,91 @@ +// --------------------------------------------------------------------------- +// Contacts+ for Miranda Instant Messenger +// _______________________________________ +// +// Copyright © 2002 Dominus Procellarum +// Copyright © 2004-2008 Joe Kucera +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// --------------------------------------------------------------------------- + +#ifndef __UTILS_H +#define __UTILS_H + + +extern HINSTANCE hInst; +extern PLUGINLINK *pluginLink; + +// Compatibility functions +int SRCCallProtoService(const char *szModule, const char *szService, WPARAM wParam, LPARAM lParam); +int SRCCallContactService(HANDLE hContact, const char *szProtoService, WPARAM wParam, LPARAM lParam); + +// utils.cpp +void __fastcall SAFE_FREE(void** p); +size_t __fastcall strlennull(const char *string); +int __fastcall strcmpnull(const char *str1, const char *str2); +char* __fastcall null_strdup(const char *string); + +char *GetContactProto(HANDLE hContact); +char *GetContactUID(HANDLE hContact, int bTchar); +TCHAR *GetContactDisplayNameT(HANDLE hContact); +TCHAR* MirandaStatusToStringT(int mirandaStatus); + +HANDLE __fastcall SRCFindFirstContact(); +HANDLE __fastcall SRCFindNextContact(HANDLE hContact); +int DBGetContactSettingT(HANDLE hContact, const char *szModule, const char* szSetting, DBVARIANT *dbv); +TCHAR* DBGetContactSettingStringT(HANDLE hContact, const char *szModule,const char* szSetting, TCHAR* szDef); +int DBWriteContactSettingStringT(HANDLE hContact, const char *szModule, const char* szSetting, TCHAR* szValue); + +void DrawProtocolIcon(HWND hwndDlg, LPARAM lParam, HANDLE hContact); +void UpdateDialogTitle(HWND hwndDlg, HANDLE hContact, char* pszTitleStart); +void UpdateDialogAddButton(HWND hwndDlg, HANDLE hContact); + +HICON InitMButton(HWND hDlg, int idButton, LPCSTR szIcon, char* szTip); + +void DialogAddContactExecute(HWND hwndDlg, HANDLE hNewContact); + +HICON LoadContactProtoIcon(HANDLE hContact); + +void EnableDlgItem(HWND hwndDlg, UINT control, int state); + +/// Unicode 2 in 1 Framework +size_t __fastcall strlenT(const TCHAR *string); +TCHAR* __fastcall strdupT(const TCHAR *string); +int __fastcall strcmpT(const TCHAR *string1, const TCHAR *string2); +TCHAR* __fastcall strcpyT(TCHAR* dest, const TCHAR* src); +TCHAR* __fastcall strncpyT(TCHAR* dest, const TCHAR* src, size_t len); +TCHAR* __fastcall strcatT(TCHAR* dest, const TCHAR* src); +int _snprintfT(TCHAR *buffer, size_t count, const char* fmt, ...); + +LRESULT SendMessageT(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +TCHAR* GetWindowTextT(HWND hWnd); +BOOL SetWindowTextT(HWND hWnd, TCHAR* lpString); +TCHAR* GetDlgItemTextT(HWND hDlg, int nIDDlgItem); +BOOL SetDlgItemTextT(HWND hDlg, int nIDDlgItem, TCHAR* lpString); +HWND CreateDialogParamT(HINSTANCE hInstance, const char* szTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); +int ListView_InsertColumnT(HWND hwnd, int iCol, const LPLVCOLUMN pcol); +void ListView_SetItemTextT(HWND hwnd, int i, int iSubItem, TCHAR* pszText); + +TCHAR* __fastcall SRCTranslateT(const char* src, const WCHAR* unibuf); + +void InitI18N(void); +TCHAR* ansi_to_tchar(const char* string, int codepage = CP_ACP); +char* tchar_to_ansi(const TCHAR* src); +TCHAR* utf8_to_tchar(const unsigned char* utf); +unsigned char *make_utf8_string(const wchar_t *unicode); + + +#endif /* __UTILS_H */ \ No newline at end of file -- cgit v1.2.3