diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-07-17 06:57:55 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-07-17 06:57:55 +0000 |
commit | 1ca120b165c2f2d9f521a04bfc31c7956d2ce422 (patch) | |
tree | f56c88f1ffdb865612a3d1e05f047c17deed68ab /plugins/ContactsPlus/src | |
parent | eb146b049b43c6fb09e6f8c7716c1bbc88bf2159 (diff) |
ContactsPlus, CountryFlags, CrashDumper: changed folder structure
git-svn-id: http://svn.miranda-ng.org/main/trunk@1000 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/ContactsPlus/src')
-rw-r--r-- | plugins/ContactsPlus/src/contacts.cpp | 31 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/contacts.h | 77 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/main.cpp | 317 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/receive.cpp | 522 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/receive.h | 65 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/resource.h | 44 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/send.cpp | 609 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/send.h | 110 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/utils.cpp | 832 | ||||
-rw-r--r-- | plugins/ContactsPlus/src/utils.h | 86 |
10 files changed, 2693 insertions, 0 deletions
diff --git a/plugins/ContactsPlus/src/contacts.cpp b/plugins/ContactsPlus/src/contacts.cpp new file mode 100644 index 0000000000..a7ba2cdfbb --- /dev/null +++ b/plugins/ContactsPlus/src/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/src/contacts.h b/plugins/ContactsPlus/src/contacts.h new file mode 100644 index 0000000000..742f577924 --- /dev/null +++ b/plugins/ContactsPlus/src/contacts.h @@ -0,0 +1,77 @@ +// ---------------------------------------------------------------------------
+// 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 <windows.h>
+#include <commctrl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <crtdbg.h>
+#include <malloc.h>
+#include <time.h>
+
+//!!this is fake - this plugin maintains backward compatibility internally
+#define MIRANDA_VER 0x0A00
+
+#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 "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/src/main.cpp b/plugins/ContactsPlus/src/main.cpp new file mode 100644 index 0000000000..da43554c29 --- /dev/null +++ b/plugins/ContactsPlus/src/main.cpp @@ -0,0 +1,317 @@ +// --------------------------------------------------------------------------
+// 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;
+
+int hLangpack;
+
+int g_NewProtoAPI = TRUE;
+
+int g_SendAckSupported = TRUE;
+int g_Utf8EventsSupported = TRUE;
+
+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),
+ "Send/Receive Contacts+",
+ 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",
+ UNICODE_AWARE,
+ {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 (CallProtoService(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 (CallProtoService(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 = Menu_AddContactMenuItem(&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
+
+
+ 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;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_SRCONTACTS, MIID_LAST};
+
+extern "C" __declspec(dllexport) int Load(void)
+{
+ mir_getLP(&pluginInfo);
+ 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/src/receive.cpp b/plugins/ContactsPlus/src/receive.cpp new file mode 100644 index 0000000000..3d3fb2f773 --- /dev/null +++ b/plugins/ContactsPlus/src/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)CallProtoService(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)CallProtoService(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*)GetWindowLongPtr(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);
+ SetWindowLongPtr(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));
+ TranslateMenu(wndData->mhPopup);
+ 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*)CallProtoService(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)CallProtoService(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/src/receive.h b/plugins/ContactsPlus/src/receive.h new file mode 100644 index 0000000000..fe35d94be6 --- /dev/null +++ b/plugins/ContactsPlus/src/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;i<cbReceived;i++) delete maReceived[i]; SAFE_FREE((void**)&maReceived); SAFE_FREE((void**)&haUin); }; };
+};
+
+extern HANDLE ghRecvWindowList;
+
+INT_PTR CALLBACK RecvDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+#endif /* __RECEIVE_H */
\ No newline at end of file diff --git a/plugins/ContactsPlus/src/resource.h b/plugins/ContactsPlus/src/resource.h new file mode 100644 index 0000000000..e4ed78f866 --- /dev/null +++ b/plugins/ContactsPlus/src/resource.h @@ -0,0 +1,44 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by contacts.rc
+//
+#define ID_SELECTALL 3
+#define IDDETAILS 5
+#define IDD_SEND 101
+#define IDC_PROTOCOL 1580
+#define IDC_NAME 1009
+#define IDC_ADD 1070
+#define IDC_USERMENU 1071
+#define IDC_DETAILS 1069
+#define IDC_HISTORY 1080
+#define IDB_LOGO 102
+#define IDD_RECEIVE 103
+#define IDD_MSGSENDERROR 104
+#define IDI_CONTACTS 109
+#define IDR_CONTACTMENU 110
+#define ID_POPUP_ADDUSER 111
+#define ID_POPUP_SENDMESSAGE 112
+#define ID_POPUP_USERDETAILS 113
+#define ID_POPUP_USERDETAILS_FAKE 114
+#define IDC_LOGO 1001
+#define IDC_OK 1002
+#define IDC_CANCEL 1003
+#define IDC_BACKIMAGE 1004
+#define IDC_GROUPS 1006
+#define IDC_ENABLEGROUPS 1007
+#define IDC_LIST 1079
+#define IDC_RESULTS 1142
+#define IDC_CONTACTS 1142
+#define IDC_STATUSBAR 1389
+#define IDC_ERRORTEXT 1400
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 114
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1008
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/ContactsPlus/src/send.cpp b/plugins/ContactsPlus/src/send.cpp new file mode 100644 index 0000000000..ac042fa63e --- /dev/null +++ b/plugins/ContactsPlus/src/send.cpp @@ -0,0 +1,609 @@ +// --------------------------------------------------------------------------
+// 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"
+
+
+/* TSendProcessList */
+
+void TSendProcessList::Add(HANDLE hProcc) {
+ EnterCriticalSection(&lock);
+ Items=(HANDLE*)realloc(Items, (Count+1)*sizeof(HANDLE));
+ Items[Count]=hProcc;
+ Count++;
+ LeaveCriticalSection(&lock);
+}
+
+
+void TSendProcessList::Remove(HANDLE hProcc) {
+ EnterCriticalSection(&lock);
+ for (int i=0; i<Count; i++)
+ if (Items[i]==hProcc) {
+ memmove(Items+i, Items+i+1, (Count-i-1)*sizeof(HANDLE));
+ Count--;
+ break;
+ }
+ LeaveCriticalSection(&lock);
+}
+
+
+TSendProcessList::TSendProcessList() {
+ InitializeCriticalSection(&lock);
+ Count = 0;
+ Items = NULL;
+}
+
+
+TSendProcessList::~TSendProcessList() {
+ if (Count)
+ SAFE_FREE((void**)&Items);
+ DeleteCriticalSection(&lock);
+}
+
+
+/* TSendContactsData */
+
+TSendContactsData::TSendContactsData(HANDLE contact): uacklist() {
+ hContact = contact;
+ hHook = NULL;
+ hError = NULL;
+ aContacts = NULL;
+ nContacts = 0;
+}
+
+
+TSendContactsData::~TSendContactsData() {
+ ClearContacts();
+ UnhookProtoAck();
+}
+
+
+void TSendContactsData::HookProtoAck(HWND hwndDlg) {
+ if (!hHook)
+ hHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_EVENTSENT);
+};
+
+
+void TSendContactsData::UnhookProtoAck() {
+ if (hHook)
+ {
+ UnhookEvent(hHook);
+ hHook=NULL;
+ };
+}
+
+
+void TSendContactsData::ShowErrorDlg(HWND hwndDlg, char* szMsg, bool bAllowRetry) {
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ EnableWindow(hwndDlg, FALSE);
+ if (!hError)
+ {
+ hError = CreateDialogParamT(hInst, MAKEINTRESOURCEA(IDD_MSGSENDERROR), hwndDlg, ErrorDlgProc, (LPARAM)szMsg);
+ if (!bAllowRetry)
+ EnableDlgItem(hError, IDOK, FALSE); // do not allow again - fatal, could not be better
+ }
+}
+
+
+void TSendContactsData::ClearContacts() {
+ if (nContacts)
+ SAFE_FREE((void**)&aContacts);
+ nContacts=0;
+}
+
+
+void TSendContactsData::AddContact(HANDLE hContact) {
+ aContacts = (HANDLE*)realloc(aContacts, (nContacts+1)*sizeof(HANDLE));
+ aContacts[nContacts] = hContact;
+ nContacts++;
+}
+
+
+int TSendContactsData::SendContactsPacket(HWND hwndDlg, HANDLE *phContacts, int nContacts) {
+ HANDLE hProcc = (HANDLE)CallContactService(hContact, PSS_CONTACTS, MAKEWPARAM(0, nContacts), (LPARAM)phContacts);
+ if (!hProcc)
+ { // on trivial error - do not close dialog
+ ShowErrorDlg(hwndDlg, "Contacts transfer failed!", FALSE);
+ return FALSE; // Failure
+ }
+ TAckData* ackData = gaAckData.Add(hProcc, new TAckData(hContact));
+ uacklist.Add(hProcc);
+ ackData->nContacts = 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 = CallProtoService(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*)GetWindowLongPtr(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);
+ SetWindowLongPtr(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; i<wndData->uacklist.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; i<wndData->uacklist.Count; i++)
+ {
+ TAckData* lla = gaAckData.Remove(wndData->uacklist.Items[i]);
+ HANDLE hProcc = (HANDLE)CallContactService(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; i<ackData->nContacts; 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; i<ackData->nContacts; 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/src/send.h b/plugins/ContactsPlus/src/send.h new file mode 100644 index 0000000000..c8580a4eb1 --- /dev/null +++ b/plugins/ContactsPlus/src/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; i<Count; i++) if (Items[i]->hProcc==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; i<Count; i++) if (Items[i]->hProcc==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; i<Count; i++) delete Items[i]; SAFE_FREE((void**)&Items); }; }
+};
+
+extern HANDLE ghSendWindowList;
+extern gAckList gaAckData;
+
+INT_PTR CALLBACK SendDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+#endif /* __SEND_H */
\ No newline at end of file diff --git a/plugins/ContactsPlus/src/utils.cpp b/plugins/ContactsPlus/src/utils.cpp new file mode 100644 index 0000000000..1838b3bea8 --- /dev/null +++ b/plugins/ContactsPlus/src/utils.cpp @@ -0,0 +1,832 @@ +// ---------------------------------------------------------------------------
+// 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"
+
+int utf8_decode(const unsigned char *from, char **to);
+
+/* a strlennull() that likes NULL */
+size_t __fastcall strlennull(const char *string)
+{
+ if (string)
+ return strlen(string);
+
+ return 0;
+}
+
+
+int __fastcall strcmpnull(const char *str1, const char *str2)
+{
+ if (!str1 || !str2) return 1;
+
+ return strcmp(str1, str2);
+}
+
+
+char* __fastcall null_strdup(const char *string)
+{
+ if (string)
+ return strdup(string);
+
+ return NULL;
+}
+
+
+void __fastcall SAFE_FREE(void** p)
+{
+ if (*p)
+ {
+ free(*p);
+ *p = NULL;
+ }
+}
+
+
+char *GetContactProto(HANDLE hContact)
+{
+ return (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+}
+
+
+TCHAR *GetContactDisplayNameT(HANDLE hContact)
+{
+ return (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, g_UnicodeCore ? GCDNF_UNICODE : 0);
+}
+
+
+char *GetContactUID(HANDLE hContact, int bTchar)
+{
+ DBVARIANT vrUid;
+ char *szUid = NULL;
+
+ char *szProto = GetContactProto(hContact);
+ char *uid = (char*)CallProtoService(szProto, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0); // v0.3+ only
+
+ if (((int)uid != CALLSERVICE_NOTFOUND) && uid)
+ { // it worked, yeah :)
+ if (!DBGetContactSettingT(hContact, szProto, uid, &vrUid))
+ {
+ if (vrUid.type == DBVT_DWORD)
+ {
+ szUid = (char*)_alloca(17);
+ szUid[0] = 0; // empty string
+ _itoa(vrUid.dVal, szUid, 10);
+ }
+ else if (vrUid.type == DBVT_ASCIIZ)
+ {
+ szUid = (char*)_alloca(strlennull(vrUid.pszVal) + 1);
+ strcpy(szUid, vrUid.pszVal);
+ }
+ else if (vrUid.type == DBVT_UTF8)
+ { // yeah, jabber gives this!
+ char *szAnsi = NULL;
+
+ if (utf8_decode((unsigned char*)vrUid.pszVal, &szAnsi))
+ {
+ szUid = (char*)_alloca(strlennull(szAnsi) + 1);
+ strcpy(szUid, szAnsi);
+ SAFE_FREE((void**)&szAnsi);
+ }
+ }
+ DBFreeVariant(&vrUid);
+ }
+ }
+ if (bTchar)
+ return ansi_to_tchar(szUid);
+ else
+ return null_strdup(szUid);
+}
+
+
+TCHAR* MirandaStatusToStringT(int mirandaStatus)
+{
+ return (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, mirandaStatus, g_UnicodeCore ? GSMDF_UNICODE : 0);
+}
+
+HANDLE __fastcall SRCFindFirstContact()
+{
+ return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+}
+
+HANDLE __fastcall SRCFindNextContact(HANDLE hContact)
+{
+ return (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+}
+
+int DBGetContactSettingT(HANDLE hContact, const char *szModule, const char* szSetting, DBVARIANT *dbv)
+{
+ if (ServiceExists(MS_DB_CONTACT_GETSETTING_STR))
+ return DBGetContactSettingW(hContact, szModule, szSetting, dbv);
+ else
+ return DBGetContactSetting(hContact, szModule, szSetting, dbv);
+}
+
+
+TCHAR* DBGetContactSettingStringT(HANDLE hContact, const char *szModule, const char* szSetting, TCHAR* szDef)
+{
+ DBVARIANT dbv = {DBVT_DELETED};
+ TCHAR* szRes;
+
+ if (g_UnicodeCore)
+ {
+ if (DBGetContactSettingWString(hContact, szModule, szSetting, &dbv))
+ return strdupT(szDef);
+
+ szRes = strdupT(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ else
+ {
+ if (DBGetContactSettingT(hContact, szModule, szSetting, &dbv))
+ return strdupT(szDef);
+
+ if (dbv.type == DBVT_ASCIIZ)
+ szRes = ansi_to_tchar(dbv.pszVal);
+ else if (dbv.type == DBVT_UTF8)
+ szRes = utf8_to_tchar((unsigned char*)dbv.pszVal);
+ else
+ szRes = strdupT(szDef);
+ DBFreeVariant(&dbv);
+ }
+ return szRes;
+}
+
+int DBWriteContactSettingStringT(HANDLE hContact, const char *szModule, const char* szSetting, TCHAR* szValue)
+{
+ if (g_UnicodeCore)
+ return DBWriteContactSettingWString(hContact, szModule, szSetting, (WCHAR*)szValue);
+ else
+ return DBWriteContactSettingString(hContact, szModule, szSetting, (char*)szValue);
+}
+
+
+
+void DialogAddContactExecute(HWND hwndDlg, HANDLE hNewContact)
+{
+ ADDCONTACTSTRUCT acs={0};
+
+ acs.handle = hNewContact;
+ acs.handleType = HANDLE_CONTACT;
+
+ CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
+}
+
+
+void DrawProtocolIcon(HWND hwndDlg, LPARAM lParam, HANDLE hContact)
+{
+ LPDRAWITEMSTRUCT dis=(LPDRAWITEMSTRUCT)lParam;
+
+ if (dis->hwndItem==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, TRUE, 0);
+ SendMessageT(hButton, BUTTONADDTOOLTIP, (WPARAM)Translate(szTip), 0);
+
+ return hIcon;
+}
+
+
+HICON LoadContactProtoIcon(HANDLE hContact)
+{
+ char* szProto = GetContactProto(hContact);
+ if (szProto)
+ return (HICON)CallProtoService(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 <peter.harris@hummingbird.com>
+ * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
+ *
+ * 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/src/utils.h b/plugins/ContactsPlus/src/utils.h new file mode 100644 index 0000000000..3bc2d8e00d --- /dev/null +++ b/plugins/ContactsPlus/src/utils.h @@ -0,0 +1,86 @@ +// ---------------------------------------------------------------------------
+// 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;
+
+// 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 |