Browse Source

add ability to send clips to other computers, automatically or by right clicking

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@80 595ec19a-5cb4-439b-94a8-42fb3063c22c
sabrogden 21 years ago
parent
commit
c33c1770ee
26 changed files with 1851 additions and 35 deletions
  1. 39 7
      CP_Main.cpp
  2. 34 2
      CP_Main.dsp
  3. 7 0
      CP_Main.h
  4. 83 0
      CP_Main.rc
  5. 341 0
      Client.cpp
  6. 91 0
      Client.h
  7. 64 0
      FriendDetails.cpp
  8. 49 0
      FriendDetails.h
  9. 86 0
      MainFrm.cpp
  10. 4 0
      MainFrm.h
  11. 145 2
      Misc.cpp
  12. 37 0
      Misc.h
  13. 250 0
      OptionFriends.cpp
  14. 62 0
      OptionFriends.h
  15. 5 0
      OptionsSheet.cpp
  16. 1 0
      OptionsSheet.h
  17. 27 0
      ProcessCopy.cpp
  18. 2 0
      ProcessCopy.h
  19. 28 10
      ProcessPaste.cpp
  20. 2 0
      ProcessPaste.h
  21. 195 10
      QPasteWnd.cpp
  22. 19 0
      QPasteWnd.h
  23. 26 4
      Resource.h
  24. 209 0
      Server.cpp
  25. 44 0
      Server.h
  26. 1 0
      StdAfx.h

+ 39 - 7
CP_Main.cpp

@@ -7,6 +7,8 @@
 #include "Misc.h"
 #include "SelectDB.h"
 #include ".\cp_main.h"
+#include "server.h"
+#include "Client.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -58,10 +60,13 @@ CCP_MainApp::CCP_MainApp()
 	// Place all significant initialization in InitInstance
 
 	m_bAsynchronousRefreshView = true;
+
+	::InitializeCriticalSection(&m_CriticalSection);
 }
 
 CCP_MainApp::~CCP_MainApp()
 {
+	::DeleteCriticalSection(&m_CriticalSection);
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -138,7 +143,12 @@ void CCP_MainApp::AfterMainCreate()
 
 	// CopyThread initialization
 	StartCopyThread();
+	
+	AfxBeginThread(MTServerThread, m_MainhWnd);
+
 	m_bAppRunning = true;
+
+	m_pcpSendRecieveError = NULL;
 }
 
 void CCP_MainApp::BeforeMainClose()
@@ -177,8 +187,8 @@ http://website.lineone.net/~codebox/focuslog.zip).
 */
 bool CCP_MainApp::TargetActiveWindow()
 {
-HWND hOld = m_hTargetWnd;
-HWND hNew = ::GetForegroundWindow();
+	HWND hOld = m_hTargetWnd;
+	HWND hNew = ::GetForegroundWindow();
 	if( hNew == m_hTargetWnd || !::IsWindow(hNew) || IsAppWnd(hNew) )
 		return false;
 
@@ -258,7 +268,7 @@ void CCP_MainApp::StopCopyThread()
 // Allocates a new CClipTypes
 CClipTypes* CCP_MainApp::LoadTypesFromDB()
 {
-CClipTypes* pTypes = new CClipTypes;
+	CClipTypes* pTypes = new CClipTypes;
 
 	try
 	{
@@ -288,15 +298,16 @@ CClipTypes* pTypes = new CClipTypes;
 
 void CCP_MainApp::ReloadTypes()
 {
-CClipTypes* pTypes = LoadTypesFromDB();
+	CClipTypes* pTypes = LoadTypesFromDB();
+
 	if( pTypes )
 		m_CopyThread.SetSupportedTypes( pTypes );
 }
 
 long CCP_MainApp::SaveCopyClips()
 {
-long lID = 0;
-int count;
+	long lID = 0;
+	int count;
 
 	CClipList* pClips = m_CopyThread.GetClips(); // we now own pClips
 	if( !pClips )
@@ -306,7 +317,28 @@ int count;
 	if( count > 0 )
 	{		
 		lID = pClips->GetTail()->m_ID;
-		OnCopyCompleted( lID, count );
+		OnCopyCompleted(lID, count);
+
+		if(g_Opt.m_lAutoSendClientCount > 0)
+		{
+			//The thread will free these
+			CIDArray *pIDArray = new CIDArray;
+			pIDArray->pIDs = new CID[count];
+			pIDArray->lCount = count;
+			
+			CClip* pClip;
+			POSITION pos;
+			int nArrayPos = 0;
+			pos = pClips->GetHeadPosition();
+			while(pos)
+			{
+				pClip = pClips->GetNext(pos);
+				pIDArray->pIDs[nArrayPos].lID = pClip->m_ID;
+				pIDArray->pIDs[nArrayPos].m_csDesc = pClip->m_Desc;
+			}
+
+			AfxBeginThread(SendClientThread, pIDArray);
+		}
 	}
 
 	delete pClips;

+ 34 - 2
CP_Main.dsp

@@ -55,7 +55,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
-# ADD LINK32 /nologo /subsystem:windows /map /machine:I386 /out:"Release/Ditto.exe"
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /subsystem:windows /map /machine:I386 /out:"Release/Ditto.exe"
 
 !ELSEIF  "$(CFG)" == "CP_Main - Win32 Debug"
 
@@ -81,7 +81,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Ditto.exe" /pdbtype:sept
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Ditto.exe" /pdbtype:sept
 
 !ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Release"
 
@@ -248,6 +248,10 @@ SOURCE=.\AddType.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\Client.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\CopyProperties.cpp
 # End Source File
 # Begin Source File
@@ -268,6 +272,10 @@ SOURCE=.\DataTable.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\FriendDetails.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\GroupCombo.cpp
 # End Source File
 # Begin Source File
@@ -296,6 +304,10 @@ SOURCE=.\Misc.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\OptionFriends.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\OptionsGeneral.cpp
 # End Source File
 # Begin Source File
@@ -348,6 +360,10 @@ SOURCE=.\SelectDB.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\Server.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\StdAfx.cpp
 # ADD CPP /Yc"stdafx.h"
 # End Source File
@@ -373,6 +389,10 @@ SOURCE=.\AddType.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\Client.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\CopyProperties.h
 # End Source File
 # Begin Source File
@@ -389,6 +409,10 @@ SOURCE=.\DataTable.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\FriendDetails.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\GroupCombo.h
 # End Source File
 # Begin Source File
@@ -421,6 +445,10 @@ SOURCE=.\Misc.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\OptionFriends.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\OptionsGeneral.h
 # End Source File
 # Begin Source File
@@ -477,6 +505,10 @@ SOURCE=.\SelectDB.h
 # End Source File
 # Begin Source File
 
+SOURCE=.\Server.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\StdAfx.h
 # End Source File
 # Begin Source File

+ 7 - 0
CP_Main.h

@@ -140,6 +140,13 @@ public:
 
 	bool	m_bAsynchronousRefreshView;
 
+	//Socket Info
+	SOCKET	m_sSocket;
+	CRITICAL_SECTION m_CriticalSection;
+	CPopup	 *m_pcpSendRecieveError;
+
+
+
 // Overrides
 	// ClassWizard generated virtual function overrides
 	//{{AFX_VIRTUAL(CCP_MainApp)

+ 83 - 0
CP_Main.rc

@@ -255,6 +255,40 @@ BEGIN
 
             MENUITEM "Prompt For New Group Names",  ID_MENU_QUICKOPTIONS_PROMPTFORNEWGROUPNAMES
 
+        END
+        POPUP "Sent To"
+        BEGIN
+            MENUITEM "Friend One",                  ID_MENU_SENTTO_FRIENDONE
+            MENUITEM "Friend Two",                  ID_MENU_SENTTO_FRIEND_TWO
+
+            MENUITEM "Friend Three",                ID_MENU_SENTTO_FRIEND_THREE
+
+            MENUITEM "Friend Fore",                 ID_MENU_SENTTO_FRIEND_FORE
+
+            MENUITEM "Friend Five",                 ID_MENU_SENTTO_FRIEND_FIVE
+
+            MENUITEM "Friend Six",                  ID_MENU_SENTTO_FRIEND_SIX
+
+            MENUITEM "Friend Seven",                ID_MENU_SENTTO_FRIEND_SEVEN
+
+            MENUITEM "Friend Eight",                ID_MENU_SENTTO_FRIEND_EIGHT
+
+            MENUITEM "Friend Nine",                 ID_MENU_SENTTO_FRIEND_NINE
+
+            MENUITEM "Friend Ten",                  ID_MENU_SENTTO_FRIEND_TEN
+
+            MENUITEM "Friend Eleven",               ID_MENU_SENTTO_FRIEND_ELEVEN
+
+            MENUITEM "Friend Twelve",               ID_MENU_SENTTO_FRIEND_TWELVE
+
+            MENUITEM "Friend Thirteen",             ID_MENU_SENTTO_FRIEND_THIRTEEN
+
+            MENUITEM "Friend Foreteen",             ID_MENU_SENTTO_FRIEND_FORETEEN
+
+            MENUITEM "Friend Fifteen",              ID_MENU_SENTTO_FRIEND_FIFTEEN
+
+            MENUITEM "Prompt for IP",               ID_MENU_SENTTO_PROMPTFORIP
+
         END
         MENUITEM "View Full Description\tF3",   ID_MENU_VIEWFULLDESCRIPTION
         MENUITEM "View Groups\tCtrl-G",         ID_MENU_VIEWGROUPS
@@ -576,6 +610,39 @@ BEGIN
     EDITTEXT        IDC_NAME,7,11,172,12,ES_AUTOHSCROLL
 END
 
+IDD_OPTIONS_FRIENDS DIALOG DISCARDABLE  0, 0, 300, 214
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Friends"
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "List1",IDC_LIST,"SysListView32",LVS_REPORT | WS_BORDER | 
+                    WS_TABSTOP,7,82,286,116
+    LTEXT           "If Send All Copies is selected then all copies from this computer will be sent to the other computer.  If that is not selected then it will just be in the right click menu to send a copy to that computer.",
+                    IDC_STATIC,7,52,278,24
+    EDITTEXT        IDC_EDIT_PLACE_ON_CLIPBOARD,83,31,210,13,ES_AUTOHSCROLL
+    LTEXT           "IP/Computer Names seperated by commas",IDC_STATIC,7,29,
+                    70,17
+    LTEXT           "When you recieve a sent copy if their ip or computer name is in this list then it will be put on the clipboard.  Otherwise it will be in the saved clips to use at a later time.",
+                    IDC_STATIC,7,7,286,18
+    CONTROL         "Log Send Receive Commands",IDC_CHECK_LOG_SEND_RECIEVE,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,199,176,12
+END
+
+IDD_FRIEND_DETAILS DIALOG DISCARDABLE  0, 0, 203, 79
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Friend Details"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "OK",IDOK,89,58,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,146,58,50,14
+    CONTROL         "Send All Copies to this friend",IDC_CHECK_SEND_ALL,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,47,7,105,10
+    LTEXT           "IP/Name",IDC_STATIC,7,23,30,8
+    EDITTEXT        IDC_EDIT_IP,47,20,83,13,ES_AUTOHSCROLL
+    LTEXT           "Description",IDC_STATIC,7,41,36,8
+    EDITTEXT        IDC_EDIT_DESCRIPTION,47,39,149,13,ES_AUTOHSCROLL
+END
+
 
 #ifndef _MAC
 /////////////////////////////////////////////////////////////////////////////
@@ -726,6 +793,22 @@ BEGIN
         TOPMARGIN, 1
         BOTTOMMARGIN, 42
     END
+
+    IDD_OPTIONS_FRIENDS, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 293
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 211
+    END
+
+    IDD_FRIEND_DETAILS, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 196
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 72
+    END
 END
 #endif    // APSTUDIO_INVOKED
 

+ 341 - 0
Client.cpp

@@ -0,0 +1,341 @@
+// Client.cpp: implementation of the CClient class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "Client.h"
+
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+BOOL SendToFriend(CIDArray *pArray, long lPos, CString csIP, CPopup *pPopup)
+{
+	LogSendRecieveInfo("@@@@@@@@@@@@@@@ - START OF Send To Friend - @@@@@@@@@@@@@@@");
+
+	CSendToFriendInfo Info;
+	Info.csIP = csIP;
+	Info.lPos = lPos;
+	Info.pArray = pArray;
+	Info.pPopup = pPopup;
+
+	AfxBeginThread(SendToFriendThread, &Info);
+
+	DWORD dwWaitResult;
+	MSG msg;
+	while(true)
+	{
+		dwWaitResult = MsgWaitForMultipleObjects(1, &Info.hThreadRunning, FALSE, 1000, QS_ALLINPUT);
+
+		// Window message to be processed
+		if(dwWaitResult == (WAIT_OBJECT_0+1))
+		{
+			while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+			{
+				// get the next message in the queue
+				TranslateMessage(&msg);
+				DispatchMessage(&msg);
+			}
+		}	
+		else if (dwWaitResult == WAIT_OBJECT_0)
+		{
+			break;
+		}
+	}
+
+	LogSendRecieveInfo("@@@@@@@@@@@@@@@ - END OF Send To Friend - @@@@@@@@@@@@@@@");
+
+	return Info.bRet;
+}
+
+UINT SendToFriendThread(LPVOID pParam)
+{
+	LogSendRecieveInfo("@@@@@@@@@@@@@@@ - START OF Send To Friend Thread - @@@@@@@@@@@@@@@");
+
+	CSendToFriendInfo *pInfo = (CSendToFriendInfo*)pParam;
+	
+	if(pInfo->lPos > -1 && pInfo->lPos < MAX_SEND_CLIENTS)
+	{
+		pInfo->csIP = g_Opt.m_SendClients[pInfo->lPos].csIP;
+	}
+
+	LogSendRecieveInfo(StrF("Sending clip to %s", pInfo->csIP));
+	CClient client;
+
+	if(client.OpenConnection(pInfo->csIP) == FALSE)
+	{
+		LogSendRecieveInfo(StrF("ERROR opening connection to %s", pInfo->csIP));
+		pInfo->bRet = FALSE;
+		SetEvent(pInfo->hThreadRunning);
+		return FALSE;
+	}
+
+	for(int i = 0; i < pInfo->pArray->lCount; i++)
+	{
+		if(pInfo->pPopup)
+		{
+			pInfo->pPopup->SendToolTipText(StrF("Sending %d of %d", i+1, pInfo->pArray->lCount));
+		}
+
+		LogSendRecieveInfo(StrF("Sending %d of %d clip to %s", i+1, pInfo->pArray->lCount, pInfo->csIP));
+
+		if(client.SendItem(&pInfo->pArray->pIDs[i]) == FALSE)
+		{
+			LogSendRecieveInfo("ERROR SendItem Failed");
+
+			pInfo->bRet = FALSE;
+			SetEvent(pInfo->hThreadRunning);
+			return FALSE;
+		}
+	}
+
+	pInfo->bRet = TRUE;
+
+	LogSendRecieveInfo("@@@@@@@@@@@@@@@ - END OF Send To Friend Thread - @@@@@@@@@@@@@@@");
+
+	SetEvent(pInfo->hThreadRunning);
+
+	return TRUE;
+}
+
+UINT  SendClientThread(LPVOID pParam)
+{	
+	EnterCriticalSection(&theApp.m_CriticalSection);
+
+	LogSendRecieveInfo("@@@@@@@@@@@@@@@ - START OF SendClientThread - @@@@@@@@@@@@@@@");
+
+	bool bError;
+	CIDArray *pArray = (CIDArray*)pParam;
+	if(pArray == NULL)
+	{
+		LogSendRecieveInfo("ERROR if(pArray == NULL)");
+		return FALSE;
+	}
+
+	LogSendRecieveInfo(StrF("Start of Send ClientThread Count - %d", pArray->lCount));
+	
+	for(int nClient = 0; nClient < MAX_SEND_CLIENTS; nClient++)
+	{
+		if(g_Opt.m_SendClients[nClient].bSendAll && 
+			g_Opt.m_SendClients[nClient].csIP.GetLength() > 0)
+		{
+			CClient client;
+			if(client.OpenConnection(g_Opt.m_SendClients[nClient].csIP) == FALSE)
+			{
+				LogSendRecieveInfo(StrF("ERROR opening connection to %s", g_Opt.m_SendClients[nClient].csIP));
+				bError = true;
+			}
+
+			bError = false;
+
+			for(int i = 0; i < pArray->lCount; i++)
+			{
+				if(bError == false)
+				{
+					LogSendRecieveInfo(StrF("Sending clip to %s", g_Opt.m_SendClients[nClient].csIP));
+				
+					if(client.SendItem(&pArray->pIDs[i]) == FALSE)
+						bError = true;
+				}
+
+				if(bError)
+				{
+					CString cs;
+					cs.Format("Error sending clip to %s",g_Opt.m_SendClients[nClient].csIP);
+					::SendMessage(theApp.m_MainhWnd, WM_SEND_RECIEVE_ERROR, (WPARAM)cs.GetBuffer(cs.GetLength()), 0);
+					cs.ReleaseBuffer();
+					break;
+				}
+			}
+
+			client.CloseConnection();
+		}
+	}
+
+	delete []pArray->pIDs;
+	pArray->pIDs = NULL;
+
+	delete pArray;
+	pArray = NULL;
+	
+	LogSendRecieveInfo("@@@@@@@@@@@@@@@ - END OF SendClientThread - @@@@@@@@@@@@@@@");
+
+	LeaveCriticalSection(&theApp.m_CriticalSection);
+
+	return TRUE;
+}
+
+CClient::CClient()
+{
+	m_Connection = NULL;
+}
+
+CClient::~CClient()
+{			
+	CloseConnection();
+}
+
+BOOL CClient::CloseConnection()
+{
+	if(m_Connection != NULL && m_Connection != 0)
+	{
+		SendInfo Info;
+		SendData(&Info, MyEnums::EXIT);
+
+		closesocket(m_Connection);
+		WSACleanup();
+
+		m_Connection = NULL;
+	}
+
+	return TRUE;
+}
+
+BOOL CClient::OpenConnection(const char* servername)
+{
+	WSADATA wsaData;
+	struct hostent *hp;
+	unsigned int addr;
+	struct sockaddr_in server;
+	int wsaret=WSAStartup(0x101,&wsaData);
+	if(wsaret)	
+	{
+		LogSendRecieveInfo("ERROR - WSAStartup(0x101,&wsaData)");
+		return FALSE;
+	}
+	
+	m_Connection = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
+
+	if(m_Connection == INVALID_SOCKET)
+	{
+		LogSendRecieveInfo("ERROR - socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)");
+		
+		return FALSE;
+	}
+
+	if(inet_addr(servername)==INADDR_NONE)
+	{
+		hp=gethostbyname(servername);
+	}
+	else
+	{
+		addr=inet_addr(servername);
+		hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
+	}
+
+	if(hp==NULL)
+	{
+		LogSendRecieveInfo("ERROR - if(hp==NULL)");
+
+		closesocket(m_Connection);
+		return FALSE;
+	}
+
+	server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
+	server.sin_family=AF_INET;
+	server.sin_port=htons(20248);
+	if(connect(m_Connection,(struct sockaddr*)&server,sizeof(server)))
+	{
+		LogSendRecieveInfo("ERROR if(connect(m_Connection,(struct sockaddr*)&server,sizeof(server)))");
+		closesocket(m_Connection);
+		return FALSE;	
+	}
+
+	return TRUE;
+}
+
+BOOL CClient::SendItem(CID *pData)
+{
+	SendInfo Info;
+	
+	strncpy(Info.m_cComputerName, GetComputerName(), sizeof(Info.m_cComputerName));
+	strncpy(Info.m_cIP, GetIPAddress(), sizeof(Info.m_cIP));
+	strncpy(Info.m_cText, pData->m_csDesc, sizeof(Info.m_cText));
+	
+	Info.m_cText[sizeof(Info.m_cText)-1] = 0;
+	Info.m_cComputerName[sizeof(Info.m_cComputerName)-1] = 0;
+	Info.m_cIP[sizeof(Info.m_cIP)-1] = 0;
+
+	if(SendData(&Info, MyEnums::START) == FALSE)
+		return FALSE;
+	
+	CClipFormat* pCF;
+
+	//If the data has not been loaded, then send a message to
+	//the main thread to load the data from the db
+	if(pData->m_Formats.GetSize() <= 0)
+	{
+		::SendMessage(theApp.m_MainhWnd, WM_LOAD_FORMATS, pData->lID, (LPARAM)&pData->m_Formats);
+	}
+	
+	int nCount = pData->m_Formats.GetSize();
+	DWORD dwSize;
+	int nDataSent;
+
+	//For each data type
+	for( int i=0; i < nCount; i++ )
+	{
+		pCF = &pData->m_Formats[i];
+
+		Info.m_lParameter1 = dwSize = GlobalSize(pCF->m_hgData);
+		strncpy(Info.m_cText, GetFormatName(pCF->m_cfType), sizeof(Info.m_cText));
+		Info.m_cText[sizeof(Info.m_cText)-1] = 0;
+
+		if(SendData(&Info, MyEnums::DATA_START) == FALSE)
+			return FALSE;
+
+		nDataSent = 0;
+		while(nDataSent < dwSize)
+		{
+			LPVOID pvData = GlobalLock(pCF->m_hgData);
+
+			if(dwSize - nDataSent < MAX_DATA_SIZE)
+				Info.m_lParameter1 = dwSize - nDataSent;
+			else
+				Info.m_lParameter1 = MAX_DATA_SIZE;
+
+			memcpy(Info.m_cText,  ((char*)pvData) + nDataSent, Info.m_lParameter1);
+
+			GlobalUnlock(pCF->m_hgData);
+
+			if(SendData(&Info, MyEnums::DATA) == FALSE)
+				return FALSE;
+
+			nDataSent += Info.m_lParameter1;
+		}
+
+		if(SendData(&Info, MyEnums::DATA_END) == FALSE)
+			return FALSE;
+	}
+	
+	if(SendData(&Info, MyEnums::END) == FALSE)
+		return FALSE;
+	
+	return TRUE;
+}
+
+BOOL CClient::SendData(SendInfo *pInfo, MyEnums::eSendType type)
+{
+	pInfo->m_Type = type;
+	long lSize = send(m_Connection, (char *)pInfo, sizeof(SendInfo), 0);
+	if(lSize != sizeof(SendInfo))
+	{
+		ASSERT(FALSE);
+	}
+
+	if(lSize == SOCKET_ERROR)
+	{
+		LogSendRecieveInfo(StrF("lSize == SOCKET_ERROR, %d", WSAGetLastError()));
+		return FALSE;
+	}
+
+	return TRUE;
+}

+ 91 - 0
Client.h

@@ -0,0 +1,91 @@
+// Client.h: interface for the CClient class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CLIENT_H__E9B55197_85B2_4ABF_92FF_E6301F346404__INCLUDED_)
+#define AFX_CLIENT_H__E9B55197_85B2_4ABF_92FF_E6301F346404__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "Server.h"
+
+class CID
+{
+public:
+	CID()
+	{
+		lID = -1;
+	}
+
+	~CID()
+	{
+		m_Formats.RemoveAll();
+	}
+	
+	long lID;
+	CString m_csDesc;
+	CClipFormats m_Formats;
+};
+
+class CIDArray
+{
+public:
+	CIDArray()
+	{
+		pIDs = NULL;
+		lCount = 0;
+	}
+	CID *pIDs;
+	long lCount;
+};
+
+class CSendToFriendInfo
+{
+public:
+	CSendToFriendInfo()
+	{
+		pPopup = NULL;
+		pArray = NULL;
+		lPos = -1;
+		bRet = FALSE;
+		hThreadRunning = CreateEvent(NULL, FALSE, FALSE, "SendToFriend");
+		ResetEvent(hThreadRunning);
+	}
+	~CSendToFriendInfo()
+	{
+		CloseHandle(hThreadRunning);
+	}
+
+	CIDArray *pArray;
+	long lPos;
+	CString csIP;
+	CPopup *pPopup;
+	BOOL bRet;
+	HANDLE hThreadRunning;
+};
+
+class CClient  
+{
+public:
+	CClient();
+	virtual ~CClient();
+
+	BOOL SendItem(CID *pData);
+	
+	BOOL OpenConnection(const char* servername);
+	BOOL CloseConnection();
+
+protected:
+	SOCKET m_Connection;
+
+	BOOL SendData(SendInfo *pInfo, MyEnums::eSendType type);
+};
+
+BOOL SendToFriend(CIDArray *pArray, long lPos, CString csIP, CPopup *pPopup);
+UINT SendToFriendThread(LPVOID pParam);
+
+UINT  SendClientThread(LPVOID pParam);
+
+#endif // !defined(AFX_CLIENT_H__E9B55197_85B2_4ABF_92FF_E6301F346404__INCLUDED_)

+ 64 - 0
FriendDetails.cpp

@@ -0,0 +1,64 @@
+// FriendDetails.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "FriendDetails.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CFriendDetails dialog
+
+
+CFriendDetails::CFriendDetails(CWnd* pParent /*=NULL*/)
+	: CDialog(CFriendDetails::IDD, pParent)
+{
+	//{{AFX_DATA_INIT(CFriendDetails)
+	m_checkSendAll = FALSE;
+	m_csDescription = _T("");
+	m_csIP = _T("");
+	//}}AFX_DATA_INIT
+}
+
+
+void CFriendDetails::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CFriendDetails)
+	DDX_Check(pDX, IDC_CHECK_SEND_ALL, m_checkSendAll);
+	DDX_Text(pDX, IDC_EDIT_DESCRIPTION, m_csDescription);
+	DDX_Text(pDX, IDC_EDIT_IP, m_csIP);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CFriendDetails, CDialog)
+	//{{AFX_MSG_MAP(CFriendDetails)
+		// NOTE: the ClassWizard will add message map macros here
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CFriendDetails message handlers
+
+BOOL CFriendDetails::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	UpdateData(FALSE);
+	
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CFriendDetails::OnOK() 
+{
+	UpdateData();
+	
+	CDialog::OnOK();
+}

+ 49 - 0
FriendDetails.h

@@ -0,0 +1,49 @@
+#if !defined(AFX_FRIENDDETAILS_H__EE25569D_E112_4F70_BDB3_6AD778477A73__INCLUDED_)
+#define AFX_FRIENDDETAILS_H__EE25569D_E112_4F70_BDB3_6AD778477A73__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// FriendDetails.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CFriendDetails dialog
+
+class CFriendDetails : public CDialog
+{
+// Construction
+public:
+	CFriendDetails(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CFriendDetails)
+	enum { IDD = IDD_FRIEND_DETAILS };
+	BOOL	m_checkSendAll;
+	CString	m_csDescription;
+	CString	m_csIP;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CFriendDetails)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CFriendDetails)
+	virtual BOOL OnInitDialog();
+	virtual void OnOK();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FRIENDDETAILS_H__EE25569D_E112_4F70_BDB3_6AD778477A73__INCLUDED_)

+ 86 - 0
MainFrm.cpp

@@ -43,6 +43,9 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 	ON_MESSAGE(WM_CLOSE_APP, OnShutDown)
 	ON_MESSAGE(WM_CLIPBOARD_COPIED, OnClipboardCopied)
 	ON_WM_CLOSE()
+	ON_MESSAGE(WM_ADD_TO_DATABASE_FROM_SOCKET, OnAddToDatabaseFromSocket)
+	ON_MESSAGE(WM_LOAD_FORMATS, OnLoadFormats)
+	ON_MESSAGE(WM_SEND_RECIEVE_ERROR, OnErrorOnSendRecieve)
 END_MESSAGE_MAP()
 
 static UINT indicators[] =
@@ -185,6 +188,8 @@ LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
 		//Simulate the Copy
 		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
 		keybd_event('C', 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
+
+		Sleep(100);
      
 		keybd_event('C', 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
 		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
@@ -326,6 +331,16 @@ void CMainFrame::OnTimer(UINT nIDEvent)
 			}
 			break;
 		}
+	case HIDE_ERROR_POPUP:
+		{
+			KillTimer(HIDE_ERROR_POPUP);
+			if(theApp.m_pcpSendRecieveError)
+			{
+				delete theApp.m_pcpSendRecieveError;
+				theApp.m_pcpSendRecieveError = NULL;				
+			}
+			break;
+		}
 	}
 
 	CFrameWnd::OnTimer(nIDEvent);
@@ -425,3 +440,74 @@ void CMainFrame::OnClose()
 	theApp.BeforeMainClose();
 	CFrameWnd::OnClose();
 }
+
+LRESULT CMainFrame::OnAddToDatabaseFromSocket(WPARAM wParam, LPARAM lParam)
+{
+	CClip *pClip = (CClip*)wParam;
+	BOOL bSetToClipBoard = (BOOL)lParam;
+
+	LogSendRecieveInfo("---------Start of OnAddToDatabaseFromSocket");
+
+	if(bSetToClipBoard)
+	{
+		LogSendRecieveInfo("---------Start of Set to ClipBoard");
+		CClip NewClip;
+		NewClip = *pClip;
+
+		LogSendRecieveInfo("---------After =");
+
+		CProcessPaste paste;
+		//Don't send the paste just load it into memory
+		paste.m_bSendPaste = false;
+		paste.m_pOle->LoadFormats(&NewClip.m_Formats);
+		paste.m_pOle->CacheGlobalData(theApp.m_cfIgnoreClipboard, NewGlobalP("Ignore", sizeof("Ignore")));
+
+		LogSendRecieveInfo("---------After LoadFormats");
+	
+		paste.DoPaste();
+
+		LogSendRecieveInfo("---------Start of Set to ClipBoard");
+	}
+
+	pClip->MakeLatestTime();
+	pClip->AddToDB(true);
+
+	LogSendRecieveInfo("---------After AddToDB");
+
+	theApp.RefreshView();
+	theApp.m_FocusID = pClip->m_ID;
+
+	LogSendRecieveInfo("---------End of OnAddToDatabaseFromSocket");
+	
+	return TRUE;
+}
+
+LRESULT CMainFrame::OnLoadFormats(WPARAM wParam, LPARAM lParam)
+{
+	int nID = (int)wParam;
+	CClipFormats *pFormats = (CClipFormats *)lParam;
+	CClip::LoadFormats(nID, *pFormats);
+	return TRUE;
+}
+
+LRESULT CMainFrame::OnErrorOnSendRecieve(WPARAM wParam, LPARAM lParam)
+{
+	KillTimer(HIDE_ERROR_POPUP);
+	if(theApp.m_pcpSendRecieveError)
+	{
+		CString csOldText = theApp.m_pcpSendRecieveError->m_csToolTipText;
+		CString csNewText = (char*)wParam;
+		CString csCombinedText = csOldText + "\n" + csNewText;
+		theApp.m_pcpSendRecieveError->Show(csCombinedText, CPoint(20, 20), true);		
+	}
+	else
+	{
+		theApp.m_pcpSendRecieveError = new CPopup(20, 20, ::GetForegroundWindow());
+		CString csNewText = (char*)wParam;
+		theApp.m_pcpSendRecieveError->Show(csNewText);
+	}
+
+	SetTimer(HIDE_ERROR_POPUP, 6000, NULL);
+
+	return TRUE;
+}

+ 4 - 0
MainFrm.h

@@ -18,6 +18,7 @@
 #define REMOVE_OLD_ENTRIES_TIMER		3
 #define CHECK_FOR_UPDATE				4
 #define CLOSE_APP						5
+#define HIDE_ERROR_POPUP				6
 
 
 class CMainFrame : public CFrameWnd
@@ -78,6 +79,9 @@ protected:
 	afx_msg LRESULT OnCopyProperties(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnShutDown(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnClipboardCopied(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnAddToDatabaseFromSocket(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnLoadFormats(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnErrorOnSendRecieve(WPARAM wParam, LPARAM lParam);
 	DECLARE_MESSAGE_MAP()
 public:
 	virtual BOOL PreTranslateMessage(MSG* pMsg);

+ 145 - 2
Misc.cpp

@@ -9,6 +9,44 @@
 
 // Debug Functions
 
+CString GetIPAddress()
+{
+	WORD wVersionRequested;
+    WSADATA wsaData;
+    char name[255];
+    CString IP;
+	PHOSTENT hostinfo;
+	wVersionRequested = MAKEWORD(2,0);
+	
+	if (WSAStartup(wVersionRequested, &wsaData)==0)
+	{
+		if(gethostname(name, sizeof(name))==0)
+		{
+			if((hostinfo=gethostbyname(name)) != NULL)
+			{
+				IP = inet_ntoa(*(struct in_addr*)* hostinfo->h_addr_list);
+			}
+		}
+		
+		WSACleanup();
+	} 
+	IP.MakeUpper();
+
+	return IP;
+}
+
+CString GetComputerName()
+{
+	char ComputerName[MAX_COMPUTERNAME_LENGTH+1]="";
+	DWORD Size=MAX_COMPUTERNAME_LENGTH+1;
+	GetComputerName(ComputerName, &Size);
+
+	CString cs(ComputerName);
+	cs.MakeUpper();
+
+	return cs;
+}
+
 void AppendToFile( const char* fn, const char* msg )
 {
 	FILE *file = fopen(fn, "a");
@@ -26,9 +64,16 @@ void Log( const char* msg )
 	//	csTemp.Format( "%04x  ", AfxGetInstanceHandle() );
 	csText += msg;
 	csText += "\n";
+	TRACE(csText);
 	AppendToFile( "Ditto.log", csText ); //(LPCTSTR)
 }
 
+void LogSendRecieveInfo(CString cs)
+{
+	if(g_Opt.m_bLogSendReceiveErrors)
+		Log(cs);
+}
+
 CString GetErrorString( int err )
 {
 	CString str;
@@ -418,6 +463,10 @@ BOOL CGetSetOptions::m_bAllwaysShowDescription;
 long CGetSetOptions::m_bDoubleClickingOnCaptionDoes;
 BOOL CGetSetOptions::m_bPrompForNewGroupName;
 BOOL CGetSetOptions::m_bSendPasteOnFirstTenHotKeys;
+CSendClients CGetSetOptions::m_SendClients[MAX_SEND_CLIENTS];
+long CGetSetOptions::m_lAutoSendClientCount;
+CString CGetSetOptions::m_csIPListToPutOnClipboard;
+BOOL CGetSetOptions::m_bLogSendReceiveErrors;
 
 CGetSetOptions g_Opt;
 
@@ -436,6 +485,15 @@ CGetSetOptions::CGetSetOptions()
 	m_bDoubleClickingOnCaptionDoes = GetDoubleClickingOnCaptionDoes();
 	m_bPrompForNewGroupName = GetPrompForNewGroupName();
 	m_bSendPasteOnFirstTenHotKeys = GetSendPasteOnFirstTenHotKeys();
+	m_csIPListToPutOnClipboard = GetListToPutOnClipboard();
+	m_bLogSendReceiveErrors = GetLogSendReceiveErrors();
+
+	for(int i = 0; i < MAX_SEND_CLIENTS; i++)
+	{
+		GetSendClients(i);
+	}
+
+	GetClientSendCount();
 }
 
 CGetSetOptions::~CGetSetOptions()
@@ -907,6 +965,81 @@ BOOL CGetSetOptions::GetPrompForNewGroupName()				{	return GetProfileLong("Promp
 void CGetSetOptions::SetSendPasteOnFirstTenHotKeys(BOOL bOption)	{	SetProfileLong("SendPasteOnFirstTenHotKeys", bOption); m_bSendPasteOnFirstTenHotKeys = bOption; }
 BOOL CGetSetOptions::GetSendPasteOnFirstTenHotKeys()				{	return GetProfileLong("SendPasteOnFirstTenHotKeys", TRUE); }
 
+void CGetSetOptions::SetSendClients(CSendClients Client, int nPos)
+{
+	CString cs;
+
+	cs.Format("sendclient_ip_%d", nPos);
+	SetProfileString(cs, Client.csIP);
+
+	cs.Format("sendclient_autosend_%d", nPos);
+	SetProfileLong(cs, Client.bSendAll);
+
+	cs.Format("sendclient_description_%d", nPos);
+	SetProfileString(cs, Client.csDescription);
+
+	m_SendClients[nPos] = Client;
+}
+
+CSendClients CGetSetOptions::GetSendClients(int nPos)
+{
+	CSendClients Client;
+
+	CString cs;
+
+	cs.Format("sendclient_ip_%d", nPos);
+	Client.csIP = GetProfileString(cs, "");
+
+	cs.Format("sendclient_autosend_%d", nPos);
+	Client.bSendAll = GetProfileLong(cs, FALSE);
+
+	cs.Format("sendclient_description_%d", nPos);
+	Client.csDescription = GetProfileString(cs, "");
+
+	m_SendClients[nPos] = Client;
+
+	return Client;
+}
+
+void CGetSetOptions::GetClientSendCount()
+{
+	m_lAutoSendClientCount = 0;
+	for(int i = 0; i < MAX_SEND_CLIENTS; i++)
+	{
+		if(m_SendClients[i].csIP.GetLength() > 0)
+		{
+			if(m_SendClients[i].bSendAll)
+				m_lAutoSendClientCount++;
+		}
+	}
+}
+
+CString	CGetSetOptions::GetListToPutOnClipboard()			
+{ 
+	CString cs = GetProfileString("ListToPutOnClipboard", "");
+	cs.MakeUpper();
+	return cs;
+}
+BOOL CGetSetOptions::SetListToPutOnClipboard(CString cs)	
+{ 
+	cs.MakeUpper();
+	m_csIPListToPutOnClipboard = cs;
+	return SetProfileString("ListToPutOnClipboard", cs); 
+	
+}
+
+void CGetSetOptions::SetLogSendReceiveErrors(BOOL bOption)
+{
+	m_bLogSendReceiveErrors = bOption;
+
+	SetProfileLong("LogSendReceiveErrors", bOption);
+}
+
+BOOL CGetSetOptions::GetLogSendReceiveErrors()
+{
+	return GetProfileLong("LogSendReceiveErrors", FALSE);
+}
+
 /*------------------------------------------------------------------*\
 CHotKey - a single system-wide hotkey
 \*------------------------------------------------------------------*/
@@ -1021,6 +1154,7 @@ bool CHotKey::Unregister(bool bOnShowingDitto)
 	else
 	{
 		m_bIsRegistered = false;
+		return true;
 	}
 	
 	return false;
@@ -1684,6 +1818,8 @@ void CPopup::AdjustPos( CPoint& pos )
 
 void CPopup::SendToolTipText( CString text )
 {
+	m_csToolTipText = text;
+	
 	//Replace the tabs with spaces, the tooltip didn't like the \t s
 	text.Replace("\t", "  ");
 	m_TI.lpszText = (LPSTR) (LPCTSTR) text;
@@ -1698,6 +1834,8 @@ void CPopup::Show( CString text, CPoint pos, bool bAdjustPos )
 {
 	if( m_hTTWnd == NULL )
 		return;
+
+	m_csToolTipText = text;
 	
 	if( !m_bIsShowing )
 		::SendMessage(m_hTTWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG(-10000,-10000));
@@ -1716,10 +1854,15 @@ void CPopup::Show( CString text, CPoint pos, bool bAdjustPos )
 }
 
 void CPopup::Show( CString text )
-{ Show( text, m_Pos ); }
+{ 
+	m_csToolTipText = text;
+	Show( text, m_Pos ); 
+}
 
 void CPopup::AllowShow( CString text )
 {
+	m_csToolTipText = text;
+	
 	if( m_bAllowShow )
 		Show( text, m_Pos );
 }
@@ -1731,4 +1874,4 @@ void CPopup::Hide()
 	// deactivate if it is currently activated
 	::SendMessage(m_hTTWnd, TTM_TRACKACTIVATE, FALSE, (LPARAM)(LPTOOLINFO) &m_TI);
 	m_bIsShowing = false;
-}
+}

+ 37 - 0
Misc.h

@@ -19,6 +19,9 @@
 #define LOG(x)
 #endif
 
+CString GetIPAddress();
+CString GetComputerName();
+
 #define FUNC		__FUNCTION__
 #define FUNCSIG		__FUNCSIG__
 void AppendToFile( const char* fn, const char *msg );
@@ -35,6 +38,8 @@ typedef struct tagTHREADNAME_INFO
 } THREADNAME_INFO;
 void SetThreadName(DWORD dwThreadID, LPCTSTR szThreadName);
 
+void LogSendRecieveInfo(CString cs);
+
 // Utility Functions
 CString StrF(const char * pszFormat, ...);
 // called after determining that the preceding character is a backslash
@@ -90,9 +95,25 @@ CString GetFilePath(CString csFullPath);
 #define WM_CLOSE_APP			WM_USER + 204
 #define WM_REFRESH_VIEW			WM_USER + 205
 #define WM_CLIPBOARD_COPIED		WM_USER + 206
+#define WM_ADD_TO_DATABASE_FROM_SOCKET		WM_USER + 207
+#define WM_LOAD_FORMATS			WM_USER + 208
+#define WM_SEND_RECIEVE_ERROR	WM_USER + 209
 
 #define REG_PATH					"Software\\Ditto"
 
+#define MAX_SEND_CLIENTS	15
+class CSendClients
+{
+public:
+	CSendClients()
+	{
+		bSendAll = FALSE;
+	}
+	BOOL bSendAll;
+	CString csIP;
+	CString csDescription;
+};
+
 /*------------------------------------------------------------------*\
 	CGetSetOptions - Manages Application Registry settings
 \*------------------------------------------------------------------*/
@@ -248,6 +269,20 @@ public:
 	static void		SetSendPasteOnFirstTenHotKeys(BOOL bOption);
 	static BOOL		GetSendPasteOnFirstTenHotKeys();
 
+	static CSendClients m_SendClients[MAX_SEND_CLIENTS];
+	static long		m_lAutoSendClientCount;
+	static void		GetClientSendCount();
+	static void		SetSendClients(CSendClients Client, int nPos);
+	static CSendClients		GetSendClients(int nPos);
+
+	static CString m_csIPListToPutOnClipboard;
+	static CString	GetListToPutOnClipboard();
+	static BOOL		SetListToPutOnClipboard(CString cs);
+
+	static BOOL		m_bLogSendReceiveErrors;
+	static void		SetLogSendReceiveErrors(BOOL bOption);
+	static BOOL		GetLogSendReceiveErrors();
+
 
 	/*
 	BOOL IsAutoRun();
@@ -438,6 +473,8 @@ public:
 
 	bool m_bAllowShow; // used by SafeShow to determine whether to show or not
 
+	CString m_csToolTipText;
+
 	CPopup();
 	CPopup( int x, int y, HWND hWndPosRelativeTo = NULL, HWND hWndInsertAfter = HWND_TOP );
 	~CPopup();

+ 250 - 0
OptionFriends.cpp

@@ -0,0 +1,250 @@
+// OptionFriends.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "OptionFriends.h"
+#include "FriendDetails.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define EMPTRY_STRING "----"
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionFriends property page
+
+IMPLEMENT_DYNCREATE(COptionFriends, CPropertyPage)
+
+COptionFriends::COptionFriends() : CPropertyPage(COptionFriends::IDD)
+{
+	//{{AFX_DATA_INIT(COptionFriends)
+	m_PlaceOnClipboard = _T("");
+	//}}AFX_DATA_INIT
+}
+
+COptionFriends::~COptionFriends()
+{
+}
+
+void COptionFriends::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionFriends)
+	DDX_Control(pDX, IDC_CHECK_LOG_SEND_RECIEVE, m_SendRecieve);
+	DDX_Control(pDX, IDC_LIST, m_List);
+	DDX_Text(pDX, IDC_EDIT_PLACE_ON_CLIPBOARD, m_PlaceOnClipboard);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(COptionFriends, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionFriends)
+	ON_NOTIFY(NM_DBLCLK, IDC_LIST, OnDblclkList)
+	ON_NOTIFY(LVN_KEYDOWN, IDC_LIST, OnKeydownList)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionFriends message handlers
+
+
+BOOL COptionFriends::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+
+	m_pParent = (COptionsSheet *)GetParent();
+	
+	m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT);
+	InitListCtrlCols();
+
+	InsertItems();
+
+	m_SendRecieve.SetCheck(CGetSetOptions::GetLogSendReceiveErrors());
+
+	m_PlaceOnClipboard = g_Opt.m_csIPListToPutOnClipboard;
+
+	UpdateData(FALSE);
+		
+	return FALSE;
+}
+
+BOOL COptionFriends::OnApply() 
+{
+	CSendClients client;
+	for (int i = 0; i < MAX_SEND_CLIENTS; i++)
+	{
+		if(m_List.GetItemText(i, 1) == "X")
+			client.bSendAll = TRUE;
+		else
+			client.bSendAll = FALSE;
+
+		client.csIP = m_List.GetItemText(i, 2);
+		if(client.csIP == EMPTRY_STRING)
+			client.csIP = "";
+		
+		client.csDescription = m_List.GetItemText(i, 3);
+		if(client.csDescription == EMPTRY_STRING)
+			client.csDescription = "";
+
+		g_Opt.SetSendClients(client, i);
+	}
+
+	CGetSetOptions::SetLogSendReceiveErrors(m_SendRecieve.GetCheck());
+
+	UpdateData();
+
+	g_Opt.SetListToPutOnClipboard(m_PlaceOnClipboard);
+
+	g_Opt.GetClientSendCount();
+	
+	return CPropertyPage::OnApply();
+}
+
+
+void COptionFriends::InitListCtrlCols()
+{
+	// Insert some columns
+	m_List.InsertColumn(0, _T(""), LVCFMT_LEFT, 25);
+	m_List.InsertColumn(1, _T("Send All Copies"), LVCFMT_LEFT, 90);
+	m_List.InsertColumn(2, _T("IP/Name"), LVCFMT_LEFT, 135);
+	m_List.InsertColumn(3, _T("Descriptions"), LVCFMT_LEFT, 157);
+
+}
+
+void COptionFriends::InsertItems()
+{
+	// Delete the current contents
+	m_List.DeleteAllItems();
+
+	// Use the LV_ITEM structure to insert the items
+	LVITEM lvi;
+	CString strItem;
+	for (int i = 0; i < MAX_SEND_CLIENTS; i++)
+	{
+		// Insert the first item
+		lvi.mask =  LVIF_TEXT;
+	
+		lvi.iItem = i;
+
+//-------------------------------------------------------------------
+
+		strItem.Format("%d", i+1);
+
+		lvi.iSubItem = 0;
+		lvi.pszText = (LPTSTR)(LPCTSTR)(strItem);
+		m_List.InsertItem(&lvi);
+
+//-------------------------------------------------------------------
+		if(g_Opt.m_SendClients[i].bSendAll)
+			strItem = "X";
+		else
+			strItem = EMPTRY_STRING;
+
+		m_List.SetItemText(i, 1, strItem);
+
+//-------------------------------------------------------------------
+
+		strItem = g_Opt.m_SendClients[i].csIP;
+		if(g_Opt.m_SendClients[i].csIP.GetLength() <= 0)
+		{
+			strItem = EMPTRY_STRING;
+		}
+
+		m_List.SetItemText(i, 2, strItem);
+
+//-------------------------------------------------------------------
+
+		strItem = g_Opt.m_SendClients[i].csDescription;
+		if(g_Opt.m_SendClients[i].csDescription.GetLength() <= 0)
+		{
+			strItem = EMPTRY_STRING;
+		}
+		
+		m_List.SetItemText(i, 3, strItem);
+	}
+}
+
+void COptionFriends::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	POSITION pos = m_List.GetFirstSelectedItemPosition();
+	if(pos)
+	{
+		int nItem = m_List.GetNextSelectedItem(pos);
+
+		EditItem(nItem);
+	}
+	
+	*pResult = 0;
+}
+
+BOOL COptionFriends::EditItem(int nItem)
+{
+	CFriendDetails dlg;
+
+	if(m_List.GetItemText(nItem, 1) == "X")
+		dlg.m_checkSendAll = TRUE;
+	else
+		dlg.m_checkSendAll = FALSE;
+
+	dlg.m_csIP = m_List.GetItemText(nItem, 2);
+	if(dlg.m_csIP == EMPTRY_STRING)
+		dlg.m_csIP = "";
+	dlg.m_csDescription = m_List.GetItemText(nItem, 3);
+	if(dlg.m_csDescription == EMPTRY_STRING)
+		dlg.m_csDescription = "";
+
+	if(dlg.DoModal() == IDOK)
+	{
+		if(dlg.m_checkSendAll)
+		{
+			m_List.SetItemText(nItem, 1, "X");
+		}
+		else
+			m_List.SetItemText(nItem, 1, "");
+
+		m_List.SetItemText(nItem, 2, dlg.m_csIP);
+		m_List.SetItemText(nItem, 3, dlg.m_csDescription);
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+void COptionFriends::OnKeydownList(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
+
+	switch (pLVKeyDow->wVKey)
+	{
+	case VK_DELETE:
+		{
+			POSITION pos = m_List.GetFirstSelectedItemPosition();
+			if(pos)
+			{
+				int nItem = m_List.GetNextSelectedItem(pos);
+				m_List.SetItemText(nItem, 1, EMPTRY_STRING);
+				m_List.SetItemText(nItem, 2, EMPTRY_STRING);
+				m_List.SetItemText(nItem, 3, EMPTRY_STRING);
+			}
+		}
+		break;
+	case VK_RETURN:
+		{
+			POSITION pos = m_List.GetFirstSelectedItemPosition();
+			if(pos)
+			{
+				int nItem = m_List.GetNextSelectedItem(pos);
+				EditItem(nItem);
+			}
+		}
+		break;
+	}
+	
+	
+	*pResult = 0;
+}

+ 62 - 0
OptionFriends.h

@@ -0,0 +1,62 @@
+#if !defined(AFX_OPTIONFRIENDS_H__E44847C3_54CA_4053_9647_349405B64DF9__INCLUDED_)
+#define AFX_OPTIONFRIENDS_H__E44847C3_54CA_4053_9647_349405B64DF9__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionFriends.h : header file
+//
+#include "OptionsSheet.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionFriends dialog
+
+class COptionFriends : public CPropertyPage
+{
+	DECLARE_DYNCREATE(COptionFriends)
+
+// Construction
+public:
+	COptionFriends();
+	~COptionFriends();
+
+// Dialog Data
+	//{{AFX_DATA(COptionFriends)
+	enum { IDD = IDD_OPTIONS_FRIENDS };
+	CButton	m_SendRecieve;
+	CListCtrl	m_List;
+	CString	m_PlaceOnClipboard;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generate virtual function overrides
+	//{{AFX_VIRTUAL(COptionFriends)
+	public:
+	virtual BOOL OnApply();
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+	void InitListCtrlCols();
+	void InsertItems();
+	BOOL EditItem(int nItem);
+
+	COptionsSheet *m_pParent;
+	
+	// Generated message map functions
+	//{{AFX_MSG(COptionFriends)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnKeydownList(NMHDR* pNMHDR, LRESULT* pResult);
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONFRIENDS_H__E44847C3_54CA_4053_9647_349405B64DF9__INCLUDED_)

+ 5 - 0
OptionsSheet.cpp

@@ -11,6 +11,7 @@
 #include "OptionsStats.h"
 #include "OptionsTypes.h"
 #include "About.h"
+#include "OptionFriends.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -34,6 +35,7 @@ COptionsSheet::COptionsSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectP
 	m_pStats = NULL;
 	m_pTypes = NULL;
 	m_pAbout = NULL;
+	m_pFriends = NULL;
 }
 
 COptionsSheet::~COptionsSheet()
@@ -45,6 +47,7 @@ COptionsSheet::~COptionsSheet()
 	DELETE_PTR(m_pStats);
 	DELETE_PTR(m_pTypes);
 	DELETE_PTR(m_pAbout);
+	DELETE_PTR(m_pFriends);
 }
 
 BEGIN_MESSAGE_MAP(COptionsSheet, CPropertySheet)
@@ -63,6 +66,7 @@ int COptionsSheet::DoModal()
 	m_pGeneralOptions = new COptionsGeneral;
 	m_pKeyBoardOptions = new COptionsKeyBoard;
 	m_pQuickPasteOptions = new COptionsQuickPaste;
+	m_pFriends = new COptionFriends;
 	m_pStats = new COptionsStats;
 	m_pTypes = new COptionsTypes;
 	m_pAbout = new CAbout;
@@ -71,6 +75,7 @@ int COptionsSheet::DoModal()
 	AddPage(m_pTypes);
 	AddPage(m_pKeyBoardOptions);
 	AddPage(m_pQuickPasteOptions);
+	AddPage(m_pFriends);
 	AddPage(m_pStats);
 	AddPage(m_pAbout);
 	

+ 1 - 0
OptionsSheet.h

@@ -46,6 +46,7 @@ protected:
 	CPropertyPage *m_pStats;
 	CPropertyPage *m_pTypes;
 	CPropertyPage *m_pAbout;
+	CPropertyPage *m_pFriends;
 
 
 	//{{AFX_MSG(COptionsSheet)

+ 27 - 0
ProcessCopy.cpp

@@ -135,6 +135,33 @@ void CClip::Clear()
 	EmptyFormats();
 }
 
+const CClip& CClip::operator=(const CClip &clip)
+{
+	const CClipFormat* pCF;
+
+	m_ID = clip.m_ID;
+	m_DataID = clip.m_DataID;
+	m_Time = clip.m_Time;
+	m_Desc = clip.m_Desc;
+	m_lTotalCopySize = clip.m_lTotalCopySize;
+
+	int nCount = clip.m_Formats.GetSize();
+	
+	for(int i = 0; i < nCount; i++)
+	{
+		pCF = &clip.m_Formats.GetData()[i];
+
+		LPVOID pvData = GlobalLock(pCF->m_hgData);
+		if(pvData)
+		{
+			AddFormat(pCF->m_cfType, pvData, GlobalSize(pCF->m_hgData));
+		}
+		GlobalUnlock(pCF->m_hgData);
+	}
+
+	return *this;
+}
+
 void CClip::EmptyFormats()
 {
 	// free global memory in m_Formats

+ 2 - 0
ProcessCopy.h

@@ -67,6 +67,8 @@ public:
 	long			m_DataID;
 	CClipFormats	m_Formats; // actual format data
 
+	const CClip& operator=(const CClip &clip);
+
 	// statistics assigned by LoadFromClipboard
 	CTime	m_Time;	 // time copied from clipboard
 	CString m_Desc;

+ 28 - 10
ProcessPaste.cpp

@@ -701,6 +701,7 @@ COleClipSource
 //IMPLEMENT_DYNAMIC(COleClipSource, COleDataSource)
 COleClipSource::COleClipSource()
 {
+	m_bLoadedFormats = false;
 }
 
 COleClipSource::~COleClipSource()
@@ -721,23 +722,21 @@ BOOL COleClipSource::DoDelayRender()
 
 BOOL COleClipSource::DoImmediateRender()
 {
+	if(m_bLoadedFormats)
+		return TRUE;
+
+	m_bLoadedFormats = true;
+	
 	int count = m_ClipIDs.GetSize();
 	if( count <= 0 )
 		return 0;
 	if( count == 1 )
 	{
 		CClipFormats formats;
-		CClipFormat* pCF;
+		
 		CClip::LoadFormats( m_ClipIDs[0], formats );
-		count = formats.GetSize(); // reusing "count"
-		for( int i=0; i < count; i++ )
-		{
-			pCF = &formats[i];
-			CacheGlobalData( pCF->m_cfType, pCF->m_hgData );
-			pCF->m_hgData = 0; // OLE owns it now
-		}
-		formats.RemoveAll();
-		return count;
+		
+		return LoadFormats(&formats);
 	}
 	
 	HGLOBAL hGlobal;
@@ -747,6 +746,25 @@ BOOL COleClipSource::DoImmediateRender()
 	return hGlobal != 0;
 }
 
+long COleClipSource::LoadFormats(CClipFormats *pFormats)
+{
+	CClipFormat* pCF;
+
+	int	count = pFormats->GetSize(); // reusing "count"
+
+	for(int i = 0; i < count; i++)
+	{
+		pCF = &pFormats->ElementAt(i);
+		CacheGlobalData( pCF->m_cfType, pCF->m_hgData );
+		pCF->m_hgData = 0; // OLE owns it now
+	}
+	pFormats->RemoveAll();
+
+	m_bLoadedFormats = true;
+
+	return count;
+}
+
 
 BEGIN_MESSAGE_MAP(COleClipSource, COleDataSource)
 END_MESSAGE_MAP()

+ 2 - 0
ProcessPaste.h

@@ -92,12 +92,14 @@ class COleClipSource : public COleDataSource
 
 public:
 	CClipIDs	m_ClipIDs;
+	bool		m_bLoadedFormats;
 
 	COleClipSource();
 	virtual ~COleClipSource();
 
 	BOOL DoDelayRender();
 	BOOL DoImmediateRender();
+	long LoadFormats(CClipFormats *pFormats);
 
 protected:
 	DECLARE_MESSAGE_MAP()

+ 195 - 10
QPasteWnd.cpp

@@ -93,7 +93,22 @@ ON_COMMAND(ID_MENU_VIEWGROUPS, OnMenuViewgroups)
 	ON_COMMAND(ID_MENU_QUICKPROPERTIES_SETTONEVERAUTODELETE, OnMenuQuickpropertiesSettoneverautodelete)
 	ON_COMMAND(ID_MENU_QUICKPROPERTIES_AUTODELETE, OnMenuQuickpropertiesAutodelete)
 	ON_COMMAND(ID_MENU_QUICKPROPERTIES_REMOVEHOTKEY, OnMenuQuickpropertiesRemovehotkey)
-	ON_UPDATE_COMMAND_UI(ID_MENU_GROUPS_MOVETOTHEGROUP_BLANK, OnUpdateMenuGroupsMovetothegroupBlank)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_EIGHT, OnMenuSenttoFriendEight)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_ELEVEN, OnMenuSenttoFriendEleven)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_FIFTEEN, OnMenuSenttoFriendFifteen)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_FIVE, OnMenuSenttoFriendFive)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_FORE, OnMenuSenttoFriendFore)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_FORETEEN, OnMenuSenttoFriendForeteen)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_NINE, OnMenuSenttoFriendNine)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_SEVEN, OnMenuSenttoFriendSeven)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_SIX, OnMenuSenttoFriendSix)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_TEN, OnMenuSenttoFriendTen)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_THIRTEEN, OnMenuSenttoFriendThirteen)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_THREE, OnMenuSenttoFriendThree)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_TWELVE, OnMenuSenttoFriendTwelve)
+	ON_COMMAND(ID_MENU_SENTTO_FRIEND_TWO, OnMenuSenttoFriendTwo)
+	ON_COMMAND(ID_MENU_SENTTO_FRIENDONE, OnMenuSenttoFriendone)
+	ON_COMMAND(ID_MENU_SENTTO_PROMPTFORIP, OnMenuSenttoPromptforip)
 	//}}AFX_MSG_MAP
 ON_MESSAGE(NM_SELECT, OnListSelect)
 ON_MESSAGE(NM_END, OnListEnd)
@@ -282,14 +297,11 @@ void CQPasteWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
 {
 	CWndEx::OnActivate(nState, pWndOther, bMinimized);
 	
-	TRACE("OnActivate\n");
-	
 	if(m_bHideWnd == false)
 		return;
 	
 	if (nState == WA_INACTIVE)
 	{
-		TRACE("WA_INACTIVE\n");
 		if(!g_Opt.m_bShowPersistent)
 		{
 			HideQPasteWindow();
@@ -300,7 +312,6 @@ void CQPasteWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
 	}
 	else if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
 	{
-		TRACE("WA_ACTIVE\n");
 		if(!theApp.m_bShowingQuickPaste)
 		{
 			ShowQPasteWindow();
@@ -892,6 +903,38 @@ void CQPasteWnd::SetMenuChecks(CMenu *pMenu)
 	{
 		pMenu->CheckMenuItem(ID_MENU_QUICKOPTIONS_PROMPTFORNEWGROUPNAMES, MF_CHECKED);
 	}
+
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIENDONE, 0);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_TWO, 1);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_THREE, 2);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_FORE, 3);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_FIVE, 4);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_SIX, 5);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_SEVEN,6);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_EIGHT,7);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_NINE,8);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_TEN,9);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_ELEVEN,10);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_TWELVE,11);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_THIRTEEN,12);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_FORETEEN,13);
+	SetSendToMenu(pMenu, ID_MENU_SENTTO_FRIEND_FIFTEEN,14);
+
+	pMenu->DeleteMenu(ID_MENU_SENTTO_PROMPTFORIP, MF_BYCOMMAND);
+}
+
+void CQPasteWnd::SetSendToMenu(CMenu *pMenu, int nMenuID, int nArrayPos)
+{
+	if(g_Opt.m_SendClients[nArrayPos].csIP.GetLength() > 0)
+	{
+		CString cs;
+		cs.Format("(%s) - %s", g_Opt.m_SendClients[nArrayPos].csIP, g_Opt.m_SendClients[nArrayPos].csDescription);
+		pMenu->ModifyMenu(nMenuID, MF_BYCOMMAND, nMenuID, cs);
+	}
+	else
+	{
+		pMenu->DeleteMenu(nMenuID, MF_BYCOMMAND);
+	}
 }
 
 LRESULT CQPasteWnd::OnSearch(WPARAM wParam, LPARAM lParam)
@@ -1002,6 +1045,8 @@ void CQPasteWnd::OnMenuReconnecttoclipboardchain()
 	::SendMessage(theApp.GetClipboardViewer(), WM_CV_RECONNECT, 0, 0);
 }
 
+#include "client.h"
+
 void CQPasteWnd::OnMenuProperties() 
 {	
 	m_bHideWnd = false;
@@ -1227,11 +1272,156 @@ void CQPasteWnd::OnMenuQuickpropertiesRemovehotkey()
 	}	
 	m_lstHeader.RefreshVisibleRows();
 }
+
+void CQPasteWnd::OnUpdateMenuGroupsMovetothegroupBlank(CCmdUI* pCmdUI) 
+{
+	// TODO: Add your command update UI handler code here
+	
+}
+
+
+void CQPasteWnd::OnMenuSenttoFriendFifteen() 
+{
+	SendToFriendbyPos(14);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendForeteen() 
+{
+	SendToFriendbyPos(13);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendThirteen() 
+{
+	SendToFriendbyPos(12);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendTwelve() 
+{
+	SendToFriendbyPos(11);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendEleven() 
+{
+	SendToFriendbyPos(10);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendTen() 
+{
+	SendToFriendbyPos(9);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendNine() 
+{
+	SendToFriendbyPos(8);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendEight() 
+{
+	SendToFriendbyPos(7);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendSeven() 
+{
+	SendToFriendbyPos(6);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendSix() 
+{
+	SendToFriendbyPos(5);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendFive() 
+{
+	SendToFriendbyPos(4);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendFore() 
+{
+	SendToFriendbyPos(3);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendThree() 
+{
+	SendToFriendbyPos(2);	
+}
+
+void CQPasteWnd::OnMenuSenttoFriendTwo() 
+{
+	SendToFriendbyPos(1);
+}
+
+void CQPasteWnd::OnMenuSenttoFriendone() 
+{
+	SendToFriendbyPos(0);
+}
+
+void CQPasteWnd::OnMenuSenttoPromptforip() 
+{
+	// TODO: Add your command handler code here
+	
+}
+
 ///////////////////////////////////////////////////////////////////////
 //END END Menu Stuff
 ///////////////////////////////////////////////////////////////////////
 
 
+BOOL CQPasteWnd::SendToFriendbyPos(int nPos)
+{
+	CWaitCursor wait;
+
+	m_bHideWnd = false;
+
+	CClipIDs IDs;
+	long lCount = m_lstHeader.GetSelectedCount();
+	if(lCount <= 0)
+		return FALSE;
+
+	m_lstHeader.GetSelectionIndexes(IDs);
+
+	CIDArray *pIDArray = new CIDArray;
+	pIDArray->pIDs = new CID[lCount];
+	pIDArray->lCount = lCount;
+
+	BOOL bRet = FALSE;
+
+	try
+	{
+		CPopup Popup(0, 0, m_hWnd);
+		Popup.Show(StrF("Sending clip to %s", g_Opt.m_SendClients[nPos].csIP));
+		
+		for(int i = 0; i < lCount; i++)
+		{
+			m_Recset.SetAbsolutePosition(IDs[i]);
+			pIDArray->pIDs[i].lID = m_Recset.m_lID;
+			pIDArray->pIDs[i].m_csDesc = m_Recset.m_strText;
+		}
+		
+		if(SendToFriend(pIDArray, nPos, "", &Popup) == FALSE)
+		{
+			MessageBox(StrF("Error Sending data to %s", g_Opt.m_SendClients[nPos].csIP), "Ditto");
+		}
+		else
+		{
+			bRet = TRUE;
+		}
+	}
+	catch(CDaoException* e)
+	{
+		e->ReportError();
+		ASSERT(0);
+		e->Delete();
+	}	
+
+	delete [] pIDArray->pIDs;
+	pIDArray->pIDs = NULL;
+	delete pIDArray;
+
+	m_bHideWnd = true;
+
+	return bRet;
+}
+
 LRESULT CQPasteWnd::OnDelete(WPARAM wParam, LPARAM lParam)
 {
 	DeleteSelectedRows();
@@ -1792,8 +1982,3 @@ void CQPasteWnd::OnBackButton()
 	theApp.EnterGroupID(theApp.m_GroupParentID);
 }
 
-void CQPasteWnd::OnUpdateMenuGroupsMovetothegroupBlank(CCmdUI* pCmdUI) 
-{
-	// TODO: Add your command update UI handler code here
-	
-}

+ 19 - 0
QPasteWnd.h

@@ -95,6 +95,9 @@ public:
 	void OnUpdateLinesPerRow(CCmdUI* pCmdUI, int nValue);
 	void OnUpdateTransparency(CCmdUI* pCmdUI, int nValue);
 	void SetMenuChecks(CMenu *pMenu);
+	void SetSendToMenu(CMenu *pMenu, int nMenuID, int nArrayPos);
+
+	BOOL SendToFriendbyPos(int nPos);
 	
 	// Generated message map functions
 protected:
@@ -145,6 +148,22 @@ protected:
 	afx_msg void OnMenuQuickpropertiesAutodelete();
 	afx_msg void OnMenuQuickpropertiesRemovehotkey();
 	afx_msg void OnUpdateMenuGroupsMovetothegroupBlank(CCmdUI* pCmdUI);
+	afx_msg void OnMenuSenttoFriendEight();
+	afx_msg void OnMenuSenttoFriendEleven();
+	afx_msg void OnMenuSenttoFriendFifteen();
+	afx_msg void OnMenuSenttoFriendFive();
+	afx_msg void OnMenuSenttoFriendFore();
+	afx_msg void OnMenuSenttoFriendForeteen();
+	afx_msg void OnMenuSenttoFriendNine();
+	afx_msg void OnMenuSenttoFriendSeven();
+	afx_msg void OnMenuSenttoFriendSix();
+	afx_msg void OnMenuSenttoFriendTen();
+	afx_msg void OnMenuSenttoFriendThirteen();
+	afx_msg void OnMenuSenttoFriendThree();
+	afx_msg void OnMenuSenttoFriendTwelve();
+	afx_msg void OnMenuSenttoFriendTwo();
+	afx_msg void OnMenuSenttoFriendone();
+	afx_msg void OnMenuSenttoPromptforip();
 	//}}AFX_MSG
 	afx_msg LRESULT OnListSelect(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnListEnd(WPARAM wParam, LPARAM lParam);

+ 26 - 4
Resource.h

@@ -20,7 +20,9 @@
 #define IDB_OPEN_FOLDER_PRESSED         146
 #define IDB_BACK                        147
 #define IDB_BACK_PRESSED                148
+#define IDD_OPTIONS_FRIENDS             148
 #define IDB_BACK_FOCUSED                149
+#define IDD_FRIEND_DETAILS              152
 #define IDC_PATH                        1000
 #define IDC_GET_PATH                    1001
 #define IDC_SELECT                      1003
@@ -37,8 +39,11 @@
 #define IDC_DATABASE_SIZE               1014
 #define IDC_LIST1                       1014
 #define IDC_ADD                         1015
+#define IDC_CHECK_SEND_ALL              1015
 #define IDC_DELETE                      1016
+#define IDC_EDIT_IP                     1016
 #define IDC_EDIT1                       1017
+#define IDC_EDIT_DESCRIPTION            1017
 #define IDC_LIST2                       1018
 #define IDC_ADD_1                       1019
 #define IDC_ADD_2                       1020
@@ -69,6 +74,7 @@
 #define IDC_CHECK1                      1042
 #define IDC_HISTORY_START_TOP           1042
 #define IDC_CHECK_SEND_PASTE            1042
+#define IDC_CHECK_LOG_SEND_RECIEVE      1042
 #define IDD_OPTIONS_KEYSTROKES          2001
 #define IDC_HOTKEY                      2002
 #define IDC_DISPLAY_IN_SYSTEMTRAY       2003
@@ -96,6 +102,7 @@
 #define IDC_COMBO1                      2023
 #define IDC_HOTKEY1                     2024
 #define IDC_HOTKEY2                     2025
+#define IDC_EDIT_PLACE_ON_CLIPBOARD     2025
 #define IDC_HOTKEY3                     2026
 #define IDC_HOTKEY4                     2027
 #define IDC_HOTKEY5                     2028
@@ -153,16 +160,31 @@
 #define ID_MENU_QUICKPROPERTIES_SETTONEVERAUTODELETE 32820
 #define ID_MENU_QUICKPROPERTIES_AUTODELETE 32821
 #define ID_MENU_QUICKPROPERTIES_REMOVEHOTKEY 32822
-#define ID_MENU_GROUPS_MOVETOTHEGROUP_BLANK 32823
+#define ID_MENU_SENTTO_FRIENDONE        32824
+#define ID_MENU_SENTTO_FRIEND_TWO       32825
+#define ID_MENU_SENTTO_FRIEND_THREE     32826
+#define ID_MENU_SENTTO_FRIEND_FORE      32827
+#define ID_MENU_SENTTO_FRIEND_FIVE      32828
+#define ID_MENU_SENTTO_FRIEND_SIX       32829
+#define ID_MENU_SENTTO_FRIEND_SEVEN     32830
+#define ID_MENU_SENTTO_FRIEND_EIGHT     32831
+#define ID_MENU_SENTTO_FRIEND_NINE      32832
+#define ID_MENU_SENTTO_FRIEND_TEN       32833
+#define ID_MENU_SENTTO_FRIEND_ELEVEN    32834
+#define ID_MENU_SENTTO_FRIEND_TWELVE    32835
+#define ID_MENU_SENTTO_FRIEND_THIRTEEN  32836
+#define ID_MENU_SENTTO_FRIEND_FORETEEN  32837
+#define ID_MENU_SENTTO_FRIEND_FIFTEEN   32838
+#define ID_MENU_SENTTO_PROMPTFORIP      32839
 
 // Next default values for new objects
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_3D_CONTROLS                     1
-#define _APS_NEXT_RESOURCE_VALUE        148
-#define _APS_NEXT_COMMAND_VALUE         32824
-#define _APS_NEXT_CONTROL_VALUE         2025
+#define _APS_NEXT_RESOURCE_VALUE        149
+#define _APS_NEXT_COMMAND_VALUE         32840
+#define _APS_NEXT_CONTROL_VALUE         2026
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

+ 209 - 0
Server.cpp

@@ -0,0 +1,209 @@
+// Server.cpp: implementation of the CServer class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "Server.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+UINT  MTServerThread(LPVOID pParam)
+{		
+	LogSendRecieveInfo("Start of ServerThread");
+
+	WSADATA wsaData;
+	sockaddr_in local;
+	int wsaret = WSAStartup(0x101,&wsaData);
+	if(wsaret!=0)
+	{
+		LogSendRecieveInfo("ERROR - int wsaret = WSAStartup(0x101,&wsaData);");
+		return 0;
+	}
+	local.sin_family = AF_INET;
+	local.sin_addr.s_addr = INADDR_ANY;
+	local.sin_port = htons((u_short)20248);
+	theApp.m_sSocket = socket(AF_INET, SOCK_STREAM, 0);
+	if(theApp.m_sSocket == INVALID_SOCKET)
+	{
+		LogSendRecieveInfo("ERROR - theApp.m_sSocket = socket(AF_INET, SOCK_STREAM, 0);");
+		return 0;
+	}
+	if(bind(theApp.m_sSocket,(sockaddr*)&local,sizeof(local))!=0)
+	{
+		LogSendRecieveInfo("ERROR - if(bind(theApp.m_sSocket,(sockaddr*)&local,sizeof(local))!=0)");
+		return 0;
+	}
+	if(listen(theApp.m_sSocket,10)!=0)
+	{
+		LogSendRecieveInfo("ERROR - if(listen(theApp.m_sSocket,10)!=0)");
+		return 0;
+	}
+
+	SOCKET socket;
+	
+	sockaddr_in from;
+	int fromlen = sizeof(from);
+
+	while(true)
+	{
+		if(theApp.m_bAppExiting)
+			break;
+
+		socket = accept(theApp.m_sSocket, (struct sockaddr*)&from,&fromlen);
+		
+		AfxBeginThread(ClientThread,(LPVOID)socket);
+	}	
+
+	LogSendRecieveInfo("End of Server Thread");
+
+	return 0;
+}
+
+BOOL Recv(SOCKET sock, SendInfo *pInfo)
+{
+	long lReceiveCount = 0;
+	long lLastRecievedCount = 0;
+	long lExpectedCount = sizeof(SendInfo);
+	SendInfo info;
+
+	while(lReceiveCount < lExpectedCount)
+	{
+		lReceiveCount = recv(sock, (char*)&info, lExpectedCount-lReceiveCount, 0);
+		if(lReceiveCount == SOCKET_ERROR)
+		{
+			LogSendRecieveInfo("********ERROR if(lReceiveCount == SOCKET_ERROR)*******");
+			return FALSE;
+		}
+		else if(lReceiveCount == 0)
+			return FALSE;
+
+		LogSendRecieveInfo(StrF("------Bytes Read %d", lReceiveCount));
+
+		memcpy(((char*)pInfo) + lLastRecievedCount, &info, lReceiveCount);
+		lReceiveCount = lLastRecievedCount + lReceiveCount;
+		lLastRecievedCount += lReceiveCount;
+	}
+
+	return TRUE;
+}
+
+UINT  ClientThread(LPVOID pParam)
+{	
+	LogSendRecieveInfo("*********************Start of ClientThread*********************");
+	
+	SOCKET socket = (SOCKET)pParam;
+
+	SendInfo info;
+	int nRecvReturn = 0;
+	CClip NewClip;
+	CClipFormat cf;
+	long lBytesCopied;
+	bool bBreak = false;
+	bool bAddToDatabase = false;
+	BYTE *pByte = NULL;
+	long lByteSize = 0;
+	BOOL bSetToClipBoard = FALSE;
+	
+	while(true)
+	{
+		if(Recv(socket, &info) == FALSE)
+			break;
+		
+		switch(info.m_Type)
+		{
+		case MyEnums::START:
+			{				
+				NewClip.Clear();
+
+				CString cs;
+				cs.Format("%s\n(%s)(%s)", info.m_cText, info.m_cComputerName, info.m_cIP);
+				
+				NewClip.m_Desc = cs;
+
+				bAddToDatabase = false;
+
+				if(g_Opt.m_csIPListToPutOnClipboard.Find(info.m_cIP) >= 0)
+					bSetToClipBoard = TRUE;
+
+				if(g_Opt.m_csIPListToPutOnClipboard.Find(info.m_cComputerName) >= 0)
+					bSetToClipBoard = TRUE;
+
+				info.m_cText[20] = 0;
+				LogSendRecieveInfo(StrF("::START %s %s %s", info.m_cText, info.m_cComputerName, info.m_cIP));
+			}
+			break;
+		case MyEnums::DATA_START:
+			{
+				if(pByte != NULL)
+				{
+					delete pByte;
+					pByte = NULL;
+				}
+				lByteSize = info.m_lParameter1;
+				pByte = new BYTE[info.m_lParameter1];
+
+				cf.m_cfType = GetFormatID(info.m_cText);
+				lBytesCopied = 0;
+				NewClip.m_lTotalCopySize += info.m_lParameter1;
+
+				LogSendRecieveInfo(StrF("::DATA_START Total Size = %d type = %s", lByteSize, info.m_cText));
+			}
+			break;
+		case MyEnums::DATA:
+			{
+				memcpy(((char*)pByte) + lBytesCopied, info.m_cText, info.m_lParameter1);
+				lBytesCopied += info.m_lParameter1;
+
+				LogSendRecieveInfo(StrF("::DATA Copy Bytes = %d TotalCopy = %d", info.m_lParameter1, lBytesCopied));
+			}
+			break;
+		case MyEnums::DATA_END:
+			{
+				cf.m_hgData = NewGlobalP(pByte, lByteSize);
+
+				NewClip.m_Formats.Add(cf);
+
+				delete pByte;
+				pByte = NULL;
+
+				bAddToDatabase = true;
+
+				LogSendRecieveInfo("::DATA_END");
+			}
+			break;
+		case MyEnums::END:
+			{
+				if(bAddToDatabase)
+				{
+					LogSendRecieveInfo("::DATA_END");
+					::SendMessage(theApp.m_MainhWnd, WM_ADD_TO_DATABASE_FROM_SOCKET, (WPARAM)&NewClip, bSetToClipBoard);
+				}
+			}
+			break;
+		case MyEnums::EXIT:
+			{				
+				LogSendRecieveInfo("::EXIT");
+				bBreak = true;
+			}
+			break;
+		}
+
+		if(bBreak || theApp.m_bAppExiting)
+			break;
+	}		
+
+	closesocket(socket);
+
+	LogSendRecieveInfo("*********************End of ClientThread*********************");
+	
+	return 0;
+}

+ 44 - 0
Server.h

@@ -0,0 +1,44 @@
+// Server.h: interface for the CServer class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_SERVER_H__581A45D4_DCC2_44D7_8B43_60412E769D39__INCLUDED_)
+#define AFX_SERVER_H__581A45D4_DCC2_44D7_8B43_60412E769D39__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "Winsock2.h"
+
+class MyEnums
+{
+public:
+	enum eSendType{START, DATA, DATA_START, DATA_END, END, EXIT};
+};
+
+#define MAX_DATA_SIZE	1000
+class SendInfo
+{
+public:
+	SendInfo()
+	{
+		m_nSize = sizeof(this);
+		m_nVersion = 1;
+	}
+	int					m_nSize;
+	MyEnums::eSendType	m_Type;
+	int					m_nVersion;
+
+	char				m_cIP[20];
+	char				m_cComputerName[MAX_COMPUTERNAME_LENGTH + 1];
+
+	long		m_lParameter1;
+	long		m_lParameter2;
+	char		m_cText[MAX_DATA_SIZE];
+};
+
+UINT  MTServerThread(LPVOID pParam);
+UINT  ClientThread(LPVOID pParam);
+
+#endif // !defined(AFX_SERVER_H__581A45D4_DCC2_44D7_8B43_60412E769D39__INCLUDED_)

+ 1 - 0
StdAfx.h

@@ -27,6 +27,7 @@
 #include <afxcmn.h>			// MFC support for Windows Common Controls
 #endif // _AFX_NO_AFXCMN_SUPPORT
 #include <afxole.h>
+#include <Winsock2.h>
 
 
 //{{AFX_INSERT_LOCATION}}