Browse Source

First Checkin

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@3 595ec19a-5cb4-439b-94a8-42fb3063c22c
sabrogden 22 years ago
parent
commit
0cff727c74
77 changed files with 13043 additions and 0 deletions
  1. 95 0
      About.cpp
  2. 52 0
      About.h
  3. 164 0
      AddType.cpp
  4. 54 0
      AddType.h
  5. 153 0
      AlphaBlend.cpp
  6. 70 0
      AlphaBlend.h
  7. 65 0
      ArrayEx.h
  8. 132 0
      CP_Main.cpp
  9. 496 0
      CP_Main.dsp
  10. 37 0
      CP_Main.dsw
  11. 82 0
      CP_Main.h
  12. 731 0
      CP_Main.rc
  13. 93 0
      ComboBoxSearch.cpp
  14. 56 0
      ComboBoxSearch.h
  15. 257 0
      CopyProperties.cpp
  16. 68 0
      CopyProperties.h
  17. 206 0
      DataTable.cpp
  18. 51 0
      DataTable.h
  19. 337 0
      DatabaseUtilities.cpp
  20. 94 0
      DatabaseUtilities.h
  21. 428 0
      HyperLink.cpp
  22. 100 0
      HyperLink.h
  23. 365 0
      InternetUpdate.cpp
  24. 36 0
      InternetUpdate.h
  25. 381 0
      MainFrm.cpp
  26. 83 0
      MainFrm.h
  27. 200 0
      MainTable.cpp
  28. 53 0
      MainTable.h
  29. 636 0
      Misc.cpp
  30. 147 0
      Misc.h
  31. 100 0
      NumberEdit.cpp
  32. 61 0
      NumberEdit.h
  33. 202 0
      OptionsGeneral.cpp
  34. 73 0
      OptionsGeneral.h
  35. 161 0
      OptionsKeyBoard.cpp
  36. 63 0
      OptionsKeyBoard.h
  37. 93 0
      OptionsQuickPaste.cpp
  38. 60 0
      OptionsQuickPaste.h
  39. 90 0
      OptionsSheet.cpp
  40. 62 0
      OptionsSheet.h
  41. 147 0
      OptionsStats.cpp
  42. 58 0
      OptionsStats.h
  43. 145 0
      OptionsTypes.cpp
  44. 57 0
      OptionsTypes.h
  45. 113 0
      OptionsUtilities.cpp
  46. 54 0
      OptionsUtilities.h
  47. 532 0
      ProcessCopy.cpp
  48. 52 0
      ProcessCopy.h
  49. 155 0
      ProcessPaste.cpp
  50. 27 0
      ProcessPaste.h
  51. 465 0
      ProgressWnd.cpp
  52. 81 0
      ProgressWnd.h
  53. 691 0
      QListCtrl.cpp
  54. 113 0
      QListCtrl.h
  55. 1001 0
      QPasteWnd.cpp
  56. 133 0
      QPasteWnd.h
  57. 137 0
      QuickPaste.cpp
  58. 28 0
      QuickPaste.h
  59. 105 0
      ReadMe.txt
  60. 111 0
      Resource.h
  61. 112 0
      SelectDB.cpp
  62. 49 0
      SelectDB.h
  63. 8 0
      StdAfx.cpp
  64. 31 0
      StdAfx.h
  65. 1117 0
      SystemTray.cpp
  66. 195 0
      SystemTray.h
  67. 89 0
      TypesTable.cpp
  68. 48 0
      TypesTable.h
  69. BIN
      Version.Lib
  70. 418 0
      WndEx.cpp
  71. 71 0
      WndEx.h
  72. BIN
      res/CP_Main.ico
  73. 13 0
      res/CP_Main.rc2
  74. BIN
      res/CP_MainDoc.ico
  75. BIN
      res/Ditto.ico
  76. BIN
      res/Toolbar.bmp
  77. BIN
      res/bitmap1.bmp

+ 95 - 0
About.cpp

@@ -0,0 +1,95 @@
+// About.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "About.h"
+#include "InternetUpdate.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CAbout property page
+
+IMPLEMENT_DYNCREATE(CAbout, CPropertyPage)
+
+CAbout::CAbout() : CPropertyPage(CAbout::IDD)
+{
+	//{{AFX_DATA_INIT(CAbout)
+		// NOTE: the ClassWizard will add member initialization here
+	//}}AFX_DATA_INIT
+}
+
+CAbout::~CAbout()
+{
+}
+
+void CAbout::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CAbout)
+	DDX_Control(pDX, IDC_HYPER_LINK, m_HyperLink);
+	DDX_Control(pDX, IDC_LIST, m_List);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CAbout, CPropertyPage)
+	//{{AFX_MSG_MAP(CAbout)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CAbout message handlers
+
+BOOL CAbout::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+
+	m_List.AddString("Ditto");
+
+	CInternetUpdate update;
+
+	long lRunningVersion = update.GetRunningVersion();
+	CString cs = update.GetVersionString(lRunningVersion);
+
+	CString csText;
+	csText = "    Version " + cs;
+	m_List.AddString(csText);
+
+	cs = CGetSetOptions::GetExeFileName();;
+	csText = "    Exe Path " + cs;
+	m_List.AddString(csText);
+
+	cs = CGetSetOptions::GetDBPath();
+	csText = "    DB Path " + cs;
+	m_List.AddString(csText);
+
+	m_List.AddString("");
+
+	m_List.AddString("Credits");
+	
+	cs = "    Author - Scott Brogden, [email protected]";
+	m_List.AddString(cs);
+
+	CRect rect;
+	GetClientRect(rect);
+	
+	rect.bottom -= 30;
+	
+	m_List.MoveWindow(rect);
+
+	rect.top = rect.bottom + 10;
+	rect.bottom = rect.top + 30;
+	
+	m_HyperLink.MoveWindow(rect);
+
+	m_HyperLink.SetURL(_T("mailto:[email protected]"));
+		
+	return TRUE;  // return TRUE unless you set the focus to a control
+	              // EXCEPTION: OCX Property Pages should return FALSE
+}

+ 52 - 0
About.h

@@ -0,0 +1,52 @@
+#if !defined(AFX_ABOUT_H__02A95202_4AEF_4854_9DC0_161326D7B914__INCLUDED_)
+#define AFX_ABOUT_H__02A95202_4AEF_4854_9DC0_161326D7B914__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// About.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CAbout dialog
+
+#include "hyperlink.h"
+
+class CAbout : public CPropertyPage
+{
+	DECLARE_DYNCREATE(CAbout)
+
+// Construction
+public:
+	CAbout();
+	~CAbout();
+
+// Dialog Data
+	//{{AFX_DATA(CAbout)
+	enum { IDD = IDD_ABOUT };
+	CHyperLink	m_HyperLink;
+	CListBox	m_List;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generate virtual function overrides
+	//{{AFX_VIRTUAL(CAbout)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+	// Generated message map functions
+	//{{AFX_MSG(CAbout)
+	virtual BOOL OnInitDialog();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ABOUT_H__02A95202_4AEF_4854_9DC0_161326D7B914__INCLUDED_)

+ 164 - 0
AddType.cpp

@@ -0,0 +1,164 @@
+// AddType.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "AddType.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CAddType dialog
+
+
+CAddType::CAddType(CWnd* pParent /*=NULL*/)
+	: CDialog(CAddType::IDD, pParent)
+{
+	//{{AFX_DATA_INIT(CAddType)
+	m_eCustomType = _T("");
+	//}}AFX_DATA_INIT
+}
+
+
+void CAddType::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CAddType)
+	DDX_Control(pDX, IDC_LIST2, m_lbOnClipboard);
+	DDX_Control(pDX, IDC_LIST1, m_lbDefaultTypes);
+	DDX_Text(pDX, IDC_EDIT1, m_eCustomType);
+	DDV_MaxChars(pDX, m_eCustomType, 50);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CAddType, CDialog)
+	//{{AFX_MSG_MAP(CAddType)
+	ON_BN_CLICKED(IDC_ADD_1, OnAdd1)
+	ON_BN_CLICKED(IDC_ADD_2, OnAdd2)
+	ON_BN_CLICKED(IDC_ADD_3, OnAdd3)
+	ON_LBN_DBLCLK(IDC_LIST1, OnDblclkList1)
+	ON_LBN_DBLCLK(IDC_LIST2, OnDblclkList2)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CAddType message handlers
+BOOL CAddType::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	m_lbDefaultTypes.AddString("CF_TEXT");
+	m_lbDefaultTypes.AddString("CF_BITMAP");
+	m_lbDefaultTypes.AddString("CF_METAFILEPICT");
+	m_lbDefaultTypes.AddString("CF_SYLK");
+	m_lbDefaultTypes.AddString("CF_DIF");
+	m_lbDefaultTypes.AddString("CF_TIFF");
+	m_lbDefaultTypes.AddString("CF_OEMTEXT");
+	m_lbDefaultTypes.AddString("CF_DIB");
+	m_lbDefaultTypes.AddString("CF_PALETTE");
+	m_lbDefaultTypes.AddString("CF_PENDATA");
+	m_lbDefaultTypes.AddString("CF_RIFF");
+	m_lbDefaultTypes.AddString("CF_WAVE");
+	m_lbDefaultTypes.AddString("CF_UNICODETEXT");
+	m_lbDefaultTypes.AddString("CF_ENHMETAFILE");
+	m_lbDefaultTypes.AddString("CF_HDROP");
+	m_lbDefaultTypes.AddString("CF_LOCALE");
+	m_lbDefaultTypes.AddString("CF_OWNERDISPLAY");
+	m_lbDefaultTypes.AddString("CF_DSPTEXT");
+	m_lbDefaultTypes.AddString("CF_DSPBITMAP");
+	m_lbDefaultTypes.AddString("CF_DSPMETAFILEPICT");
+	m_lbDefaultTypes.AddString("CF_DSPENHMETAFILE");
+	m_lbDefaultTypes.AddString(GetFormatName(RegisterClipboardFormat(CF_RTF)));
+	m_lbDefaultTypes.AddString(GetFormatName(RegisterClipboardFormat(CF_RTFNOOBJS)));
+	m_lbDefaultTypes.AddString(GetFormatName(RegisterClipboardFormat(CF_RETEXTOBJ)));
+	m_lbDefaultTypes.AddString(GetFormatName(RegisterClipboardFormat("HTML Format")));
+		
+	COleDataObject oleData;
+
+	if(!oleData.AttachClipboard())
+		return FALSE;
+	
+	oleData.BeginEnumFormats();
+
+	FORMATETC test;
+	
+	while(oleData.GetNextFormat(&test))
+	{
+		BOOL b = oleData.IsDataAvailable(test.cfFormat);
+		m_lbOnClipboard.AddString(GetFormatName(test.cfFormat));
+	}
+	
+	oleData.Release();
+
+	m_lbDefaultTypes.SetFocus();
+	return FALSE;
+}
+
+void CAddType::OnAdd1() 
+{
+	m_csSelectedTypes.RemoveAll();
+
+	int nCount = m_lbDefaultTypes.GetSelCount();
+	if(nCount)
+	{
+		CString cs;
+		CArray<int,int> items;
+		items.SetSize(nCount);
+		m_lbDefaultTypes.GetSelItems(nCount, items.GetData()); 
+
+		for(int i = 0; i < nCount; i++)
+		{
+			m_lbDefaultTypes.GetText(items[i], cs);
+			m_csSelectedTypes.Add(cs);
+		}
+	}
+	
+	EndDialog(IDOK);
+}
+
+void CAddType::OnAdd2() 
+{
+	UpdateData();
+	m_csSelectedTypes.RemoveAll();
+	m_csSelectedTypes.Add(m_eCustomType);
+		
+	EndDialog(IDOK);
+}
+
+void CAddType::OnAdd3() 
+{
+	m_csSelectedTypes.RemoveAll();
+
+	int nCount = m_lbOnClipboard.GetSelCount();
+	if(nCount)
+	{
+		CString cs;
+		CArray<int,int> items;
+		items.SetSize(nCount);
+		m_lbOnClipboard.GetSelItems(nCount, items.GetData()); 
+
+		for(int i = 0; i < nCount; i++)
+		{
+			m_lbOnClipboard.GetText(items[i], cs);
+			m_csSelectedTypes.Add(cs);
+		}
+	}
+
+	EndDialog(IDOK);
+}
+
+
+void CAddType::OnDblclkList1() 
+{
+	OnAdd1();
+}
+
+void CAddType::OnDblclkList2() 
+{
+	OnAdd3();
+}

+ 54 - 0
AddType.h

@@ -0,0 +1,54 @@
+#if !defined(AFX_ADDTYPE_H__783BC68A_076E_41CD_8F88_D8169D90BA55__INCLUDED_)
+#define AFX_ADDTYPE_H__783BC68A_076E_41CD_8F88_D8169D90BA55__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// AddType.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CAddType dialog
+
+class CAddType : public CDialog
+{
+// Construction
+public:
+	CAddType(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CAddType)
+	enum { IDD = IDD_ADD_TYPE };
+	CListBox	m_lbOnClipboard;
+	CListBox	m_lbDefaultTypes;
+	CString	m_eCustomType;
+	//}}AFX_DATA
+
+	CStringArray m_csSelectedTypes;
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CAddType)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CAddType)
+	afx_msg void OnAdd1();
+	afx_msg void OnAdd2();
+	afx_msg void OnAdd3();
+	virtual BOOL OnInitDialog();
+	afx_msg void OnDblclkList1();
+	afx_msg void OnDblclkList2();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ADDTYPE_H__783BC68A_076E_41CD_8F88_D8169D90BA55__INCLUDED_)

+ 153 - 0
AlphaBlend.cpp

@@ -0,0 +1,153 @@
+// AlphaBlend.cpp: implementation of the CAlphaBlend class.
+//
+//////////////////////////////////////////////////////////////////////
+// By Mike Ryan ([email protected])
+// Copyright (c) 2000
+// 07.03.2000
+//
+// Free usage granted in all applications including commercial.
+// Do NOT distribute without permission from me.  I can be reached
+// at [email protected], http://www.codexia.com
+// Please feel free to email me about this class.
+//
+// NOTE:
+//
+// You will need the latest Win32 API availble at:
+// http://msdn.microsoft.com/downloads/c-frame.htm?007#/downloads/sdks/
+// in order to compile this programs.
+//
+// This will only run under Windows 2000.  It is not compatible with
+// Windows 9x or Windows NT 4.0.
+//
+// Also, you must add the following lines to the StdAfx.h at the top
+// above the #define VC_EXTRALEAN.
+//
+//	#define _WIN32_WINNT 0x0500
+//	#define WINVER 0x0500
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "AlphaBlend.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CAlphaBlend::CAlphaBlend()
+{
+	m_hWnd = NULL;
+	m_nOpacity = 0;
+	m_bTransparent = false;
+}
+
+CAlphaBlend::~CAlphaBlend()
+{
+}
+
+CAlphaBlend::CAlphaBlend(HWND hWnd, int nOpactiy)
+{
+	m_hWnd = NULL;
+	m_nOpacity = 0;
+	m_bTransparent = false;
+
+	SetWindowHandle(hWnd);
+	SetOpacity(nOpactiy);
+}
+
+CAlphaBlend::CAlphaBlend(CWnd *pWnd, int nOpacity)
+{
+	m_hWnd = NULL;
+	m_nOpacity = 0;
+	m_bTransparent = false;
+
+	SetWindowHandle(pWnd);
+	SetOpacity(nOpacity);
+}
+
+BOOL CAlphaBlend::SetWindowHandle(HWND hWnd)
+{
+	if (::IsWindow(hWnd)) m_hWnd = hWnd;
+	else return false;
+
+	return true;
+}
+
+BOOL CAlphaBlend::SetWindowHandle(CWnd *pWnd)
+{
+	if (pWnd && ::IsWindow(pWnd->GetSafeHwnd())) m_hWnd = pWnd->GetSafeHwnd();
+	else return false;
+	return true;
+}
+
+BOOL CAlphaBlend::SetOpacity(int nOpacity)
+{
+	if (nOpacity >= 0 && nOpacity <= OPACITY_MAX)
+	{
+		m_nOpacity = nOpacity;
+		if (m_bTransparent)
+		{
+			// update the transparency
+			ASSERT(::IsWindow(m_hWnd));
+			SetLayeredWindowAttributes(m_hWnd, 0, m_nOpacity, LWA_ALPHA);		
+		}
+		return true;
+	}
+	return false;
+}
+
+void CAlphaBlend::SetTransparent(BOOL bTransparent)
+{
+	if (bTransparent)
+	{
+		// make sure they have set it up properly
+		ASSERT(m_nOpacity >= 0 && m_nOpacity <= OPACITY_MAX);
+		ASSERT(m_hWnd && ::IsWindow(m_hWnd));
+
+		// make it transparent
+		long l = GetWindowLong(m_hWnd, GWL_EXSTYLE);
+		if(!(l & WS_EX_LAYERED))
+		{
+			l |= WS_EX_LAYERED;
+			SetWindowLong(m_hWnd, GWL_EXSTYLE, l);
+		}
+
+		SetLayeredWindowAttributes(m_hWnd, 0, m_nOpacity, LWA_ALPHA);
+
+		CRect r;
+		::GetWindowRect(m_hWnd, r);
+		::InvalidateRect(m_hWnd, r, true);
+
+		m_bTransparent = true;
+	}
+	else
+	{
+		long l = GetWindowLong(m_hWnd, GWL_EXSTYLE);
+		if(l & WS_EX_LAYERED)
+		{
+			l ^= WS_EX_LAYERED;
+			SetWindowLong(m_hWnd, GWL_EXSTYLE, l);
+			CRect r;
+			::GetWindowRect(m_hWnd, r);
+			::InvalidateRect(m_hWnd, r, true);
+		}
+		m_bTransparent = false;
+	}
+}
+
+BOOL CAlphaBlend::SetTransparent(HWND hWnd, int nOpacity, BOOL bTransparent)
+{
+	// set members
+	if (!SetWindowHandle(hWnd)) return false;
+	if (!SetOpacity(nOpacity)) return false;
+
+	SetTransparent(bTransparent);
+
+	return true;
+}

+ 70 - 0
AlphaBlend.h

@@ -0,0 +1,70 @@
+// AlphaBlend.h: interface for the CAlphaBlend class.
+//
+//////////////////////////////////////////////////////////////////////
+// By Mike Ryan ([email protected])
+// Copyright (c) 2000
+// 07.03.2000
+//
+// Free usage granted in all applications including commercial.
+// Do NOT distribute without permission from me.  I can be reached
+// at [email protected], http://www.codexia.com
+// Please feel free to email me about this class.
+//
+// NOTE:
+//
+// You will need the latest Win32 API availble at:
+// http://msdn.microsoft.com/downloads/c-frame.htm?007#/downloads/sdks/
+// in order to compile this programs.
+//
+// This will only run under Windows 2000.  It is not compatible with
+// Windows 9x or Windows NT 4.0.
+//
+// Also, you must add the following lines to the StdAfx.h at the top
+// above the #define VC_EXTRALEAN.
+//
+//	#define _WIN32_WINNT 0x0500
+//	#define WINVER 0x0500
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_ALPHABLEND_H__B453CE58_5571_48B4_BD84_3BB70D6A41A3__INCLUDED_)
+#define AFX_ALPHABLEND_H__B453CE58_5571_48B4_BD84_3BB70D6A41A3__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define OPACITY_MAX			255
+
+class CAlphaBlend  
+{
+public:
+	CAlphaBlend();
+	CAlphaBlend(HWND hWnd, int nOpacity=220);
+	CAlphaBlend(CWnd *pWnd, int nOpacity=220);
+	virtual ~CAlphaBlend();
+
+	//// SET DATA MEMBERS ////
+	BOOL SetWindowHandle(HWND hWnd);
+	BOOL SetWindowHandle(CWnd *pWnd);
+	BOOL SetOpacity(int nOpacity=220);
+
+	//// RUN IT ////
+	void SetTransparent(BOOL bTransparent=true);
+
+	//// FOR THOSE OF US WHO ARE LAZY ////
+	BOOL SetTransparent(HWND hWnd, int nOpactiy=220, BOOL bTransparent=true);
+
+	//// GET TRANSPARENT/OPACITY STATUS ////
+	int GetOpacity(void) { return m_nOpacity; }
+	HWND GetWindow(void) { return m_hWnd; }
+	BOOL IsTransparent(void) { return m_bTransparent; }
+
+protected:
+	int m_nOpacity;
+	HWND m_hWnd;
+
+	BOOL m_bTransparent;
+};
+
+#endif // !defined(AFX_ALPHABLEND_H__B453CE58_5571_48B4_BD84_3BB70D6A41A3__INCLUDED_)

+ 65 - 0
ArrayEx.h

@@ -0,0 +1,65 @@
+#if !defined(AFX_CARRAYEX_H__BE2C5983_CE26_11D3_BAE6_0000C0D475E2__INCLUDED_)
+#define AFX_CARRAYEX_H__BE2C5983_CE26_11D3_BAE6_0000C0D475E2__INCLUDED_
+
+//#if _MSC_VER > 1000
+#pragma once
+//#endif // _MSC_VER > 1000
+
+#include <afxtempl.h>
+
+template <class TYPE> class CArrayEx : public CArray<TYPE,TYPE>
+{
+public:
+	inline const TYPE&	operator[](int nIndex) const
+	{
+		ASSERT(0 <= nIndex && nIndex < GetSize());
+		return (GetData()[nIndex]);
+	};
+
+	inline const TYPE&	GetAt(int nIndex) const
+	{
+		ASSERT(0 <= nIndex && nIndex < GetSize());
+		return (GetData()[nIndex]);
+	};
+
+	inline TYPE& operator[](int nIndex)
+	{
+		ASSERT(0 <= nIndex && nIndex < GetSize());
+		return (GetData()[nIndex]);
+	};
+
+	void SortAscending()
+	{
+		qsort(GetData(), GetSize(), sizeof(TYPE), CArrayEx::CompareAscending);
+	}
+
+	void SortDescending()
+	{
+		qsort(GetData(), GetSize(), sizeof(TYPE), CArrayEx::CompareDescending);
+	}
+	
+	static int CompareAscending(const void * p1, const void * p2)
+	{	
+		return *(TYPE *)p1 - *(TYPE *)p2;
+	}
+
+	static int CompareDescending(const void * p1, const void * p2)
+	{	
+		return *(TYPE *)p2 - *(TYPE *)p1;
+	}
+	
+	BOOL Find(TYPE type)
+	{
+		LPVOID lpVoid = NULL;
+		lpVoid = bsearch(&type, GetData(), GetSize(), sizeof(TYPE), CArrayEx::CompareAscending);
+
+		if(lpVoid)
+			return TRUE;
+		
+		return FALSE;
+	}
+};
+
+typedef CArrayEx<int>				ARRAY;
+
+#endif // !defined(AFX_OCARRAY_H__BE2C5983_CE26_11D3_BAE6_0000C0D475E2__INCLUDED_)

+ 132 - 0
CP_Main.cpp

@@ -0,0 +1,132 @@
+// CP_Main.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "MainFrm.h"
+#include "Misc.h"
+#include "SelectDB.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CCP_MainApp
+
+BEGIN_MESSAGE_MAP(CCP_MainApp, CWinApp)
+	//{{AFX_MSG_MAP(CCP_MainApp)
+		// NOTE - the ClassWizard will add and remove mapping macros here.
+		//    DO NOT EDIT what you see in these blocks of generated code!
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCP_MainApp construction
+
+CCP_MainApp::CCP_MainApp()
+{
+	// TODO: add construction code here,
+	// Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CCP_MainApp object
+
+CCP_MainApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CCP_MainApp initialization
+
+BOOL CCP_MainApp::InitInstance()
+{
+	AfxEnableControlContainer();
+
+	m_hMutex = CreateMutex(NULL, FALSE, "Ditto Is Now Running");
+	DWORD dwError = GetLastError();
+	if(dwError == ERROR_ALREADY_EXISTS)
+	{
+		HWND hWnd = (HWND)CGetSetOptions::GetMainHWND();
+		if(hWnd)
+			::SendMessage(hWnd, WM_SHOW_TRAY_ICON, TRUE, TRUE);
+
+		return TRUE;
+	}
+
+	m_bShowingOptions = false;
+	m_bShowingQuickPaste = false;
+	m_bHandleClipboardDataChange = true;
+	m_bReloadTypes = true;
+	m_atomHotKey = GlobalAddAtom(HK_ACTIVATE);
+	m_atomNamedCopy = GlobalAddAtom(HK_NAMED_COPY);
+	m_MainhWnd = NULL;
+	m_pDatabase = NULL;
+	ShowCopyProperties = NULL;
+
+	if(CheckDBExists(CGetSetOptions::GetDBPath()) == FALSE)
+	{
+		AfxMessageBox("Error Opening Database.");
+		return TRUE;
+	}
+
+	AfxOleInit();
+
+	CMainFrame* pFrame = new CMainFrame;
+	m_pMainWnd = pFrame;
+
+	pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
+
+	pFrame->ShowWindow(SW_SHOW);
+	pFrame->UpdateWindow();
+
+	return TRUE;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCP_MainApp message handlers
+
+int CCP_MainApp::ExitInstance() 
+{
+	if(CGetSetOptions::GetCompactAndRepairOnExit())
+		CompactDatabase();
+	
+	CloseDB();
+
+	return CWinApp::ExitInstance();
+}
+
+CDaoDatabase* CCP_MainApp::EnsureOpenDB(CString csName)
+{
+	if(!m_pDatabase)
+		m_pDatabase = new CDaoDatabase;
+
+	if(!m_pDatabase->IsOpen())
+	{
+		if(csName == "")
+			m_pDatabase->Open(GetDBName());
+		else
+			m_pDatabase->Open(csName);
+	}
+
+	if(m_pMainWnd)
+		((CMainFrame *)m_pMainWnd)->ResetKillDBTimer();
+
+	return m_pDatabase;
+}
+
+BOOL CCP_MainApp::CloseDB()
+{
+	if(m_pDatabase)
+	{
+		if(m_pDatabase->IsOpen())
+			m_pDatabase->Close();
+
+		delete m_pDatabase;
+		m_pDatabase = NULL;
+	}
+
+	return TRUE;
+}

+ 496 - 0
CP_Main.dsp

@@ -0,0 +1,496 @@
+# Microsoft Developer Studio Project File - Name="CP_Main" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=CP_Main - Win32 Pre 2000 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "CP_Main.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "CP_Main.mak" CFG="CP_Main - Win32 Pre 2000 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CP_Main - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "CP_Main - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "CP_Main - Win32 Pre 2000 Release" (based on "Win32 (x86) Application")
+!MESSAGE "CP_Main - Win32 Pre 2000 Debug" (based on "Win32 (x86) Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""$/CopyPro/CP_Main", CAAAAAAA"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "CP_Main - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "AFTER_98" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /machine:I386 /out:"Release/Ditto.exe"
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "AFTER_98" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# 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
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "CP_Main___Win32_Pre_2000_Release"
+# PROP BASE Intermediate_Dir "CP_Main___Win32_Pre_2000_Release"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "CP_Main___Win32_Pre_2000_Release"
+# PROP Intermediate_Dir "CP_Main___Win32_Pre_2000_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\CP_Database" /I "..\CP_GUI" /I "..\Controls" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 /out:"Release/Ditto.exe"
+# ADD LINK32 /nologo /subsystem:windows /machine:I386 /out:"Release/Ditto_Pre2000.exe"
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "CP_Main___Win32_Pre_2000_Debug"
+# PROP BASE Intermediate_Dir "CP_Main___Win32_Pre_2000_Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "CP_Main___Win32_Pre_2000_Debug"
+# PROP Intermediate_Dir "CP_Main___Win32_Pre_2000_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\CP_Database" /I "..\CP_GUI" /I "..\Controls" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Ditto.exe" /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Ditto_Pre2000.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CP_Main - Win32 Release"
+# Name "CP_Main - Win32 Debug"
+# Name "CP_Main - Win32 Pre 2000 Release"
+# Name "CP_Main - Win32 Pre 2000 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Group "Controls"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\AlphaBlend.cpp
+
+!IF  "$(CFG)" == "CP_Main - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\AlphaBlend.h
+
+!IF  "$(CFG)" == "CP_Main - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF  "$(CFG)" == "CP_Main - Win32 Pre 2000 Debug"
+
+# PROP Exclude_From_Build 1
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\ArrayEx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ComboBoxSearch.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ComboBoxSearch.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\HyperLink.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\NumberEdit.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\NumberEdit.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QListCtrl.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\QListCtrl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\WndEx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\WndEx.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\About.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\AddType.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CopyProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CP_Main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CP_Main.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\DatabaseUtilities.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DataTable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\InternetUpdate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainTable.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Misc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsGeneral.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsKeyBoard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsQuickPaste.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsSheet.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsStats.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsTypes.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsUtilities.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessCopy.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessPaste.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProgressWnd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\QPasteWnd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\QuickPaste.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SelectDB.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\SystemTray.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TypesTable.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\About.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\AddType.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CopyProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CP_Main.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DatabaseUtilities.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DataTable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\HyperLink.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\InternetUpdate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainTable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Misc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsGeneral.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsKeyBoard.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsQuickPaste.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsSheet.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsStats.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\OptionsUtilities.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessCopy.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProcessPaste.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ProgressWnd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QPasteWnd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QuickPaste.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SelectDB.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SystemTray.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TypesTable.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\bitmap1.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\CP_Main.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\CP_Main.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\CP_MainDoc.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Ditto.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Toolbar.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Version.Lib
+# End Source File
+# End Target
+# End Project

+ 37 - 0
CP_Main.dsw

@@ -0,0 +1,37 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "CP_Main"=.\CP_Main.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+    begin source code control
+    "$/", AAAAAAAA
+    .
+    end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+    begin source code control
+    "$/Ditto", UFAAAAAA
+    .
+    end source code control
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

+ 82 - 0
CP_Main.h

@@ -0,0 +1,82 @@
+// CP_Main.h : main header file for the CP_MAIN application
+//
+
+#if !defined(AFX_CP_MAIN_H__DAB2F753_2CC1_4FED_8095_763987961026__INCLUDED_)
+#define AFX_CP_MAIN_H__DAB2F753_2CC1_4FED_8095_763987961026__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef __AFXWIN_H__
+	#error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h"       // main symbols
+#include "ProcessCopy.h"
+#include "DatabaseUtilities.h"
+#include "Misc.h"
+#include "DataTable.h"
+#include "MainTable.h"
+#include "TypesTable.h"
+#include "ArrayEx.h"
+
+#define MAIN_WND_TITLE		"Ditto MainWnd"
+//#define GET_APP    ((CCP_MainApp *)AfxGetApp())	
+
+//#define GET_APP ((CMainWnd*)theApp)
+extern class CCP_MainApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CCP_MainApp:
+// See CP_Main.cpp for the implementation of this class
+//
+class CCP_MainApp : public CWinApp
+{
+public:
+	CCP_MainApp();
+
+	bool m_bShowingOptions;
+	bool m_bShowingQuickPaste;
+	bool m_bHandleClipboardDataChange;
+	bool m_bReloadTypes;
+	bool ShowCopyProperties;
+
+	HANDLE m_hMutex;
+
+	ATOM m_atomHotKey;
+
+	ATOM m_atomNamedCopy;
+	
+	HWND m_MainhWnd;
+
+	CDaoDatabase	*m_pDatabase;
+
+	CDaoDatabase	*EnsureOpenDB(CString csName = "");
+	BOOL			CloseDB();
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CCP_MainApp)
+	public:
+	virtual BOOL InitInstance();
+	virtual int ExitInstance();
+	//}}AFX_VIRTUAL
+	
+
+// Implementation
+	//{{AFX_MSG(CCP_MainApp)
+	afx_msg void OnAppAbout();
+		// NOTE - the ClassWizard will add and remove member functions here.
+		//    DO NOT EDIT what you see in these blocks of generated code !
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CP_MAIN_H__DAB2F753_2CC1_4FED_8095_763987961026__INCLUDED_)

+ 731 - 0
CP_Main.rc

@@ -0,0 +1,731 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+    "#ifdef _WIN32\r\n"
+    "LANGUAGE 9, 1\r\n"
+    "#pragma code_page(1252)\r\n"
+    "#endif //_WIN32\r\n"
+    "#include ""res\\CP_Main.rc2""  // non-Microsoft Visual C++ edited resources\r\n"
+    "#include ""afxres.rc""         // Standard components\r\n"
+    "#include ""afxprint.rc""       // printing/print preview resources\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME           ICON    DISCARDABLE     "res\\Ditto.ico"
+IDR_CP_MAITYPE          ICON    DISCARDABLE     "res\\CP_MainDoc.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDR_MAINFRAME           BITMAP  MOVEABLE PURE   "res\\Toolbar.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Toolbar
+//
+
+IDR_MAINFRAME TOOLBAR DISCARDABLE  16, 15
+BEGIN
+    BUTTON      ID_FILE_NEW
+    BUTTON      ID_FILE_OPEN
+    BUTTON      ID_FILE_SAVE
+    SEPARATOR
+    BUTTON      ID_EDIT_CUT
+    BUTTON      ID_EDIT_COPY
+    BUTTON      ID_EDIT_PASTE
+    SEPARATOR
+    BUTTON      ID_FILE_PRINT
+    SEPARATOR
+    BUTTON      ID_APP_ABOUT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MAINFRAME MENU PRELOAD DISCARDABLE 
+BEGIN
+    POPUP "&File"
+    BEGIN
+        MENUITEM "&New\tCtrl+N",                ID_FILE_NEW
+        MENUITEM "&Open...\tCtrl+O",            ID_FILE_OPEN
+        MENUITEM "&Save\tCtrl+S",               ID_FILE_SAVE
+        MENUITEM "Save &As...",                 ID_FILE_SAVE_AS
+        MENUITEM SEPARATOR
+        MENUITEM "&Print...\tCtrl+P",           ID_FILE_PRINT
+        MENUITEM "Print Pre&view",              ID_FILE_PRINT_PREVIEW
+        MENUITEM "P&rint Setup...",             ID_FILE_PRINT_SETUP
+        MENUITEM SEPARATOR
+        MENUITEM "Recent File",                 ID_FILE_MRU_FILE1, GRAYED
+        MENUITEM SEPARATOR
+        MENUITEM "E&xit",                       ID_APP_EXIT
+    END
+    POPUP "&Edit"
+    BEGIN
+        MENUITEM "&Undo\tCtrl+Z",               ID_EDIT_UNDO
+        MENUITEM SEPARATOR
+        MENUITEM "Cu&t\tCtrl+X",                ID_EDIT_CUT
+        MENUITEM "&Copy\tCtrl+C",               ID_EDIT_COPY
+        MENUITEM "&Paste\tCtrl+V",              ID_EDIT_PASTE
+    END
+    POPUP "&View"
+    BEGIN
+        MENUITEM "&Toolbar",                    ID_VIEW_TOOLBAR
+        MENUITEM "&Status Bar",                 ID_VIEW_STATUS_BAR
+    END
+    POPUP "&Help"
+    BEGIN
+        MENUITEM "&About CP_Main...",           ID_APP_ABOUT
+    END
+END
+
+IDR_MENU MENU DISCARDABLE 
+BEGIN
+    POPUP "First"
+    BEGIN
+        MENUITEM "Reconnect To Clipboard Chain", 
+                                                ID_FIRST_RECONNECTTOCLIPBOARDCHAIN
+
+        MENUITEM "Options",                     ID_FIRST_OPTION
+        MENUITEM "Show Quick Paste",            ID_FIRST_SHOWQUICKPASTE
+        MENUITEM SEPARATOR
+        MENUITEM "Exit",                        ID_FIRST_EXIT
+    END
+END
+
+IDR_QUICK_PASTE MENU DISCARDABLE 
+BEGIN
+    POPUP "Menu"
+    BEGIN
+        POPUP "Lines Per Row"
+        BEGIN
+            MENUITEM "1",                           ID_MENU_LINESPERROW_1
+            MENUITEM "2",                           ID_MENU_LINESPERROW_2
+            MENUITEM "3",                           ID_MENU_LINESPERROW_3
+            MENUITEM "4",                           ID_MENU_LINESPERROW_4
+            MENUITEM "5",                           ID_MENU_LINESPERROW_5
+        END
+        POPUP "Transparency"
+        BEGIN
+            MENUITEM "None",                        ID_MENU_TRANSPARENCY_NONE
+
+            MENUITEM "5 %",                         ID_MENU_TRANSPARENCY_5
+            MENUITEM "10 %",                        ID_MENU_TRANSPARENCY_10
+            MENUITEM "15 %",                        ID_MENU_TRANSPARENCY_15
+            MENUITEM "20 %",                        ID_MENU_TRANSPARENCY_20
+            MENUITEM "25 %",                        ID_MENU_TRANSPARENCY_25
+            MENUITEM "30 %",                        ID_MENU_TRANSPARENCY_30
+            MENUITEM "40 %",                        ID_MENU_TRANSPARENCY_40
+        END
+        POPUP "Positioning"
+        BEGIN
+            MENUITEM "At Caret",                    ID_MENU_POSITIONING_ATCARET
+
+            MENUITEM "At Cursor",                   ID_MENU_POSITIONING_ATCURSOR
+
+            MENUITEM "At Previous Position",        ID_MENU_POSITIONING_ATPREVIOUSPOSITION
+
+        END
+        POPUP "First Ten Hot Keys"
+        BEGIN
+            MENUITEM "Use Ctrl - Num",              ID_MENU_FIRSTTENHOTKEYS_USECTRLNUM
+
+            MENUITEM "Show Hot Key Text",           ID_MENU_FIRSTTENHOTKEYS_SHOWHOTKEYTEXT
+
+        END
+        MENUITEM "Reconnect To Clipboard Chain", 
+                                                ID_MENU_RECONNECTTOCLIPBOARDCHAIN
+
+        MENUITEM SEPARATOR
+        MENUITEM "Properties\tAlt-Enter",       ID_MENU_PROPERTIES
+        MENUITEM SEPARATOR
+        MENUITEM "Options",                     ID_MENU_OPTIONS
+        MENUITEM SEPARATOR
+        MENUITEM "Delete Copy Entry",           ID_MENU_DELETE
+        MENUITEM SEPARATOR
+        MENUITEM "Exit Program",                ID_MENU_EXITPROGRAM
+    END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE 
+BEGIN
+    "N",            ID_FILE_NEW,            VIRTKEY, CONTROL
+    "O",            ID_FILE_OPEN,           VIRTKEY, CONTROL
+    "S",            ID_FILE_SAVE,           VIRTKEY, CONTROL
+    "P",            ID_FILE_PRINT,          VIRTKEY, CONTROL
+    "Z",            ID_EDIT_UNDO,           VIRTKEY, CONTROL
+    "X",            ID_EDIT_CUT,            VIRTKEY, CONTROL
+    "C",            ID_EDIT_COPY,           VIRTKEY, CONTROL
+    "V",            ID_EDIT_PASTE,          VIRTKEY, CONTROL
+    VK_BACK,        ID_EDIT_UNDO,           VIRTKEY, ALT
+    VK_DELETE,      ID_EDIT_CUT,            VIRTKEY, SHIFT
+    VK_INSERT,      ID_EDIT_COPY,           VIRTKEY, CONTROL
+    VK_INSERT,      ID_EDIT_PASTE,          VIRTKEY, SHIFT
+    VK_F6,          ID_NEXT_PANE,           VIRTKEY 
+    VK_F6,          ID_PREV_PANE,           VIRTKEY, SHIFT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE  0, 0, 235, 55
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About CP_Main"
+FONT 8, "MS Sans Serif"
+BEGIN
+    ICON            IDR_MAINFRAME,IDC_STATIC,11,17,20,20
+    LTEXT           "CP_Main Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX
+    LTEXT           "Copyright (C) 2002",IDC_STATIC,40,25,119,8
+    DEFPUSHBUTTON   "OK",IDOK,178,7,50,14,WS_GROUP
+END
+
+IDD_OPTIONS_UTILITIES DIALOG DISCARDABLE  0, 0, 241, 137
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Database"
+FONT 8, "MS Sans Serif"
+BEGIN
+    PUSHBUTTON      "Compact Database",IDC_COMPACT_DB,14,18,107,14
+    PUSHBUTTON      "Repair Database",IDC_REPAIR,14,37,107,14
+    EDITTEXT        IDC_PATH,14,67,198,12,ES_AUTOHSCROLL
+    PUSHBUTTON      "....",IDC_GET_PATH,214,67,14,12
+    LTEXT           "Database Path:",IDC_STATIC,14,56,50,8
+END
+
+IDD_OPTIONS_TYPES DIALOG DISCARDABLE  0, 0, 230, 172
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Supported Types"
+FONT 8, "MS Sans Serif"
+BEGIN
+    LISTBOX         IDC_LIST1,7,7,129,158,LBS_SORT | LBS_NOINTEGRALHEIGHT | 
+                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "&Add",IDC_ADD,147,10,38,14
+    PUSHBUTTON      "&Delete",IDC_DELETE,147,30,38,14
+END
+
+IDD_OPTIONS_QUICK_PASTE DIALOG DISCARDABLE  0, 0, 256, 138
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Quick Paste"
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "Enable Quick Paste Transparency",IDC_TRANSPARENCY,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,29,122,10
+    EDITTEXT        IDC_TRANS_PERC,140,28,19,12,ES_AUTOHSCROLL
+    LTEXT           "%",IDC_STATIC,162,31,8,8
+    LTEXT           "Text Lines per Row",IDC_STATIC,18,44,62,8
+    EDITTEXT        IDC_LINES_ROW,82,42,19,12,ES_AUTOHSCROLL
+    GROUPBOX        "Positioning",IDC_STATIC,11,57,196,41
+    CONTROL         "At Caret",IDC_AT_CARET,"Button",BS_AUTORADIOBUTTON,22,
+                    66,41,10
+    CONTROL         "At Cursor",IDC_AT_CURSOR,"Button",BS_AUTORADIOBUTTON,22,
+                    76,45,10
+    CONTROL         "At Previous Position",IDC_AT_PREVIOUS,"Button",
+                    BS_AUTORADIOBUTTON,22,86,79,10
+    CONTROL         "Use Ctrl - Num for first ten copy hot keys",
+                    IDC_CTRL_CLICK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,
+                    7,142,10
+    CONTROL         "Show text for first ten copy hot keys",
+                    IDC_SHOW_TEXT_FOR_FIRST_TEN_HOT_KEYS,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,18,17,128,10
+    LTEXT           "** befere text  = text has a hot key assigned to it.",
+                    IDC_STATIC,18,105,153,8
+    LTEXT           "* before text = text will never be auto deleted.",
+                    IDC_STATIC,18,116,143,8
+END
+
+IDD_OPTIONS_KEYSTROKES DIALOG DISCARDABLE  0, 0, 186, 90
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Keyboard Shortcuts"
+FONT 8, "MS Sans Serif"
+BEGIN
+    LTEXT           "Activate Ditto",IDC_STATIC,19,22,44,8
+    CONTROL         "HotKey1",IDC_HOTKEY,"msctls_hotkey32",WS_BORDER | 
+                    WS_TABSTOP,71,19,80,14
+    CONTROL         "HotKey1",IDC_NAMED_COPY,"msctls_hotkey32",WS_BORDER | 
+                    WS_TABSTOP,72,39,80,14
+    LTEXT           "Named Copy",IDC_STATIC,19,42,42,8
+END
+
+IDD_OPTIONS_GENERAL DIALOG DISCARDABLE  0, 0, 256, 166
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "General"
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "Display Icon in System Tray",IDC_DISPLAY_IN_SYSTEMTRAY,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,28,103,10
+    CONTROL         "Start Ditto on System Startup",IDC_START_ON_STARTUP,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,15,107,10
+    CONTROL         "Maximum Number of Saved Copies",IDC_MAXIMUM,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,23,41,126,10
+    CONTROL         "Paste Entries Expire after",IDC_EXPIRE,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,23,54,95,10
+    EDITTEXT        IDC_EXPIRE_AFTER,118,53,19,12,ES_AUTOHSCROLL
+    LTEXT           "Days",IDC_STATIC,142,56,26,8
+    EDITTEXT        IDC_MAX_SAVED_COPIES,149,41,19,12,ES_AUTOHSCROLL
+    CONTROL         "Compact and Repair Database on Exit",IDC_COMPACT_REPAIR,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,67,137,10
+    PUSHBUTTON      "Compact and Repair",IDC_BT_COMPACT_AND_REPAIR,161,66,69,
+                    11
+    CONTROL         "Automatically check for updates online",
+                    IDC_CHECK_UPDATES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+                    23,106,137,10
+    PUSHBUTTON      "Check Now",IDC_CHECK_FOR_UPDATES,161,106,50,11
+    CONTROL         "Set Database Path",IDC_SET_DB_PATH,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,23,79,76,10
+    EDITTEXT        IDC_PATH,23,89,198,12,ES_AUTOHSCROLL
+    PUSHBUTTON      "....",IDC_GET_PATH,222,89,14,12
+END
+
+IDD_SELECT_DB DIALOG DISCARDABLE  0, 0, 276, 46
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
+CAPTION "Select Database"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "OK",IDOK,101,25,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,170,25,50,14
+    EDITTEXT        IDC_PATH,7,7,244,13,ES_AUTOHSCROLL
+    PUSHBUTTON      "...",IDC_SELECT,254,7,15,12
+    PUSHBUTTON      "Use Default",IDC_USE_DEFAULT,27,25,50,14
+END
+
+IDD_OPTIONS_STATS DIALOG DISCARDABLE  0, 0, 272, 163
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Stats"
+FONT 8, "MS Sans Serif"
+BEGIN
+    EDITTEXT        IDC_TRIP_COPIES,157,34,25,13,ES_AUTOHSCROLL
+    LTEXT           "Copies",IDC_STATIC,131,36,22,8
+    EDITTEXT        IDC_TRIP_PASTES,157,50,25,13,ES_AUTOHSCROLL
+    LTEXT           "Pastes",IDC_STATIC,131,51,22,8
+    PUSHBUTTON      "Reset",IDC_RESET_COUNTS,193,34,32,12
+    GROUPBOX        "Trip Odometer",IDC_STATIC,128,7,105,60
+    EDITTEXT        IDC_ALL_COPIES,41,34,25,13,ES_AUTOHSCROLL
+    LTEXT           "Copies",IDC_STATIC,15,36,22,8
+    EDITTEXT        IDC_ALL_PASTES,41,50,25,13,ES_AUTOHSCROLL
+    LTEXT           "Pastes",IDC_STATIC,15,51,22,8
+    GROUPBOX        "Odometer",IDC_STATIC,7,7,110,60
+    EDITTEXT        IDC_TRIP_DATE,132,17,97,12,ES_AUTOHSCROLL
+    EDITTEXT        IDC_EDIT_ALL_DATE,13,17,97,12,ES_AUTOHSCROLL
+    LTEXT           "Saved Copies",IDC_STATIC,15,78,45,8
+    EDITTEXT        IDC_SAVED_COPIES,76,77,41,13,ES_AUTOHSCROLL
+    LTEXT           "Saved Copy Data",IDC_STATIC,15,96,57,8
+    EDITTEXT        IDC_SAVED_COPY_DATA,76,94,41,13,ES_AUTOHSCROLL
+    PUSHBUTTON      "Remove All",IDC_REMOVE_ALL,122,77,44,13
+    LTEXT           "Database Size",IDC_STATIC,15,111,47,13,SS_CENTERIMAGE
+    EDITTEXT        IDC_DATABASE_SIZE,76,111,41,13,ES_AUTOHSCROLL
+END
+
+IDD_ADD_TYPE DIALOG DISCARDABLE  0, 0, 276, 230
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Add Supported Type"
+FONT 8, "MS Sans Serif"
+BEGIN
+    PUSHBUTTON      "Cancel",IDCANCEL,219,209,50,14
+    LISTBOX         IDC_LIST1,7,15,113,174,LBS_SORT | LBS_NOINTEGRALHEIGHT | 
+                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
+    EDITTEXT        IDC_EDIT1,135,15,91,14,ES_AUTOHSCROLL
+    LISTBOX         IDC_LIST2,135,43,97,146,LBS_SORT | LBS_NOINTEGRALHEIGHT | 
+                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "Add",IDC_ADD_1,7,191,31,11
+    PUSHBUTTON      "Add",IDC_ADD_2,231,15,31,11
+    PUSHBUTTON      "Add",IDC_ADD_3,130,191,31,11
+    LTEXT           "Custom Type",IDC_STATIC,135,7,42,8
+    LTEXT           "Currently on the Clipboard",IDC_STATIC,135,35,82,8
+    LTEXT           "Main Types",IDC_STATIC,7,7,38,8
+END
+
+IDD_COPY_PROPERTIES DIALOG DISCARDABLE  0, 0, 244, 211
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Copy Properties"
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "HotKey1",IDC_HOTKEY,"msctls_hotkey32",WS_BORDER | 
+                    WS_TABSTOP,37,7,82,13
+    CONTROL         "&Never Auto Delete",IDC_NEVER_AUTO_DELETE,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,37,23,75,10
+    EDITTEXT        IDC_EDIT_DISPLAY_TEXT,7,44,230,56,ES_MULTILINE | 
+                    ES_AUTOHSCROLL | ES_WANTRETURN
+    LISTBOX         IDC_COPY_DATA,7,111,230,75,LBS_SORT | 
+                    LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | 
+                    WS_TABSTOP
+    PUSHBUTTON      "Delete",IDC_DELETE_COPY_DATA,7,188,24,12
+    DEFPUSHBUTTON   "OK",IDOK,133,190,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,187,190,50,14
+    EDITTEXT        IDC_DATE,149,7,88,13,ES_AUTOHSCROLL | NOT WS_TABSTOP
+    LTEXT           "Item Title",IDC_STATIC,7,35,46,8
+    LTEXT           "Date",IDC_STATIC,128,7,16,13,SS_CENTERIMAGE
+    LTEXT           "Hot Key",IDC_STATIC,7,7,28,13,SS_CENTERIMAGE
+    LTEXT           "Copy Formats",IDC_STATIC,7,102,46,8
+END
+
+IDD_ABOUT DIALOG DISCARDABLE  0, 0, 292, 124
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "MS Sans Serif"
+BEGIN
+    LISTBOX         IDC_LIST,7,16,271,86,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | 
+                    WS_TABSTOP
+    LTEXT           "E-mail Scott Brogden",IDC_HYPER_LINK,7,109,67,8
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,4
+ PRODUCTVERSION 1,0,0,4
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "Comments", "\0"
+            VALUE "CompanyName", "\0"
+            VALUE "FileDescription", "CP_Main MFC Application\0"
+            VALUE "FileVersion", "1, 0, 0, 4\0"
+            VALUE "InternalName", "CP_Main\0"
+            VALUE "LegalCopyright", "Copyright (C) 2002\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "CP_Main.EXE\0"
+            VALUE "PrivateBuild", "\0"
+            VALUE "ProductName", "CP_Main Application\0"
+            VALUE "ProductVersion", "1, 0, 0, 4\0"
+            VALUE "SpecialBuild", "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE 
+BEGIN
+    IDD_ABOUTBOX, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 228
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 48
+    END
+
+    IDD_OPTIONS_UTILITIES, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 234
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 130
+    END
+
+    IDD_OPTIONS_TYPES, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 223
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 165
+    END
+
+    IDD_OPTIONS_QUICK_PASTE, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 249
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 131
+    END
+
+    IDD_OPTIONS_KEYSTROKES, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 179
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 83
+    END
+
+    IDD_OPTIONS_GENERAL, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 249
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 158
+    END
+
+    IDD_SELECT_DB, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 269
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 39
+    END
+
+    IDD_OPTIONS_STATS, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 265
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 156
+    END
+
+    IDD_ADD_TYPE, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 269
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 223
+    END
+
+    IDD_COPY_PROPERTIES, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 237
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 204
+    END
+
+    IDD_ABOUT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 285
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 117
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE PRELOAD DISCARDABLE 
+BEGIN
+    IDR_MAINFRAME           "CP_Main\n\nCP_Mai\n\n\nCPMain.Document\nCP_Mai Document"
+END
+
+STRINGTABLE PRELOAD DISCARDABLE 
+BEGIN
+    AFX_IDS_APP_TITLE       "CP_Main"
+    AFX_IDS_IDLEMESSAGE     "Ready"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_INDICATOR_EXT        "EXT"
+    ID_INDICATOR_CAPS       "CAP"
+    ID_INDICATOR_NUM        "NUM"
+    ID_INDICATOR_SCRL       "SCRL"
+    ID_INDICATOR_OVR        "OVR"
+    ID_INDICATOR_REC        "REC"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_FILE_NEW             "Create a new document\nNew"
+    ID_FILE_OPEN            "Open an existing document\nOpen"
+    ID_FILE_CLOSE           "Close the active document\nClose"
+    ID_FILE_SAVE            "Save the active document\nSave"
+    ID_FILE_SAVE_AS         "Save the active document with a new name\nSave As"
+    ID_FILE_PAGE_SETUP      "Change the printing options\nPage Setup"
+    ID_FILE_PRINT_SETUP     "Change the printer and printing options\nPrint Setup"
+    ID_FILE_PRINT           "Print the active document\nPrint"
+    ID_FILE_PRINT_PREVIEW   "Display full pages\nPrint Preview"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_APP_ABOUT            "Display program information, version number and copyright\nAbout"
+    ID_APP_EXIT             "Quit the application; prompts to save documents\nExit"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_FILE_MRU_FILE1       "Open this document"
+    ID_FILE_MRU_FILE2       "Open this document"
+    ID_FILE_MRU_FILE3       "Open this document"
+    ID_FILE_MRU_FILE4       "Open this document"
+    ID_FILE_MRU_FILE5       "Open this document"
+    ID_FILE_MRU_FILE6       "Open this document"
+    ID_FILE_MRU_FILE7       "Open this document"
+    ID_FILE_MRU_FILE8       "Open this document"
+    ID_FILE_MRU_FILE9       "Open this document"
+    ID_FILE_MRU_FILE10      "Open this document"
+    ID_FILE_MRU_FILE11      "Open this document"
+    ID_FILE_MRU_FILE12      "Open this document"
+    ID_FILE_MRU_FILE13      "Open this document"
+    ID_FILE_MRU_FILE14      "Open this document"
+    ID_FILE_MRU_FILE15      "Open this document"
+    ID_FILE_MRU_FILE16      "Open this document"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_NEXT_PANE            "Switch to the next window pane\nNext Pane"
+    ID_PREV_PANE            "Switch back to the previous window pane\nPrevious Pane"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_WINDOW_SPLIT         "Split the active window into panes\nSplit"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_EDIT_CLEAR           "Erase the selection\nErase"
+    ID_EDIT_CLEAR_ALL       "Erase everything\nErase All"
+    ID_EDIT_COPY            "Copy the selection and put it on the Clipboard\nCopy"
+    ID_EDIT_CUT             "Cut the selection and put it on the Clipboard\nCut"
+    ID_EDIT_FIND            "Find the specified text\nFind"
+    ID_EDIT_PASTE           "Insert Clipboard contents\nPaste"
+    ID_EDIT_REPEAT          "Repeat the last action\nRepeat"
+    ID_EDIT_REPLACE         "Replace specific text with different text\nReplace"
+    ID_EDIT_SELECT_ALL      "Select the entire document\nSelect All"
+    ID_EDIT_UNDO            "Undo the last action\nUndo"
+    ID_EDIT_REDO            "Redo the previously undone action\nRedo"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    ID_VIEW_TOOLBAR         "Show or hide the toolbar\nToggle ToolBar"
+    ID_VIEW_STATUS_BAR      "Show or hide the status bar\nToggle StatusBar"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    AFX_IDS_SCSIZE          "Change the window size"
+    AFX_IDS_SCMOVE          "Change the window position"
+    AFX_IDS_SCMINIMIZE      "Reduce the window to an icon"
+    AFX_IDS_SCMAXIMIZE      "Enlarge the window to full size"
+    AFX_IDS_SCNEXTWINDOW    "Switch to the next document window"
+    AFX_IDS_SCPREVWINDOW    "Switch to the previous document window"
+    AFX_IDS_SCCLOSE         "Close the active window and prompts to save the documents"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    AFX_IDS_SCRESTORE       "Restore the window to normal size"
+    AFX_IDS_SCTASKLIST      "Activate Task List"
+END
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    AFX_IDS_PREVIEW_CLOSE   "Close print preview mode\nCancel Preview"
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\CP_Main.rc2"  // non-Microsoft Visual C++ edited resources
+#include "afxres.rc"         // Standard components
+#include "afxprint.rc"       // printing/print preview resources
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+

+ 93 - 0
ComboBoxSearch.cpp

@@ -0,0 +1,93 @@
+// ComboBoxSearch.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "ComboBoxSearch.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CComboBoxSearch
+
+CComboBoxSearch::CComboBoxSearch()
+{
+	m_bShowingDropDown = FALSE;
+}
+
+CComboBoxSearch::~CComboBoxSearch()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CComboBoxSearch, CComboBox)
+	//{{AFX_MSG_MAP(CComboBoxSearch)
+	ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown)
+	ON_CONTROL_REFLECT(CBN_SELENDCANCEL, OnSelendcancel)
+	ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendok)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CComboBoxSearch message handlers
+
+void CComboBoxSearch::OnDropdown() 
+{
+	m_bShowingDropDown = TRUE;
+	SetCurSel(0);
+}
+
+void CComboBoxSearch::OnSelendcancel() 
+{
+	m_bShowingDropDown = FALSE;
+}
+
+void CComboBoxSearch::OnSelendok() 
+{
+	m_bShowingDropDown = FALSE;
+}
+
+BOOL CComboBoxSearch::PreTranslateMessage(MSG* pMsg) 
+{
+	switch(pMsg->message) 
+	{
+		case WM_KEYDOWN:
+		{
+			if(pMsg->wParam == VK_RETURN && m_bShowingDropDown == FALSE)
+			{
+				CWnd *pWnd = GetParent();
+				if(pWnd)
+				{
+					if(GetCurSel() == -1)
+					{
+						//Add the text to the combo
+						CString csText;
+						GetWindowText(csText);
+						int nRet = InsertString(0, csText);
+						SetCurSel(nRet);
+					}
+
+					//Send a message to the parent to refill the lb from the search
+					pWnd->PostMessage(CB_SEARCH, 0, 0);
+				}
+
+				return TRUE;
+			}	
+			if (pMsg->wParam == VK_DOWN)
+			{
+				if(!m_bShowingDropDown)
+				{
+					ShowDropDown();
+					return TRUE;
+				}
+			}
+			break;
+		}
+	}
+	
+	return CComboBox::PreTranslateMessage(pMsg);
+}

+ 56 - 0
ComboBoxSearch.h

@@ -0,0 +1,56 @@
+#if !defined(AFX_COMBOBOXSEARCH_H__24A1E936_2E2A_45D5_99F8_0BDC62E3F2A9__INCLUDED_)
+#define AFX_COMBOBOXSEARCH_H__24A1E936_2E2A_45D5_99F8_0BDC62E3F2A9__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// ComboBoxSearch.h : header file
+//
+
+#define CB_SEARCH					WM_USER+0x104
+
+
+class CComboBoxSearch : public CComboBox
+{
+// Construction
+public:
+	CComboBoxSearch();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+	BOOL GetShowingDropDown()		{ return m_bShowingDropDown;	}
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CComboBoxSearch)
+	public:
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	//}}AFX_VIRTUAL
+
+protected:
+	BOOL m_bShowingDropDown;
+// Implementation
+public:
+	virtual ~CComboBoxSearch();
+
+	// Generated message map functions
+protected:
+	//{{AFX_MSG(CComboBoxSearch)
+	afx_msg void OnDropdown();
+	afx_msg void OnSelendcancel();
+	afx_msg void OnSelendok();
+	//}}AFX_MSG
+
+	DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_COMBOBOXSEARCH_H__24A1E936_2E2A_45D5_99F8_0BDC62E3F2A9__INCLUDED_)

+ 257 - 0
CopyProperties.cpp

@@ -0,0 +1,257 @@
+// CopyProperties.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "CopyProperties.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CCopyProperties dialog
+
+
+CCopyProperties::CCopyProperties(long lCopyID, CWnd* pParent /*=NULL*/)
+	: CDialog(CCopyProperties::IDD, pParent)
+{
+	m_lCopyID = lCopyID;
+	m_bDeletedData = false;
+	m_bChangedText = false;
+	m_bHandleKillFocus = false;
+	m_bHideOnKillFocus = false;
+	//{{AFX_DATA_INIT(CCopyProperties)
+	m_eDisplayText = _T("");
+	m_eDate = _T("");
+	m_bNeverAutoDelete = FALSE;
+	//}}AFX_DATA_INIT
+}
+
+
+void CCopyProperties::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CCopyProperties)
+	DDX_Control(pDX, IDC_HOTKEY, m_HotKey);
+	DDX_Control(pDX, IDC_COPY_DATA, m_lCopyData);
+	DDX_Text(pDX, IDC_EDIT_DISPLAY_TEXT, m_eDisplayText);
+	DDV_MaxChars(pDX, m_eDisplayText, 250);
+	DDX_Text(pDX, IDC_DATE, m_eDate);
+	DDX_Check(pDX, IDC_NEVER_AUTO_DELETE, m_bNeverAutoDelete);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CCopyProperties, CDialog)
+	//{{AFX_MSG_MAP(CCopyProperties)
+	ON_BN_CLICKED(IDC_DELETE_COPY_DATA, OnDeleteCopyData)
+	ON_WM_ACTIVATE()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCopyProperties message handlers
+
+BOOL CCopyProperties::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+
+	m_MainTable.Open("SELECT * FROM Main WHERE lID = %d", m_lCopyID);
+	if(!m_MainTable.IsEOF())
+	{
+		CTime time(m_MainTable.m_lDate);
+		m_eDate = time.Format("%m/%d/%Y %I:%M %p");
+
+		m_eDisplayText = m_MainTable.m_strText;
+
+		if(m_MainTable.m_lDontAutoDelete)
+		{
+			m_bNeverDelete = TRUE;
+			m_bNeverAutoDelete = TRUE;
+		}
+		else
+		{
+			m_bNeverAutoDelete = FALSE;
+			m_bNeverDelete = FALSE;
+		}
+
+
+		m_HotKey.SetHotKey(LOBYTE(m_MainTable.m_lShortCut), HIBYTE(m_MainTable.m_lShortCut));
+		m_HotKey.SetRules(HKCOMB_A, 0);
+
+		CString cs;
+		cs.Format("SELECT * FROM Data WHERE lParentID = %d", m_MainTable.m_lID);
+
+		m_DataTable.Open(AFX_DAO_USE_DEFAULT_TYPE, cs ,NULL);
+
+		while(!m_DataTable.IsEOF())
+		{
+			cs.Format("%s, %d", m_DataTable.m_strClipBoardFormat, m_DataTable.m_ooData.m_dwDataLength);
+			int nIndex = m_lCopyData.AddString(cs);
+			m_lCopyData.SetItemData(nIndex, m_DataTable.m_lID);
+
+			m_DataTable.MoveNext();
+		}
+	}
+
+	UpdateData(FALSE);
+
+
+	SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+
+	m_HotKey.SetFocus();
+	
+	return FALSE;
+}
+
+void CCopyProperties::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
+{
+	CDialog::OnActivate(nState, pWndOther, bMinimized);
+
+	if (nState == WA_INACTIVE)
+	{
+		if(m_bHideOnKillFocus)
+		{
+			if(!m_bHandleKillFocus)
+			{
+				EndDialog(-1);
+				m_bHandleKillFocus = false;
+			}
+		}
+	}
+	else if (nState == WA_ACTIVE)
+	{
+		SetFocus();
+		::SetForegroundWindow(m_hWnd);
+	}
+
+}
+void CCopyProperties::OnOK() 
+{
+	UpdateData();
+
+	bool bUpdate = false;
+
+	long lHotKey = m_HotKey.GetHotKey();
+		
+	if(lHotKey != m_MainTable.m_lShortCut)
+	{
+		if(lHotKey > 0)
+		{
+			CMainTable recset;
+			recset.Open("SELECT * FROM Main WHERE lShortCut = %d", lHotKey);
+			if(!recset.IsEOF())
+			{
+				CString cs;
+				cs.Format("The shortcut is currently assigned to \n\n%s\n\nAssign to new copy item?", recset.m_strText);
+
+				if(MessageBox(cs, "Ditto", MB_YESNO) == IDNO)
+					return;
+
+				recset.Edit();
+				recset.m_lShortCut = 0;
+				recset.Update();
+			}
+		}
+
+		if(!bUpdate)
+			m_MainTable.Edit();
+
+		m_MainTable.m_lShortCut = lHotKey;
+
+		bUpdate = true;
+	}
+
+	if(m_eDisplayText != m_MainTable.m_strText)
+	{
+		if(!bUpdate)
+			m_MainTable.Edit();
+
+		m_bChangedText = true;
+
+		m_MainTable.m_strText = m_eDisplayText;
+
+		bUpdate = true;
+	}
+
+	if(m_bNeverAutoDelete != m_bNeverDelete)
+	{
+		if(!bUpdate)
+			m_MainTable.Edit();
+
+		if(m_bNeverAutoDelete)
+			m_MainTable.m_lDontAutoDelete = (long)CTime::GetCurrentTime().GetTime();
+		else
+			m_MainTable.m_lDontAutoDelete = 0;
+
+		bUpdate = true;
+	}
+
+	if(m_bDeletedData)
+	{
+		m_DeletedData.SortAscending();
+		
+		long lNewTotalSize = 0;
+
+		//Go through the data table and find the deleted items
+		m_DataTable.MoveFirst();
+		while(!m_DataTable.IsEOF())
+		{
+			if(m_DeletedData.Find(m_DataTable.m_lID))
+				m_DataTable.Delete();
+			else
+				lNewTotalSize += m_DataTable.m_ooData.m_dwDataLength;
+
+			m_DataTable.MoveNext();
+		}
+
+		if(lNewTotalSize > 0)
+		{
+			if(!bUpdate)
+				m_MainTable.Edit();
+
+			m_MainTable.m_lTotalCopySize = lNewTotalSize;
+			bUpdate = true;
+		}
+	}
+
+	if(bUpdate)
+		m_MainTable.Update();
+	
+	m_bHandleKillFocus = true;
+
+	CDialog::OnOK();
+}
+
+void CCopyProperties::OnDeleteCopyData() 
+{
+	int nCount = m_lCopyData.GetSelCount();
+	if(nCount)
+	{
+		m_bDeletedData = true;
+
+		//Get the selected indexes
+		ARRAY items;
+		items.SetSize(nCount);
+		m_lCopyData.GetSelItems(nCount, items.GetData()); 
+
+		items.SortDescending();
+
+		//Get the selected itemdata
+		for(int i = 0; i < nCount; i++)
+		{
+			m_DeletedData.Add(m_lCopyData.GetItemData(items[i]));
+			m_lCopyData.DeleteString(items[i]);
+		}		
+	}
+}
+
+void CCopyProperties::OnCancel() 
+{
+	m_bHandleKillFocus = true;
+		
+	CDialog::OnCancel();
+}

+ 68 - 0
CopyProperties.h

@@ -0,0 +1,68 @@
+#if !defined(AFX_COPYPROPERTIES_H__129FE1CD_D305_487A_B88C_BB01CD9C1BB7__INCLUDED_)
+#define AFX_COPYPROPERTIES_H__129FE1CD_D305_487A_B88C_BB01CD9C1BB7__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// CopyProperties.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CCopyProperties dialog
+
+class CCopyProperties : public CDialog
+{
+// Construction
+public:
+	CCopyProperties(long lCopyID, CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CCopyProperties)
+	enum { IDD = IDD_COPY_PROPERTIES };
+	CHotKeyCtrl	m_HotKey;
+	CListBox	m_lCopyData;
+	CString	m_eDisplayText;
+	CString	m_eDate;
+	BOOL	m_bNeverAutoDelete;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CCopyProperties)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+public:
+	bool m_bChangedText;
+	void	SetHideOnKillFocus(bool bVal)	{ m_bHideOnKillFocus = bVal;	}
+
+// Implementation
+protected:
+
+	long		m_lCopyID;
+	CDataTable	m_DataTable;
+	CMainTable	m_MainTable;
+	ARRAY		m_DeletedData;
+	bool		m_bDeletedData;
+	BOOL		m_bNeverDelete;
+	bool		m_bHideOnKillFocus;
+
+	bool		m_bHandleKillFocus;
+
+	// Generated message map functions
+	//{{AFX_MSG(CCopyProperties)
+	virtual BOOL OnInitDialog();
+	virtual void OnOK();
+	afx_msg void OnDeleteCopyData();
+	virtual void OnCancel();
+	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_COPYPROPERTIES_H__129FE1CD_D305_487A_B88C_BB01CD9C1BB7__INCLUDED_)

+ 206 - 0
DataTable.cpp

@@ -0,0 +1,206 @@
+// DataTable.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "DataTable.h"
+#include "DatabaseUtilities.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDataTable
+
+IMPLEMENT_DYNAMIC(CDataTable, CDaoRecordset)
+
+CDataTable::CDataTable(CDaoDatabase* pdb)
+:CDaoRecordset(pdb)
+{
+	//{{AFX_FIELD_INIT(CDataTable)
+	m_lID = 0;
+	m_lParentID = 0;
+	m_strClipBoardFormat = _T("");
+	m_nFields = 4;
+	//}}AFX_FIELD_INIT
+	m_nDefaultType = dbOpenDynaset;
+}
+
+
+CString CDataTable::GetDefaultDBName()
+{
+	return GetDBName();
+}
+
+CString CDataTable::GetDefaultSQL()
+{
+	return _T("[Data]");
+}
+
+void CDataTable::DoFieldExchange(CDaoFieldExchange* pFX)
+{
+	//{{AFX_FIELD_MAP(CDataTable)
+	pFX->SetFieldType(CDaoFieldExchange::outputColumn);
+	DFX_Long(pFX, _T("[lID]"), m_lID);
+	DFX_Long(pFX, _T("[lParentID]"), m_lParentID);
+	DFX_Text(pFX, _T("[strClipBoardFormat]"), m_strClipBoardFormat);
+	DFX_LongBinary(pFX, _T("[ooData]"), m_ooData);
+	//}}AFX_FIELD_MAP
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CDataTable diagnostics
+
+#ifdef _DEBUG
+void CDataTable::AssertValid() const
+{
+	CDaoRecordset::AssertValid();
+}
+
+void CDataTable::Dump(CDumpContext& dc) const
+{
+	CDaoRecordset::Dump(dc);
+}
+#endif //_DEBUG
+
+BOOL CDataTable::DeleteAll()
+{
+	BOOL bRet = FALSE;
+	try
+	{
+		theApp.EnsureOpenDB();
+		theApp.m_pDatabase->Execute("DELETE * FROM Data", dbFailOnError);
+		bRet = TRUE;
+	}
+	catch(CDaoException* e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		e->Delete();
+	}
+
+	return bRet;
+}
+
+BOOL CDataTable::SetData(HGLOBAL hgData)
+{
+	//Get the data from the clipboard sent in
+	LPVOID pvData = NULL;
+	pvData = GlobalLock(hgData);
+	if(!pvData)
+		return FALSE;
+
+	//Size
+	UINT unSize = GlobalSize(hgData);
+
+	//Realocate m_ooData.m_hData
+	if(m_ooData.m_hData)
+		m_ooData.m_hData = GlobalReAlloc(m_ooData.m_hData, unSize, GMEM_MOVEABLE);
+	else
+		m_ooData.m_hData = GlobalAlloc(GHND, unSize);
+
+	//Get the data associated 
+	LPVOID pvNewData = NULL;
+	pvNewData = GlobalLock(m_ooData.m_hData);
+	if(!pvNewData)
+		return FALSE;
+
+	//Set the size
+	m_ooData.m_dwDataLength = unSize;
+
+	//Set the size
+	memcpy(pvNewData, pvData, unSize);
+
+	//Set the fields dirty
+	SetFieldDirty(&m_ooData);
+	SetFieldNull(&m_ooData,FALSE);
+
+	return TRUE;
+}
+
+BOOL CDataTable::LoadData(COleDataSource *pData, UINT uiPastType)
+{
+	BOOL fRetVal = FALSE;
+	
+	//Retrieve size of array
+	ULONG ulBufLen = m_ooData.m_dwDataLength;
+
+	if(ulBufLen > 0)
+	{
+		HGLOBAL hGlobal;
+
+		hGlobal = GlobalAlloc(GMEM_ZEROINIT, ulBufLen);
+		if(hGlobal != NULL)
+		{
+			LPVOID pvData = NULL;
+			pvData = GlobalLock(hGlobal);
+			if(!pvData)
+				return FALSE;
+
+			LPVOID pvData2 = NULL;
+			pvData2 = GlobalLock(m_ooData.m_hData);
+			if(!pvData2)
+				return FALSE;
+
+			memcpy(pvData, pvData2, ulBufLen);
+			
+			GlobalUnlock(hGlobal);
+			GlobalUnlock(m_ooData.m_hData);
+
+			pData->CacheGlobalData(uiPastType, hGlobal);
+
+			fRetVal = TRUE;
+		}
+		else
+			ASSERT(FALSE);
+	}
+	else
+		ASSERT(FALSE);
+	
+	return fRetVal;
+
+}
+
+void CDataTable::Open(LPCTSTR lpszFormat,...) 
+{
+	m_pDatabase = theApp.EnsureOpenDB();
+
+	CString csText;
+	va_list vlist;
+
+	ASSERT(AfxIsValidString(lpszFormat));
+	va_start(vlist,lpszFormat);
+	csText.FormatV(lpszFormat,vlist);
+	va_end(vlist);
+	
+	CDaoRecordset::Open(AFX_DAO_USE_DEFAULT_TYPE, csText, 0);
+}
+
+void CDataTable::Open(int nOpenType, LPCTSTR lpszSql, int nOptions) 
+{
+	m_pDatabase = theApp.EnsureOpenDB();
+	
+	CDaoRecordset::Open(nOpenType, lpszSql, nOptions);
+}
+
+BOOL CDataTable::DataEqual(HGLOBAL hgData)
+{
+	LPVOID saved = NULL;
+	saved = GlobalLock(m_ooData.m_hData);
+	if(!saved)
+		return FALSE;
+
+	LPVOID data = NULL;
+	data = GlobalLock(hgData);
+	if(!data)
+		return FALSE;
+
+	GlobalUnlock(hgData);
+	GlobalUnlock(m_ooData.m_hData);
+
+	int nRet = (memcmp(data, saved, m_ooData.m_dwDataLength) == 0);
+
+	return nRet;
+}

+ 51 - 0
DataTable.h

@@ -0,0 +1,51 @@
+#if !defined(AFX_DATATABLE_H__B70F6A02_C464_4FFE_91E8_E7F59765178F__INCLUDED_)
+#define AFX_DATATABLE_H__B70F6A02_C464_4FFE_91E8_E7F59765178F__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// DataTable.h : header file
+//
+
+class CDataTable : public CDaoRecordset
+{
+public:
+	CDataTable(CDaoDatabase* pDatabase = NULL);
+	DECLARE_DYNAMIC(CDataTable)
+
+// Field/Param Data
+	//{{AFX_FIELD(CDataTable, CDaoRecordset)
+	long	m_lID;
+	long	m_lParentID;
+	CString	m_strClipBoardFormat;
+	CLongBinary	m_ooData;
+	//}}AFX_FIELD
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CDataTable)
+	public:
+	virtual CString GetDefaultDBName();		// Default database name
+	virtual CString GetDefaultSQL();		// Default SQL for Recordset
+	virtual void DoFieldExchange(CDaoFieldExchange* pFX);  // RFX support
+	virtual void Open(int nOpenType = AFX_DAO_USE_DEFAULT_TYPE, LPCTSTR lpszSql = NULL, int nOptions = 0);
+	//}}AFX_VIRTUAL
+public:
+	BOOL SetData(HGLOBAL hgData);
+	BOOL DeleteAll();
+	BOOL LoadData(COleDataSource *pSource, UINT uiPastType);
+	void Open(LPCTSTR lpszFormat,...);
+	BOOL DataEqual(HGLOBAL hgData);
+
+
+// Implementation
+#ifdef _DEBUG
+	virtual void AssertValid() const;
+	virtual void Dump(CDumpContext& dc) const;
+#endif
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DATATABLE_H__B70F6A02_C464_4FFE_91E8_E7F59765178F__INCLUDED_)

+ 337 - 0
DatabaseUtilities.cpp

@@ -0,0 +1,337 @@
+// DatabaseUtilites.cpp: implementation of the CDatabaseUtilites class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "DatabaseUtilities.h"
+#include "io.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CString GetDBName()
+{
+	return CGetSetOptions::GetDBPath();
+}
+
+CString GetDefaultDBName()
+{
+	CString csDefaultPath;
+	LPMALLOC pMalloc;
+	
+	if(SUCCEEDED(::SHGetMalloc(&pMalloc))) 
+	{ 
+		LPITEMIDLIST pidlPrograms;
+
+		SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidlPrograms);
+
+		char string[MAX_PATH];
+		SHGetPathFromIDList(pidlPrograms, string);
+
+		pMalloc->Free(pidlPrograms);
+		pMalloc->Release();
+
+		csDefaultPath = string;		
+		csDefaultPath += "\\Ditto\\";
+		
+		if(_access(csDefaultPath, 0) != -1)
+			CreateDirectory(csDefaultPath, NULL);
+		
+		csDefaultPath += DEFAULT_DB_NAME;
+	}
+
+	return csDefaultPath;
+}
+
+BOOL CheckDBExists(CString csDBPath)
+{
+	if(_access(csDBPath, 0) == -1)
+	{
+		//Database didn't exist
+		CGetSetOptions::SetDBPath("");
+		
+		// -- create a new one
+		CreateDB(GetDefaultDBName());
+		return TRUE;
+	}
+
+	BOOL bRet = FALSE;
+
+	if(ValidDB(csDBPath) == FALSE)
+	{
+		theApp.CloseDB();
+		
+		CGetSetOptions::SetDBPath("");
+
+		//Db existed but was bad
+
+		CString csMarkAsBad;
+		
+		csMarkAsBad = csDBPath;
+		csMarkAsBad.Replace(".", "_BAD.");
+		
+		CString csPath = GetDefaultDBName();
+
+		CString cs;
+		cs.Format("Unrecognized Database Format \"%s\",\n"
+					"the file will be renamed \"%s\",\n"
+					"and a new database will be created,\n"
+					"\"%s\"", csDBPath, csMarkAsBad, csPath);
+
+		AfxMessageBox(cs);
+		
+		CFile::Rename(csDBPath, csMarkAsBad);
+		
+
+		bRet = CreateDB(csPath);
+	}
+	else
+		bRet = TRUE;
+
+	return bRet;
+}
+
+BOOL ValidDB(CString csPath)
+{
+	try
+	{
+		CDaoDatabase db;
+		db.Open(csPath);
+
+		CDaoTableDef table(&db);
+		CDaoFieldInfo info;
+
+		table.Open("Main");
+		table.GetFieldInfo("lID", info);
+		table.GetFieldInfo("lDate", info);
+		table.GetFieldInfo("strType", info);
+		table.GetFieldInfo("strText", info);
+		table.GetFieldInfo("lShortCut", info);
+		table.GetFieldInfo("lDontAutoDelete", info);
+		table.GetFieldInfo("lTotalCopySize", info);
+		table.Close();
+
+		table.Open("Data");
+		table.GetFieldInfo("lID", info);
+		table.GetFieldInfo("lParentID", info);
+		table.GetFieldInfo("strClipBoardFormat", info);
+		table.GetFieldInfo("ooData", info);
+		table.Close();
+
+		table.Open("Types");
+		table.GetFieldInfo("ID", info);
+		table.GetFieldInfo("TypeText", info);
+		table.Close();
+	}
+	catch(CDaoException* e)
+	{
+		e->Delete();
+		ASSERT(FALSE);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CreateDB(CString csPath)
+{
+	CDaoDatabase db;
+
+	try
+	{
+		if(_access(csPath, 0) == 0)
+			DeleteFile(csPath);
+
+		db.Create(csPath);
+		
+		CDaoTableDefEx table(&db);
+
+		//Creat the Main table
+		table.Create("Main");
+		
+		table.CreateField("lID", dbLong, 4, dbAutoIncrField);
+		table.CreateIndex(TRUE, "lID");
+
+		table.CreateField("lDate", dbLong, 4, 0, "0");
+		table.CreateIndex(FALSE, "lDate");
+
+		table.CreateField("strType", dbText, 50, dbVariableField);
+		table.CreateField("strText", dbText, 255, dbVariableField);
+
+		table.CreateField("lShortCut", dbLong, 4, 0, "0");
+		table.CreateIndex(FALSE, "lShortCut");
+		
+		table.CreateField("lDontAutoDelete", dbLong, 4, 0, "0");
+
+		table.CreateField("lTotalCopySize", dbLong, 4, 0, "0");
+
+		table.Append();
+		table.Close();
+
+		//Create the Data Table
+		table.Create("Data");
+		
+		table.CreateField("lID", dbLong, 4, dbAutoIncrField);
+		table.CreateIndex(TRUE, "lID");
+
+		table.CreateField("lParentID", dbLong, 4, 0, "0");
+		table.CreateIndex(FALSE, "lParentID");
+
+		table.CreateField("strClipBoardFormat", dbText, 50, dbVariableField);
+		table.CreateField("ooData", dbLongBinary, 0);
+
+		table.Append();
+		table.Close();
+
+		//Create the Types table
+		table.Create("Types");
+		table.CreateField("ID", dbLong, 4, dbAutoIncrField);
+		table.CreateField("TypeText", dbText, 50, dbVariableField);
+
+		table.Append();
+		table.Close();
+
+		db.Close();
+		
+		return TRUE;
+	}
+	catch(CDaoException *e)
+	{
+		ASSERT(FALSE);
+		e->Delete();
+	}
+
+	return FALSE;
+}
+
+
+BOOL CompactDatabase()
+{
+	if(!theApp.CloseDB())
+		return FALSE;
+
+	CString csDBName = GetDBName();
+	CString csTempDBName = csDBName;
+	csTempDBName.Replace(".mdb", "TempDBName.mdb");
+
+	//Compact the database			
+	try
+	{
+		CDaoWorkspace::CompactDatabase(csDBName, csTempDBName);//, dbLangGeneral, 0, "andrew");//DATABASE_PASSWORD);
+	}
+	catch(CDaoException* e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		DeleteFile(csTempDBName);
+		e->Delete();
+		return FALSE;
+	}
+	catch(CMemoryException* e) 
+	{
+		AfxMessageBox("Memory Exception");
+		DeleteFile(csTempDBName);
+		e->Delete();
+		return FALSE;
+	}
+
+
+	//Since compacting the database creates a new db delete the old one and replace it
+	//with the compacted db
+	if(DeleteFile(csDBName))
+	{
+		try
+		{
+			CFile::Rename(csTempDBName, csDBName);
+		}
+		catch(CFileException *e)
+		{
+			e->ReportError();
+			e->Delete();
+			return FALSE;
+		}
+	}
+	else
+		AfxMessageBox("Error Compacting Database");
+
+	return TRUE;
+}
+
+BOOL RepairDatabase()
+{
+	if(!theApp.CloseDB())
+		return FALSE;
+
+	try
+	{
+		CDaoWorkspace::RepairDatabase(GetDBName());
+	}
+	catch(CDaoException *e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		e->Delete();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL RemoveOldEntries()
+{
+	if(CGetSetOptions::GetCheckForMaxEntries())
+	{
+		long lMax = CGetSetOptions::GetMaxEntries();
+
+		CMainTable recset;
+		recset.Open("SELECT * FROM Main ORDER BY lDate DESC");
+		if(!recset.IsEOF())
+		{
+			recset.MoveLast();
+
+			long lCount = recset.GetRecordCount();
+
+			ARRAY IDs;
+
+			while((lCount > lMax) && (!recset.IsBOF()))
+			{
+				//Don't delete entries that have shorcuts or the flag set
+				if(recset.m_lDontAutoDelete <= 0)
+					IDs.Add(recset.m_lID);
+
+				lCount--;
+				recset.MovePrev();
+			}
+
+			recset.DeleteRows(IDs);
+		}
+	}
+
+	if(CGetSetOptions::GetCheckForExpiredEntries())
+	{
+		long lExpire = CGetSetOptions::GetExpiredEntries();
+
+		if(lExpire)
+		{
+			CTime now = CTime::GetCurrentTime();
+			now -= CTimeSpan(lExpire, 0, 0, 0);
+
+			CMainTable recset;
+			recset.Open("SELECT * FROM Main "
+						"WHERE lDate < %d AND "
+						"lShortCut <= 0 AND lDontAutoDelete <= 0", now.GetTime());
+
+			ARRAY IDs;
+
+			while(!recset.IsEOF())
+			{
+				IDs.Add(recset.m_lID);
+				recset.MoveNext();
+			}
+
+			recset.DeleteRows(IDs);
+		}
+	}
+
+	return TRUE;
+}

+ 94 - 0
DatabaseUtilities.h

@@ -0,0 +1,94 @@
+// DatabaseUtilites.h: interface for the CDatabaseUtilites class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DATABASEUTILITES_H__039F53EB_228F_4640_8009_3D2B1FF435D4__INCLUDED_)
+#define AFX_DATABASEUTILITES_H__039F53EB_228F_4640_8009_3D2B1FF435D4__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define DEFAULT_DB_NAME "DittoDB.mdb"
+
+class CDaoTableDefEx : public CDaoTableDef
+{
+public:
+	CDaoTableDefEx(CDaoDatabase* pDatabase)
+		:CDaoTableDef(pDatabase)
+	{
+	}
+
+	BOOL CreateIndex(BOOL bPrimaryKey, CString csField)
+	{
+		try
+		{
+			CDaoIndexInfo IndexInfo;
+			CDaoIndexFieldInfo IndexFieldInfo[1];
+			IndexFieldInfo[0].m_strName = csField;
+			IndexFieldInfo[0].m_bDescending = TRUE;
+			IndexInfo.m_strName = csField;
+			IndexInfo.m_pFieldInfos = IndexFieldInfo;
+			IndexInfo.m_nFields = 1;
+			IndexInfo.m_bPrimary = bPrimaryKey;
+			IndexInfo.m_bUnique = FALSE;
+			IndexInfo.m_bIgnoreNulls = FALSE;
+			IndexInfo.m_bRequired = FALSE;
+
+			CDaoTableDef::CreateIndex( IndexInfo );
+		}
+		catch(CDaoException *e)
+		{
+			ASSERT(FALSE);
+			e->Delete();
+			return FALSE;
+		}
+
+		return TRUE;
+	}
+
+	BOOL CreateField(LPCTSTR lpszName, short nType, long lSize, long lAttributes = 0, CString csDefault = "")
+	{
+		try
+		{
+			CDaoFieldInfo fieldinfo;
+
+			// Initialize everything so only correct properties will be set
+			fieldinfo.m_strName = lpszName;
+			fieldinfo.m_nType = nType;
+			fieldinfo.m_lSize = lSize;
+			fieldinfo.m_lAttributes = lAttributes;
+			fieldinfo.m_nOrdinalPosition = 0;
+			fieldinfo.m_bRequired = FALSE;
+			fieldinfo.m_bAllowZeroLength = FALSE;
+			fieldinfo.m_lCollatingOrder = 0;
+			fieldinfo.m_strDefaultValue = csDefault;
+
+			CDaoTableDef::CreateField(fieldinfo);
+
+			return TRUE;
+		}
+		catch(CDaoException *e)
+		{
+			e->Delete();
+			ASSERT(FALSE);
+		}
+
+	return FALSE;
+		
+	}
+
+
+	
+};
+
+CString GetDBName();
+BOOL CompactDatabase();
+CString GetDefaultDBName();
+BOOL RepairDatabase();
+BOOL CheckDBExists(CString csDBPath);
+BOOL RemoveOldEntries();
+BOOL CreateDB(CString csPath);
+BOOL ValidDB(CString csPath);
+
+#endif // !defined(AFX_DATABASEUTILITES_H__039F53EB_228F_4640_8009_3D2B1FF435D4__INCLUDED_)

+ 428 - 0
HyperLink.cpp

@@ -0,0 +1,428 @@
+// HyperLink.cpp : implementation file
+//
+// HyperLink static control. Will open the default browser with the given URL
+// when the user clicks on the link.
+//
+// Copyright (C) 1997, 1998 Chris Maunder
+// All rights reserved. May not be sold for profit.
+//
+// Thanks to Pål K. Tønder for auto-size and window caption changes.
+//
+// "GotoURL" function by Stuart Patterson
+// As seen in the August, 1997 Windows Developer's Journal.
+// Copyright 1997 by Miller Freeman, Inc. All rights reserved.
+// Modified by Chris Maunder to use TCHARs instead of chars.
+//
+// "Default hand cursor" from Paul DiLascia's Jan 1998 MSJ article.
+//
+
+#include "stdafx.h"
+#include "HyperLink.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define TOOLTIP_ID 1
+
+/////////////////////////////////////////////////////////////////////////////
+// CHyperLink
+
+CHyperLink::CHyperLink()
+{
+    m_hLinkCursor       = NULL;                 // No cursor as yet
+    m_crLinkColour      = RGB(  0,   0, 238);   // Blue
+    m_crVisitedColour   = RGB( 85,  26, 139);   // Purple
+    m_crHoverColour     = ::GetSysColor(COLOR_HIGHLIGHT);
+    m_bOverControl      = FALSE;                // Cursor not yet over control
+    m_bVisited          = FALSE;                // Hasn't been visited yet.
+    m_bUnderline        = TRUE;                 // Underline the link?
+    m_bAdjustToFit      = TRUE;                 // Resize the window to fit the text?
+    m_strURL.Empty();
+}
+
+CHyperLink::~CHyperLink()
+{
+    m_Font.DeleteObject();
+}
+
+BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
+    //{{AFX_MSG_MAP(CHyperLink)
+    ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
+    ON_WM_CTLCOLOR_REFLECT()
+    ON_WM_SETCURSOR()
+    ON_WM_MOUSEMOVE()
+    //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CHyperLink message handlers
+
+BOOL CHyperLink::PreTranslateMessage(MSG* pMsg) 
+{
+    m_ToolTip.RelayEvent(pMsg);
+    return CStatic::PreTranslateMessage(pMsg);
+}
+
+void CHyperLink::OnClicked()
+{
+    int result = (int)GotoURL(m_strURL, SW_SHOW);
+    m_bVisited = (result > HINSTANCE_ERROR);
+    if (!m_bVisited) {
+        MessageBeep(MB_ICONEXCLAMATION);     // Unable to follow link
+        ReportError(result);
+    } else 
+        SetVisited();                        // Repaint to show visited colour
+}
+
+HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT nCtlColor) 
+{
+    ASSERT(nCtlColor == CTLCOLOR_STATIC);
+
+    if (m_bOverControl)
+        pDC->SetTextColor(m_crHoverColour);
+    else if (m_bVisited)
+        pDC->SetTextColor(m_crVisitedColour);
+    else
+        pDC->SetTextColor(m_crLinkColour);
+
+    // transparent text.
+    pDC->SetBkMode(TRANSPARENT);
+    return (HBRUSH)GetStockObject(NULL_BRUSH);
+}
+
+void CHyperLink::OnMouseMove(UINT nFlags, CPoint point) 
+{
+    CStatic::OnMouseMove(nFlags, point);
+
+    if (m_bOverControl)        // Cursor is currently over control
+    {
+        CRect rect;
+        GetClientRect(rect);
+
+        if (!rect.PtInRect(point))
+        {
+            m_bOverControl = FALSE;
+            ReleaseCapture();
+            RedrawWindow();
+            return;
+        }
+    }
+    else                      // Cursor has just moved over control
+    {
+        m_bOverControl = TRUE;
+        RedrawWindow();
+        SetCapture();
+    }
+}
+
+BOOL CHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/) 
+{
+    if (m_hLinkCursor)
+    {
+        ::SetCursor(m_hLinkCursor);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+void CHyperLink::PreSubclassWindow() 
+{
+    // We want to get mouse clicks via STN_CLICKED
+    DWORD dwStyle = GetStyle();
+    ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);
+    
+    // Set the URL as the window text
+    if (m_strURL.IsEmpty())
+        GetWindowText(m_strURL);
+
+    // Check that the window text isn't empty. If it is, set it as the URL.
+    CString strWndText;
+    GetWindowText(strWndText);
+    if (strWndText.IsEmpty()) {
+        ASSERT(!m_strURL.IsEmpty());    // Window and URL both NULL. DUH!
+        SetWindowText(m_strURL);
+    }
+
+    // Create the font
+    LOGFONT lf;
+    GetFont()->GetLogFont(&lf);
+    lf.lfUnderline = m_bUnderline;
+    m_Font.CreateFontIndirect(&lf);
+    SetFont(&m_Font);
+
+    PositionWindow();        // Adjust size of window to fit URL if necessary
+    SetDefaultCursor();      // Try and load up a "hand" cursor
+
+    // Create the tooltip
+    CRect rect; 
+    GetClientRect(rect);
+    m_ToolTip.Create(this);
+    m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);
+
+    CStatic::PreSubclassWindow();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CHyperLink operations
+
+void CHyperLink::SetURL(CString strURL)
+{
+    m_strURL = strURL;
+
+    if (::IsWindow(GetSafeHwnd())) {
+        PositionWindow();
+        m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
+    }
+}
+
+CString CHyperLink::GetURL() const
+{ 
+    return m_strURL;   
+}
+
+void CHyperLink::SetColours(COLORREF crLinkColour, COLORREF crVisitedColour,
+                            COLORREF crHoverColour /* = -1 */) 
+{ 
+    m_crLinkColour    = crLinkColour; 
+    m_crVisitedColour = crVisitedColour;
+
+	if (crHoverColour == -1)
+		m_crHoverColour = ::GetSysColor(COLOR_HIGHLIGHT);
+	else
+		m_crHoverColour = crHoverColour;
+
+    if (::IsWindow(m_hWnd))
+        Invalidate(); 
+}
+
+COLORREF CHyperLink::GetLinkColour() const
+{ 
+    return m_crLinkColour; 
+}
+
+COLORREF CHyperLink::GetVisitedColour() const
+{
+    return m_crVisitedColour; 
+}
+
+COLORREF CHyperLink::GetHoverColour() const
+{
+    return m_crHoverColour;
+}
+
+void CHyperLink::SetVisited(BOOL bVisited /* = TRUE */) 
+{ 
+    m_bVisited = bVisited; 
+
+    if (::IsWindow(GetSafeHwnd()))
+        Invalidate(); 
+}
+
+BOOL CHyperLink::GetVisited() const
+{ 
+    return m_bVisited; 
+}
+
+void CHyperLink::SetLinkCursor(HCURSOR hCursor)
+{ 
+    m_hLinkCursor = hCursor;
+    if (m_hLinkCursor == NULL)
+        SetDefaultCursor();
+}
+
+HCURSOR CHyperLink::GetLinkCursor() const
+{
+    return m_hLinkCursor;
+}
+
+void CHyperLink::SetUnderline(BOOL bUnderline /* = TRUE */)
+{
+    m_bUnderline = bUnderline;
+
+    if (::IsWindow(GetSafeHwnd()))
+    {
+        LOGFONT lf;
+        GetFont()->GetLogFont(&lf);
+        lf.lfUnderline = m_bUnderline;
+
+        m_Font.DeleteObject();
+        m_Font.CreateFontIndirect(&lf);
+        SetFont(&m_Font);
+
+        Invalidate(); 
+    }
+}
+
+BOOL CHyperLink::GetUnderline() const
+{ 
+    return m_bUnderline; 
+}
+
+void CHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */)
+{
+    m_bAdjustToFit = bAutoSize;
+
+    if (::IsWindow(GetSafeHwnd()))
+        PositionWindow();
+}
+
+BOOL CHyperLink::GetAutoSize() const
+{ 
+    return m_bAdjustToFit; 
+}
+
+
+// Move and resize the window so that the window is the same size
+// as the hyperlink text. This stops the hyperlink cursor being active
+// when it is not directly over the text. If the text is left justified
+// then the window is merely shrunk, but if it is centred or right
+// justified then the window will have to be moved as well.
+//
+// Suggested by Pål K. Tønder 
+
+void CHyperLink::PositionWindow()
+{
+    if (!::IsWindow(GetSafeHwnd()) || !m_bAdjustToFit) 
+        return;
+
+    // Get the current window position
+    CRect rect;
+    GetWindowRect(rect);
+
+    CWnd* pParent = GetParent();
+    if (pParent)
+        pParent->ScreenToClient(rect);
+
+    // Get the size of the window text
+    CString strWndText;
+    GetWindowText(strWndText);
+
+    CDC* pDC = GetDC();
+    CFont* pOldFont = pDC->SelectObject(&m_Font);
+    CSize Extent = pDC->GetTextExtent(strWndText);
+    pDC->SelectObject(pOldFont);
+    ReleaseDC(pDC);
+
+    // Get the text justification via the window style
+    DWORD dwStyle = GetStyle();
+
+    // Recalc the window size and position based on the text justification
+    if (dwStyle & SS_CENTERIMAGE)
+        rect.DeflateRect(0, (rect.Height() - Extent.cy)/2);
+    else
+        rect.bottom = rect.top + Extent.cy;
+
+    if (dwStyle & SS_CENTER)   
+        rect.DeflateRect((rect.Width() - Extent.cx)/2, 0);
+    else if (dwStyle & SS_RIGHT) 
+        rect.left  = rect.right - Extent.cx;
+    else // SS_LEFT = 0, so we can't test for it explicitly 
+        rect.right = rect.left + Extent.cx;
+
+    // Move the window
+    SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CHyperLink implementation
+
+// The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
+// It loads a "hand" cursor from the winhlp32.exe module
+void CHyperLink::SetDefaultCursor()
+{
+    if (m_hLinkCursor == NULL)                // No cursor handle - load our own
+    {
+        // Get the windows directory
+        CString strWndDir;
+        GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
+        strWndDir.ReleaseBuffer();
+
+        strWndDir += _T("\\winhlp32.exe");
+        // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
+        HMODULE hModule = LoadLibrary(strWndDir);
+        if (hModule) {
+            HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
+            if (hHandCursor)
+                m_hLinkCursor = CopyCursor(hHandCursor);
+        }
+        FreeLibrary(hModule);
+    }
+}
+
+LONG CHyperLink::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
+{
+    HKEY hkey;
+    LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);
+
+    if (retval == ERROR_SUCCESS) {
+        long datasize = MAX_PATH;
+        TCHAR data[MAX_PATH];
+        RegQueryValue(hkey, NULL, data, &datasize);
+        lstrcpy(retdata,data);
+        RegCloseKey(hkey);
+    }
+
+    return retval;
+}
+
+void CHyperLink::ReportError(int nError)
+{
+    CString str;
+    switch (nError) {
+        case 0:                       str = "The operating system is out\nof memory or resources."; break;
+        case SE_ERR_PNF:              str = "The specified path was not found."; break;
+        case SE_ERR_FNF:              str = "The specified file was not found."; break;
+        case ERROR_BAD_FORMAT:        str = "The .EXE file is invalid\n(non-Win32 .EXE or error in .EXE image)."; break;
+        case SE_ERR_ACCESSDENIED:     str = "The operating system denied\naccess to the specified file."; break;
+        case SE_ERR_ASSOCINCOMPLETE:  str = "The filename association is\nincomplete or invalid."; break;
+        case SE_ERR_DDEBUSY:          str = "The DDE transaction could not\nbe completed because other DDE transactions\nwere being processed."; break;
+        case SE_ERR_DDEFAIL:          str = "The DDE transaction failed."; break;
+        case SE_ERR_DDETIMEOUT:       str = "The DDE transaction could not\nbe completed because the request timed out."; break;
+        case SE_ERR_DLLNOTFOUND:      str = "The specified dynamic-link library was not found."; break;
+        case SE_ERR_NOASSOC:          str = "There is no application associated\nwith the given filename extension."; break;
+        case SE_ERR_OOM:              str = "There was not enough memory to complete the operation."; break;
+        case SE_ERR_SHARE:            str = "A sharing violation occurred. ";
+        default:                      str.Format("Unknown Error (%d) occurred.", nError); break;
+    }
+    str = "Unable to open hyperlink:\n\n" + str;
+    AfxMessageBox(str, MB_ICONEXCLAMATION | MB_OK);
+}
+
+HINSTANCE CHyperLink::GotoURL(LPCTSTR url, int showcmd)
+{
+    TCHAR key[MAX_PATH + MAX_PATH];
+
+    // First try ShellExecute()
+    HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);
+
+    // If it failed, get the .htm regkey and lookup the program
+    if ((UINT)result <= HINSTANCE_ERROR) {
+
+        if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS) {
+            lstrcat(key, _T("\\shell\\open\\command"));
+
+            if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) {
+                TCHAR *pos;
+                pos = _tcsstr(key, _T("\"%1\""));
+                if (pos == NULL) {                     // No quotes found
+                    pos = strstr(key, _T("%1"));       // Check for %1, without quotes 
+                    if (pos == NULL)                   // No parameter at all...
+                        pos = key+lstrlen(key)-1;
+                    else
+                        *pos = '\0';                   // Remove the parameter
+                }
+                else
+                    *pos = '\0';                       // Remove the parameter
+
+                lstrcat(pos, _T(" "));
+                lstrcat(pos, url);
+                result = (HINSTANCE) WinExec(key,showcmd);
+            }
+        }
+    }
+
+    return result;
+}

+ 100 - 0
HyperLink.h

@@ -0,0 +1,100 @@
+// HyperLink.h : header file
+//
+//
+// HyperLink static control. Will open the default browser with the given URL
+// when the user clicks on the link.
+//
+// Copyright Chris Maunder, 1997
+// Feel free to use and distribute. May not be sold for profit. 
+
+#if !defined(AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_)
+#define AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+/////////////////////////////////////////////////////////////////////////////
+// CHyperLink window
+
+class CHyperLink : public CStatic
+{
+// Construction/destruction
+public:
+    CHyperLink();
+    virtual ~CHyperLink();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+    void SetURL(CString strURL);
+    CString GetURL() const;
+
+    void SetColours(COLORREF crLinkColour, COLORREF crVisitedColour, 
+                    COLORREF crHoverColour = -1);
+    COLORREF GetLinkColour() const;
+    COLORREF GetVisitedColour() const;
+    COLORREF GetHoverColour() const;
+
+    void SetVisited(BOOL bVisited = TRUE);
+    BOOL GetVisited() const;
+
+    void SetLinkCursor(HCURSOR hCursor);
+    HCURSOR GetLinkCursor() const;
+
+    void SetUnderline(BOOL bUnderline = TRUE);
+    BOOL GetUnderline() const;
+
+    void SetAutoSize(BOOL bAutoSize = TRUE);
+    BOOL GetAutoSize() const;
+
+// Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CHyperLink)
+    public:
+    virtual BOOL PreTranslateMessage(MSG* pMsg);
+    protected:
+    virtual void PreSubclassWindow();
+    //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+    HINSTANCE GotoURL(LPCTSTR url, int showcmd);
+    void ReportError(int nError);
+    LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata);
+    void PositionWindow();
+    void SetDefaultCursor();
+
+// Protected attributes
+protected:
+    COLORREF m_crLinkColour, m_crVisitedColour;     // Hyperlink colours
+    COLORREF m_crHoverColour;                       // Hover colour
+    BOOL     m_bOverControl;                        // cursor over control?
+    BOOL     m_bVisited;                            // Has it been visited?
+    BOOL     m_bUnderline;                          // underline hyperlink?
+    BOOL     m_bAdjustToFit;                        // Adjust window size to fit text?
+    CString  m_strURL;                              // hyperlink URL
+    CFont    m_Font;                                // Underline font if necessary
+    HCURSOR  m_hLinkCursor;                         // Cursor for hyperlink
+    CToolTipCtrl m_ToolTip;                         // The tooltip
+
+    // Generated message map functions
+protected:
+    //{{AFX_MSG(CHyperLink)
+    afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
+    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
+    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+    //}}AFX_MSG
+    afx_msg void OnClicked();
+    DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_)

+ 365 - 0
InternetUpdate.cpp

@@ -0,0 +1,365 @@
+// InternetUpdate.cpp: implementation of the CInternetUpdate class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "InternetUpdate.h"
+#include <afxinet.h>
+#include "ProgressWnd.h"
+#include "io.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+#define HTTPBUFLEN    512 // Size of HTTP Buffer...
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CInternetUpdate::CInternetUpdate()
+{
+
+}
+
+CInternetUpdate::~CInternetUpdate()
+{
+
+}
+
+BOOL CInternetUpdate::CheckForUpdate(HWND hParent, BOOL bCheckForPrevUpdate, BOOL bShowNoUpdatesDlg)
+{
+	m_bShowMessages = bShowNoUpdatesDlg;
+	m_hParent = hParent;
+	
+	CTime Now = CTime::GetCurrentTime();
+	tm tmNow = *(Now.GetLocalTm());
+	long lCurrentDayOfYear = tmNow.tm_yday;
+
+	CGetSetOptions::SetLastUpdate(lCurrentDayOfYear);
+
+	RemoveOldUpdateFile();
+	
+	if(bCheckForPrevUpdate)
+	{
+		if(!CGetSetOptions::GetCheckForUpdates())
+			return FALSE;
+
+		if((lCurrentDayOfYear - CGetSetOptions::GetLastUpdate()) > 15)
+		{
+			//If it's been more than 15 days then check for updates
+		}
+		else
+		{
+			//Only check every 15 days
+			if((lCurrentDayOfYear % 15) != 0)
+				return FALSE;
+
+			//if the last time we check was today return
+			if(CGetSetOptions::GetLastUpdate() == lCurrentDayOfYear)
+				return FALSE;
+		}
+	}
+	
+	BOOL bRet = FALSE;
+	
+	m_lRunningVersion = GetRunningVersion();
+	m_lUpdateVersion = GetUpdateVersion();
+
+	if(m_lUpdateVersion > m_lRunningVersion)
+	{
+		CString csMessage;
+		csMessage.Format(	"Updates available for Ditto.\n\n"
+							"Running Version, %s\n"
+							"Update Version, %s\n\n"
+							"Download updated version?",
+							GetVersionString(m_lRunningVersion), 
+							GetVersionString(m_lUpdateVersion));
+
+		if(MessageBox(hParent, csMessage, "Ditto", MB_YESNO) == IDYES)
+		{
+			CString csFile = DownloadUpdate();
+
+			if(!csFile.IsEmpty())
+			{
+				CloseHandle(theApp.m_hMutex);
+				Sleep(100);
+				ShellExecute(NULL, NULL, csFile, NULL, NULL, SW_SHOWNORMAL);
+			}
+
+			bRet = TRUE;
+		}
+	}
+	else if(m_bShowMessages)
+	{
+		MessageBox(hParent, "No updates available", "Ditto", MB_OK);
+	}
+
+	return bRet;
+}
+
+BOOL CInternetUpdate::RemoveOldUpdateFile()
+{
+	CString csFile = CGetSetOptions::GetExeFileName();
+	csFile = GetFilePath(csFile);
+	csFile += "DittoSetup.exe";
+	
+	BOOL bRet = TRUE;
+	if(_access(csFile, 0) != -1)
+	{
+		bRet = ::DeleteFile(csFile);
+	}
+
+	return bRet;
+}
+
+CString CInternetUpdate::GetVersionString(long lVersion)
+{
+	CString csLine;
+	csLine.Format("%02i.%02i.%02i%02i", 
+		(lVersion >> 24) & 0x03f,
+		(lVersion >> 16) & 0x03f,
+		((lVersion >> 8) & 0x07f),
+		lVersion & 0x07f);
+
+	return csLine;
+}
+
+long CInternetUpdate::GetRunningVersion()
+{
+	CString csFileName = CGetSetOptions::GetExeFileName();
+
+    DWORD dwSize, dwHandle;
+    LPBYTE lpData;
+    UINT iBuffSize;
+    VS_FIXEDFILEINFO *lpFFI;
+    long ver;
+
+    dwSize = GetFileVersionInfoSize(csFileName, &dwHandle);
+    if(dwSize != 0)
+    {
+		if((lpData=(unsigned char *)malloc(dwSize)) != NULL)
+		{
+			if(GetFileVersionInfo(csFileName, dwHandle, dwSize, lpData) != 0)
+			{
+				if(VerQueryValue(lpData, "\\", (LPVOID*)&lpFFI, &iBuffSize) != 0)
+				{
+					if(iBuffSize > 0)
+					{
+					ver =        (HIWORD(lpFFI->dwFileVersionMS) & 0x00ff) << 24;
+					ver = ver + ((LOWORD(lpFFI->dwFileVersionMS) & 0x00ff) << 16);
+					ver = ver + ((HIWORD(lpFFI->dwFileVersionLS) & 0x00ff) << 8);
+					ver = ver +   LOWORD(lpFFI->dwFileVersionLS);
+					free(lpData);
+					return(ver);
+					}
+				}
+			}
+			free(lpData);
+		}
+    }
+
+    return(0);
+}
+
+
+long CInternetUpdate::GetUpdateVersion()
+{
+	char httpbuff[HTTPBUFLEN];
+	
+	//Try to get a path from the regestry
+	CString csPath = CGetSetOptions::GetUpdateFilePath();
+
+	//if nothing there get the default
+	if(csPath.IsEmpty())
+		csPath = "sabrogden.0Catch.com/DittoVersion.txt";
+
+	CString csUrl = "http://" + csPath;
+	
+	CString csFile = CGetSetOptions::GetExeFileName();
+
+	csFile = GetFilePath(csFile);
+	csFile += "DittoVersion.txt";
+
+	bool bError = false;
+	CStdioFile *remotefile = NULL;
+
+	long lReturn = -1;
+	try
+	{
+		CInternetSession mysession;
+		remotefile = mysession.OpenURL(csUrl,1,INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_RELOAD);
+		if(!remotefile)
+			return 0;
+		
+		CFile myfile(csFile, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
+		
+		UINT unBytesRead = 0;
+		UINT unTotalBytes = 0;
+		
+		while (unBytesRead = remotefile->Read(httpbuff, HTTPBUFLEN))
+		{
+			unTotalBytes += unBytesRead;
+			myfile.Write(httpbuff, unBytesRead);
+
+			if(!remotefile)
+			{
+				unTotalBytes = 0;
+				break;
+			}
+		}
+		
+		myfile.Close();
+		
+		if(unTotalBytes)
+		{
+			CStdioFile file;
+			if(file.Open(csFile, CFile::modeRead|CFile::typeText))
+			{
+				CString csVersion;
+				if(file.ReadString(csVersion))
+				{
+					file.Close();		
+					lReturn = atol(csVersion);
+				}
+			}
+		}
+	}
+	catch(CInternetException *pEX)
+	{
+		bError = true;	
+		pEX->Delete();
+	}
+	catch(CFileException *e)
+	{
+		bError = true;
+		e->Delete();
+	}
+	catch(...)
+	{
+		bError = true;
+		csFile.Empty();
+	}
+
+	if(bError)
+	{
+		if(m_bShowMessages)
+		{
+			MessageBox(m_hParent, "Error Connecting.", "Ditto", MB_OK);
+			m_bShowMessages = FALSE;
+		}
+	}
+	
+	if(remotefile)
+	{
+		remotefile->Close();
+
+		delete remotefile;
+		remotefile = NULL;
+	}
+
+	if(access(csFile, 0) != -1)
+		CFile::Remove(csFile);
+
+	return lReturn;
+}
+
+CString CInternetUpdate::DownloadUpdate()
+{
+	char httpbuff[HTTPBUFLEN];
+	
+	//Try to get a path from the regestry
+	CString csPath = CGetSetOptions::GetUpdateInstallPath();
+
+	//if nothing there get the default
+	if(csPath.IsEmpty())
+		csPath = "sabrogden.0Catch.com/DittoSetup.exe";
+
+	CString csUrl = "http://" + csPath;
+	
+	CString csFile = CGetSetOptions::GetExeFileName();
+	csFile = GetFilePath(csFile);
+	csFile += "DittoSetup.exe";
+
+	long lReturn = -1;
+	CHttpFile	*RemoteFile = NULL;
+
+	try
+	{
+		CInternetSession mysession;
+
+		RemoteFile = (CHttpFile*)mysession.OpenURL(csUrl,1,INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_RELOAD);
+		if(!RemoteFile)
+			return "";
+
+		//Get the file size
+		DWORD		dFileSize;
+		RemoteFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, dFileSize);
+
+		//Set up the progress wnd
+		CProgressWnd progress;
+		progress.Create(CWnd::FromHandlePermanent(m_hParent), "Ditto Update");
+		progress.SetRange(0, dFileSize, HTTPBUFLEN);
+		progress.SetText("Downloading Ditto Update ...");
+		
+		//Create the file to put the info in
+		CFile myfile(csFile, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
+		
+		UINT unBytesRead = 0;
+		UINT unTotalBytes = 0;
+		
+		//Read in the file
+		while (unBytesRead = RemoteFile->Read(httpbuff, HTTPBUFLEN))
+		{
+			progress.StepIt();
+			progress.PeekAndPump();
+			if(progress.Cancelled())
+			{
+				csFile.Empty();
+				break;
+			}
+			
+			unTotalBytes += unBytesRead;
+			myfile.Write(httpbuff, unBytesRead);
+
+			if(!RemoteFile)
+			{
+				MessageBox(m_hParent, "Error Downloading update.", "Ditto", MB_OK);
+				csFile = "";
+				break;
+			}
+		}
+				
+		myfile.Close();
+	}
+	catch(CInternetException *pEX)
+	{
+		MessageBox(m_hParent, "Error Downloading update.", "Ditto", MB_OK);
+		csFile.Empty();
+		pEX->Delete();
+	}
+	catch(CFileException *e)
+	{
+		MessageBox(m_hParent, "Error Downloading update.", "Ditto", MB_OK);
+		csFile.Empty();
+		e->Delete();
+	}
+	catch(...)
+	{
+		MessageBox(m_hParent, "Error Downloading update.", "Ditto", MB_OK);
+		csFile.Empty();
+	}
+
+	if(RemoteFile)
+	{
+		RemoteFile->Close();
+		delete RemoteFile;
+		RemoteFile = NULL;
+	}
+
+	return csFile;
+}

+ 36 - 0
InternetUpdate.h

@@ -0,0 +1,36 @@
+// InternetUpdate.h: interface for the CInternetUpdate class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_INTERNETUPDATE_H__0ED6CFE4_1E10_4D32_93A1_1C5CC1FDA3D2__INCLUDED_)
+#define AFX_INTERNETUPDATE_H__0ED6CFE4_1E10_4D32_93A1_1C5CC1FDA3D2__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CInternetUpdate  
+{
+public:
+	CInternetUpdate();
+	virtual ~CInternetUpdate();
+
+	BOOL CheckForUpdate(HWND hParent, BOOL bCheckForPrevUpdate, BOOL bShowNoUpdatesDlg);
+
+	long GetRunningVersion();
+	long GetUpdateVersion();
+
+	CString GetVersionString(long lVersion);
+	CString DownloadUpdate();
+	
+protected:
+	long m_lRunningVersion;
+	long m_lUpdateVersion;
+	HWND m_hParent;
+	BOOL m_bShowMessages;
+
+	BOOL RemoveOldUpdateFile();
+
+};
+
+#endif // !defined(AFX_INTERNETUPDATE_H__0ED6CFE4_1E10_4D32_93A1_1C5CC1FDA3D2__INCLUDED_)

+ 381 - 0
MainFrm.cpp

@@ -0,0 +1,381 @@
+// MainFrm.cpp : implementation of the CMainFrame class
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "MainFrm.h"
+#include "afxole.h"
+#include "Misc.h"
+#include "CopyProperties.h"
+#include "InternetUpdate.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define	WM_ICON_NOTIFY			WM_APP+10
+
+#define ONE_MINUTE				60000
+
+#define KILL_DB_TIMER				1
+#define HIDE_ICON_TIMER				2
+#define REMOVE_OLD_ENTRIES_TIMER	3
+#define CHECK_FOR_UPDATE			4
+#define CLOSE_APP					5
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame
+
+
+IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
+
+BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
+	//{{AFX_MSG_MAP(CMainFrame)
+	ON_WM_CREATE()
+	ON_COMMAND(ID_FIRST_OPTION, OnFirstOption)
+	ON_COMMAND(ID_FIRST_EXIT, OnFirstExit)
+	ON_WM_CHANGECBCHAIN()
+	ON_WM_DRAWCLIPBOARD()
+	ON_WM_TIMER()
+	ON_COMMAND(ID_FIRST_SHOWQUICKPASTE, OnFirstShowquickpaste)
+	ON_COMMAND(ID_FIRST_RECONNECTTOCLIPBOARDCHAIN, OnFirstReconnecttoclipboardchain)
+	ON_UPDATE_COMMAND_UI(ID_FIRST_RECONNECTTOCLIPBOARDCHAIN, OnUpdateFirstReconnecttoclipboardchain)
+	//}}AFX_MSG_MAP
+	ON_MESSAGE(WM_HOTKEY, OnHotKey)
+	ON_MESSAGE(WM_SHOW_TRAY_ICON, OnShowTrayIcon)
+	ON_MESSAGE(WM_RECONNECT_TO_COPY_CHAIN, OnReconnectToCopyChain)
+	ON_MESSAGE(WM_IS_TOP_VIEWER, OnGetIsTopView)
+	ON_MESSAGE(WM_COPYPROPERTIES, OnCopyProperties)
+	ON_MESSAGE(WM_CLOSE_APP, OnShutDown)
+END_MESSAGE_MAP()
+
+static UINT indicators[] =
+{
+	ID_SEPARATOR,           // status line indicator
+	ID_INDICATOR_CAPS,
+	ID_INDICATOR_NUM,
+	ID_INDICATOR_SCRL,
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame construction/destruction
+
+CMainFrame::CMainFrame()
+{
+}
+
+CMainFrame::~CMainFrame()
+{
+	if(m_hNextClipboardViewer)
+	{
+		if(::IsWindow(m_hNextClipboardViewer))
+			ChangeClipboardChain(m_hNextClipboardViewer);
+	}
+
+	CGetSetOptions::SetMainHWND(0);
+}
+
+int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	SetWindowText(MAIN_WND_TITLE);
+
+	HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+
+	m_TrayIcon.Create(
+						NULL,				// Let icon deal with its own messages
+						WM_ICON_NOTIFY,	// Icon notify message to use
+						_T("Ditto"),	// tooltip
+						hIcon,
+						IDR_MENU,			// ID of tray icon
+						FALSE,
+						_T(""),			// balloon tip
+						_T(""),			// balloon title
+						NULL,				// balloon icon
+						20 );
+
+
+	m_TrayIcon.MinimiseToTray(this);
+	m_TrayIcon.SetMenuDefaultItem(ID_FIRST_SHOWQUICKPASTE, FALSE);
+
+	//Only if in release
+	#ifndef _DEBUG
+	{
+		//If not showing the icon show it for 40 seconds so they can get to the option
+		//in case they can't remember the hot keys or something like that
+		if(!(CGetSetOptions::GetShowIconInSysTray()))
+			SetTimer(HIDE_ICON_TIMER, 40000, 0);
+	}
+	#endif
+
+	SetTimer(CHECK_FOR_UPDATE, ONE_MINUTE*5, 0);
+	SetTimer(REMOVE_OLD_ENTRIES_TIMER, ONE_MINUTE*2, 0);
+
+	m_ulCopyGap = CGetSetOptions::GetCopyGap();
+
+	//Set up the clip board viewer
+	theApp.m_bHandleClipboardDataChange = false;
+    m_hNextClipboardViewer = SetClipboardViewer();
+    theApp.m_bHandleClipboardDataChange = true;
+	
+	theApp.m_MainhWnd = m_hWnd;
+
+	CGetSetOptions::SetMainHWND((long)m_hWnd);
+
+	//Set up the hot key
+	CGetSetOptions::RegisterHotKey(theApp.m_MainhWnd, 
+									CGetSetOptions::GetHotKey(), 
+									theApp.m_atomHotKey);
+
+	CGetSetOptions::RegisterHotKey(theApp.m_MainhWnd, 
+									CGetSetOptions::GetNamedCopyHotKey(), 
+									theApp.m_atomNamedCopy);
+
+	return 0;
+}
+
+BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
+{
+	if( !CFrameWnd::PreCreateWindow(cs) )
+		return FALSE;
+
+	WNDCLASS wc;	
+	wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+	wc.lpfnWndProc = AfxWndProc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hInstance = AfxGetInstanceHandle();
+	wc.hIcon = NULL;
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+	wc.lpszMenuName =  NULL;
+	wc.lpszClassName = "Ditto";
+
+	// Create the QPaste window class
+	if (!AfxRegisterClass(&wc))
+		return FALSE;
+
+	cs.lpszClass = wc.lpszClassName;
+	
+	return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame diagnostics
+
+#ifdef _DEBUG
+void CMainFrame::AssertValid() const
+{
+	CFrameWnd::AssertValid();
+}
+
+void CMainFrame::Dump(CDumpContext& dc) const
+{
+	CFrameWnd::Dump(dc);
+}
+
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame message handlers
+
+
+void CMainFrame::OnFirstOption() 
+{
+	DoOptions(this);	
+}
+
+void CMainFrame::OnFirstExit() 
+{
+	this->SendMessage(WM_CLOSE, 0, 0);
+}
+
+LRESULT CMainFrame::OnHotKey(WPARAM wParam, LPARAM lParam)
+{
+	if(wParam == theApp.m_atomHotKey)
+	{
+		QuickPaste.ShowQPasteWnd(this);
+	}
+	else if(wParam == theApp.m_atomNamedCopy)
+	{
+		theApp.ShowCopyProperties = true;
+
+		//Simulate the Copy
+		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
+		keybd_event('C', 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
+     
+		keybd_event('C', 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+	}
+
+	return TRUE;
+}
+
+void CMainFrame::OnChangeCbChain(HWND hWndRemove, HWND hWndAfter) 
+{
+    // If the next window in the chain is being removed, reset our
+    // "next window" handle.
+	if(m_hNextClipboardViewer == hWndRemove)
+    {
+		m_hNextClipboardViewer = hWndAfter;
+    }
+	// If there is a next clipboard viewer, pass the message on to it.
+	else if (m_hNextClipboardViewer != NULL)
+    {
+		::SendMessage ( m_hNextClipboardViewer, WM_CHANGECBCHAIN, 
+						(WPARAM) hWndRemove, (LPARAM) hWndAfter );
+    }
+}
+
+//Message that the clipboard data has changed
+void CMainFrame::OnDrawClipboard() 
+{
+	if(!theApp.m_bHandleClipboardDataChange)
+		return;
+
+	m_Copy.DoCopy();
+
+	if (m_hNextClipboardViewer != NULL)
+		::SendMessage(m_hNextClipboardViewer, WM_DRAWCLIPBOARD, 0, 0);	
+}
+
+void CMainFrame::OnTimer(UINT nIDEvent) 
+{
+	if(nIDEvent == HIDE_ICON_TIMER)
+	{
+		m_TrayIcon.HideIcon();
+		KillTimer(nIDEvent);
+	}
+	else if(nIDEvent == KILL_DB_TIMER)
+	{
+		if(QuickPaste.CloseQPasteWnd())
+		{
+			theApp.CloseDB();
+			AfxDaoTerm();
+			KillTimer(KILL_DB_TIMER);
+		}
+	}
+	else if(nIDEvent == REMOVE_OLD_ENTRIES_TIMER)
+	{
+		RemoveOldEntries();
+		KillTimer(REMOVE_OLD_ENTRIES_TIMER);
+	}
+	else if(nIDEvent == CHECK_FOR_UPDATE)
+	{
+		CInternetUpdate Update;
+		if(Update.CheckForUpdate(NULL, TRUE, FALSE))
+		{
+			SendMessage(WM_CLOSE, 0, 0);
+		}
+
+		KillTimer(CHECK_FOR_UPDATE);
+	}
+	else if(nIDEvent == CLOSE_APP)
+	{
+		if(theApp.m_bShowingOptions == false)
+		{
+			PostMessage(WM_CLOSE, 0, 0);
+			KillTimer(CLOSE_APP);
+		}
+	}
+	
+	CFrameWnd::OnTimer(nIDEvent);
+}
+
+LRESULT CMainFrame::OnShowTrayIcon(WPARAM wParam, LPARAM lParam)
+{
+	if(lParam)
+	{
+		if(!m_TrayIcon.Visible())
+		{
+			KillTimer(HIDE_ICON_TIMER);
+			SetTimer(HIDE_ICON_TIMER, 40000, 0);
+		}
+	}
+
+	if(wParam)
+		m_TrayIcon.ShowIcon();
+	else 
+		m_TrayIcon.HideIcon();
+
+	return TRUE;
+}
+
+void CMainFrame::OnFirstShowquickpaste() 
+{
+	QuickPaste.ShowQPasteWnd(this, TRUE);
+}
+
+LRESULT CMainFrame::OnReconnectToCopyChain(WPARAM wParam, LPARAM lParam)
+{
+	if(GetClipboardViewer() != this)
+	{
+		//Remove it from the change
+		ChangeClipboardChain(m_hNextClipboardViewer);
+		
+		//reset it as the top viewer
+		m_bCallingSetClipboardViewer = TRUE;
+		m_hNextClipboardViewer = SetClipboardViewer();
+		m_bCallingSetClipboardViewer = FALSE;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+void CMainFrame::OnFirstReconnecttoclipboardchain() 
+{
+	OnReconnectToCopyChain(0, 0);
+}
+
+void CMainFrame::OnUpdateFirstReconnecttoclipboardchain(CCmdUI* pCmdUI) 
+{
+	if(GetClipboardViewer() == this)
+		pCmdUI->m_pMenu->DeleteMenu(ID_FIRST_RECONNECTTOCLIPBOARDCHAIN, MF_BYCOMMAND);
+}
+
+LRESULT CMainFrame::OnGetIsTopView(WPARAM wParam, LPARAM lParam)
+{
+	return (GetClipboardViewer() == this);
+}
+
+BOOL CMainFrame::ResetKillDBTimer()
+{
+	KillTimer(KILL_DB_TIMER);
+	
+	SetTimer(KILL_DB_TIMER, ONE_MINUTE*2, NULL);
+
+	return TRUE;
+}
+
+LRESULT CMainFrame::OnCopyProperties(WPARAM wParam, LPARAM lParam)
+{
+	long lID = (long)wParam;
+
+	if(lID > 0)
+	{
+		theApp.m_bHandleClipboardDataChange = false;
+		theApp.m_bShowingOptions = true;
+
+		CCopyProperties props(lID, this);
+		props.SetHideOnKillFocus(true);
+		props.DoModal();
+
+		theApp.m_bHandleClipboardDataChange = true;
+		theApp.m_bShowingOptions = false;
+	}
+
+	return TRUE;
+}
+
+LRESULT CMainFrame::OnShutDown(WPARAM wParam, LPARAM lParam)
+{
+	SetTimer(CLOSE_APP, 100, NULL);
+
+	return TRUE;
+}

+ 83 - 0
MainFrm.h

@@ -0,0 +1,83 @@
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MAINFRM_H__147283E8_5032_4C0A_9828_1CC59DECFD62__INCLUDED_)
+#define AFX_MAINFRM_H__147283E8_5032_4C0A_9828_1CC59DECFD62__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "SystemTray.h"
+#include "QuickPaste.h"
+
+class CMainFrame : public CFrameWnd
+{
+public:
+	CMainFrame();
+protected: 
+	DECLARE_DYNAMIC(CMainFrame)
+
+// Attributes
+public:
+
+// Operations
+public:
+
+	BOOL ResetKillDBTimer();
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CMainFrame)
+	public:
+	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+//	virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
+	//}}AFX_VIRTUAL
+
+// Implementation
+public:
+	virtual ~CMainFrame();
+#ifdef _DEBUG
+	virtual void AssertValid() const;
+	virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+	CSystemTray m_TrayIcon;
+	HWND m_hNextClipboardViewer;
+	BOOL m_bCallingSetClipboardViewer;
+	
+	CQuickPaste QuickPaste;
+	CProcessCopy m_Copy;
+
+	ULONG m_ulCopyGap;
+
+// Generated message map functions
+protected:
+	//{{AFX_MSG(CMainFrame)
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnFirstOption();
+	afx_msg void OnFirstExit();
+	afx_msg void OnChangeCbChain(HWND hWndRemove, HWND hWndAfter);
+	afx_msg void OnDrawClipboard();
+	afx_msg void OnTimer(UINT nIDEvent);
+	afx_msg void OnFirstShowquickpaste();
+	afx_msg void OnFirstReconnecttoclipboardchain();
+	afx_msg void OnUpdateFirstReconnecttoclipboardchain(CCmdUI* pCmdUI);
+	//}}AFX_MSG
+	afx_msg LRESULT OnHotKey(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnShowTrayIcon(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnReconnectToCopyChain(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnGetIsTopView(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnCopyProperties(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnShutDown(WPARAM wParam, LPARAM lParam);
+	DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINFRM_H__147283E8_5032_4C0A_9828_1CC59DECFD62__INCLUDED_)

+ 200 - 0
MainTable.cpp

@@ -0,0 +1,200 @@
+// MainTable.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "MainTable.h"
+#include "DatabaseUtilities.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainTable
+
+IMPLEMENT_DYNAMIC(CMainTable, CDaoRecordset)
+
+CMainTable::CMainTable(CDaoDatabase* pdb)
+	: CDaoRecordset(pdb)
+{
+	//{{AFX_FIELD_INIT(CMainTable)
+	m_lID = 0;
+	m_lDate = 0;
+	m_strType = _T("");
+	m_strText = _T("");
+	m_lShortCut = 0;
+	m_lDontAutoDelete = 0;
+	m_lTotalCopySize = 0;
+
+	m_nFields = 7;
+	//}}AFX_FIELD_INIT
+	m_nDefaultType = dbOpenDynaset;
+}
+
+CString CMainTable::GetDefaultDBName()
+{
+	return GetDBName();
+}
+
+CString CMainTable::GetDefaultSQL()
+{
+	return _T("[Main]");
+}
+
+void CMainTable::DoFieldExchange(CDaoFieldExchange* pFX)
+{
+	//{{AFX_FIELD_MAP(CMainTable)
+	pFX->SetFieldType(CDaoFieldExchange::outputColumn);
+	DFX_Long(pFX, _T("[lID]"), m_lID);
+	DFX_Long(pFX, _T("[lDate]"), m_lDate);
+	DFX_Text(pFX, _T("[strType]"), m_strType);
+	DFX_Text(pFX, _T("[strText]"), m_strText);
+	DFX_Long(pFX, _T("[lShortCut]"), m_lShortCut);
+	DFX_Long(pFX, _T("[lDontAutoDelete]"), m_lDontAutoDelete);
+	DFX_Long(pFX, _T("[lTotalCopySize]"), m_lTotalCopySize);
+	//}}AFX_FIELD_MAP
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainTable diagnostics
+
+#ifdef _DEBUG
+void CMainTable::AssertValid() const
+{
+	CDaoRecordset::AssertValid();
+}
+
+void CMainTable::Dump(CDumpContext& dc) const
+{
+	CDaoRecordset::Dump(dc);
+}
+#endif //_DEBUG
+
+BOOL CMainTable::DeleteAll()
+{
+	BOOL bRet = FALSE;
+	try
+	{
+		theApp.EnsureOpenDB();
+		theApp.m_pDatabase->Execute("DELETE * FROM Main", dbFailOnError);
+		bRet = TRUE;
+	}
+	catch(CDaoException* e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		e->Delete();
+	}
+
+	return bRet;
+}
+
+BOOL CMainTable::DeleteRows(ARRAY &IDs)
+{
+	if(IDs.GetSize() <= 0)
+		return FALSE;
+
+	CString csMainSQL = "DELETE FROM Main WHERE";
+	CString csDataSQL = "DELETE FROM Data WHERE";
+	CString csMainFormat;
+
+	csMainFormat.Format(" lID = %d", IDs[0]);
+	csMainSQL += csMainFormat;
+
+	csMainFormat.Format(" lParentID = %d", IDs[0]);
+	csDataSQL += csMainFormat;
+
+	for(int i = 1; i < IDs.GetSize(); i++)
+	{
+		csMainFormat.Format(" Or lID = %d", IDs[i]);
+		csMainSQL += csMainFormat;
+
+		csMainFormat.Format(" Or lParentID = %d", IDs[i]);
+		csDataSQL += csMainFormat;
+	}
+		
+	BOOL bRet = TRUE;
+
+	try
+	{
+		theApp.EnsureOpenDB();
+		theApp.m_pDatabase->Execute(csMainSQL, dbFailOnError);
+	}
+	catch(CDaoException* e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		e->Delete();
+		bRet = FALSE;
+	}
+
+	if(bRet)
+	{
+		try
+		{
+			theApp.EnsureOpenDB();
+			theApp.m_pDatabase->Execute(csDataSQL, dbFailOnError);
+		}
+		catch(CDaoException* e)
+		{
+			AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+			e->Delete();
+			bRet = FALSE;
+		}
+	}
+	
+	return bRet;
+}
+
+HACCEL CMainTable::LoadAcceleratorKeys()
+{
+	CMainTable recset;
+
+	try
+	{
+		recset.Open("SELECT * FROM Main WHERE lShortCut > 0");
+		
+		CArray<ACCEL, ACCEL> keys;
+
+		while(!recset.IsEOF())
+		{
+			ACCEL me;
+			me.cmd = (USHORT)recset.m_lID;
+			me.fVirt = 0;
+			if( HIBYTE(recset.m_lShortCut) & HOTKEYF_SHIFT )   me.fVirt |= FSHIFT;
+			if( HIBYTE(recset.m_lShortCut) & HOTKEYF_CONTROL ) me.fVirt |= FCONTROL;
+			if( HIBYTE(recset.m_lShortCut) & HOTKEYF_ALT )     me.fVirt |= FALT;	
+			me.fVirt |= FVIRTKEY;
+			me.key = LOBYTE(recset.m_lShortCut);
+
+			keys.Add(me);
+
+			recset.MoveNext();
+		}
+
+		if(keys.GetSize() > 0)
+			return CreateAcceleratorTable(keys.GetData(), keys.GetSize());
+	}
+	catch(CDaoException* e)
+	{
+		e->Delete();
+	}
+
+	return NULL;
+}
+
+void CMainTable::Open(LPCTSTR lpszFormat,...) 
+{
+	m_pDatabase = theApp.EnsureOpenDB();
+
+	CString csText;
+	va_list vlist;
+
+	ASSERT(AfxIsValidString(lpszFormat));
+	va_start(vlist,lpszFormat);
+	csText.FormatV(lpszFormat,vlist);
+	va_end(vlist);
+	
+	CDaoRecordset::Open(AFX_DAO_USE_DEFAULT_TYPE, csText, 0);
+}

+ 53 - 0
MainTable.h

@@ -0,0 +1,53 @@
+#if !defined(AFX_MAINTABLE_H__F5CFB0A6_A6E1_4C55_A685_AB5F1A0FCF53__INCLUDED_)
+#define AFX_MAINTABLE_H__F5CFB0A6_A6E1_4C55_A685_AB5F1A0FCF53__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+#include "ArrayEx.h"
+
+class CMainTable : public CDaoRecordset
+{
+public:
+	CMainTable(CDaoDatabase* pDatabase = NULL);
+	DECLARE_DYNAMIC(CMainTable)
+
+
+// Field/Param Data
+	//{{AFX_FIELD(CMainTable, CDaoRecordset)
+	long	m_lID;
+	long	m_lDate;
+	CString	m_strType;
+	CString	m_strText;
+	long	m_lShortCut;
+	long	m_lDontAutoDelete;
+	long	m_lTotalCopySize;
+	//}}AFX_FIELD
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CMainTable)
+	public:
+	virtual CString GetDefaultDBName();		// Default database name
+	virtual CString GetDefaultSQL();		// Default SQL for Recordset
+	virtual void DoFieldExchange(CDaoFieldExchange* pFX);  // RFX support
+	//}}AFX_VIRTUAL
+
+public:
+	BOOL DeleteRows(ARRAY &IDs);
+	BOOL DeleteAll();
+	static HACCEL LoadAcceleratorKeys();
+	void Open(LPCTSTR lpszFormat,...);
+
+
+// Implementation
+#ifdef _DEBUG
+	virtual void AssertValid() const;
+	virtual void Dump(CDumpContext& dc) const;
+#endif
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINTABLE_H__F5CFB0A6_A6E1_4C55_A685_AB5F1A0FCF53__INCLUDED_)

+ 636 - 0
Misc.cpp

@@ -0,0 +1,636 @@
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "Misc.h"
+#include "OptionsSheet.h"
+
+#ifdef AFTER_98
+	#include "AlphaBlend.h"
+#endif
+
+
+long DoOptions(CWnd *pParent)
+{
+	//Don't let it open up more than once
+	if(theApp.m_bShowingOptions)
+		return FALSE;
+
+	theApp.m_bShowingOptions = true;
+	
+	COptionsSheet Sheet("Copy Pro Options", pParent);
+
+	int nRet = Sheet.DoModal();
+
+	theApp.m_bShowingOptions = false;
+
+	return nRet;
+}
+
+HWND GetActiveWnd(CPoint *pPointCaret)
+{
+	HWND hWndFocus = NULL;
+	if (pPointCaret)
+		*pPointCaret = CPoint(-1, -1);
+	
+	HWND hWndForground = GetForegroundWindow(); // Get the desktop's foreground window
+	if (hWndForground != NULL)
+	{
+		DWORD ProcID;
+		DWORD ThreadID = GetWindowThreadProcessId(hWndForground, &ProcID);
+		
+		// Attach other thread's message queue to our own to ensure GetFocus() is working properly
+		BOOL ARes = AttachThreadInput(ThreadID, GetCurrentThreadId(), TRUE);
+		if (ARes)
+		{
+			// Get the other thread's focussed window
+			CWnd *pWnd = CWnd::FromHandle(hWndForground);
+
+			if (pWnd)
+			{
+				CWnd *pWndFocus = pWnd->GetFocus();
+				if (pWndFocus)
+				{
+					hWndFocus = pWndFocus->m_hWnd;
+					if (pPointCaret)
+					{
+						*pPointCaret = pWndFocus->GetCaretPos();
+						pWndFocus->ClientToScreen(pPointCaret);
+					}
+				}
+			}
+
+			// Detach other thread's message queue from our own again
+			ARes = AttachThreadInput(ThreadID, GetCurrentThreadId(), FALSE);
+		}
+	}
+
+	return hWndFocus;
+}
+
+
+//Do not change these these are stored in the database
+CLIPFORMAT GetFormatID(LPCSTR cbName)
+{
+	if(strcmp(cbName, "CF_TEXT") == 0)
+		return CF_TEXT;
+	else if(strcmp(cbName, "CF_METAFILEPICT") == 0)
+		return CF_METAFILEPICT;
+	else if(strcmp(cbName, "CF_SYLK") == 0)
+		return CF_SYLK;
+	else if(strcmp(cbName, "CF_DIF") == 0)
+		return CF_DIF;
+	else if(strcmp(cbName, "CF_TIFF") == 0)
+		return CF_TIFF;
+	else if(strcmp(cbName, "CF_OEMTEXT") == 0)
+		return CF_OEMTEXT;
+	else if(strcmp(cbName, "CF_DIB") == 0)
+		return CF_DIB;
+	else if(strcmp(cbName, "CF_PALETTE") == 0)
+		return CF_PALETTE;
+	else if(strcmp(cbName, "CF_PENDATA") == 0)
+		return CF_PENDATA;
+	else if(strcmp(cbName, "CF_RIFF") == 0)
+		return CF_RIFF;
+	else if(strcmp(cbName, "CF_WAVE") == 0)
+		return CF_WAVE;
+	else if(strcmp(cbName, "CF_UNICODETEXT") == 0)
+		return CF_UNICODETEXT;
+	else if(strcmp(cbName, "CF_ENHMETAFILE") == 0)
+		return CF_ENHMETAFILE;
+	else if(strcmp(cbName, "CF_HDROP") == 0)
+		return CF_HDROP;
+	else if(strcmp(cbName, "CF_LOCALE") == 0)
+		return CF_LOCALE;
+	else if(strcmp(cbName, "CF_OWNERDISPLAY") == 0)
+		return CF_OWNERDISPLAY;
+	else if(strcmp(cbName, "CF_DSPTEXT") == 0)
+		return CF_DSPTEXT;
+	else if(strcmp(cbName, "CF_DSPBITMAP") == 0)
+		return CF_DSPBITMAP;
+	else if(strcmp(cbName, "CF_DSPMETAFILEPICT") == 0)
+		return CF_DSPMETAFILEPICT;
+	else if(strcmp(cbName, "CF_DSPENHMETAFILE") == 0)
+		return CF_DSPENHMETAFILE;
+	
+	
+	return ::RegisterClipboardFormat(cbName);
+}
+
+//Do not change these these are stored in the database
+CString GetFormatName(CLIPFORMAT cbType)
+{
+	switch(cbType)
+	{
+	case CF_TEXT:
+		return "CF_TEXT";
+	case CF_BITMAP:
+		return "CF_BITMAP";
+	case CF_METAFILEPICT:
+		return "CF_METAFILEPICT";
+	case CF_SYLK:
+		return "CF_SYLK";
+	case CF_DIF:
+		return "CF_DIF";
+	case CF_TIFF:
+		return "CF_TIFF";
+	case CF_OEMTEXT:
+		return "CF_OEMTEXT";
+	case CF_DIB:
+		return "CF_DIB";
+	case CF_PALETTE:
+		return "CF_PALETTE";
+	case CF_PENDATA:
+		return "CF_PENDATA";
+	case CF_RIFF:
+		return "CF_RIFF";
+	case CF_WAVE:
+		return "CF_WAVE";
+	case CF_UNICODETEXT:
+		return "CF_UNICODETEXT";
+	case CF_ENHMETAFILE:
+		return "CF_ENHMETAFILE";
+	case CF_HDROP:
+		return "CF_HDROP";
+	case CF_LOCALE:
+		return "CF_LOCALE";
+	case CF_OWNERDISPLAY:
+		return "CF_OWNERDISPLAY";
+	case CF_DSPTEXT:
+		return "CF_DSPTEXT";
+	case CF_DSPBITMAP:
+		return "CF_DSPBITMAP";
+	case CF_DSPMETAFILEPICT:
+		return "CF_DSPMETAFILEPICT";
+	case CF_DSPENHMETAFILE:
+		return "CF_DSPENHMETAFILE";
+	default:
+	{
+		//Not a default type get the name from the clipboard
+		if (cbType != 0)
+		{
+			TCHAR szFormat[256];
+            GetClipboardFormatName(cbType, szFormat, 256);
+			return szFormat;
+		}
+		break;
+	}
+	}
+
+	return "ERROR";
+}
+
+CString GetFilePath(CString csFileName)
+{
+	long lSlash = csFileName.ReverseFind('\\');
+			
+	if(lSlash > -1)
+	{
+		csFileName = csFileName.Left(lSlash + 1);
+	}
+
+	return csFileName;
+}
+
+CGetSetOptions::CGetSetOptions()
+{
+
+}
+
+CGetSetOptions::~CGetSetOptions()
+{
+
+}
+
+long CGetSetOptions::GetProfileLong(CString csName, long bDefaultValue)
+{
+	HKEY hkKey;
+
+	long lResult = RegOpenKeyEx(HKEY_CURRENT_USER, _T(REG_PATH),
+								NULL, KEY_READ, &hkKey);
+	
+	if(lResult != ERROR_SUCCESS)
+		return bDefaultValue;
+
+	DWORD buffer;
+	DWORD len =  sizeof(buffer);
+	DWORD type;
+
+	lResult = ::RegQueryValueEx(hkKey, csName, 0, &type, (LPBYTE)&buffer, &len);
+	
+	RegCloseKey(hkKey);
+	
+	if(lResult == ERROR_SUCCESS)
+		return (long)buffer;
+
+	return bDefaultValue;
+}
+
+CString CGetSetOptions::GetProfileString(CString csName, CString csDefault)
+{
+	HKEY hkKey;
+
+	long lResult = RegOpenKeyEx(HKEY_CURRENT_USER, _T(REG_PATH),
+								NULL, KEY_READ, &hkKey);
+	
+	char szString[256];
+	DWORD dwBufLen = 256;
+	
+	lResult = ::RegQueryValueEx(hkKey , csName, NULL, NULL, (LPBYTE)szString, &dwBufLen);
+
+	if(lResult != ERROR_SUCCESS)
+		return csDefault;
+
+	return CString(szString);
+}
+
+BOOL CGetSetOptions::SetProfileLong(CString csName, long lValue)
+{
+	HKEY hkKey;
+	DWORD dWord;
+	long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, _T(REG_PATH), NULL, 
+						NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 
+						NULL, &hkKey, &dWord);
+
+	if(lResult != ERROR_SUCCESS)
+		return FALSE;
+
+	DWORD val = (DWORD)lValue;
+	lResult = ::RegSetValueEx(hkKey, csName, 0, REG_DWORD, (LPBYTE)&val, sizeof(DWORD));
+
+	RegCloseKey(hkKey);
+
+	return lResult == ERROR_SUCCESS;
+}
+
+BOOL CGetSetOptions::SetProfileString(CString csName, CString csValue)
+{
+	HKEY hkKey;
+	DWORD dWord;
+	long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, _T(REG_PATH), NULL, 
+						NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 
+						NULL, &hkKey, &dWord);
+
+	if(lResult != ERROR_SUCCESS)
+		return FALSE;
+
+	::RegSetValueEx(hkKey, csName, NULL, REG_SZ,
+			(BYTE*)(LPCTSTR)csValue, csValue.GetLength()+sizeof(TCHAR));
+
+	RegCloseKey(hkKey);
+
+	return lResult == ERROR_SUCCESS;
+}
+
+BOOL CGetSetOptions::GetShowIconInSysTray() 
+{
+	return GetProfileLong("ShowIconInSystemTray", TRUE);
+}
+
+BOOL CGetSetOptions::SetShowIconInSysTray(BOOL bShow) 
+{
+	return SetProfileLong("ShowIconInSystemTray", bShow);
+}
+
+DWORD CGetSetOptions::GetHotKey() 
+{
+	//704 is ctrl-tilda
+	return (DWORD)GetProfileLong("HotKey", 704);
+}
+
+BOOL CGetSetOptions::SetHotKey(DWORD dwHotKey) 
+{
+	return SetProfileLong("HotKey", dwHotKey);
+}
+
+DWORD CGetSetOptions::GetNamedCopyHotKey() 
+{
+	return (DWORD)GetProfileLong("NamedCopyHotKey", 0);
+}
+
+BOOL CGetSetOptions::SetNamedCopyHotKey(long lHotKey) 
+{
+	return SetProfileLong("NamedCopyHotKey", lHotKey);
+}
+
+BOOL CGetSetOptions::SetEnableTransparency(BOOL bCheck)
+{
+	return SetProfileLong("EnableTransparency", bCheck);
+}
+
+BOOL CGetSetOptions::GetEnableTransparency()
+{
+	return GetProfileLong("EnableTransparency", FALSE);
+}
+
+BOOL CGetSetOptions::SetTransparencyPercent(long lPercent)
+{
+	#ifdef AFTER_98
+		if(lPercent > OPACITY_MAX)
+			lPercent = OPACITY_MAX;
+		if(lPercent < 0)
+			lPercent = 0;
+
+		return SetProfileLong("TransparencyPercent", lPercent);
+	#endif
+		return FALSE;
+}
+
+long CGetSetOptions::GetTransparencyPercent()
+{
+	#ifdef AFTER_98
+		long lValue = GetProfileLong("TransparencyPercent", 14);
+
+		if(lValue > OPACITY_MAX) lValue = OPACITY_MAX;
+		if(lValue < 0) lValue = 0;
+
+		return lValue;
+	#endif
+		return 0;
+}
+
+BOOL CGetSetOptions::SetLinesPerRow(long lLines)
+{
+	return SetProfileLong("LinesPerRow", lLines);
+}
+
+long CGetSetOptions::GetLinesPerRow()
+{
+	return GetProfileLong("LinesPerRow", 2);
+}
+
+BOOL CGetSetOptions::GetRunOnStartUp()
+{
+	HKEY hkRun;
+	
+	LONG nResult = RegOpenKeyEx(HKEY_CURRENT_USER,
+		_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
+		NULL, KEY_READ, &hkRun);
+	
+	if(nResult != ERROR_SUCCESS)
+		return FALSE;
+
+	nResult = RegQueryValueEx(hkRun, GetAppName(), NULL, NULL, NULL, NULL);
+	RegCloseKey(hkRun);
+	return nResult == ERROR_SUCCESS;
+}
+
+void CGetSetOptions::SetRunOnStartUp(BOOL bRun)
+{
+	if(bRun == GetRunOnStartUp())
+		return;
+
+	HKEY hkRun;
+	LONG nResult = RegOpenKeyEx(HKEY_CURRENT_USER,
+		_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
+		NULL, KEY_ALL_ACCESS, &hkRun);
+
+	if(nResult != ERROR_SUCCESS)
+		return;
+
+	if(bRun)
+	{
+		CString sExeName = GetExeFileName();
+		::RegSetValueEx(hkRun, GetAppName(), NULL, REG_SZ,
+			(BYTE*)(LPCTSTR)sExeName, sExeName.GetLength()+sizeof(TCHAR));
+	} 
+	else 
+	{
+		::RegDeleteValue(hkRun, GetAppName());
+	}
+
+	::RegCloseKey(hkRun);
+}
+
+CString CGetSetOptions::GetExeFileName()
+{
+	CString sExeName;
+	GetModuleFileName(NULL, sExeName.GetBuffer(_MAX_PATH),_MAX_PATH);
+	sExeName.ReleaseBuffer();
+	return sExeName;
+}
+
+CString CGetSetOptions::GetAppName()
+{
+	return "Ditto";
+}
+
+BOOL CGetSetOptions::SetQuickPastePosition(long lPosition)
+{
+	return SetProfileLong("ShowQuickPastePosition", lPosition);
+}
+
+long CGetSetOptions::GetQuickPastePosition()
+{
+	return GetProfileLong("ShowQuickPastePosition", POS_AT_PREVIOUS);
+}
+
+BOOL CGetSetOptions::RegisterHotKey(HWND hWnd, DWORD wHotKey, ATOM atomID)
+{
+	if(wHotKey == 0)
+		return FALSE;
+
+	return ::RegisterHotKey(hWnd, atomID, GetModifier(wHotKey), LOBYTE(wHotKey));
+}
+
+UINT CGetSetOptions::GetModifier(DWORD wHotKey)
+{
+	UINT uMod = 0;
+	if( HIBYTE(wHotKey) & HOTKEYF_SHIFT )   uMod |= MOD_SHIFT;
+	if( HIBYTE(wHotKey) & HOTKEYF_CONTROL ) uMod |= MOD_CONTROL;
+	if( HIBYTE(wHotKey) & HOTKEYF_ALT )     uMod |= MOD_ALT;
+	if( HIBYTE(wHotKey) & HOTKEYF_EXT )     uMod |= MOD_WIN;
+
+	return uMod;
+}
+
+BOOL CGetSetOptions::SetQuickPasteSize(CSize size)
+{
+	BOOL bRet = SetProfileLong("QuickPasteCX", size.cx);
+	bRet = SetProfileLong("QuickPasteCY", size.cy);
+
+	return bRet;
+}
+void CGetSetOptions::GetQuickPasteSize(CSize &size)
+{
+	size.cx = GetProfileLong("QuickPasteCX", 300);
+	size.cy = GetProfileLong("QuickPasteCY", 300);
+}
+
+BOOL CGetSetOptions::SetQuickPastePoint(CPoint point)
+{
+	BOOL bRet = SetProfileLong("QuickPasteX", point.x);
+	bRet = SetProfileLong("QuickPasteY", point.y);
+
+	return bRet;
+}
+
+void CGetSetOptions::GetQuickPastePoint(CPoint &point)
+{
+	point.x = GetProfileLong("QuickPasteX", 300);
+	point.y = GetProfileLong("QuickPasteY", 300);
+}
+
+long CGetSetOptions::GetCopyGap()
+{
+	return GetProfileLong("CopyGap", 150);
+}
+
+BOOL CGetSetOptions::SetDBPath(CString csPath)
+{
+	return SetProfileString("DBPath", csPath);
+}
+
+CString CGetSetOptions::GetDBPath(BOOL bDefault/* = TRUE*/)
+{
+	//First check the reg string
+	CString csDefaultPath = GetProfileString("DBPath", "");
+
+	//If there is nothing in the regesty then get the default
+	//In the users application data in my documents
+	if(bDefault)
+	{
+		if(csDefaultPath.IsEmpty())
+			csDefaultPath = GetDefaultDBName();
+	}
+		
+	return csDefaultPath;
+}
+
+void CGetSetOptions::SetCheckForMaxEntries(BOOL bVal)
+{
+	SetProfileLong("CheckForMaxEntries", bVal);
+}
+
+BOOL CGetSetOptions::GetCheckForMaxEntries()
+{
+	return GetProfileLong("CheckForMaxEntries", 0);
+}
+
+void CGetSetOptions::SetCheckForExpiredEntries(BOOL bVal)
+{
+	SetProfileLong("CheckForExpiredEntries", bVal);
+}
+
+BOOL CGetSetOptions::GetCheckForExpiredEntries()
+{
+	return GetProfileLong("CheckForExpiredEntries", 0);
+}
+
+void CGetSetOptions::SetMaxEntries(long lVal)
+{
+	SetProfileLong("MaxEntries", lVal);
+}
+
+long CGetSetOptions::GetMaxEntries()
+{
+	return GetProfileLong("MaxEntries", 500);
+}
+
+void CGetSetOptions::SetExpiredEntries(long lVal)
+{
+	SetProfileLong("ExpiredEntries", lVal);
+}
+
+long CGetSetOptions::GetExpiredEntries()
+{
+	return GetProfileLong("ExpiredEntries", 5);
+}
+
+void CGetSetOptions::SetTripCopyCount(long lVal)
+{
+	if(lVal == -1)
+		lVal = GetTripCopyCount() + 1;
+
+	if(GetTripDate() == 0)
+		SetTripDate(-1);
+
+	SetProfileLong("TripCopies", lVal);
+}
+
+long CGetSetOptions::GetTripCopyCount()
+{
+	return GetProfileLong("TripCopies", 0);
+}
+
+void CGetSetOptions::SetTripPasteCount(long lVal)
+{
+	if(lVal == -1)
+		lVal = GetTripPasteCount() + 1;
+
+	if(GetTripDate() == 0)
+		SetTripDate(-1);
+
+	SetProfileLong("TripPastes", lVal);
+}
+
+long CGetSetOptions::GetTripPasteCount()
+{
+	return GetProfileLong("TripPastes", 0);
+}
+
+void CGetSetOptions::SetTripDate(long lDate)
+{
+	if(lDate == -1)
+		lDate = (long)CTime::GetCurrentTime().GetTime();
+
+	SetProfileLong("TripDate", lDate);
+}
+
+long CGetSetOptions::GetTripDate()
+{
+	return GetProfileLong("TripDate", 0);
+}
+
+void CGetSetOptions::SetTotalCopyCount(long lVal)
+{
+	if(lVal == -1)
+		lVal = GetTotalCopyCount() + 1;
+
+	if(GetTotalDate() == 0)
+		SetTotalDate(-1);
+
+	SetProfileLong("TotalCopies", lVal);
+}
+
+long CGetSetOptions::GetTotalCopyCount()
+{
+	return GetProfileLong("TotalCopies", 0);
+}
+
+void CGetSetOptions::SetTotalPasteCount(long lVal)
+{
+	if(lVal == -1)
+		lVal = GetTotalPasteCount() + 1;
+
+	if(GetTotalDate() == 0)
+		SetTotalDate(-1);
+
+	SetProfileLong("TotalPastes", lVal);
+}
+
+long CGetSetOptions::GetTotalPasteCount()
+{
+	return GetProfileLong("TotalPastes", 0);
+}
+
+void CGetSetOptions::SetTotalDate(long lDate)
+{
+	if(lDate == -1)
+		lDate = (long)CTime::GetCurrentTime().GetTime();
+
+	SetProfileLong("TotalDate", lDate);
+}
+
+long CGetSetOptions::GetTotalDate()
+{
+	return GetProfileLong("TotalDate", 0);
+}
+
+void CGetSetOptions::SetCompactAndRepairOnExit(BOOL bVal)
+{
+	SetProfileLong("CompactAndRepairOnExit", bVal);
+}
+
+BOOL CGetSetOptions::GetCompactAndRepairOnExit()
+{
+	return GetProfileLong("CompactAndRepairOnExit", 0);
+}

+ 147 - 0
Misc.h

@@ -0,0 +1,147 @@
+
+#if !defined(AFX_CP_GUI_GLOBALS__FBCDED09_A6F2_47EB_873F_50A746EBC86B__INCLUDED_)
+#define AFX_CP_GUI_H__FBCDED09_A6F2_47EB_873F_50A746EBC86B__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "DatabaseUtilities.h"
+
+#define HK_ACTIVATE		"HK_ACTIVATE"
+#define HK_NAMED_COPY	"NAMED_COPY"
+
+long DoOptions(CWnd *pParent);
+HWND GetActiveWnd(CPoint *pPointCaret = NULL);
+
+CLIPFORMAT GetFormatID(LPCSTR cbName);
+CString GetFormatName(CLIPFORMAT cbType);
+BOOL PreTranslateGuiDll(MSG *pMsg);
+
+CString GetFilePath(CString csFullPath);
+
+#define POS_AT_CARET	1
+#define POS_AT_CURSOR	2
+#define POS_AT_PREVIOUS	3
+
+//Message to the main window to show icon or not
+#define WM_SHOW_TRAY_ICON			WM_USER + 200
+#define WM_RECONNECT_TO_COPY_CHAIN	WM_USER + 201
+#define WM_IS_TOP_VIEWER			WM_USER + 202
+#define WM_COPYPROPERTIES			WM_USER + 203
+#define WM_CLOSE_APP				WM_USER + 204
+
+#define REG_PATH					"Software\\Ditto"
+
+class CGetSetOptions  
+{
+public:
+	CGetSetOptions();
+	virtual ~CGetSetOptions();
+
+	//System Tray Icon
+	static BOOL GetShowIconInSysTray();
+	static BOOL SetShowIconInSysTray(BOOL bShow);
+
+	//Hot Keys
+	static DWORD GetHotKey();
+	static BOOL SetHotKey(DWORD dwHotKey);
+	static BOOL RegisterHotKey(HWND hWnd, DWORD wHotKey, ATOM atomID);
+	static UINT GetModifier(DWORD wHotKey);
+	static DWORD GetNamedCopyHotKey();
+	static BOOL SetNamedCopyHotKey(long lHotKey);
+
+	//Run At StartUp
+	static BOOL GetRunOnStartUp();
+	static void SetRunOnStartUp(BOOL bRun);
+	static CString GetExeFileName();
+	static CString GetAppName();
+	
+	static BOOL SetProfileLong(CString csName, long lValue);
+	static long GetProfileLong(CString csName, long bDefaultValue = -1);
+
+	static CString GetProfileString(CString csName, CString csDefault);
+	static BOOL	SetProfileString(CString csName, CString csValue);
+
+	static BOOL SetQuickPasteSize(CSize size);
+	static void GetQuickPasteSize(CSize &size);
+
+	static BOOL SetQuickPastePoint(CPoint point);
+	static void GetQuickPastePoint(CPoint &point);
+
+	static BOOL SetEnableTransparency(BOOL bCheck);
+	static BOOL GetEnableTransparency();
+
+	static BOOL SetTransparencyPercent(long lPercent);
+	static long GetTransparencyPercent();
+
+	static BOOL SetLinesPerRow(long lLines);
+	static long GetLinesPerRow();
+
+	static BOOL SetQuickPastePosition(long lPosition);
+	static long GetQuickPastePosition();
+
+	static long CGetSetOptions::GetCopyGap();
+
+	static BOOL SetDBPath(CString csPath);
+	static CString GetDBPath(BOOL bDefault = TRUE);
+
+	static void SetCheckForMaxEntries(BOOL bVal);
+	static BOOL GetCheckForMaxEntries();
+
+	static void SetCheckForExpiredEntries(BOOL bVal);
+	static BOOL GetCheckForExpiredEntries();
+
+	static void SetCompactAndRepairOnExit(BOOL bVal);
+	static BOOL GetCompactAndRepairOnExit();
+
+	static void SetMaxEntries(long lVal);
+	static long GetMaxEntries();
+
+	static void SetExpiredEntries(long lVal);
+	static long GetExpiredEntries();
+
+	static void SetTripCopyCount(long lVal);
+	static long GetTripCopyCount();
+	static void SetTripPasteCount(long lVal);
+	static long GetTripPasteCount();
+	static void SetTripDate(long lDate);
+	static long GetTripDate();
+
+	static void SetTotalCopyCount(long lVal);
+	static long GetTotalCopyCount();
+	static void SetTotalPasteCount(long lVal);
+	static long GetTotalPasteCount();
+	static void SetTotalDate(long lDate);
+	static long GetTotalDate();
+
+	static CString	GetUpdateFilePath()				{ return GetProfileString("UpdateFilePath", "");	}
+	static BOOL		SetUpdateFilePath(CString cs)	{ return SetProfileString("UpdateFilePath", cs);	}
+
+	static CString	GetUpdateInstallPath()				{ return GetProfileString("UpdateInstallPath", "");	}
+	static BOOL		SetUpdateInstallPath(CString cs)	{ return SetProfileString("UpdateInstallPath", cs);	}
+
+	static long		GetLastUpdate()				{ return GetProfileLong("LastUpdateDay", 0);		}
+	static long		SetLastUpdate(long lValue)	{ return SetProfileLong("LastUpdateDay", lValue);	}
+
+	static BOOL		GetCheckForUpdates()			{ return GetProfileLong("CheckForUpdates", TRUE);	}
+	static BOOL		SetCheckForUpdates(BOOL bCheck)	{ return SetProfileLong("CheckForUpdates", bCheck);	}
+
+	static void		SetUseCtrlNumForFirstTenHotKeys(BOOL bVal)	{	SetProfileLong("UseCtrlNumForFirstTenHotKeys", bVal);		}
+	static BOOL		GetUseCtrlNumForFirstTenHotKeys()			{	return GetProfileLong("UseCtrlNumForFirstTenHotKeys", 0);	}
+
+	static void		SetShowTextForFirstTenHotKeys(BOOL bVal)	{	SetProfileLong("ShowTextForFirstTenHotKeys", bVal);			}
+	static BOOL		GetShowTextForFirstTenHotKeys()				{	return GetProfileLong("ShowTextForFirstTenHotKeys", TRUE);	}
+
+	static void		SetMainHWND(long lhWnd)		{	SetProfileLong("MainhWnd", lhWnd);		}
+	static BOOL		GetMainHWND()				{	return GetProfileLong("MainhWnd", 0);	}
+
+	/*
+	BOOL IsAutoRun();
+	void SetAutoRun(BOOL bRun);
+	CString GetExeFileName();
+	*/
+};
+
+
+#endif // !defined(AFX_CP_GUI_GLOBALS__FBCDED09_A6F2_47EB_873F_50A746EBC86B__INCLUDED_)

+ 100 - 0
NumberEdit.cpp

@@ -0,0 +1,100 @@
+// NumberEdit.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "NumberEdit.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumberEdit
+
+CNumberEdit::CNumberEdit()
+{
+	m_dMax = LONG_MAX;
+}
+
+CNumberEdit::~CNumberEdit()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CNumberEdit, CEdit)
+	//{{AFX_MSG_MAP(CNumberEdit)
+	ON_WM_CHAR()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumberEdit message handlers
+
+void CNumberEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
+{
+	//Only allow the number 0 - 9 and a the backspace to go through
+	if(((nChar < '0') || (nChar > '9')) && (nChar != VK_BACK))
+		return;
+
+	CString csText;
+	GetWindowText(csText);
+
+	//Save this if the validate fails then these get set back
+	int nStartChar, nEndChar;
+	GetSel(nStartChar, nEndChar);
+
+	//Set the new number
+	CEdit::OnChar(nChar, nRepCnt, nFlags);
+	
+	//If its not valid set it back to the old number
+	if(!ValidateNumber(GetNumberD()))
+	{
+		SetWindowText(csText);
+		SetSel(nStartChar, nEndChar);
+	}
+}
+
+BOOL CNumberEdit::ValidateNumber(double dNumber)
+{
+	if(dNumber > m_dMax)
+		return FALSE;
+
+	return TRUE;
+}
+
+long CNumberEdit::GetNumber()
+{
+	CString csText;
+	GetWindowText(csText);
+	
+	return atol(csText);
+}
+
+double CNumberEdit::GetNumberD()
+{
+	CString csText;
+	GetWindowText(csText);
+	
+	return atof(csText);
+}
+
+BOOL CNumberEdit::SetNumber(long lNumber)
+{
+	//Check if its a good number
+	if(!ValidateNumber(lNumber))
+	{
+		MessageBeep(0);
+		return FALSE;
+	}
+
+	//Its good
+	CString csText;
+	csText.Format("%d", lNumber);
+	SetWindowText(csText);
+
+	return TRUE;
+}
+

+ 61 - 0
NumberEdit.h

@@ -0,0 +1,61 @@
+#if !defined(AFX_NUMBEREDIT_H__C68189CB_8445_4009_8F29_34645AEBD9C5__INCLUDED_)
+#define AFX_NUMBEREDIT_H__C68189CB_8445_4009_8F29_34645AEBD9C5__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// NumberEdit.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CNumberEdit window
+
+class CNumberEdit : public CEdit
+{
+// Construction
+public:
+	CNumberEdit();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CNumberEdit)
+	//}}AFX_VIRTUAL
+
+public:
+	double GetNumberD();
+	long GetNumber();
+	BOOL SetNumber(long lNumber);
+	
+	void SetMaxNumber(long lMax)		{ m_dMax = lMax;		}
+	long GetMaxNumber()					{ return (long)m_dMax;	}
+	
+protected:
+	BOOL ValidateNumber(double dNumber);
+
+	double m_dMax;
+
+// Implementation
+public:
+	virtual ~CNumberEdit();
+
+	// Generated message map functions
+protected:
+	//{{AFX_MSG(CNumberEdit)
+	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+	//}}AFX_MSG
+
+	DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_NUMBEREDIT_H__C68189CB_8445_4009_8F29_34645AEBD9C5__INCLUDED_)

+ 202 - 0
OptionsGeneral.cpp

@@ -0,0 +1,202 @@
+// OptionsGeneral.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsGeneral.h"
+#include "InternetUpdate.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsGeneral property page
+
+IMPLEMENT_DYNCREATE(COptionsGeneral, CPropertyPage)
+
+COptionsGeneral::COptionsGeneral() : CPropertyPage(COptionsGeneral::IDD)
+{
+	//{{AFX_DATA_INIT(COptionsGeneral)
+	//}}AFX_DATA_INIT
+}
+
+COptionsGeneral::~COptionsGeneral()
+{
+}
+
+void COptionsGeneral::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionsGeneral)
+	DDX_Control(pDX, IDC_GET_PATH, m_btGetPath);
+	DDX_Control(pDX, IDC_PATH, m_ePath);
+	DDX_Control(pDX, IDC_SET_DB_PATH, m_btSetDatabasePath);
+	DDX_Control(pDX, IDC_CHECK_UPDATES, m_btCheckForUpdates);
+	DDX_Control(pDX, IDC_COMPACT_REPAIR, m_btCompactAndRepair);
+	DDX_Control(pDX, IDC_EXPIRE_AFTER, m_eExpireAfter);
+	DDX_Control(pDX, IDC_MAX_SAVED_COPIES, m_eMaxSavedCopies);
+	DDX_Control(pDX, IDC_MAXIMUM, m_btMaximumCheck);
+	DDX_Control(pDX, IDC_EXPIRE, m_btExpire);
+	DDX_Control(pDX, IDC_DISPLAY_IN_SYSTEMTRAY, m_btShowIconInSysTray);
+	DDX_Control(pDX, IDC_START_ON_STARTUP, m_btRunOnStartup);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(COptionsGeneral, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionsGeneral)
+	ON_BN_CLICKED(IDC_BT_COMPACT_AND_REPAIR, OnBtCompactAndRepair)
+	ON_BN_CLICKED(IDC_CHECK_FOR_UPDATES, OnCheckForUpdates)
+	ON_BN_CLICKED(IDC_SET_DB_PATH, OnSetDbPath)
+	ON_BN_CLICKED(IDC_GET_PATH, OnGetPath)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsGeneral message handlers
+
+BOOL COptionsGeneral::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+	
+	m_pParent = (COptionsSheet *)GetParent();
+
+	m_btRunOnStartup.SetCheck(CGetSetOptions::GetRunOnStartUp());
+	m_btShowIconInSysTray.SetCheck(CGetSetOptions::GetShowIconInSysTray());
+	m_btMaximumCheck.SetCheck(CGetSetOptions::GetCheckForMaxEntries());
+	m_btExpire.SetCheck(CGetSetOptions::GetCheckForExpiredEntries());
+	m_btCompactAndRepair.SetCheck(CGetSetOptions::GetCompactAndRepairOnExit());
+	m_btCheckForUpdates.SetCheck(CGetSetOptions::GetCheckForUpdates());
+	
+	m_eExpireAfter.SetNumber(CGetSetOptions::GetExpiredEntries());
+	m_eMaxSavedCopies.SetNumber(CGetSetOptions::GetMaxEntries());
+
+	CString csPath = CGetSetOptions::GetDBPath(FALSE);
+	if(csPath.IsEmpty())
+	{
+		m_ePath.EnableWindow(FALSE);
+		m_btGetPath.EnableWindow(FALSE);
+	}
+	else
+	{
+		m_btSetDatabasePath.SetCheck(BST_CHECKED);
+		m_ePath.SetWindowText(csPath);
+	}
+
+	return TRUE;
+}
+
+BOOL COptionsGeneral::OnApply()
+{
+	UpdateData();
+
+	::SendMessage(theApp.m_MainhWnd, WM_SHOW_TRAY_ICON, m_btShowIconInSysTray.GetCheck(), 0);
+
+	CGetSetOptions::SetShowIconInSysTray(m_btShowIconInSysTray.GetCheck());
+	CGetSetOptions::SetRunOnStartUp(m_btRunOnStartup.GetCheck());
+	CGetSetOptions::SetCheckForMaxEntries(m_btMaximumCheck.GetCheck());
+	CGetSetOptions::SetCheckForExpiredEntries(m_btExpire.GetCheck());
+	CGetSetOptions::SetCompactAndRepairOnExit(m_btCompactAndRepair.GetCheck());
+	CGetSetOptions::SetCheckForUpdates(m_btCheckForUpdates.GetCheck());
+	
+	CGetSetOptions::SetMaxEntries(m_eMaxSavedCopies.GetNumber());
+	CGetSetOptions::SetExpiredEntries(m_eExpireAfter.GetNumber());
+
+	if(m_btSetDatabasePath.GetCheck() == BST_CHECKED)
+	{
+		CString csPath;
+		m_ePath.GetWindowText(csPath);
+
+		if(csPath.IsEmpty() == FALSE)
+		{
+			if(ValidDB(csPath) == FALSE)
+			{
+				MessageBox("Invalid Database", "Ditto", MB_OK);
+				m_ePath.SetFocus();
+				return FALSE;
+			}			
+		}	
+		
+		if(csPath != CGetSetOptions::GetDBPath(FALSE))
+		{
+			CGetSetOptions::SetDBPath(csPath);
+			theApp.CloseDB();
+		}
+	}
+	
+	return CPropertyPage::OnApply();
+}
+
+BOOL COptionsGeneral::OnSetActive() 
+{	
+	return CPropertyPage::OnSetActive();
+}
+void COptionsGeneral::OnBtCompactAndRepair() 
+{
+	CompactDatabase();
+	RepairDatabase();
+}
+
+void COptionsGeneral::OnCheckForUpdates() 
+{
+	CInternetUpdate update;
+
+	if(update.CheckForUpdate(m_hWnd, FALSE, TRUE))
+	{
+		::PostMessage(theApp.m_MainhWnd, WM_CLOSE_APP, 0, 0);
+		m_pParent->EndDialog(-1);
+	}
+}
+
+void COptionsGeneral::OnSetDbPath() 
+{
+	if(m_btSetDatabasePath.GetCheck() == BST_CHECKED)
+	{
+		m_ePath.EnableWindow(TRUE);
+		m_btGetPath.EnableWindow(TRUE);
+	}
+	else
+	{
+		m_ePath.EnableWindow(FALSE);
+		m_btGetPath.EnableWindow(FALSE);
+	}	
+}
+
+void COptionsGeneral::OnGetPath() 
+{
+	OPENFILENAME	FileName;
+
+	char			szFileName[400];
+	char			szDir[400];
+
+	memset(&FileName, 0, sizeof(FileName));
+	memset(szFileName, 0, sizeof(szFileName));
+	memset(&szDir, 0, sizeof(szDir));
+
+	FileName.lStructSize = sizeof(FileName);
+
+	
+	FileName.lpstrTitle = "Open Database";
+	FileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST;
+	FileName.nMaxFile = 400;
+	FileName.lpstrFile = szFileName;
+	FileName.lpstrInitialDir = szDir;
+	FileName.lpstrFilter = "Database Files (.MDB)\0*.mdb";
+	FileName.lpstrDefExt = "mdb";
+
+	if(GetOpenFileName(&FileName) == 0)
+		return;
+
+	CString	csPath(FileName.lpstrFile);
+
+	if(ValidDB(csPath) == FALSE)
+	{
+		MessageBox("Invalid Database", "Ditto", MB_OK);
+		m_ePath.SetFocus();
+	}
+	else
+		m_ePath.SetWindowText(csPath);	
+}

+ 73 - 0
OptionsGeneral.h

@@ -0,0 +1,73 @@
+#if !defined(AFX_OPTIONSGENERAL_H__A13ABBF6_7636_4426_9A31_0189D4CA8F2F__INCLUDED_)
+#define AFX_OPTIONSGENERAL_H__A13ABBF6_7636_4426_9A31_0189D4CA8F2F__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionsGeneral.h : header file
+//
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsSheet.h"
+#include "NumberEdit.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsGeneral dialog
+
+class COptionsGeneral : public CPropertyPage
+{
+	DECLARE_DYNCREATE(COptionsGeneral)
+
+// Construction
+public:
+	COptionsGeneral();
+	~COptionsGeneral();
+
+// Dialog Data
+	//{{AFX_DATA(COptionsGeneral)
+	enum { IDD = IDD_OPTIONS_GENERAL };
+	CButton	m_btGetPath;
+	CEdit	m_ePath;
+	CButton	m_btSetDatabasePath;
+	CButton	m_btCheckForUpdates;
+	CButton	m_btCompactAndRepair;
+	CNumberEdit	m_eExpireAfter;
+	CNumberEdit	m_eMaxSavedCopies;
+	CButton	m_btMaximumCheck;
+	CButton	m_btExpire;
+	CButton		m_btShowIconInSysTray;
+	CButton		m_btRunOnStartup;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generate virtual function overrides
+	//{{AFX_VIRTUAL(COptionsGeneral)
+	public:
+	virtual BOOL OnSetActive();
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	virtual BOOL OnApply();
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+	
+	COptionsSheet *m_pParent;
+
+	// Generated message map functions
+	//{{AFX_MSG(COptionsGeneral)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnBtCompactAndRepair();
+	afx_msg void OnCheckForUpdates();
+	afx_msg void OnSetDbPath();
+	afx_msg void OnGetPath();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONSGENERAL_H__A13ABBF6_7636_4426_9A31_0189D4CA8F2F__INCLUDED_)

+ 161 - 0
OptionsKeyBoard.cpp

@@ -0,0 +1,161 @@
+// OptionsKeyBoard.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsKeyBoard.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsKeyBoard property page
+
+IMPLEMENT_DYNCREATE(COptionsKeyBoard, CPropertyPage)
+
+COptionsKeyBoard::COptionsKeyBoard() : CPropertyPage(COptionsKeyBoard::IDD)
+{
+	//{{AFX_DATA_INIT(COptionsKeyBoard)
+		// NOTE: the ClassWizard will add member initialization here
+	//}}AFX_DATA_INIT
+}
+
+COptionsKeyBoard::~COptionsKeyBoard()
+{
+}
+
+void COptionsKeyBoard::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionsKeyBoard)
+	DDX_Control(pDX, IDC_NAMED_COPY, m_NamedCopy);
+	DDX_Control(pDX, IDC_HOTKEY, m_HotKey);
+	//}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(COptionsKeyBoard, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionsKeyBoard)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsKeyBoard message handlers
+
+BOOL COptionsKeyBoard::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+
+	m_pParent = (COptionsSheet *)GetParent();
+
+	DWORD wHotKey = CGetSetOptions::GetHotKey();
+	
+	m_HotKey.SetHotKey(LOBYTE(wHotKey),HIBYTE(wHotKey));
+
+	//Unregister the hotkey
+	//Re regester it on cancel or ok
+	UnregisterHotKey(theApp.m_MainhWnd, theApp.m_atomHotKey);
+	
+	wHotKey = CGetSetOptions::GetNamedCopyHotKey();
+	
+	m_NamedCopy.SetHotKey(LOBYTE(wHotKey),HIBYTE(wHotKey));
+
+	//Unregister the hotkey
+	//Re regester it on cancel or ok
+	UnregisterHotKey(theApp.m_MainhWnd, theApp.m_atomNamedCopy);
+
+	m_HotKey.SetFocus();
+
+	return FALSE;
+}
+
+LRESULT COptionsKeyBoard::OnWizardNext() 
+{
+	
+	return CPropertyPage::OnWizardNext();
+}
+
+BOOL COptionsKeyBoard::OnWizardFinish() 
+{
+	
+	
+	return CPropertyPage::OnWizardFinish();
+}
+
+BOOL COptionsKeyBoard::OnApply()
+{
+	DWORD wHotKey = m_HotKey.GetHotKey();
+	DWORD wNamedCopy = m_NamedCopy.GetHotKey();
+
+	if((wHotKey == wNamedCopy) && (wHotKey != 0))
+	{
+		MessageBox("Activate Hot Key and Named Copy Hot Key cannot be the same.");
+		return FALSE;
+	}
+
+	CGetSetOptions::SetNamedCopyHotKey(wNamedCopy);
+	CGetSetOptions::SetHotKey(wHotKey);
+
+	if(wHotKey > 0)
+	{
+		if(!CGetSetOptions::RegisterHotKey(theApp.m_MainhWnd, wHotKey, theApp.m_atomHotKey))
+		{
+			MessageBox("Error Registering HotKey to Activate Ditto");
+			return FALSE;
+		}
+	}
+
+	if(wNamedCopy > 0)
+	{
+		if(!CGetSetOptions::RegisterHotKey(theApp.m_MainhWnd, wNamedCopy, theApp.m_atomNamedCopy))
+		{
+			MessageBox("Error Registering HotKey for Named Copy");
+			return FALSE;
+		}
+	}
+		
+	return CPropertyPage::OnApply();
+}
+
+BOOL COptionsKeyBoard::ValidateHotKey(WORD wHotKey)
+{
+	ATOM id = GlobalAddAtom("HK_VALIDATE");
+	BOOL bResult = CGetSetOptions::RegisterHotKey(theApp.m_MainhWnd, wHotKey, FALSE);
+	
+	if(bResult)
+		UnregisterHotKey(GetSafeHwnd(), id);
+
+	GlobalDeleteAtom(id);
+
+	return bResult;
+}
+
+void COptionsKeyBoard::OnCancel() 
+{
+	if(CGetSetOptions::GetHotKey())
+	{
+		if(!CGetSetOptions::RegisterHotKey(theApp.m_MainhWnd, 
+										CGetSetOptions::GetHotKey(), 
+										theApp.m_atomHotKey))
+		{
+			MessageBox("Error Registering HotKey to Activate Ditto");
+			return;
+		}
+	}
+
+	if(CGetSetOptions::GetNamedCopyHotKey())
+	{
+		if(!CGetSetOptions::RegisterHotKey(theApp.m_MainhWnd, 
+										CGetSetOptions::GetNamedCopyHotKey(), 
+										theApp.m_atomNamedCopy))
+		{
+			MessageBox("Error Registering HotKey for Named Copy");
+			return;
+		}
+	}
+	
+	
+	CPropertyPage::OnCancel();
+}

+ 63 - 0
OptionsKeyBoard.h

@@ -0,0 +1,63 @@
+#if !defined(AFX_OPTIONSKEYBOARD_H__3E1A060F_019B_4117_8C53_15326D1ABFAE__INCLUDED_)
+#define AFX_OPTIONSKEYBOARD_H__3E1A060F_019B_4117_8C53_15326D1ABFAE__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionsKeyBoard.h : header file
+//
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsSheet.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsKeyBoard dialog
+
+class COptionsKeyBoard : public CPropertyPage
+{
+	DECLARE_DYNCREATE(COptionsKeyBoard)
+
+// Construction
+public:
+	COptionsKeyBoard();
+	~COptionsKeyBoard();
+
+// Dialog Data
+	//{{AFX_DATA(COptionsKeyBoard)
+	enum { IDD = IDD_OPTIONS_KEYSTROKES };
+	CHotKeyCtrl	m_NamedCopy;
+	CHotKeyCtrl	m_HotKey;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generate virtual function overrides
+	//{{AFX_VIRTUAL(COptionsKeyBoard)
+	public:
+	virtual LRESULT OnWizardNext();
+	virtual BOOL OnWizardFinish();
+	virtual BOOL OnApply();
+	virtual void OnCancel();
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+	BOOL RegisterHotKey(WORD wHotKey);
+	BOOL ValidateHotKey(WORD wHotKey);
+
+	COptionsSheet *m_pParent;
+
+	// Generated message map functions
+	//{{AFX_MSG(COptionsKeyBoard)
+	virtual BOOL OnInitDialog();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONSKEYBOARD_H__3E1A060F_019B_4117_8C53_15326D1ABFAE__INCLUDED_)

+ 93 - 0
OptionsQuickPaste.cpp

@@ -0,0 +1,93 @@
+// OptionsQuickPaste.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsQuickPaste.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsQuickPaste property page
+
+IMPLEMENT_DYNCREATE(COptionsQuickPaste, CPropertyPage)
+
+COptionsQuickPaste::COptionsQuickPaste() : CPropertyPage(COptionsQuickPaste::IDD)
+{
+	//{{AFX_DATA_INIT(COptionsQuickPaste)
+		// NOTE: the ClassWizard will add member initialization here
+	//}}AFX_DATA_INIT
+}
+
+COptionsQuickPaste::~COptionsQuickPaste()
+{
+}
+
+void COptionsQuickPaste::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionsQuickPaste)
+	DDX_Control(pDX, IDC_SHOW_TEXT_FOR_FIRST_TEN_HOT_KEYS, m_btShowText);
+	DDX_Control(pDX, IDC_LINES_ROW, m_eLinesPerRow);
+	DDX_Control(pDX, IDC_TRANS_PERC, m_eTransparencyPercent);
+	DDX_Control(pDX, IDC_TRANSPARENCY, m_btEnableTransparency);
+	DDX_Control(pDX, IDC_CTRL_CLICK, m_btUseCtrlNum);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(COptionsQuickPaste, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionsQuickPaste)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsQuickPaste message handlers
+
+BOOL COptionsQuickPaste::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+
+	m_pParent = (COptionsSheet *)GetParent();
+	
+	m_btEnableTransparency.SetCheck(CGetSetOptions::GetEnableTransparency());
+	m_eTransparencyPercent.SetNumber(CGetSetOptions::GetTransparencyPercent());
+	m_eLinesPerRow.SetNumber(CGetSetOptions::GetLinesPerRow());
+
+	if(CGetSetOptions::GetQuickPastePosition() == POS_AT_CARET)
+		CheckDlgButton(IDC_AT_CARET, BST_CHECKED);
+	else if(CGetSetOptions::GetQuickPastePosition() == POS_AT_CURSOR)
+		CheckDlgButton(IDC_AT_CURSOR, BST_CHECKED);
+	else if(CGetSetOptions::GetQuickPastePosition() == POS_AT_PREVIOUS)
+		CheckDlgButton(IDC_AT_PREVIOUS, BST_CHECKED);
+
+	m_btUseCtrlNum.SetCheck(CGetSetOptions::GetUseCtrlNumForFirstTenHotKeys());
+
+	m_btShowText.SetCheck(CGetSetOptions::GetShowTextForFirstTenHotKeys());
+		
+	return FALSE;
+}
+
+BOOL COptionsQuickPaste::OnApply() 
+{
+	CGetSetOptions::SetEnableTransparency(m_btEnableTransparency.GetCheck());
+	CGetSetOptions::SetTransparencyPercent(m_eTransparencyPercent.GetNumber());
+	CGetSetOptions::SetLinesPerRow(m_eLinesPerRow.GetNumber());
+	
+
+	if(IsDlgButtonChecked(IDC_AT_CARET))
+		CGetSetOptions::SetQuickPastePosition(POS_AT_CARET);
+	else if(IsDlgButtonChecked(IDC_AT_CURSOR))
+		CGetSetOptions::SetQuickPastePosition(POS_AT_CURSOR);
+	else if(IsDlgButtonChecked(IDC_AT_PREVIOUS))
+		CGetSetOptions::SetQuickPastePosition(POS_AT_PREVIOUS);
+	
+	CGetSetOptions::SetUseCtrlNumForFirstTenHotKeys(m_btUseCtrlNum.GetCheck());
+	CGetSetOptions::SetShowTextForFirstTenHotKeys(m_btShowText.GetCheck());
+	
+	return CPropertyPage::OnApply();
+}

+ 60 - 0
OptionsQuickPaste.h

@@ -0,0 +1,60 @@
+#if !defined(AFX_OPTIONSQUICKPASTE_H__69465009_2717_4BD5_BFFC_8CD537732050__INCLUDED_)
+#define AFX_OPTIONSQUICKPASTE_H__69465009_2717_4BD5_BFFC_8CD537732050__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionsQuickPaste.h : header file
+#include "NumberEdit.h"
+#include "OptionsSheet.h"
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsQuickPaste dialog
+
+class COptionsQuickPaste : public CPropertyPage
+{
+	DECLARE_DYNCREATE(COptionsQuickPaste)
+
+// Construction
+public:
+	COptionsQuickPaste();
+	~COptionsQuickPaste();
+
+// Dialog Data
+	//{{AFX_DATA(COptionsQuickPaste)
+	enum { IDD = IDD_OPTIONS_QUICK_PASTE };
+	CButton	m_btShowText;
+	CNumberEdit	m_eLinesPerRow;
+	CNumberEdit	m_eTransparencyPercent;
+	CButton	m_btEnableTransparency;
+	CButton	m_btUseCtrlNum;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generate virtual function overrides
+	//{{AFX_VIRTUAL(COptionsQuickPaste)
+	public:
+	virtual BOOL OnApply();
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+protected:
+	COptionsSheet *m_pParent;
+
+
+// Implementation
+protected:
+	// Generated message map functions
+	//{{AFX_MSG(COptionsQuickPaste)
+	virtual BOOL OnInitDialog();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONSQUICKPASTE_H__69465009_2717_4BD5_BFFC_8CD537732050__INCLUDED_)

+ 90 - 0
OptionsSheet.cpp

@@ -0,0 +1,90 @@
+// OptionsSheet.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsSheet.h"
+#include "OptionsKeyBoard.h"
+#include "OptionsGeneral.h"
+#include "OptionsQuickPaste.h"
+#include "OptionsUtilities.h"
+#include "OptionsStats.h"
+#include "OptionsTypes.h"
+#include "About.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define DELETE_PTR(ptr)	if(ptr) { delete ptr; ptr = NULL;	}
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsSheet
+
+IMPLEMENT_DYNAMIC(COptionsSheet, CPropertySheet)
+
+COptionsSheet::COptionsSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
+	:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
+{
+	m_pKeyBoardOptions = NULL;
+	m_pGeneralOptions = NULL;
+	m_pQuickPasteOptions = NULL;
+	m_pUtilites = NULL;
+	m_pStats = NULL;
+	m_pTypes = NULL;
+	m_pAbout = NULL;
+}
+
+COptionsSheet::~COptionsSheet()
+{
+	DELETE_PTR(m_pKeyBoardOptions);
+	DELETE_PTR(m_pGeneralOptions);
+	DELETE_PTR(m_pQuickPasteOptions);
+	DELETE_PTR(m_pUtilites);
+	DELETE_PTR(m_pStats);
+	DELETE_PTR(m_pTypes);
+	DELETE_PTR(m_pAbout);
+}
+
+BEGIN_MESSAGE_MAP(COptionsSheet, CPropertySheet)
+	//{{AFX_MSG_MAP(COptionsSheet)
+		// NOTE - the ClassWizard will add and remove mapping macros here.
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsSheet message handlers
+
+int COptionsSheet::DoModal() 
+{
+	EnableStackedTabs(TRUE);
+
+	m_pGeneralOptions = new COptionsGeneral;
+	m_pKeyBoardOptions = new COptionsKeyBoard;
+	m_pQuickPasteOptions = new COptionsQuickPaste;
+	m_pStats = new COptionsStats;
+	m_pTypes = new COptionsTypes;
+	m_pAbout = new CAbout;
+
+	AddPage(m_pGeneralOptions);
+	AddPage(m_pTypes);
+	AddPage(m_pKeyBoardOptions);
+	AddPage(m_pQuickPasteOptions);
+	AddPage(m_pStats);
+	AddPage(m_pAbout);
+	
+	return CPropertySheet::DoModal();
+}
+
+BOOL COptionsSheet::OnInitDialog() 
+{
+	BOOL bResult = CPropertySheet::OnInitDialog();
+	
+	SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+
+	SetWindowText("Ditto");
+	
+	return bResult;
+}

+ 62 - 0
OptionsSheet.h

@@ -0,0 +1,62 @@
+#if !defined(AFX_OPTIONSSHEET_H__D8A13849_DBC6_4CD6_A981_E572ECDC2E94__INCLUDED_)
+#define AFX_OPTIONSSHEET_H__D8A13849_DBC6_4CD6_A981_E572ECDC2E94__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionsSheet.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsSheet
+
+class COptionsSheet : public CPropertySheet
+{
+	DECLARE_DYNAMIC(COptionsSheet)
+
+// Construction
+public:
+	COptionsSheet(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(COptionsSheet)
+	public:
+	virtual int DoModal();
+	virtual BOOL OnInitDialog();
+	//}}AFX_VIRTUAL
+
+// Implementation
+public:
+	virtual ~COptionsSheet();
+
+	// Generated message map functions
+protected:
+
+	CPropertyPage *m_pKeyBoardOptions;
+	CPropertyPage *m_pGeneralOptions;
+	CPropertyPage *m_pQuickPasteOptions;
+	CPropertyPage *m_pUtilites;
+	CPropertyPage *m_pStats;
+	CPropertyPage *m_pTypes;
+	CPropertyPage *m_pAbout;
+
+
+	//{{AFX_MSG(COptionsSheet)
+		// NOTE - the ClassWizard will add and remove member functions here.
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONSSHEET_H__D8A13849_DBC6_4CD6_A981_E572ECDC2E94__INCLUDED_)

+ 147 - 0
OptionsStats.cpp

@@ -0,0 +1,147 @@
+// OptionsStats.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "OptionsStats.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsStats dialog
+
+IMPLEMENT_DYNCREATE(COptionsStats, CPropertyPage)
+
+COptionsStats::COptionsStats()
+	: CPropertyPage(COptionsStats::IDD)
+{
+	//{{AFX_DATA_INIT(COptionsStats)
+	m_eAllCopies = _T("");
+	m_eAllPastes = _T("");
+	m_eAllDate = _T("");
+	m_eTripCopies = _T("");
+	m_eTripDate = _T("");
+	m_eTripPastes = _T("");
+	m_eSavedCopies = _T("");
+	m_eSavedCopyData = _T("");
+	m_eDatabaseSize = _T("");
+	//}}AFX_DATA_INIT
+}
+
+
+void COptionsStats::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionsStats)
+	DDX_Text(pDX, IDC_ALL_COPIES, m_eAllCopies);
+	DDX_Text(pDX, IDC_ALL_PASTES, m_eAllPastes);
+	DDX_Text(pDX, IDC_EDIT_ALL_DATE, m_eAllDate);
+	DDX_Text(pDX, IDC_TRIP_COPIES, m_eTripCopies);
+	DDX_Text(pDX, IDC_TRIP_DATE, m_eTripDate);
+	DDX_Text(pDX, IDC_TRIP_PASTES, m_eTripPastes);
+	DDX_Text(pDX, IDC_SAVED_COPIES, m_eSavedCopies);
+	DDX_Text(pDX, IDC_SAVED_COPY_DATA, m_eSavedCopyData);
+	DDX_Text(pDX, IDC_DATABASE_SIZE, m_eDatabaseSize);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(COptionsStats, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionsStats)
+	ON_BN_CLICKED(IDC_RESET_COUNTS, OnResetCounts)
+	ON_BN_CLICKED(IDC_REMOVE_ALL, OnRemoveAll)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsStats message handlers
+
+BOOL COptionsStats::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+
+	CTime time(CGetSetOptions::GetTotalDate());
+	m_eAllDate = time.Format("%m/%d/%Y %I:%M %p");
+	m_eAllCopies.Format("%d", CGetSetOptions::GetTotalCopyCount());
+	m_eAllPastes.Format("%d", CGetSetOptions::GetTotalPasteCount());
+
+	CTime time2(CGetSetOptions::GetTripDate());
+	m_eTripDate = time2.Format("%m/%d/%Y %I:%M %p");
+	m_eTripCopies.Format("%d", CGetSetOptions::GetTripCopyCount());
+	m_eTripPastes.Format("%d", CGetSetOptions::GetTripPasteCount());
+
+	CMainTable recset;
+	recset.Open("SELECT * FROM Main");
+	if(!recset.IsEOF())
+	{
+		recset.MoveLast();
+		m_eSavedCopies.Format("%d", recset.GetRecordCount());
+	}
+
+	CDataTable recset2;
+	recset2.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Data" ,NULL);
+	if(!recset2.IsEOF())
+	{
+		recset2.MoveLast();
+		m_eSavedCopyData.Format("%d", recset2.GetRecordCount());
+	}
+
+	struct _stat buf;
+	int nResult;
+	nResult = _stat(GetDBName(), &buf);
+	if(nResult == 0)
+		m_eDatabaseSize.Format("%d KB", (buf.st_size/1024));
+
+	UpdateData(FALSE);
+		
+	return TRUE;
+}
+
+void COptionsStats::OnResetCounts() 
+{
+	CGetSetOptions::SetTripCopyCount(0);
+	CGetSetOptions::SetTripPasteCount(0);
+	CGetSetOptions::SetTripDate(0);
+
+	m_eTripDate.Empty();
+	m_eTripCopies.Empty();
+	m_eTripPastes.Empty();
+
+	UpdateData(FALSE);
+}
+
+void COptionsStats::OnRemoveAll() 
+{
+	if(MessageBox("This will remove all Copy Entries!\n\nContinue?", "Warning", MB_YESNO) == IDYES)
+	{
+		CMainTable MainTable;
+		if(MainTable.DeleteAll())
+		{
+			CDataTable DataTable;
+			if(DataTable.DeleteAll())
+			{
+				if(CompactDatabase())
+				{
+					RepairDatabase();
+
+					m_eSavedCopies.Empty();
+					m_eSavedCopyData.Empty();
+
+					struct _stat buf;
+					int nResult;
+					nResult = _stat(GetDBName(), &buf);
+					if(nResult == 0)
+						m_eDatabaseSize.Format("%d KB", (buf.st_size/1024));
+
+					UpdateData(FALSE);
+				}
+			}
+		}
+	}
+}

+ 58 - 0
OptionsStats.h

@@ -0,0 +1,58 @@
+#if !defined(AFX_OPTIONSSTATS_H__5F6FFD2C_E563_4166_8294_A0CBBD17403B__INCLUDED_)
+#define AFX_OPTIONSSTATS_H__5F6FFD2C_E563_4166_8294_A0CBBD17403B__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionsStats.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsStats dialog
+
+class COptionsStats : public CPropertyPage
+{
+	DECLARE_DYNCREATE(COptionsStats)
+
+// Construction
+public:
+	COptionsStats();   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(COptionsStats)
+	enum { IDD = IDD_OPTIONS_STATS };
+	CString	m_eAllCopies;
+	CString	m_eAllPastes;
+	CString	m_eAllDate;
+	CString	m_eTripCopies;
+	CString	m_eTripDate;
+	CString	m_eTripPastes;
+	CString	m_eSavedCopies;
+	CString	m_eSavedCopyData;
+	CString	m_eDatabaseSize;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(COptionsStats)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(COptionsStats)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnResetCounts();
+	afx_msg void OnRemoveAll();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONSSTATS_H__5F6FFD2C_E563_4166_8294_A0CBBD17403B__INCLUDED_)

+ 145 - 0
OptionsTypes.cpp

@@ -0,0 +1,145 @@
+// OptionsTypes.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsTypes.h"
+#include "ArrayEx.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsTypes property page
+
+IMPLEMENT_DYNCREATE(COptionsTypes, CPropertyPage)
+
+COptionsTypes::COptionsTypes() : CPropertyPage(COptionsTypes::IDD)
+{
+	//{{AFX_DATA_INIT(COptionsTypes)
+	//}}AFX_DATA_INIT
+
+	m_bSave = false;
+}
+
+COptionsTypes::~COptionsTypes()
+{
+}
+
+void COptionsTypes::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionsTypes)
+	DDX_Control(pDX, IDC_LIST1, m_List);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(COptionsTypes, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionsTypes)
+	ON_BN_CLICKED(IDC_DELETE, OnDelete)
+	ON_BN_CLICKED(IDC_ADD, OnAdd)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsTypes message handlers
+
+BOOL COptionsTypes::OnApply() 
+{
+	if(m_bSave)
+	{
+		theApp.m_bReloadTypes = true;
+
+		CTypesTable recset;
+		recset.DeleteAll();
+
+		recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Types" ,NULL);
+
+		int nCount = m_List.GetCount();
+
+		for(int i = 0; i < nCount; i++)
+		{
+			recset.AddNew();
+			m_List.GetText(i, recset.m_TypeText);
+			recset.Update();
+		}
+	}
+	
+	return CPropertyPage::OnApply();
+}
+
+BOOL COptionsTypes::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+	
+	CTypesTable recset;
+	recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Types" ,NULL);
+	if(recset.IsEOF())
+	{
+		m_List.AddString("CF_TEXT");
+		m_List.AddString(GetFormatName(RegisterClipboardFormat(CF_RTF)));
+	}
+	while(!recset.IsEOF())
+	{
+		m_List.AddString(recset.m_TypeText);
+		recset.MoveNext();
+	}
+	
+	m_List.SetFocus();
+	return FALSE;
+}
+
+void COptionsTypes::OnDelete() 
+{
+	int nCount = m_List.GetSelCount();
+	if(nCount)
+	{
+		m_bSave = true;
+		CArrayEx<int> items;
+		items.SetSize(nCount);
+		m_List.GetSelItems(nCount, items.GetData()); 
+		items.SortDescending();
+
+		for(int i = 0; i < nCount; i++)
+			m_List.DeleteString(items[i]);
+	}
+}
+
+#include "AddType.h"
+void COptionsTypes::OnAdd() 
+{
+	CAddType add(this);
+
+	if(add.DoModal() == IDOK)
+	{
+		int nCount = add.m_csSelectedTypes.GetSize();
+		if(nCount)
+		{
+			m_bSave = true;
+			for(int i = 0; i < nCount; i++)
+			{
+				if(TextAllReadyThere(add.m_csSelectedTypes[i]) == FALSE)
+					m_List.AddString(add.m_csSelectedTypes[i]);
+			}
+		}
+	}	
+}
+
+BOOL COptionsTypes::TextAllReadyThere(const CString &cs)
+{
+	CString csThere;
+	int nCount = m_List.GetCount();
+
+	for(int i = 0; i < nCount; i++)
+	{
+		m_List.GetText(i, csThere);
+		if(cs == csThere)
+			return TRUE;
+	}
+
+	return FALSE;
+}

+ 57 - 0
OptionsTypes.h

@@ -0,0 +1,57 @@
+#if !defined(AFX_OPTIONSTYPES_H__3E35B866_595F_41CA_8654_E4F8E39B1D81__INCLUDED_)
+#define AFX_OPTIONSTYPES_H__3E35B866_595F_41CA_8654_E4F8E39B1D81__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionsTypes.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsTypes dialog
+
+class COptionsTypes : public CPropertyPage
+{
+	DECLARE_DYNCREATE(COptionsTypes)
+
+// Construction
+public:
+	COptionsTypes();
+	~COptionsTypes();
+
+// Dialog Data
+	//{{AFX_DATA(COptionsTypes)
+	enum { IDD = IDD_OPTIONS_TYPES };
+	CListBox	m_List;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generate virtual function overrides
+	//{{AFX_VIRTUAL(COptionsTypes)
+	public:
+	virtual BOOL OnApply();
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+	bool m_bSave;
+	BOOL TextAllReadyThere(const CString &cs);
+
+
+	// Generated message map functions
+	//{{AFX_MSG(COptionsTypes)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnDelete();
+	afx_msg void OnAdd();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONSTYPES_H__3E35B866_595F_41CA_8654_E4F8E39B1D81__INCLUDED_)

+ 113 - 0
OptionsUtilities.cpp

@@ -0,0 +1,113 @@
+// OptionsUtilities.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsUtilities.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsUtilities property page
+
+IMPLEMENT_DYNCREATE(COptionsUtilities, CPropertyPage)
+
+COptionsUtilities::COptionsUtilities() : CPropertyPage(COptionsUtilities::IDD)
+{
+	//{{AFX_DATA_INIT(COptionsUtilities)
+		// NOTE: the ClassWizard will add member initialization here
+	//}}AFX_DATA_INIT
+}
+
+COptionsUtilities::~COptionsUtilities()
+{
+}
+
+void COptionsUtilities::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionsUtilities)
+	DDX_Control(pDX, IDC_PATH, m_ePath);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(COptionsUtilities, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionsUtilities)
+	ON_BN_CLICKED(IDC_COMPACT_DB, OnCompactDB)
+	ON_BN_CLICKED(IDC_REPAIR, OnRepair)
+	ON_BN_CLICKED(IDC_GET_PATH, OnGetPath)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsUtilities message handlers
+
+void COptionsUtilities::OnCompactDB() 
+{
+	CompactDatabase();
+}
+
+BOOL COptionsUtilities::OnApply() 
+{
+	CString csPath;
+	m_ePath.GetWindowText(csPath);
+
+	CString csOldPath = CGetSetOptions::GetDBPath(FALSE);
+
+	if(csOldPath != csPath)
+	{
+		theApp.CloseDB();
+		CGetSetOptions::SetDBPath(csPath);
+	}
+		
+	return CPropertyPage::OnApply();
+}
+
+BOOL COptionsUtilities::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+	
+	m_ePath.SetWindowText(CGetSetOptions::GetDBPath(FALSE));
+		
+	return TRUE;
+}
+
+void COptionsUtilities::OnRepair() 
+{
+	RepairDatabase();
+}
+
+void COptionsUtilities::OnGetPath() 
+{
+	OPENFILENAME	FileName;
+
+	char			szFileName[400];
+	char			szDir[400];
+
+	memset(&FileName, 0, sizeof(FileName));
+	memset(szFileName, 0, sizeof(szFileName));
+	memset(&szDir, 0, sizeof(szDir));
+
+	FileName.lStructSize = sizeof(FileName);
+
+	
+	FileName.lpstrTitle = "Open Database";
+	FileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
+	FileName.nMaxFile = 400;
+	FileName.lpstrFile = szFileName;
+	FileName.lpstrInitialDir = szDir;
+	FileName.lpstrFilter = "Database Files (.MDB)\0*.mdb";
+	FileName.lpstrDefExt = "mdb";
+
+	if(GetOpenFileName(&FileName) == 0)
+		return;
+
+	CString	csPath(FileName.lpstrFile);
+	
+	m_ePath.SetWindowText(csPath);		
+}

+ 54 - 0
OptionsUtilities.h

@@ -0,0 +1,54 @@
+#if !defined(AFX_OPTIONSUTILITIES_H__094B311D_3C47_43A8_A254_A009E3F0A75D__INCLUDED_)
+#define AFX_OPTIONSUTILITIES_H__094B311D_3C47_43A8_A254_A009E3F0A75D__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// OptionsUtilities.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsUtilities dialog
+
+class COptionsUtilities : public CPropertyPage
+{
+	DECLARE_DYNCREATE(COptionsUtilities)
+
+// Construction
+public:
+	COptionsUtilities();
+	~COptionsUtilities();
+
+// Dialog Data
+	//{{AFX_DATA(COptionsUtilities)
+	enum { IDD = IDD_OPTIONS_UTILITIES };
+	CEdit	m_ePath;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generate virtual function overrides
+	//{{AFX_VIRTUAL(COptionsUtilities)
+	public:
+	virtual BOOL OnApply();
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+	// Generated message map functions
+	//{{AFX_MSG(COptionsUtilities)
+	afx_msg void OnCompactDB();
+	virtual BOOL OnInitDialog();
+	afx_msg void OnRepair();
+	afx_msg void OnGetPath();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_OPTIONSUTILITIES_H__094B311D_3C47_43A8_A254_A009E3F0A75D__INCLUDED_)

+ 532 - 0
ProcessCopy.cpp

@@ -0,0 +1,532 @@
+// ProcessCopy.cpp: implementation of the CProcessCopy class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "ProcessCopy.h"
+#include "DatabaseUtilities.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+HGLOBAL COleDataObjectEx::GetGlobalData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
+{
+    bool bRet = theApp.m_bHandleClipboardDataChange;
+    theApp.m_bHandleClipboardDataChange = false;
+
+    HGLOBAL global = COleDataObject::GetGlobalData(cfFormat, lpFormatEtc);
+
+    theApp.m_bHandleClipboardDataChange = bRet;
+
+    return global;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CProcessCopy::CProcessCopy()
+{
+	InitializeCriticalSection(&m_CriticalSection);
+}
+
+CProcessCopy::~CProcessCopy()
+{
+	DeleteCriticalSection(&m_CriticalSection);
+}
+
+#define EXIT_DO_COPY(ret)	{ m_oleData.Release(); LeaveCriticalSection(&m_CriticalSection); return(ret);	}
+
+BOOL CProcessCopy::DoCopy()
+{
+	EnterCriticalSection(&m_CriticalSection);
+	
+	//Attach the clip board
+	if(!m_oleData.AttachClipboard())
+		EXIT_DO_COPY(FALSE);
+
+	m_oleData.EnsureClipboardObject();
+
+	//Included in copy if the data is supposed to be private
+	//If it is there then return
+	if(m_oleData.IsDataAvailable(RegisterClipboardFormat("Clipboard Viewer Ignore")))
+	{
+		EXIT_DO_COPY(FALSE);
+	}
+
+	if((theApp.m_bReloadTypes) || (m_SupportedTypes.GetSize() == 0))
+		LoadSupportedTypes();
+	
+	//Start the copy process
+	//This checks if valid data is available
+	//If so it adds the text the the main table and returns the id
+	long lID = StartCopyProcess();
+	if(lID == -1)
+	{
+		EXIT_DO_COPY(FALSE);
+	}
+
+	try
+	{
+		//open the data table and add the data for supported types
+		CDataTable recset;
+		CString csDbString;
+
+		recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Data" ,NULL);
+		
+		CLIPFORMAT format;
+		int nSize = m_SupportedTypes.GetSize();
+		for(int i = 0; i < nSize; i++)
+		{
+			format = m_SupportedTypes[i];
+
+			if(m_oleData.IsDataAvailable(format))
+			{
+				recset.AddNew();
+
+				recset.m_lParentID = lID;
+				recset.m_strClipBoardFormat = GetFormatName(format);
+
+				HGLOBAL hgData = m_oleData.GetGlobalData(format);
+
+				bool bReadData = false;
+				if(hgData != NULL)
+				{
+					recset.SetData(hgData);
+				
+					//update the DB
+					recset.Update();
+					bReadData = true;
+
+					// Free the memory that GetGlobalData() allocated for us.
+					GlobalUnlock(hgData);
+					GlobalFree(hgData);
+					hgData = NULL;
+				}
+				else
+				{
+					// The data isn't in global memory, so try getting an IStream 
+					// interface to it.
+					STGMEDIUM stg;
+					
+					if(m_oleData.GetData(format, &stg))
+					{
+						switch(stg.tymed)
+						{
+							case TYMED_HGLOBAL:
+							{
+								recset.SetData(stg.hGlobal);
+
+								//Update the db
+								recset.Update();
+								bReadData = true;
+							}
+							break;
+							
+							case TYMED_ISTREAM:
+							{
+								UINT            uDataSize;
+								LARGE_INTEGER	li;
+								ULARGE_INTEGER	uli;
+								
+								li.HighPart = li.LowPart = 0;
+								
+								if ( SUCCEEDED( stg.pstm->Seek ( li, STREAM_SEEK_END, &uli )))
+								{
+									HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, uli.LowPart );
+									void* pv = GlobalLock(hg);
+									
+									stg.pstm->Seek(li, STREAM_SEEK_SET, NULL);
+                            
+									if(SUCCEEDED(stg.pstm->Read(pv, uli.LowPart, (PULONG)&uDataSize)))
+									{
+										GlobalUnlock(hg);
+
+										recset.SetData(hg);
+
+										//Update the DB
+										recset.Update();
+										bReadData = true;
+										
+										// Free the memory we just allocated.
+										GlobalFree(hg);
+									}
+									else
+									{
+										GlobalUnlock(hg);
+									}
+								}
+							}
+							break;  // case TYMED_ISTREAM
+						}
+						
+						ReleaseStgMedium(&stg);
+					}
+				}
+
+				if(bReadData)
+				{
+					GlobalUnlock(recset.m_ooData.m_hData);
+					GlobalFree(recset.m_ooData.m_hData);
+					recset.m_ooData.m_hData = NULL;
+				}
+			}
+		}
+		
+		recset.Close();
+
+		RemoveOldEntries();
+		CGetSetOptions::SetTripCopyCount(-1);
+		CGetSetOptions::SetTotalCopyCount(-1);
+	}
+	catch(CDaoException* e)
+	{
+		ASSERT(FALSE);
+		e->Delete();
+	}
+	
+	EXIT_DO_COPY(TRUE);
+}
+
+long CProcessCopy::StartCopyProcess()
+{
+	CString			csDescription;
+	BOOL			bReturn = FALSE;
+	CLIPFORMAT		MainType;
+	long			lReturnID = -1;
+
+	if(!GetCopyInfo(MainType))
+		return -1;
+
+	if(!GetDescriptionText(csDescription))
+		return -1;
+
+	long lRecID;
+	if((lRecID = DoesCopyEntryExist()) >= 0)
+	{
+		CMainTable recset;
+		recset.Open("SELECT * FROM Main WHERE lID = %d", lRecID);
+
+		if(!recset.IsEOF())
+		{
+			recset.Edit();
+
+			//Set the time to now since the entry was allready in the db
+			CTime now = CTime::GetCurrentTime();
+			recset.m_lDate = (long)now.GetTime();
+
+			recset.Update();
+
+			ShowCopyProperties(lRecID);
+			return -1;
+		}
+		else
+			ASSERT(FALSE);
+	}
+	
+	try
+	{
+		//There were valid types present add the text to the main table
+		CMainTable recset;
+
+		recset.Open("SELECT * FROM Main");
+			
+		recset.AddNew();
+
+		CTime now = CTime::GetCurrentTime();
+
+		recset.m_lDate = (long)now.GetTime();
+
+		recset.m_strType = GetDescriptionString(MainType);
+		recset.m_strText = csDescription;
+
+		recset.m_lTotalCopySize = m_lTotalCopySize;
+		
+		recset.Update();
+
+		recset.MoveLast();
+		
+		lReturnID = recset.m_lID;
+
+		recset.Close();
+
+		ShowCopyProperties(lReturnID);
+	}
+	catch(CDaoException* e)
+	{
+		ASSERT(FALSE);
+		e->Delete();
+		return -1;
+	}
+
+	return lReturnID;
+	
+
+	return -1;
+}
+
+void CProcessCopy::ShowCopyProperties(long lRecID)
+{
+	if(theApp.ShowCopyProperties)
+	{
+		HWND hWndFocus = GetActiveWnd();
+
+		::SendMessage(theApp.m_MainhWnd, WM_COPYPROPERTIES, lRecID, 0);
+		theApp.ShowCopyProperties = false;
+
+		::SetForegroundWindow(hWndFocus);
+	}
+}
+
+BOOL CProcessCopy::GetCopyInfo(CLIPFORMAT &MainType)
+{
+	m_lTotalCopySize = 0;
+	MainType = 0;
+	m_lSupportedTypesAvailable = 0;
+
+	//For each type we want to save
+	for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
+	{
+		//Is data available for that type
+		if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
+		{
+			m_lSupportedTypesAvailable++;
+
+			HGLOBAL hgData = m_oleData.GetGlobalData(m_SupportedTypes[i]);
+
+			//Get the size of the data
+			if(hgData != NULL)
+				m_lTotalCopySize += GlobalSize(hgData);
+		
+			if(MainType == 0)
+				MainType = m_SupportedTypes[i];			
+		}
+	}
+
+	return(m_lTotalCopySize > 0);
+}
+
+BOOL CProcessCopy::GetDescriptionText(CString &csText)
+{
+	BOOL bRet = FALSE;
+
+	if(m_oleData.IsDataAvailable(CF_TEXT))
+	{
+		//Get the text version of the data and return the text
+		char *text;
+		HGLOBAL hgData = m_oleData.GetGlobalData(CF_TEXT);
+
+		if(hgData != NULL)
+		{
+			//Get the text from the clipboard
+			text = (char *)GlobalLock(hgData);
+			ULONG ulBufLen = GlobalSize(hgData);
+
+			if(ulBufLen > LENGTH_OF_TEXT_SNIPET)
+				ulBufLen = LENGTH_OF_TEXT_SNIPET;
+
+			strncpy(csText.GetBuffer(ulBufLen-1), text, ulBufLen-1);
+			csText.ReleaseBuffer();
+			csText += '\0';
+					
+			//Unlock the data
+			GlobalUnlock(hgData);
+
+			// Free the memory that GetGlobalData() allocated for us.
+            GlobalFree(hgData);
+
+			bRet = TRUE;
+		}
+	}
+	else
+	{
+		//If the text is not available then get the description
+		for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
+		{
+			if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
+			{
+				csText = GetDescriptionString(m_SupportedTypes[i]);
+				bRet = TRUE;
+				break;
+			}
+		}
+	}
+
+	return bRet;
+}
+
+BOOL CProcessCopy::DoesCopyEntryExist()
+{
+	try
+	{
+		//Look for any other entries that have the save size
+		CMainTable recset;
+
+		recset.Open("SELECT * FROM Main WHERE lTotalCopySize = %d", m_lTotalCopySize);
+		
+		while(!recset.IsEOF())
+		{
+			//if there is any then look if it is an exact match
+			if(IsExactMatch(recset.m_lID))
+				return recset.m_lID;
+
+			recset.MoveNext();
+		}
+
+		recset.Close();
+	}
+	catch(CDaoException* e)
+	{
+		ASSERT(FALSE);
+		e->Delete();
+	}
+
+	return -1;
+}
+
+BOOL CProcessCopy::IsExactMatch(long lParentID)
+{
+	CDataTable recset;
+
+	//First check if they both have the same number of saved types
+	recset.Open("SELECT * FROM Data WHERE lParentID = %d", lParentID);
+	recset.MoveLast();
+	if(recset.GetRecordCount() != m_lSupportedTypesAvailable)
+		return FALSE;
+	recset.Close();
+	
+	//For each supported type
+	for(int i = 0; i < m_SupportedTypes.GetSize(); i++)
+	{
+		//That data is a available
+		if(m_oleData.IsDataAvailable(m_SupportedTypes[i]))
+		{
+			//look if there is a data with the same clipboard format name 'CF_TEXT' 'CF_DIB'
+			recset.Open("SELECT * FROM Data WHERE lParentID = %d AND strClipBoardFormat = \'%s\'", 
+							lParentID, GetFormatName(m_SupportedTypes[i]));
+
+			//Move last to get the total returned
+			recset.MoveLast();
+
+			long lRecordCount = recset.GetRecordCount();
+
+			//If it found one - it should only find one
+			if(lRecordCount == 1)
+			{
+				//Check the internal data of each if it is not a match then return FALSE
+				if(!recset.DataEqual(m_oleData.GetGlobalData(m_SupportedTypes[i])))
+					return FALSE;
+			}
+			else if(lRecordCount == 0)
+				return FALSE;
+			else if(lRecordCount > 1)
+			{
+				ASSERT(FALSE);
+				return FALSE;
+			}
+
+			recset.Close();
+		}
+	}
+
+	return TRUE;
+}
+
+CString CProcessCopy::GetDescriptionString(CLIPFORMAT cbType)
+{
+	switch(cbType)
+	{
+	case CF_TEXT:
+		return "CF_TEXT";
+	case CF_BITMAP:
+		return "CF_BITMAP";
+	case CF_METAFILEPICT:
+		return "CF_METAFILEPICT";
+	case CF_SYLK:
+		return "CF_SYLK";
+	case CF_DIF:
+		return "CF_DIF";
+	case CF_TIFF:
+		return "CF_TIFF";
+	case CF_OEMTEXT:
+		return "CF_OEMTEXT";
+	case CF_DIB:
+		return "CF_DIB";
+	case CF_PALETTE:
+		return "CF_PALETTE";
+	case CF_PENDATA:
+		return "CF_PENDATA";
+	case CF_RIFF:
+		return "CF_RIFF";
+	case CF_WAVE:
+		return "CF_WAVE";
+	case CF_UNICODETEXT:
+		return "CF_UNICODETEXT";
+	case CF_ENHMETAFILE:
+		return "CF_ENHMETAFILE";
+	case CF_HDROP:
+		return "CF_HDROP";
+	case CF_LOCALE:
+		return "CF_LOCALE";
+	case CF_OWNERDISPLAY:
+		return "CF_OWNERDISPLAY";
+	case CF_DSPTEXT:
+		return "CF_DSPTEXT";
+	case CF_DSPBITMAP:
+		return "CF_DSPBITMAP";
+	case CF_DSPMETAFILEPICT:
+		return "CF_DSPMETAFILEPICT";
+	case CF_DSPENHMETAFILE:
+		return "CF_DSPENHMETAFILE";
+	default:
+	{
+		//Not a default type get the name from the clipboard
+		if (cbType != 0)
+		{
+			TCHAR szFormat[256];
+            GetClipboardFormatName(cbType, szFormat, 256);
+			return szFormat;
+		}
+		break;
+	}
+	}
+
+	return "ERROR";
+}
+
+BOOL CProcessCopy::LoadSupportedTypes()
+{
+	m_SupportedTypes.RemoveAll();
+
+	try
+	{
+		CTypesTable recset;
+		recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Types" ,NULL);
+		if(recset.IsEOF())
+		{
+			m_SupportedTypes.Add(CF_TEXT);
+			m_SupportedTypes.Add(RegisterClipboardFormat(CF_RTF));
+		}
+		while(!recset.IsEOF())
+		{
+			m_SupportedTypes.Add(GetFormatID(recset.m_TypeText));
+			recset.MoveNext();
+		}
+	}
+	catch(CDaoException* e)
+	{
+		ASSERT(FALSE);
+		e->Delete();
+		m_SupportedTypes.Add(CF_TEXT);
+		m_SupportedTypes.Add(RegisterClipboardFormat(CF_RTF));
+	}
+
+	theApp.m_bReloadTypes = false;
+
+	return TRUE;
+}

+ 52 - 0
ProcessCopy.h

@@ -0,0 +1,52 @@
+// ProcessCopy.h: interface for the CProcessCopy class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PROCESSCOPY_H__185CBB6F_4B63_4397_8FF9_E18D777DA506__INCLUDED_)
+#define AFX_PROCESSCOPY_H__185CBB6F_4B63_4397_8FF9_E18D777DA506__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+#include <afxole.h>
+#include <afxtempl.h>
+
+class COleDataObjectEx : public COleDataObject
+{
+public:
+	HGLOBAL GetGlobalData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc = NULL);
+};
+
+
+#define LENGTH_OF_TEXT_SNIPET	249
+
+class CProcessCopy
+{
+public:
+	CProcessCopy();
+	virtual ~CProcessCopy();
+
+	BOOL DoCopy();
+	static CString GetDBString(CLIPFORMAT cbType);
+	static CString GetDescriptionString(CLIPFORMAT cbType);
+
+protected:
+	//Functions
+	BOOL IsSupportedType(CLIPFORMAT cbType);
+	long StartCopyProcess();
+	BOOL GetDescriptionText(CString &csText);
+	BOOL LoadSupportedTypes();
+	BOOL GetCopyInfo(CLIPFORMAT &MainType);
+	BOOL DoesCopyEntryExist();
+	BOOL IsExactMatch(long lParentID);
+	void ShowCopyProperties(long lRecID);
+
+	//Variables
+	COleDataObjectEx m_oleData;
+	CArray<CLIPFORMAT, CLIPFORMAT> m_SupportedTypes;
+	ULONG	m_lTotalCopySize;
+	long	m_lSupportedTypesAvailable;
+	CRITICAL_SECTION m_CriticalSection;
+};
+
+#endif // !defined(AFX_PROCESSCOPY_H__185CBB6F_4B63_4397_8FF9_E18D777DA506__INCLUDED_)

+ 155 - 0
ProcessPaste.cpp

@@ -0,0 +1,155 @@
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "ProcessPaste.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CProcessPaste::CProcessPaste()
+{
+}
+
+CProcessPaste::~CProcessPaste()
+{
+}
+
+BOOL CProcessPaste::LoadDataAndPaste(long lID, HWND hWnd)
+{
+	COleDataSource *pData = new COleDataSource;
+	if(LoadData(lID, pData))
+	{
+		MarkDataAsPasted(lID);
+
+		//Set this becase we just change the clipboard data so we will get a 
+		//clipboard change message
+		//If this is set we don't handle that message
+		theApp.m_bHandleClipboardDataChange = false;
+
+//		pData->FlushClipboard();
+		pData->SetClipboard();
+		
+		SendPaste(hWnd);
+		
+		//Set this back to handling messages
+		theApp.m_bHandleClipboardDataChange = true;
+
+		return TRUE;
+		
+	}
+
+	return FALSE;
+}
+
+BOOL CProcessPaste::LoadDataAndDrag(long lID)
+{
+	COleDataSource *pData = new COleDataSource;
+	if(LoadData(lID, pData))
+	{
+		if(pData->DoDragDrop(DROPEFFECT_COPY) != DROPEFFECT_NONE)
+		{
+			MarkDataAsPasted(lID);
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+BOOL CProcessPaste::MarkDataAsPasted(long lID)
+{
+	try
+	{	
+		//Update the time it was copied so that it appears at the top of the 
+		//past list items are sorted by this time
+		CMainTable ctMain;
+		ctMain.Open("SELECT * FROM Main WHERE lID = %d", lID);
+		ctMain.Edit();
+	
+		CTime now = CTime::GetCurrentTime();
+		ctMain.m_lDate = (long)now.GetTime();
+	
+		ctMain.Update();
+		ctMain.Close();
+
+		CGetSetOptions::SetTripPasteCount(-1);
+		CGetSetOptions::SetTotalPasteCount(-1);
+
+		return TRUE;
+	}
+	catch(CDaoException *e)
+	{
+		ASSERT(FALSE);
+		e->Delete();
+	}
+
+	return FALSE;
+}
+
+BOOL CProcessPaste::LoadData(long lID, COleDataSource *pData)
+{
+	if(pData)
+	{
+		int nCounter = 0;
+
+		try
+		{
+			CDataTable recset;
+
+			//Open the data table for all that have the parent id
+			CString csSQL, csFormatText;
+			csSQL.Format("SELECT * FROM Data WHERE lParentID = %d", lID);
+				
+			recset.Open(AFX_DAO_USE_DEFAULT_TYPE, csSQL);
+
+			//Go throught each item in the db putting it on the clipboard
+			while(!recset.IsEOF())
+			{
+				csFormatText = recset.m_strClipBoardFormat;
+				
+				if(recset.LoadData(pData, GetFormatID(csFormatText)))
+					nCounter++;
+
+				recset.MoveNext();		
+			}
+
+			recset.Close();
+
+			if(nCounter)
+				return TRUE;
+		}
+		catch(CDaoException* e)
+		{
+			ASSERT(FALSE);
+			e->Delete();
+		}
+	}
+
+	return FALSE;
+}
+
+void CProcessPaste::SendPaste(HWND hWnd)
+{
+	if(hWnd)
+	{
+		//Set a Control key down then a 'V' down then the ups
+		//To simulate a paste
+		::SetForegroundWindow(hWnd);
+		::SetFocus(hWnd);
+	
+		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
+		keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
+
+     
+		keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+		keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+	}
+	else
+		ASSERT(FALSE);
+}

+ 27 - 0
ProcessPaste.h

@@ -0,0 +1,27 @@
+// ProcessPaste.h: interface for the CProcessCopy class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PROCESSPASTE_H__185CBB6F_4B63_4397_8FF9_E18D777DA506__INCLUDED_)
+#define AFX_PROCESSPASTE_H__185CBB6F_4B63_4397_8FF9_E18D777DA506__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CProcessPaste
+{
+public:
+	CProcessPaste();
+	virtual ~CProcessPaste();
+
+	BOOL LoadDataAndPaste(long lID, HWND hWnd);
+	BOOL LoadDataAndDrag(long lID);
+
+protected:
+	void SendPaste(HWND hWnd);
+	BOOL LoadData(long lID, COleDataSource *pData);
+	BOOL MarkDataAsPasted(long lID);
+};
+
+#endif // !defined(AFX_PROCESSPASTE_H__185CBB6F_4B63_4397_8FF9_E18D777DA506__INCLUDED_)

+ 465 - 0
ProgressWnd.cpp

@@ -0,0 +1,465 @@
+#include "stdafx.h"
+#include "ProgressWnd.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define IDC_CANCEL   10
+#define IDC_TEXT     11
+#define IDC_PROGRESS 12
+
+LPCTSTR szSection = _T("Settings");   
+LPCTSTR szEntryX  = _T("X");
+LPCTSTR szEntryY  = _T("Y");
+
+/////////////////////////////////////////////////////////////////////////////
+// CProgressWnd
+
+CProgressWnd::CProgressWnd()
+{
+    CommonConstruct();
+}
+
+CProgressWnd::CProgressWnd(CWnd* pParent, LPCTSTR pszTitle, BOOL bSmooth /* = FALSE */)
+{
+    CommonConstruct();
+    m_strTitle = pszTitle;
+
+    Create(pParent, pszTitle, bSmooth);
+}
+
+void CProgressWnd::CommonConstruct()
+{
+    m_nNumTextLines  = 4;
+    m_nPrevPos       = 0;
+    m_nPrevPercent   = 0;
+    m_nStep          = 1;
+    m_nMinValue      = 0;
+    m_nMaxValue      = 100;
+
+    m_strTitle       = _T("Progress");
+    m_strCancelLabel = _T(" Cancel ");
+    m_bCancelled     = FALSE;
+    m_bModal         = FALSE;
+
+    m_bPersistantPosition = TRUE;   // saves and restores position automatically
+}
+
+CProgressWnd::~CProgressWnd()
+{
+    DestroyWindow();
+}
+
+BOOL CProgressWnd::Create(CWnd* pParent, LPCTSTR pszTitle, BOOL bSmooth /* = FALSE */)
+{
+    BOOL bSuccess;
+
+	m_strTitle = pszTitle;
+    // Register window class
+    CString csClassName = AfxRegisterWndClass(CS_OWNDC|CS_HREDRAW|CS_VREDRAW,
+                                              ::LoadCursor(NULL, IDC_APPSTARTING),
+                                              CBrush(::GetSysColor(COLOR_BTNFACE)));
+
+    // Get the system window message font for use in the cancel button and text area
+    NONCLIENTMETRICS ncm;
+    ncm.cbSize = sizeof(NONCLIENTMETRICS);
+    VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
+    m_font.CreateFontIndirect(&(ncm.lfMessageFont)); 
+
+    // If no parent supplied then try and get a pointer to it anyway
+    if (!pParent)
+        pParent = AfxGetMainWnd();
+
+    // Create popup window
+    //bSuccess = CreateEx(WS_EX_DLGMODALFRAME|WS_EX_TOPMOST, // Extended style
+	bSuccess = CreateEx(WS_EX_DLGMODALFRAME,
+                        csClassName,                       // Classname
+                        pszTitle,                          // Title
+                        WS_POPUP|WS_BORDER|WS_CAPTION,     // style
+                        0,0,                               // position - updated soon.
+                        390,130,                           // Size - updated soon
+                        pParent->GetSafeHwnd(),            // handle to parent
+                        0,                                 // No menu
+                        NULL);    
+    if (!bSuccess) return FALSE;
+
+    // Now create the controls
+    CRect TempRect(0,0,10,10);
+
+    bSuccess = m_Text.Create(_T(""), WS_CHILD|WS_VISIBLE|SS_NOPREFIX|SS_LEFTNOWORDWRAP,
+                             TempRect, this, IDC_TEXT);
+    if (!bSuccess) return FALSE;
+
+    DWORD dwProgressStyle = WS_CHILD|WS_VISIBLE;
+#ifdef PBS_SMOOTH    
+    if (bSmooth)
+       dwProgressStyle |= PBS_SMOOTH;
+#endif
+    bSuccess = m_wndProgress.Create(dwProgressStyle,TempRect, this, IDC_PROGRESS);
+    if (!bSuccess) return FALSE;
+
+    bSuccess = m_CancelButton.Create(m_strCancelLabel, 
+                                   WS_CHILD|WS_VISIBLE|WS_TABSTOP| BS_PUSHBUTTON, 
+                                     TempRect, this, IDC_CANCEL);
+    if (!bSuccess) return FALSE;
+
+    m_CancelButton.SetFont(&m_font, TRUE);
+    m_Text.SetFont(&m_font, TRUE);
+
+    // Resize the whole thing according to the number of text lines, desired window
+    // width and current font.
+    SetWindowSize(m_nNumTextLines, 390);
+
+    // Center and show window
+    if (m_bPersistantPosition)
+        GetPreviousSettings();
+    else
+        CenterWindow();
+
+    Show();
+
+    return TRUE;
+}
+
+BOOL CProgressWnd::GoModal(LPCTSTR pszTitle /*=_T("Progress")"*/, BOOL bSmooth /*=FALSE*/)
+{
+    CWnd *pMainWnd = AfxGetMainWnd();
+
+    if (!::IsWindow(m_hWnd) && !Create(pMainWnd, pszTitle, bSmooth))
+        return FALSE;
+
+    // Disable main window
+    if (pMainWnd)
+        pMainWnd->EnableWindow(FALSE);
+
+    // Re-enable this window
+    EnableWindow(TRUE);
+
+    m_bModal = TRUE;
+
+    return TRUE;
+}
+    
+void CProgressWnd::SetWindowSize(int nNumTextLines, int nWindowWidth /*=390*/)
+{
+    int nMargin = 10;
+    CSize EdgeSize(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
+
+    CRect TextRect, CancelRect, ProgressRect;
+    CSize CancelSize;
+
+    // Set up a default size for the text area in case things go wrong
+    TextRect.SetRect(nMargin,nMargin, nWindowWidth-2*nMargin, 100+2*nMargin);
+
+    // Get DrawText to tell us how tall the text area will be (while we're at
+    // it, we'll see how big the word "Cancel" is)
+    CDC* pDC = GetDC();
+    if (pDC) {
+        CFont* pOldFont = pDC->SelectObject(&m_font);
+        CString str = _T("M");
+        for (int i = 0; i < nNumTextLines-1; i++) str += _T("\nM");
+        pDC->DrawText(str, TextRect, DT_CALCRECT|DT_NOCLIP|DT_NOPREFIX);
+        TextRect.right = TextRect.left + nWindowWidth;
+        CancelSize = pDC->GetTextExtent(m_strCancelLabel + _T("  ")) +
+                                             CSize(EdgeSize.cx*4, EdgeSize.cy*3);
+        pDC->SelectObject(pOldFont);
+        ReleaseDC(pDC);
+    }
+    
+    // Work out how big (and where) the cancel button should be
+    CancelRect.SetRect(TextRect.right-CancelSize.cx, TextRect.bottom+nMargin, 
+                       TextRect.right, TextRect.bottom+nMargin + CancelSize.cy);
+
+
+    // Work out how big (and where) the progress control should be
+    ProgressRect.SetRect(TextRect.left, CancelRect.top + EdgeSize.cy, 
+                         CancelRect.left-nMargin, CancelRect.bottom - EdgeSize.cy);
+
+
+    // Resize the main window to fit the controls
+    CSize ClientSize(nMargin + TextRect.Width() + nMargin,
+                     nMargin + TextRect.Height() + nMargin + CancelRect.Height() + nMargin);
+
+    CRect WndRect, ClientRect;
+    GetWindowRect(WndRect); GetClientRect(ClientRect);
+    WndRect.right = WndRect.left + WndRect.Width()-ClientRect.Width()+ClientSize.cx;
+    WndRect.bottom = WndRect.top + WndRect.Height()-ClientRect.Height()+ClientSize.cy;
+    MoveWindow(WndRect);
+
+    // Now reposition the controls...
+    m_wndProgress.MoveWindow(ProgressRect);
+    m_CancelButton.MoveWindow(CancelRect);
+    m_Text.MoveWindow(TextRect);
+}
+
+void CProgressWnd::Clear() 
+{ 
+    SetText(_T(""));
+    SetPos(0);
+    m_bCancelled = FALSE; 
+    m_nPrevPos = 0;
+
+    if (::IsWindow(GetSafeHwnd()))
+        UpdateWindow();
+}
+
+void CProgressWnd::Hide()  
+{ 
+    if (!::IsWindow(GetSafeHwnd())) 
+        return;
+
+    if (IsWindowVisible())
+    {
+        ShowWindow(SW_HIDE);
+        ModifyStyle(WS_VISIBLE, 0);
+    }
+}
+
+void CProgressWnd::Show()  
+{ 
+    if (!::IsWindow(GetSafeHwnd()))
+        return;
+
+    if (!IsWindowVisible())
+    {
+        ModifyStyle(0, WS_VISIBLE);
+        ShowWindow(SW_SHOWNA);
+        RedrawWindow(NULL,NULL,RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
+    }
+}
+
+void CProgressWnd::SetRange(int nLower, int nUpper, int nStep /* = 1 */)    
+{
+    if (!::IsWindow(GetSafeHwnd())) 
+        return;
+
+ #ifdef PBM_SETRANGE32
+    ASSERT(-0x7FFFFFFF <= nLower && nLower <= 0x7FFFFFFF);
+    ASSERT(-0x7FFFFFFF <= nUpper && nUpper <= 0x7FFFFFFF);
+    m_wndProgress.SendMessage(PBM_SETRANGE32, (WPARAM) nLower, (LPARAM) nUpper);
+#else
+    ASSERT(0 <= nLower && nLower <= 65535);
+    ASSERT(0 <= nUpper && nUpper <= 65535);
+    m_wndProgress.SetRange(nLower, nUpper);
+#endif
+
+    m_nMaxValue = nUpper;
+    m_nMinValue = nLower;
+    m_nStep     = nStep;
+
+    m_wndProgress.SetStep(nStep);
+}
+
+int CProgressWnd::OffsetPos(int nPos)
+{ 
+    if (!::IsWindow(GetSafeHwnd())) 
+        return m_nPrevPos;
+
+    Show();
+
+    return SetPos(m_nPrevPos + nPos);  
+}
+
+int CProgressWnd::StepIt()                
+{
+    if (!::IsWindow(GetSafeHwnd())) 
+        return m_nPrevPos;
+
+    Show();
+
+    return SetPos(m_nPrevPos + m_nStep); 
+}
+
+int CProgressWnd::SetStep(int nStep)
+{
+    int nOldStep = m_nStep;
+    m_nStep = nStep;
+    if (!::IsWindow(GetSafeHwnd())) 
+        return nOldStep;
+
+    return m_wndProgress.SetStep(nStep); 
+}
+
+int CProgressWnd::SetPos(int nPos)                    
+{
+#ifdef PBM_SETRANGE32
+    ASSERT(-0x7FFFFFFF <= nPos && nPos <= 0x7FFFFFFF);
+#else
+    ASSERT(0 <= nPos && nPos <= 65535);
+#endif
+
+    if (!::IsWindow(GetSafeHwnd())) 
+        return m_nPrevPos;
+
+    Show();
+
+    CString strTitle;
+//  int nPercentage;
+    
+    m_nPrevPos = nPos;
+
+//    if (m_nMaxValue > m_nMinValue)
+//        nPercentage = (nPos*100)/(m_nMaxValue - m_nMinValue);
+//    else
+//        nPercentage = 0;
+
+//    if (nPercentage != m_nPrevPercent) 
+//    {
+//        m_nPrevPercent = nPercentage;
+//        strTitle.Format(_T("%s [%d%%]"),m_strTitle,nPercentage);
+		strTitle.Format(_T("%s"),m_strTitle);
+        SetWindowText(strTitle);
+//    }
+    return m_wndProgress.SetPos(nPos);        
+}
+
+void CProgressWnd::SetText(LPCTSTR fmt, ...)
+{
+    if (!::IsWindow(GetSafeHwnd())) 
+        return;
+
+    va_list args;
+    TCHAR buffer[512];
+
+    va_start(args, fmt);
+    _vstprintf(buffer, fmt, args);
+    va_end(args);
+
+    m_Text.SetWindowText(buffer);
+}
+
+BEGIN_MESSAGE_MAP(CProgressWnd, CWnd)
+    //{{AFX_MSG_MAP(CProgressWnd)
+    ON_WM_ERASEBKGND()
+	//}}AFX_MSG_MAP
+    ON_BN_CLICKED(IDC_CANCEL, OnCancel)
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CProgressWnd message handlers
+
+BOOL CProgressWnd::OnEraseBkgnd(CDC* pDC) 
+{
+    // Fill background with Catchment background colour
+    CBrush backBrush(GetSysColor(COLOR_BTNFACE));
+    CBrush* pOldBrush = pDC->SelectObject(&backBrush);
+    CRect rect;
+    pDC->GetClipBox(&rect);     // Erase the area needed
+    pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
+    pDC->SelectObject(pOldBrush);
+
+    return TRUE;
+}
+
+void CProgressWnd::OnCancel() 
+{
+    m_bCancelled = TRUE;
+    Hide();
+
+    if (m_bModal)
+        SendMessage(WM_CLOSE);
+
+    CWnd *pWnd = AfxGetMainWnd();
+    if (pWnd && ::IsWindow(pWnd->m_hWnd))
+        pWnd->SetForegroundWindow();
+}
+
+
+BOOL CProgressWnd::DestroyWindow() 
+{
+    if (m_bPersistantPosition)
+        SaveCurrentSettings();
+
+    if (m_bModal)
+    {
+        m_bModal = FALSE;
+        CWnd *pMainWnd = AfxGetMainWnd();
+
+        if (pMainWnd)
+            pMainWnd->EnableWindow(TRUE);
+    }
+	
+	return CWnd::DestroyWindow();
+}
+
+void CProgressWnd::PeekAndPump(BOOL bCancelOnESCkey /*= TRUE*/)
+{
+    if (m_bModal && ::GetFocus() != m_hWnd)
+        SetFocus();
+
+    MSG msg;
+    while (!m_bCancelled && ::PeekMessage(&msg, NULL,0,0,PM_NOREMOVE)) 
+    {
+        if (bCancelOnESCkey && (msg.message == WM_CHAR) && (msg.wParam == VK_ESCAPE))
+            OnCancel();
+
+        // Cancel button disabled if modal, so we fake it.
+        if (m_bModal && (msg.message == WM_LBUTTONUP))
+        {
+            CRect rect;
+            m_CancelButton.GetWindowRect(rect);
+            if (rect.PtInRect(msg.pt))
+                OnCancel();
+        }
+  
+        if (!AfxGetApp()->PumpMessage()) 
+        {
+            ::PostQuitMessage(0);
+            return;
+        } 
+    }
+}
+
+// Retores the previous window size from the registry
+void CProgressWnd::GetPreviousSettings()
+{
+    int x = AfxGetApp()->GetProfileInt(szSection, szEntryX, -1);
+    int y = AfxGetApp()->GetProfileInt(szSection, szEntryY, -1);
+
+    if (x >= 0 && x < GetSystemMetrics(SM_CXSCREEN) &&
+        y >= 0 && y < GetSystemMetrics(SM_CYSCREEN))
+    {
+        SetWindowPos(NULL, x,y, 0,0, SWP_NOSIZE|SWP_NOZORDER);
+    }
+    else
+        CenterWindow();
+}
+
+// Saves the current window position registry
+void CProgressWnd::SaveCurrentSettings()
+{   
+    if (!IsWindow(m_hWnd))
+        return;
+
+    CRect rect;
+    GetWindowRect(rect);
+
+    AfxGetApp()->WriteProfileInt(szSection, szEntryX, rect.left);
+    AfxGetApp()->WriteProfileInt(szSection, szEntryY, rect.top);
+}
+
+void CProgressWnd::HideCancel()
+{
+	m_CancelButton.ShowWindow(SW_HIDE);
+	UpdateData(FALSE);
+}
+
+void CProgressWnd::ShowCancel()
+{
+	m_CancelButton.ShowWindow(SW_SHOW);
+	UpdateData(FALSE);
+}
+
+void CProgressWnd::SetTitleText(CString csTitle)
+{
+	m_strTitle = csTitle;
+	
+	CString title;
+	title.Format(_T("%s"),m_strTitle);
+	
+	SetWindowText(title);
+}

+ 81 - 0
ProgressWnd.h

@@ -0,0 +1,81 @@
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CProgressWnd : public CWnd
+{
+// Construction/Destruction
+public:
+    CProgressWnd();
+    CProgressWnd(CWnd* pParent, LPCTSTR pszTitle, BOOL bSmooth = FALSE);
+    virtual ~CProgressWnd();
+
+    BOOL Create(CWnd* pParent, LPCTSTR pszTitle, BOOL bSmooth = FALSE);
+    BOOL GoModal(LPCTSTR pszTitle =_T("Progress"), BOOL bSmooth = FALSE);
+
+protected:
+    void CommonConstruct();
+
+// Operations
+public:
+    void SetRange(int nLower, int nUpper, int nStep = 1);
+                                                    // Set range and step size
+    int OffsetPos(int nPos);                        // Same as CProgressCtrl
+    int StepIt();                                   //    "
+    int SetStep(int nStep);                         //    "
+    int SetPos(int nPos);                           //    "
+
+    void SetText(LPCTSTR fmt, ...);                 // Set text in text area
+
+    void Clear();                                   // Clear text, reset bar
+    void Hide();                                    // Hide window
+    void Show();                                    // Show window
+	void HideCancel();
+	void ShowCancel();
+	int	 GetPos() const		{ return m_nPrevPos;	}
+
+    BOOL Cancelled() { return m_bCancelled; }       // Was "Cancel" hit?
+
+	void SetWindowSize(int nNumTextLines, int nWindowWidth = 390);
+
+    void PeekAndPump(BOOL bCancelOnESCkey = TRUE);  // Message pumping for modal operation   
+
+	void SetTitleText(CString csTitle);
+    
+// Implementation
+protected:
+    void GetPreviousSettings();
+    void SaveCurrentSettings();
+
+protected:
+    BOOL m_bCancelled;
+    BOOL m_bModal;
+    BOOL m_bPersistantPosition;
+    int  m_nPrevPos, m_nPrevPercent;
+    int  m_nStep;
+    int  m_nMaxValue, m_nMinValue;
+    int  m_nNumTextLines;
+
+    CStatic       m_Text;
+    CProgressCtrl m_wndProgress;
+    CButton       m_CancelButton;
+    CString       m_strTitle,
+                  m_strCancelLabel;
+    CFont         m_font;
+
+
+// Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CProgressWnd)
+	public:
+	virtual BOOL DestroyWindow();
+	//}}AFX_VIRTUAL
+
+// Generated message map functions
+protected:
+    //{{AFX_MSG(CProgressWnd)
+    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+	//}}AFX_MSG
+    afx_msg void OnCancel();
+    DECLARE_MESSAGE_MAP()
+};

+ 691 - 0
QListCtrl.cpp

@@ -0,0 +1,691 @@
+ // QListCtrl.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "QListCtrl.h"
+#include "ProcessPaste.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define ROW_BOTTOM_BORDER		2
+#define ROW_LEFT_BORDER			3
+#define COLOR_SHADOW			RGB(245, 245, 245)
+#define DUMMY_COL_WIDTH			1
+
+/////////////////////////////////////////////////////////////////////////////
+// CQListCtrl
+
+CQListCtrl::CQListCtrl()
+{
+	m_pchTip = NULL;
+	m_pwchTip = NULL;
+
+	LOGFONT lf;
+	
+	lf.lfHeight = -9;
+	lf.lfWidth = 0;
+	lf.lfEscapement = 0;
+	lf.lfOrientation = 0;
+	lf.lfWeight = FW_LIGHT;
+	lf.lfItalic = FALSE;
+	lf.lfUnderline = FALSE;
+	lf.lfStrikeOut = FALSE;
+	lf.lfCharSet = ANSI_CHARSET;
+	lf.lfOutPrecision = OUT_STRING_PRECIS;
+	lf.lfClipPrecision = CLIP_STROKE_PRECIS;
+	lf.lfQuality = DEFAULT_QUALITY;
+	lf.lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
+	lstrcpy(lf.lfFaceName, "Small Font");
+
+	m_SmallFont = CreateFontIndirect(&lf);
+
+	m_bShowTextForFirstTenHotKeys = true;
+	m_Accelerator = NULL;
+	m_acFirstTen = NULL;
+}
+
+CQListCtrl::~CQListCtrl()
+{
+	if(m_pchTip != NULL)
+		delete m_pchTip;
+
+	if(m_pwchTip != NULL)
+		delete m_pwchTip;
+
+	DestroyAndCreateAccelerator(FALSE);
+
+	if(m_acFirstTen)
+	{
+		DestroyAcceleratorTable(m_acFirstTen);
+		m_acFirstTen = NULL;
+	}
+}
+
+
+BEGIN_MESSAGE_MAP(CQListCtrl, CListCtrl)
+	//{{AFX_MSG_MAP(CQListCtrl)
+	ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
+	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
+	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdrawList)
+	ON_WM_SYSKEYDOWN()
+	ON_WM_ERASEBKGND()
+	ON_WM_CREATE()
+	ON_WM_VSCROLL()
+	ON_WM_HSCROLL()
+	//}}AFX_MSG_MAP
+	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
+	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CQListCtrl message handlers
+
+void CQListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
+	
+	switch (pLVKeyDow->wVKey)
+	{
+	case VK_RETURN:
+		{
+			ARRAY arr;
+			GetSelectionIndexes(arr);
+			
+			SendSelection(arr);
+		}
+		break;
+
+	case VK_ESCAPE:
+		GetParent()->SendMessage(NM_END, 0, 0);
+		break;
+
+	case VK_RIGHT:
+		{
+			int nItem = GetNextItem(-1, LVNI_SELECTED);
+			if (nItem != -1)
+				GetParent()->SendMessage(NM_RIGHT, nItem, 0);
+		}
+		break;
+
+	case VK_LEFT:
+		GetParent()->SendMessage(NM_LEFT, 0, 0);
+		break;
+	case VK_DELETE:
+		GetParent()->SendMessage(NM_DELETE, 0, 0);
+		break;
+	}
+
+	*pResult = 0;
+}
+
+void CQListCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	LPNMITEMACTIVATE lpnmItem = (LPNMITEMACTIVATE) pNMHDR;
+	
+	UINT Flags;
+	int nItem = -1;
+	if ((nItem = HitTest(lpnmItem->ptAction, &Flags)) != -1)
+	{
+		if (Flags | LVHT_ONITEM)
+			SendSelection(nItem);
+	}
+
+	*pResult = 0;
+}
+
+void CQListCtrl::SendSelection(int nItem)
+{
+	GetParent()->SendMessage(NM_SELECT, 1, (LPARAM) &nItem);
+}
+
+void CQListCtrl::SendSelection(ARRAY &arrItems)
+{
+	GetParent()->SendMessage(NM_SELECT, arrItems.GetSize(), (LPARAM) arrItems.GetData());
+}
+
+void CQListCtrl::GetSelectionIndexes(ARRAY &arr)
+{
+	arr.RemoveAll();
+
+	POSITION pos = GetFirstSelectedItemPosition();
+	while (pos)
+		arr.Add(GetNextSelectedItem(pos));
+	
+
+	/*
+	int nItem = GetNextItem(-1, LVNI_SELECTED);
+	while (nItem != -1)
+	{
+		arr.Add(nItem);
+		nItem = GetNextItem(nItem, LVNI_SELECTED);
+	}
+	*/
+}
+
+void CQListCtrl::GetSelectionItemData(ARRAY &arr)
+{
+	arr.RemoveAll();
+	POSITION pos = GetFirstSelectedItemPosition();
+	while (pos)
+		arr.Add(GetItemData(GetNextSelectedItem(pos)));
+	
+	/*
+	int nItem = GetNextItem(-1, LVNI_SELECTED);
+	while (nItem != -1)
+	{
+		arr.Add((int)GetItemData(nItem));
+		nItem = GetNextItem(nItem, LVNI_SELECTED);
+	}
+	*/
+}
+
+void CQListCtrl::RemoveAllSelection()
+{
+	POSITION pos = GetFirstSelectedItemPosition();
+	while (pos)
+	{
+		SetSelection(GetNextSelectedItem(pos), FALSE);
+	}
+}
+
+BOOL CQListCtrl::SetSelection(int nRow, BOOL bSelect)
+{
+	if(bSelect)
+		return SetItemState(nRow, LVIS_SELECTED, LVIS_SELECTED);
+	else
+		return SetItemState(nRow, ~LVIS_SELECTED, LVIS_SELECTED);
+}
+
+BOOL CQListCtrl::SetText(int nRow, int nCol, CString cs)
+{
+	return SetItemText(nRow, nCol, cs);
+}
+
+BOOL CQListCtrl::SetCaret(int nRow, BOOL bFocus)	
+{
+	if(bFocus)
+		return SetItemState(nRow, LVIS_FOCUSED, LVIS_FOCUSED);
+	else
+		return SetItemState(nRow, ~LVIS_FOCUSED, LVIS_FOCUSED);
+}
+
+long CQListCtrl::GetCaret()
+{
+	return GetNextItem(0, LVNI_FOCUSED);
+}
+
+BOOL CQListCtrl::SetFormattedText(int nRow, int nCol, LPCTSTR lpszFormat,...)
+{
+	CString csText;
+	va_list vlist;
+
+	ASSERT(AfxIsValidString(lpszFormat));
+	va_start(vlist,lpszFormat);
+	csText.FormatV(lpszFormat,vlist);
+	va_end(vlist);
+
+	return SetText(nRow,nCol,csText);
+}
+
+void CQListCtrl::SetNumberOfLinesPerRow(int nLines)
+{
+	CDC *pDC = GetDC();
+
+	CRect crRect(0, 0, 0, 0);
+
+	CFont *pOldFont = pDC->SelectObject(GetFont());
+
+	//Get the height to draw one character
+	pDC->DrawText("W", crRect, DT_VCENTER | DT_EXPANDTABS | DT_CALCRECT);
+
+	pDC->SelectObject(pOldFont);
+
+	//Get the total height of each row
+	int nHeight = (crRect.Height() * nLines) + ROW_BOTTOM_BORDER;
+
+	//Create a image list of that height and set it to the list box
+	CImageList imglist;
+	imglist.Create(DUMMY_COL_WIDTH, nHeight, ILC_COLOR16 | ILC_MASK, 1, 1);
+	SetImageList(&imglist, LVSIL_SMALL );
+}
+
+void CQListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
+    
+    *pResult = 0;
+
+    // Request item-specific notifications if this is the
+    // beginning of the paint cycle.
+    if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
+	{
+        *pResult = CDRF_NOTIFYITEMDRAW;
+	}
+    else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
+	{
+        LVITEM   rItem;
+        int      nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec );
+        CDC*     pDC   = CDC::FromHandle ( pLVCD->nmcd.hdc );
+        COLORREF crBkgnd;
+        BOOL     bListHasFocus;
+        CRect    rcItem;
+                		
+        bListHasFocus = ( GetSafeHwnd() == ::GetFocus() );
+        
+        // Get the image index and selected/focused state of the
+        // item being drawn.
+        ZeroMemory ( &rItem, sizeof(LVITEM) );
+        rItem.mask  = LVIF_STATE;
+        rItem.iItem = nItem;
+        rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
+        GetItem(&rItem);
+				
+        // Get the rect that bounds the text label.
+        GetItemRect(nItem, rcItem, LVIR_LABEL);
+		rcItem.left -= DUMMY_COL_WIDTH;
+
+		CPen cpWhite;
+		cpWhite.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+		CPen *pOldPen = NULL;
+		COLORREF OldColor = -1;
+		int nOldBKMode = -1;
+		
+        // Draw the background of the list item.  Colors are selected 
+        // according to the item's state.
+        if(rItem.state & LVIS_SELECTED)
+		{
+            if(bListHasFocus)
+			{
+                crBkgnd = GetSysColor(COLOR_HIGHLIGHT);
+                OldColor = pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
+				pOldPen = pDC->SelectObject((CPen*)&cpWhite);
+			}
+            else
+			{
+                crBkgnd = GetSysColor(COLOR_BTNFACE);
+                OldColor = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
+			}
+		}
+        else
+		{
+            //Shade alternating Rows
+			if((nItem % 2) == 0)
+				crBkgnd = COLOR_SHADOW;
+			else
+				crBkgnd = GetSysColor(COLOR_WINDOW);
+			
+            OldColor = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
+		}
+		
+        pDC->FillSolidRect(rcItem, crBkgnd);
+        nOldBKMode = pDC->SetBkMode(TRANSPARENT);
+		
+        CRect rcText = rcItem;
+        rcText.left += ROW_LEFT_BORDER;
+		rcText.top++;
+		
+        // Draw the text.
+        CString csText = GetItemText(nItem, 0);
+	
+		if(m_bShowTextForFirstTenHotKeys)
+		{
+			if(nItem < 10)
+				rcText.left += 12;
+		}
+
+		pDC->DrawText(csText, rcText, DT_VCENTER | DT_EXPANDTABS);
+		
+        // Draw a focus rect around the item if necessary.
+        if(bListHasFocus && (rItem.state & LVIS_FOCUSED))
+			pDC->DrawFocusRect(rcItem);
+
+		if((nItem < 10) && (m_bShowTextForFirstTenHotKeys))
+		{
+			CString cs;
+			if(nItem == 9)
+				cs.Format("%d", 0);
+			else
+				cs.Format("%d", nItem+1);
+
+			CRect crClient;
+			
+			GetWindowRect(crClient);
+			ScreenToClient(crClient);
+			
+			CRect crHotKey = rcItem;
+			
+			crHotKey.right = crHotKey.left + 11;
+			crHotKey.left += 2;
+			crHotKey.top += 2;
+
+			HFONT hOldFont = (HFONT)pDC->SelectObject(m_SmallFont);
+
+			pDC->DrawText(cs, crHotKey, DT_BOTTOM);
+
+			pDC->MoveTo(CPoint(rcItem.left + 11, rcItem.top));
+			pDC->LineTo(CPoint(rcItem.left + 11, rcItem.bottom));
+			
+			pDC->SelectObject(hOldFont);
+		}
+
+		if(pOldPen)
+			pDC->SelectObject(pOldPen);
+
+		if(OldColor > -1)
+			pDC->SetTextColor(OldColor);
+
+		if(nOldBKMode > -1)
+			pDC->SetBkMode(nOldBKMode);
+
+        *pResult = CDRF_SKIPDEFAULT;    // We've painted everything.
+	}
+}
+
+void CQListCtrl::RefreshVisibleRows()
+{
+	int nTopIndex = GetTopIndex();
+	int nLastIndex = nTopIndex + GetCountPerPage();
+	RedrawItems(nTopIndex, nLastIndex);
+	::UpdateWindow(m_hWnd);
+}
+
+void CQListCtrl::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
+{
+	if(GetKeyState(VK_RETURN) & 0x800)
+		GetParent()->SendMessage(NM_PROPERTIES, 0, 0);
+	else
+		CListCtrl::OnSysKeyDown(nChar, nRepCnt, nFlags);
+}
+
+BOOL CQListCtrl::OnEraseBkgnd(CDC* pDC) 
+{
+//	return TRUE;
+	return CListCtrl::OnEraseBkgnd(pDC);
+}
+
+BOOL CQListCtrl::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
+{
+	// need to handle both ANSI and UNICODE versions of the message
+	TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
+	TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
+	CString strTipText;
+
+	UINT nID = pNMHDR->idFrom;
+
+	if(nID == 0)	  	// Notification in NT from automatically
+		return FALSE;   	// created tooltip
+	
+	::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 500);
+
+	// Use Item's name as the tool tip. Change this for something different.
+	// Like use its file size, etc.
+	strTipText = GetToolTipText(nID-1);
+
+	//Replace the tabs with 5 spaces, the tooltip didn't like the \t s
+	strTipText.Replace("\t", "     ");
+
+#ifndef _UNICODE
+	if (pNMHDR->code == TTN_NEEDTEXTA)
+	{
+		if(m_pchTip != NULL)
+			delete m_pchTip;
+		
+		m_pchTip = new TCHAR[strTipText.GetLength()+1];
+		lstrcpyn(m_pchTip, strTipText, strTipText.GetLength());
+		m_pchTip[strTipText.GetLength()] = 0;
+		pTTTW->lpszText = (WCHAR*)m_pchTip;
+	}
+	else
+	{
+		if(m_pwchTip != NULL)
+			delete m_pwchTip;
+
+		m_pwchTip = new WCHAR[strTipText.GetLength()+1];
+		_mbstowcsz(m_pwchTip, strTipText, strTipText.GetLength());
+		m_pwchTip[strTipText.GetLength()] = 0; // end of text
+		pTTTW->lpszText = (WCHAR*)m_pwchTip;
+	}
+#else
+	if(pNMHDR->code == TTN_NEEDTEXTA)
+	{
+		if(m_pchTip != NULL)
+			delete m_pchTip;
+
+		m_pchTip = new TCHAR[strTipText.GetLength()+1];
+		_wcstombsz(m_pchTip, strTipText, strTipText.GetLength());
+		m_pchTip[strTipText.GetLength()] = 0; // end of text
+		pTTTA->lpszText = (LPTSTR)m_pchTip;
+	}
+	else
+	{
+		if(m_pwchTip != NULL)
+			delete m_pwchTip;
+
+		m_pwchTip = new WCHAR[strTipText.GetLength()+1];
+		lstrcpyn(m_pwchTip, strTipText, strTipText.GetLength());
+		m_pwchTip[strTipText.GetLength()] = 0;
+		pTTTA->lpszText = (LPTSTR) m_pwchTip;
+	}
+#endif
+	*pResult = 0;
+
+	return TRUE;    // message was handled
+}
+
+int CQListCtrl::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
+{
+	CRect rect;
+	GetClientRect(&rect);
+	if(rect.PtInRect(point))
+	{
+		if(GetItemCount())
+		{
+			int nTopIndex = GetTopIndex();
+			int nBottomIndex = nTopIndex + GetCountPerPage();
+			if(nBottomIndex > GetItemCount()) nBottomIndex = GetItemCount();
+			for(int nIndex = nTopIndex; nIndex <= nBottomIndex; nIndex++)
+			{
+				GetItemRect(nIndex, rect, LVIR_BOUNDS);
+				if(rect.PtInRect(point))
+				{
+					pTI->hwnd = m_hWnd;
+					pTI->uId = (UINT)(nIndex+1);
+					pTI->lpszText = LPSTR_TEXTCALLBACK;
+					pTI->rect = rect;
+					return pTI->uId;
+				}
+			}
+		}
+	}
+
+	return -1;
+}
+
+int CQListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
+{
+	if (CListCtrl::OnCreate(lpCreateStruct) == -1)
+		return -1;
+	
+	EnableToolTips();
+
+	return 0;
+}
+
+BOOL CQListCtrl::PreTranslateMessage(MSG* pMsg) 
+{
+	if(m_Accelerator)
+	{
+		m_CheckingAccelerator = true;
+		if(TranslateAccelerator(m_hWnd, m_Accelerator, pMsg) != 0)
+		{
+			m_CheckingAccelerator = false;
+			return TRUE;
+		}
+		m_CheckingAccelerator = false;
+	}
+
+	if(m_acFirstTen)
+	{
+		m_CheckingAccelerator = true;
+		if(TranslateAccelerator(m_hWnd, m_acFirstTen, pMsg) != 0)
+		{
+			m_CheckingAccelerator = false;
+			return TRUE;
+		}
+		m_CheckingAccelerator = false;
+	}
+
+	switch(pMsg->message) 
+	{
+	case WM_KEYDOWN:
+		if(pMsg->wParam == 'A')
+		{
+			if(GetKeyState(VK_CONTROL) & 0x8000)
+			{
+				int nCount = GetItemCount();
+				for(int i = 0; i < nCount; i++)
+				{
+					SetSelection(i);
+				}
+				return TRUE;
+			}
+		}
+		break;
+	}
+
+	return CListCtrl::PreTranslateMessage(pMsg);
+}
+
+CString CQListCtrl::GetToolTipText(int nItem)
+{
+	CString cs;
+
+	if((GetStyle() & LVS_OWNERDATA))
+	{
+		CWnd* pParent=GetParent();
+		if(pParent && (pParent->GetSafeHwnd() != NULL))
+		{
+			CQListToolTipText info;
+			memset(&info, 0, sizeof(info));
+			info.hdr.code = NM_GETTOOLTIPTEXT;
+			info.hdr.hwndFrom = GetSafeHwnd();
+			info.hdr.idFrom = GetDlgCtrlID();
+
+			info.lItem = nItem;
+					
+			pParent->SendMessage(WM_NOTIFY,(WPARAM)info.hdr.idFrom,(LPARAM)&info);
+
+			cs = info.cText;
+		}
+	}
+
+	return cs;
+}
+
+DWORD CQListCtrl::GetItemData(int nItem)
+{
+	if((GetStyle() & LVS_OWNERDATA))
+	{
+		CWnd* pParent=GetParent();
+		if(pParent && (pParent->GetSafeHwnd() != NULL))
+		{
+			LV_DISPINFO info;
+			memset(&info, 0, sizeof(info));
+			info.hdr.code = LVN_GETDISPINFO;
+			info.hdr.hwndFrom = GetSafeHwnd();
+			info.hdr.idFrom = GetDlgCtrlID();
+
+			info.item.iItem = nItem;
+			info.item.lParam = -1;
+			info.item.mask = LVIF_PARAM;
+		
+			pParent->SendMessage(WM_NOTIFY,(WPARAM)info.hdr.idFrom,(LPARAM)&info);
+
+			return info.item.lParam;
+		}
+	}
+
+	return CListCtrl::GetItemData(nItem);
+}
+
+void CQListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
+{		
+	CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
+}
+
+void CQListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
+{	
+	CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
+}
+
+void CQListCtrl::DestroyAndCreateAccelerator(BOOL bCreate)
+{
+	if(m_Accelerator)
+	{
+		DestroyAcceleratorTable(m_Accelerator);
+		m_Accelerator = NULL;
+	}
+	
+	if(bCreate)
+		m_Accelerator = CMainTable::LoadAcceleratorKeys();
+}
+
+void CQListCtrl::LoadFirstTenHotKeys(CMainTable &recset)
+{
+	if(m_acFirstTen)
+	{
+		DestroyAcceleratorTable(m_acFirstTen);
+		m_acFirstTen = NULL;
+	}
+
+	int nMax = min(10, recset.GetRecordCount());
+	CArray<ACCEL, ACCEL> keys;
+	recset.MoveFirst();
+	BOOL bAddControl = CGetSetOptions::GetUseCtrlNumForFirstTenHotKeys();
+	
+	for(int i = 0; i < nMax; i++)
+	{
+		ACCEL me;
+		me.cmd = (USHORT)recset.m_lID;
+		me.fVirt = 0;
+		
+		if(bAddControl)
+		{
+			me.fVirt |= FCONTROL;
+		}
+		
+		me.fVirt |= FVIRTKEY;
+
+		if(i == 9)
+			me.key = 48;
+		else
+			me.key = 49+i;
+
+		keys.Add(me);
+
+		recset.MoveNext();
+	}
+
+	if(keys.GetSize() > 0)
+		m_acFirstTen = CreateAcceleratorTable(keys.GetData(), keys.GetSize());
+}
+
+BOOL CQListCtrl::OnCommand(WPARAM wParam, LPARAM lParam) 
+{
+	//return 1 if from accelerator
+	if((HIWORD(wParam) == 1) && (m_CheckingAccelerator))
+	{
+		USHORT usPasteID = LOWORD(wParam);
+
+		GetParent()->SendMessage(NM_SELECT_DB_ID, usPasteID, 0);
+
+		return TRUE;
+	}
+	
+	return CListCtrl::OnCommand(wParam, lParam);
+}

+ 113 - 0
QListCtrl.h

@@ -0,0 +1,113 @@
+ #if !defined(AFX_QLISTCTRL_H__30BEB04A_4B97_4943_BB73_C5128E66B4ED__INCLUDED_)
+#define AFX_QLISTCTRL_H__30BEB04A_4B97_4943_BB73_C5128E66B4ED__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// QListCtrl.h : header file
+//
+#include "ArrayEx.h"
+
+#define NM_SELECT					WM_USER+0x100
+#define NM_RIGHT					WM_USER+0x101
+#define NM_LEFT						WM_USER+0x102
+#define NM_END						WM_USER+0x103
+#define NM_DELETE					WM_USER+0x105
+#define NM_PROPERTIES				WM_USER+0x106
+#define NM_LBUTTONDOWN				WM_USER+0x107
+#define NM_GETTOOLTIPTEXT	        WM_USER+0x108
+#define NM_SELECT_DB_ID		        WM_USER+0x109
+
+class CQListToolTipText
+{
+public:
+	CQListToolTipText()
+	{
+		memset(&cText, 0, sizeof(cText));
+	}
+
+	NMHDR hdr;
+	char cText[500];
+	long lItem;
+};
+
+class CQListCtrl : public CListCtrl
+{
+// Construction
+public:
+	CQListCtrl();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CQListCtrl)
+	public:
+	virtual int OnToolHitTest(CPoint point, TOOLINFO * pTI) const;
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+	//}}AFX_VIRTUAL
+
+// Implementation
+public:
+	virtual ~CQListCtrl();
+
+	void SetNumberOfLinesPerRow(int nLines);
+	void GetSelectionIndexes(ARRAY &arr);
+	void GetSelectionItemData(ARRAY &arr);
+	void RefreshVisibleRows();
+	void RemoveAllSelection();
+	BOOL SetSelection(int nRow, BOOL bSelect = TRUE);
+	BOOL SetText(int nRow, int nCol, CString cs);
+	BOOL SetFormattedText(int nRow, int nCol, LPCTSTR lpszFormat,...);
+	BOOL SetCaret(int nRow, BOOL bFocus = TRUE);
+	long GetCaret();
+	DWORD GetItemData(int nItem);
+	CString GetToolTipText(int nItem);
+
+	void SetShowTextForFirstTenHotKeys(BOOL bVal)	{ m_bShowTextForFirstTenHotKeys = bVal;	}
+
+	void DestroyAndCreateAccelerator(BOOL bCreate);
+	void LoadFirstTenHotKeys(CMainTable &recset);
+
+protected:
+	void SendSelection(int nItem);;
+	void SendSelection(ARRAY &arrItems);
+	
+	WCHAR *m_pwchTip;
+	TCHAR *m_pchTip;
+
+	HFONT m_SmallFont;
+	BOOL  m_bShowTextForFirstTenHotKeys;
+
+	//Accelerator
+	HACCEL	m_Accelerator;
+	HACCEL	m_acFirstTen;
+	bool	m_CheckingAccelerator;
+	
+	// Generated message map functions
+protected:
+	//{{AFX_MSG(CQListCtrl)
+	afx_msg void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnDblclk(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+	//}}AFX_MSG
+	afx_msg BOOL OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult );
+	DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_QLISTCTRL_H__30BEB04A_4B97_4943_BB73_C5128E66B4ED__INCLUDED_)

+ 1001 - 0
QPasteWnd.cpp

@@ -0,0 +1,1001 @@
+// QPasteWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "QPasteWnd.h"
+#include "ProcessPaste.h"
+#include "CopyProperties.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define ID_LIST_HEADER			0x201
+#define ID_EDIT_SEARCH			0x202
+#define ID_CANCEL				0x203
+
+
+#define QPASTE_WIDTH			200
+#define	QPASTE_HEIGHT			200
+
+/////////////////////////////////////////////////////////////////////////////
+// CQPasteWnd
+
+CQPasteWnd::CQPasteWnd()
+{	
+	m_bHideWnd = true;
+	m_Recset.m_strSort = "lDate DESC";
+}
+
+CQPasteWnd::~CQPasteWnd()
+{
+	
+}
+
+
+BEGIN_MESSAGE_MAP(CQPasteWnd, CWndEx)
+	//{{AFX_MSG_MAP(CQPasteWnd)
+	ON_WM_CREATE()
+	ON_WM_SIZE()
+	ON_WM_SETFOCUS()
+	ON_WM_ACTIVATE()
+	ON_COMMAND(ID_MENU_LINESPERROW_1, OnMenuLinesperrow1)
+	ON_COMMAND(ID_MENU_LINESPERROW_2, OnMenuLinesperrow2)
+	ON_COMMAND(ID_MENU_LINESPERROW_3, OnMenuLinesperrow3)
+	ON_COMMAND(ID_MENU_LINESPERROW_4, OnMenuLinesperrow4)
+	ON_COMMAND(ID_MENU_LINESPERROW_5, OnMenuLinesperrow5)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_10, OnMenuTransparency10)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_15, OnMenuTransparency15)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_20, OnMenuTransparency20)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_25, OnMenuTransparency25)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_30, OnMenuTransparency30)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_40, OnMenuTransparency40)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_5, OnMenuTransparency5)
+	ON_COMMAND(ID_MENU_TRANSPARENCY_NONE, OnMenuTransparencyNone)
+	ON_NOTIFY(NM_RCLICK, ID_LIST_HEADER, OnRclickQuickPaste)
+	ON_COMMAND(ID_MENU_DELETE, OnMenuDelete)
+	ON_COMMAND(ID_MENU_POSITIONING_ATCARET, OnMenuPositioningAtcaret)
+	ON_COMMAND(ID_MENU_POSITIONING_ATCURSOR, OnMenuPositioningAtcursor)
+	ON_COMMAND(ID_MENU_POSITIONING_ATPREVIOUSPOSITION, OnMenuPositioningAtpreviousposition)
+	ON_COMMAND(ID_MENU_OPTIONS, OnMenuOptions)
+	ON_BN_CLICKED(ID_CANCEL, OnCancelFilter)
+	ON_COMMAND(ID_MENU_EXITPROGRAM, OnMenuExitprogram)
+	ON_COMMAND(ID_MENU_RECONNECTTOCLIPBOARDCHAIN, OnMenuReconnecttoclipboardchain)
+	ON_COMMAND(ID_MENU_PROPERTIES, OnMenuProperties)
+	ON_WM_CLOSE()
+	ON_NOTIFY(LVN_BEGINDRAG, ID_LIST_HEADER, OnBegindrag)
+	ON_WM_SYSKEYDOWN()
+	ON_NOTIFY(LVN_GETDISPINFO, ID_LIST_HEADER, GetDispInfo)
+	ON_NOTIFY(LVN_ODFINDITEM, ID_LIST_HEADER, OnFindItem)
+	ON_COMMAND(ID_MENU_FIRSTTENHOTKEYS_USECTRLNUM, OnMenuFirsttenhotkeysUsectrlnum)
+	ON_COMMAND(ID_MENU_FIRSTTENHOTKEYS_SHOWHOTKEYTEXT, OnMenuFirsttenhotkeysShowhotkeytext)
+	//}}AFX_MSG_MAP
+	ON_MESSAGE(NM_SELECT, OnListSelect)
+	ON_MESSAGE(NM_END, OnListEnd)
+	ON_MESSAGE(CB_SEARCH, OnSearch)
+	ON_MESSAGE(NM_DELETE, OnDelete)
+	ON_MESSAGE(NM_PROPERTIES, OnProperties)
+	ON_NOTIFY(NM_GETTOOLTIPTEXT, ID_LIST_HEADER, OnGetToolTipText)
+	ON_MESSAGE(NM_SELECT_DB_ID, OnListSelect_DB_ID)
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CQPasteWnd message handlers
+
+BOOL CQPasteWnd::Create(const POINT& ptStart, CWnd* pParentWnd) 
+{
+	// Get the previous size of the QPaste window
+	CSize szWnd;
+	CGetSetOptions::GetQuickPasteSize(szWnd);
+	
+	return CWndEx::Create(CRect(ptStart, szWnd), pParentWnd);
+}
+
+int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
+{
+	if (CWndEx::OnCreate(lpCreateStruct) == -1)
+		return -1;
+	
+	SetWindowText("Ditto");
+	
+	m_cbSearch.Create(CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP | WS_CHILD | WS_VISIBLE | CBS_AUTOHSCROLL, 
+						CRect(0, 0, 0, 0), this, ID_EDIT_SEARCH);
+	
+	// Create the header control
+	if (!m_lstHeader.Create(WS_TABSTOP|WS_CHILD|WS_VISIBLE|LVS_NOCOLUMNHEADER|LVS_REPORT|LVS_SHOWSELALWAYS|LVS_OWNERDATA,
+		CRect(0, 0, 0, 0),	this, ID_LIST_HEADER))
+	{
+		ASSERT(FALSE);
+		return -1;
+	}
+
+	m_btCancel.Create("&C", WS_CHILD|BS_PUSHBUTTON|WS_TABSTOP/*|BS_FLAT*/, CRect(0, 0, 0, 0), this, ID_CANCEL);
+
+	//Set the z-order
+	m_lstHeader.SetWindowPos(this, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+	m_cbSearch.SetWindowPos(&m_lstHeader, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+	m_btCancel.SetWindowPos(&m_cbSearch, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+
+	//LVS_EX_FLATSB
+	m_lstHeader.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP);
+
+	// Create the columns
+	if (m_lstHeader.InsertColumn(0, "", LVCFMT_LEFT, 0, 0) != 0)
+	{
+		ASSERT(FALSE);
+		return -1;
+	}
+
+	#ifdef AFTER_98
+		m_Alpha.SetWindowHandle(m_hWnd);	
+	#endif
+	
+	//Show the window
+	ShowQPasteWindow(FALSE);
+	
+	m_TitleFont.CreateFont(14,0,-900,0,400,FALSE,FALSE,0,ANSI_CHARSET,
+	OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
+	DEFAULT_PITCH|FF_SWISS,"Arial");
+	
+	m_SearchFont.CreatePointFont(80, "MS Sans Serif");
+
+	m_cbSearch.SetFont(&m_SearchFont);
+	m_btCancel.SetFont(&m_SearchFont);
+
+	
+	return 0;
+}
+
+void CQPasteWnd::OnSize(UINT nType, int cx, int cy) 
+{
+	CWndEx::OnSize(nType, cx, cy);
+
+	if(!IsWindow(m_lstHeader.m_hWnd))
+		return;
+
+	//Create the region for drawing the rounded top edge
+	CRect rect;
+	GetWindowRect(rect);
+	CRgn rgnRect, rgnRect2, rgnRound, rgnFinalA, rgnFinalB;
+
+	rgnRect.CreateRectRgn(0, 0, 20, rect.Height());
+	rgnRound.CreateRoundRectRgn(0, 0, rect.Width(), rect.Height()+1, 15, 15);
+
+	rgnFinalB.CreateRectRgn(0, 0, 0, 0);
+	rgnFinalB.CombineRgn(&rgnRect, &rgnRound, RGN_OR);
+
+	rgnRect2.CreateRectRgn(0, 20, rect.Width()-1, rect.Height());
+	rgnFinalA.CreateRectRgn(0, 0, 0, 0);
+	rgnFinalA.CombineRgn(&rgnRect2, &rgnFinalB, RGN_OR);
+
+	//Set the region
+	SetWindowRgn(rgnFinalA, TRUE);
+
+	MoveControls();
+}
+
+void CQPasteWnd::MoveControls()
+{
+	CRect crRect;
+	GetClientRect(crRect);
+	int cx = crRect.Width();
+	int cy = crRect.Height();
+
+	// Resize the list control
+	m_lstHeader.MoveWindow(0, 0, cx, cy - 22);
+
+	int nWidth = cx;
+
+	if(m_Recset.m_strFilter.IsEmpty() == FALSE)
+	{
+		m_btCancel.MoveWindow(cx - 20, cy - 20, 20, 20);
+		nWidth -= 19;
+	}
+
+	m_cbSearch.MoveWindow(0, cy - 22, nWidth, 100);
+
+	// Set the column widths
+	//m_lstHeader.SetColumnWidth(0, cx);
+}
+
+void CQPasteWnd::OnSetFocus(CWnd* pOldWnd)
+{
+	CWndEx::OnSetFocus(pOldWnd);
+
+	// Set the focus to the list control
+	m_lstHeader.SetFocus();
+}
+
+void CQPasteWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
+{
+	CWndEx::OnActivate(nState, pWndOther, bMinimized);
+	
+	if(m_bHideWnd == false)
+		return;
+
+	if (nState == WA_INACTIVE)
+	{
+		HideQPasteWindow();
+	}
+	else if (nState == WA_ACTIVE)
+	{
+		ShowQPasteWindow();
+	}
+}
+
+BOOL CQPasteWnd::HideQPasteWindow()
+{
+	if(m_cbSearch.GetShowingDropDown())
+		return FALSE;
+
+	if(m_Recset.IsOpen())
+		m_Recset.Close();
+
+	//Reset the flag
+	theApp.m_bShowingQuickPaste = false;
+
+	m_lstHeader.DestroyAndCreateAccelerator(FALSE);
+
+	//Save the size
+	CRect rect;
+	GetWindowRect(rect);
+	CGetSetOptions::SetQuickPasteSize(rect.Size());
+	CGetSetOptions::SetQuickPastePoint(rect.TopLeft());
+
+	// Hide the window when the focus is lost
+	ShowWindow(SW_HIDE);
+
+	//Rest the selection on the search combo
+	m_cbSearch.SetCurSel(-1);
+
+	//Set focus back
+	if(m_hWndFocus)
+	{
+		::SetForegroundWindow(m_hWndFocus);
+		::SetFocus(m_hWndFocus);
+	}
+
+	return TRUE;
+}
+
+BOOL CQPasteWnd::ShowQPasteWindow(BOOL bFillList)
+{
+	//Set the flag so we can't open this up again
+	theApp.m_bShowingQuickPaste = true;
+
+	m_lstHeader.DestroyAndCreateAccelerator(TRUE);
+
+	m_bHideWnd = true;
+
+	#ifdef AFTER_98
+		//Set the transparency
+		if(CGetSetOptions::GetEnableTransparency())
+		{
+			m_Alpha.SetTransparent(TRUE);
+
+			float fPercent =  CGetSetOptions::GetTransparencyPercent() / (float)100.0;
+
+			m_Alpha.SetOpacity(OPACITY_MAX - (int)(fPercent * OPACITY_MAX));
+		}
+		else
+		{
+			m_Alpha.SetTransparent(FALSE);
+		}
+	#endif
+
+	m_lstHeader.SetNumberOfLinesPerRow(CGetSetOptions::GetLinesPerRow());
+
+	m_lstHeader.SetShowTextForFirstTenHotKeys(CGetSetOptions::GetShowTextForFirstTenHotKeys());
+	
+	if(bFillList)
+		FillList();
+
+	m_btCancel.ShowWindow(SW_HIDE);
+	
+	MoveControls();
+	
+	ShowWindow(SW_SHOW);
+
+	return TRUE;
+}
+
+bool CQPasteWnd::Add(const CString &csHeader, const CString &csText, int nID)
+{
+	int nNewIndex;
+	
+	// Insert the item in the list control
+	if ((nNewIndex = m_lstHeader.InsertItem(m_lstHeader.GetItemCount(), csHeader)) == -1)
+		return false;
+
+	m_lstHeader.SetItemData(nNewIndex, nID);
+	
+	return true;
+}
+
+LRESULT CQPasteWnd::OnListSelect_DB_ID(WPARAM wParam, LPARAM lParam)
+{
+	ShowWindow(SW_HIDE);
+
+	CProcessPaste past;
+	past.LoadDataAndPaste(wParam, m_hWndFocus);
+
+	return TRUE;
+}
+
+LRESULT CQPasteWnd::OnListSelect(WPARAM wParam, LPARAM lParam)
+{
+	int nCount = (int) wParam;
+	long *pItems = (long*) lParam;
+
+	
+	if(nCount)
+	{			
+		int nID = m_lstHeader.GetItemData(pItems[0]);
+
+		ShowWindow(SW_HIDE);
+
+		CProcessPaste past;
+		past.LoadDataAndPaste(nID, m_hWndFocus);
+	}
+
+	return TRUE;
+}
+
+
+LRESULT CQPasteWnd::OnListEnd(WPARAM wParam, LPARAM lParam)
+{
+	HideQPasteWindow();
+
+	return 0;
+}
+
+BOOL CQPasteWnd::FillList(CString csSQLSearch/*=""*/)
+{
+//	if(m_Recset.IsOpen())
+//		m_Recset.Close();
+
+	m_lstHeader.DeleteAllItems();
+
+	CRect crRect;
+	GetClientRect(crRect);
+
+	// Create the columns
+	if(m_lstHeader.InsertColumn(0, "", LVCFMT_LEFT, 2500, 0) != 0)
+	{	
+		ASSERT(FALSE);	
+		return -1;	
+	}
+
+	CString csSQL;
+	if(csSQLSearch == "")
+	{
+		m_Recset.m_strFilter = "";
+		if(m_Recset.IsOpen())
+			m_Recset.Requery();		
+	}
+	else
+	{
+		//Replace all single ' with a double '
+		csSQLSearch.Replace("'", "''");
+
+		//Can't query of strings that have '|' in them
+		//this should be removed later
+		if(csSQLSearch.Find("|") >= 0)
+			return FALSE;
+
+		m_Recset.m_strFilter.Format("strText LIKE \'*%s*\'", csSQLSearch);
+		if(m_Recset.IsOpen())
+			m_Recset.Requery();
+	}
+
+	try
+	{
+		if(m_Recset.IsOpen() == FALSE)
+			m_Recset.Open("");
+					
+		if(!m_Recset.IsEOF())
+		{
+			m_Recset.MoveLast();
+			m_lstHeader.SetItemCountEx(m_Recset.GetRecordCount());
+
+			m_lstHeader.LoadFirstTenHotKeys(m_Recset);
+		}	
+	}
+	catch(CDaoException* e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		e->Delete();
+	}
+
+	m_lstHeader.SetSelection(0);
+	m_lstHeader.SetCaret(0);
+
+	m_lstHeader.Invalidate();
+		
+	return TRUE;
+}
+
+
+
+void CQPasteWnd::OnRclickQuickPaste(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	POINT pp;
+	CMenu cmPopUp;
+	CMenu *cmSubMenu = NULL;
+	
+	GetCursorPos(&pp);
+	if(cmPopUp.LoadMenu(IDR_QUICK_PASTE) != 0)
+	{
+		cmSubMenu = cmPopUp.GetSubMenu(0);
+		if(!cmSubMenu)
+			return;
+
+		SetMenuChecks(cmSubMenu);
+
+		cmSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
+				pp.x, pp.y, this, NULL);
+	}
+	
+	*pResult = 0;
+}
+
+void CQPasteWnd::SetMenuChecks(CMenu *pMenu)
+{
+	//Set the transparency Check
+	if(!CGetSetOptions::GetEnableTransparency())
+	{
+		pMenu->CheckMenuItem(ID_MENU_TRANSPARENCY_NONE, MF_CHECKED);
+	}
+	else
+	{
+		int nTrans = CGetSetOptions::GetTransparencyPercent();
+		int nCheckID = -1;
+		switch(nTrans)
+		{
+		case 5:
+			nCheckID = ID_MENU_TRANSPARENCY_5;
+			break;
+		case 10:
+			nCheckID = ID_MENU_TRANSPARENCY_10;
+			break;
+		case 15:
+			nCheckID = ID_MENU_TRANSPARENCY_15;
+			break;
+		case 20:
+			nCheckID = ID_MENU_TRANSPARENCY_20;
+			break;
+		case 25:
+			nCheckID = ID_MENU_TRANSPARENCY_25;
+			break;
+		case 30:
+			nCheckID = ID_MENU_TRANSPARENCY_30;
+			break;
+		case 40:
+			nCheckID = ID_MENU_TRANSPARENCY_40;
+			break;
+		}
+		if(nCheckID >= 0)
+			pMenu->CheckMenuItem(nCheckID, MF_CHECKED);
+	}
+
+	//Set the lines per row check
+	int nLinesPerRow = CGetSetOptions::GetLinesPerRow();
+	int nCheckID = -1;
+	switch(nLinesPerRow)
+	{
+	case 1:
+		nCheckID = ID_MENU_LINESPERROW_1;
+		break;
+	case 2:
+		nCheckID = ID_MENU_LINESPERROW_2;
+		break;
+	case 3:
+		nCheckID = ID_MENU_LINESPERROW_3;
+		break;
+	case 4:
+		nCheckID = ID_MENU_LINESPERROW_4;
+		break;
+	case 5:
+		nCheckID = ID_MENU_LINESPERROW_5;
+		break;
+	}
+	if(nCheckID >= 0)
+		pMenu->CheckMenuItem(nCheckID, MF_CHECKED);
+
+	//Set the position check
+	int nPosition = CGetSetOptions::GetQuickPastePosition();
+	nCheckID = -1;
+	switch(nPosition)
+	{
+	case POS_AT_CARET:
+		nCheckID = ID_MENU_POSITIONING_ATCARET;
+		break;
+	case POS_AT_CURSOR:
+		nCheckID = ID_MENU_POSITIONING_ATCURSOR;
+		break;
+	case POS_AT_PREVIOUS:
+		nCheckID = ID_MENU_POSITIONING_ATPREVIOUSPOSITION;
+		break;
+	}
+	if(nCheckID >= 0)
+		pMenu->CheckMenuItem(nCheckID, MF_CHECKED);
+
+	if(::SendMessage(theApp.m_MainhWnd, WM_IS_TOP_VIEWER, 0, 0))
+		pMenu->DeleteMenu(ID_MENU_RECONNECTTOCLIPBOARDCHAIN, MF_BYCOMMAND);
+
+	if(CGetSetOptions::GetShowTextForFirstTenHotKeys())
+		pMenu->CheckMenuItem(ID_MENU_FIRSTTENHOTKEYS_SHOWHOTKEYTEXT, MF_CHECKED);
+
+	if(CGetSetOptions::GetUseCtrlNumForFirstTenHotKeys())
+		pMenu->CheckMenuItem(ID_MENU_FIRSTTENHOTKEYS_USECTRLNUM, MF_CHECKED);
+}
+
+LRESULT CQPasteWnd::OnSearch(WPARAM wParam, LPARAM lParam)
+{
+	CString csText;
+	m_cbSearch.GetWindowText(csText);
+	
+	if(csText == "")
+		return FALSE;
+
+	FillList(csText);
+
+	m_lstHeader.SetFocus();
+
+	m_btCancel.ShowWindow(SW_SHOW);
+
+	MoveControls();
+
+	m_cbSearch.SetEditSel(-1, 0);
+
+	return TRUE;
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//Menu Stuff
+///////////////////////////////////////////////////////////////////////
+void CQPasteWnd::OnMenuLinesperrow1()	{ SetLinesPerRow(1);	}
+void CQPasteWnd::OnMenuLinesperrow2()	{ SetLinesPerRow(2);	}
+void CQPasteWnd::OnMenuLinesperrow3()	{ SetLinesPerRow(3);	}
+void CQPasteWnd::OnMenuLinesperrow4()	{ SetLinesPerRow(4);	}
+void CQPasteWnd::OnMenuLinesperrow5()	{ SetLinesPerRow(5);	}
+void CQPasteWnd::SetLinesPerRow(long lLines)
+{
+	CGetSetOptions::SetLinesPerRow(lLines);
+	m_lstHeader.SetNumberOfLinesPerRow(lLines);
+	
+	FillList();
+}
+void CQPasteWnd::OnMenuTransparencyNone()	{ SetTransparency(0);	}
+void CQPasteWnd::OnMenuTransparency5()		{ SetTransparency(5);	}
+void CQPasteWnd::OnMenuTransparency10()		{ SetTransparency(10);	}
+void CQPasteWnd::OnMenuTransparency15()		{ SetTransparency(15);	}
+void CQPasteWnd::OnMenuTransparency20()		{ SetTransparency(20);	}
+void CQPasteWnd::OnMenuTransparency25()		{ SetTransparency(25);	}
+void CQPasteWnd::OnMenuTransparency30()		{ SetTransparency(25);	}
+void CQPasteWnd::OnMenuTransparency40()		{ SetTransparency(40);	}
+
+void CQPasteWnd::SetTransparency(long lPercent)
+{
+	#ifdef AFTER_98
+		if(lPercent)
+		{
+			CGetSetOptions::SetTransparencyPercent(lPercent);
+			CGetSetOptions::SetEnableTransparency(TRUE);
+
+			m_Alpha.SetTransparent(TRUE);
+
+			float fPercent =  lPercent / (float)100.0;
+
+			m_Alpha.SetOpacity(OPACITY_MAX - (int)(fPercent * OPACITY_MAX));
+		}
+		else
+		{
+			CGetSetOptions::SetEnableTransparency(FALSE);
+			m_Alpha.SetTransparent(FALSE);
+		}
+	#endif
+}
+
+void CQPasteWnd::OnMenuDelete() 
+{
+	DeleteSelectedRows();
+}
+
+void CQPasteWnd::OnMenuPositioningAtcaret() 
+{
+	CGetSetOptions::SetQuickPastePosition(POS_AT_CARET);
+}
+
+void CQPasteWnd::OnMenuPositioningAtcursor() 
+{
+	CGetSetOptions::SetQuickPastePosition(POS_AT_CURSOR);
+}
+
+void CQPasteWnd::OnMenuPositioningAtpreviousposition() 
+{
+	CGetSetOptions::SetQuickPastePosition(POS_AT_PREVIOUS);
+}
+
+void CQPasteWnd::OnMenuOptions() 
+{
+	m_bHideWnd = false;
+
+	DoOptions(this);
+
+	ShowQPasteWindow(TRUE);
+	
+	m_bHideWnd = true;
+	m_lstHeader.SetFocus();
+}
+
+void CQPasteWnd::OnMenuExitprogram() 
+{
+	::SendMessage(theApp.m_MainhWnd, WM_CLOSE, 0, 0);
+}
+
+void CQPasteWnd::OnMenuReconnecttoclipboardchain() 
+{
+	::SendMessage(theApp.m_MainhWnd, WM_RECONNECT_TO_COPY_CHAIN, 0, 0);
+}
+
+void CQPasteWnd::OnMenuProperties() 
+{
+	m_bHideWnd = false;
+
+	ARRAY IDs, Indexes;
+	m_lstHeader.GetSelectionItemData(IDs);
+	m_lstHeader.GetSelectionIndexes(Indexes);
+
+	int nSize = IDs.GetSize();
+	if(nSize < 1)
+		return;
+
+	long lID = IDs[0];
+	int nRow = Indexes[0];
+
+	if(lID < 0)
+		return;
+	
+	m_lstHeader.RemoveAllSelection();
+	m_lstHeader.SetSelection(nRow);
+
+	CCopyProperties props(lID, this);
+	int nDo = props.DoModal();
+
+	if(nDo == IDOK)
+	{
+		m_lstHeader.DestroyAndCreateAccelerator(TRUE);
+		m_lstHeader.RefreshVisibleRows();
+	}
+		
+	SetFocus();
+	m_bHideWnd = true;
+
+	if(nDo == IDOK || nDo == IDCANCEL)
+	{
+		m_lstHeader.SetFocus();
+		m_lstHeader.SetCaret(nRow);
+	}
+}
+
+void CQPasteWnd::OnMenuFirsttenhotkeysUsectrlnum() 
+{	
+	CGetSetOptions::SetUseCtrlNumForFirstTenHotKeys(!CGetSetOptions::GetUseCtrlNumForFirstTenHotKeys());
+	m_lstHeader.RefreshVisibleRows();
+}
+
+void CQPasteWnd::OnMenuFirsttenhotkeysShowhotkeytext() 
+{
+	CGetSetOptions::SetShowTextForFirstTenHotKeys(!CGetSetOptions::GetShowTextForFirstTenHotKeys());
+
+	m_lstHeader.SetShowTextForFirstTenHotKeys(CGetSetOptions::GetShowTextForFirstTenHotKeys());
+
+	m_lstHeader.RefreshVisibleRows();
+}
+
+///////////////////////////////////////////////////////////////////////
+//END END Menu Stuff
+///////////////////////////////////////////////////////////////////////
+
+
+LRESULT CQPasteWnd::OnDelete(WPARAM wParam, LPARAM lParam)
+{
+	DeleteSelectedRows();
+	
+	return TRUE;
+}
+
+void CQPasteWnd::DeleteSelectedRows()
+{
+	ARRAY IDs;
+	m_lstHeader.GetSelectionItemData(IDs);
+
+	if(m_Recset.DeleteRows(IDs))
+	{
+		m_Recset.Requery();
+
+		long lCount = 0;
+		if(m_Recset.IsEOF() == FALSE)
+		{
+			m_Recset.MoveLast();
+			lCount = m_Recset.GetRecordCount();
+			m_lstHeader.LoadFirstTenHotKeys(m_Recset);
+		}
+
+		m_lstHeader.SetItemCountEx(lCount);
+		m_lstHeader.Invalidate();
+	}
+
+	int nCurSel = m_lstHeader.GetCaret();
+	if(nCurSel < 0) 
+		nCurSel = 0;
+
+	m_lstHeader.RemoveAllSelection();
+
+	m_lstHeader.SetSelection(nCurSel);
+	m_lstHeader.SetCaret(nCurSel);
+
+	m_lstHeader.RefreshVisibleRows();
+}
+
+
+BOOL CQPasteWnd::PreTranslateMessage(MSG* pMsg) 
+{	
+	switch(pMsg->message) 
+	{
+	case WM_KEYDOWN:
+		if(pMsg->wParam == VK_ESCAPE)
+		{
+			if(!m_cbSearch.GetShowingDropDown())
+			{
+				HideQPasteWindow();
+
+				return TRUE;
+			}
+		}
+		else if(pMsg->wParam == VK_TAB)
+		{
+			BOOL bPrev = FALSE;
+
+			if(GetKeyState(VK_SHIFT) & 0x8000)
+				bPrev = TRUE;
+
+			CWnd *pFocus = GetFocus();
+			if(pFocus)
+			{
+				CWnd *pNextWnd = GetNextDlgTabItem(pFocus, bPrev);
+				if(pNextWnd)
+					pNextWnd->SetFocus();
+			}
+
+			return TRUE;
+		}
+		else if(pMsg->wParam == 'A')
+		{
+			if(GetKeyState(VK_CONTROL) & 0x8000)
+			{
+				int nCount = m_lstHeader.GetItemCount();
+				for(int i = 0; i < nCount; i++)
+				{
+					m_lstHeader.SetSelection(i);
+				}
+				return TRUE;
+			}
+		}
+		break;
+	case WM_SYSKEYDOWN:
+		if(pMsg->wParam == 'C')
+		{
+			BYTE key[256];
+			GetKeyboardState((LPBYTE)(&key));
+			if(key[VK_MENU]&128)
+			{
+				OnCancelFilter();				
+			}
+		}
+		break;
+	}
+
+	
+	return CWndEx::PreTranslateMessage(pMsg);
+}
+
+void CQPasteWnd::OnCancelFilter()
+{
+	FillList();
+
+	m_btCancel.ShowWindow(SW_HIDE);
+
+	m_cbSearch.SetCurSel(-1);
+	MoveControls();
+
+	m_lstHeader.SetFocus();
+}
+
+LRESULT CQPasteWnd::OnProperties(WPARAM wParam, LPARAM lParam)
+{
+	OnMenuProperties();
+	return TRUE;
+}
+
+void CQPasteWnd::OnClose() 
+{
+	HideQPasteWindow();
+}
+
+void CQPasteWnd::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
+	
+    int nItem =  ((NM_LISTVIEW*) pNMHDR)->iItem;
+
+	long lID = m_lstHeader.GetItemData(nItem);
+
+	if(lID >= 0)
+	{
+		CProcessPaste past;
+		past.LoadDataAndDrag(lID);
+	}
+
+	*pResult = 0;
+}
+
+void CQPasteWnd::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
+{	
+	CWndEx::OnSysKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CQPasteWnd::GetDispInfo(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	if(m_Recset.IsOpen() == FALSE)
+		return;
+	
+	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
+	LV_ITEM* pItem= &(pDispInfo)->item;
+	
+	if(pItem->mask & LVIF_TEXT) //valid text buffer?
+	{		
+		switch(pItem->iSubItem)
+		{
+		case 0:
+			try
+			{
+				m_Recset.SetAbsolutePosition(pItem->iItem);
+
+				CString cs;
+				if(m_Recset.m_lDontAutoDelete)
+					cs = "* ";
+
+				if(m_Recset.m_lShortCut > 0)
+					cs += "** ";
+
+				cs += m_Recset.m_strText;
+				lstrcpy(pItem->pszText, cs);
+			}
+			catch(CDaoException *e)
+			{
+				ASSERT(FALSE);
+				e->Delete();
+			}
+		break;
+		}
+	}
+
+	if(pItem->mask & LVIF_PARAM)
+	{
+		switch(pItem->iSubItem)
+		{
+		case 0:
+			try
+			{
+				m_Recset.SetAbsolutePosition(pItem->iItem);
+				pItem->lParam = m_Recset.m_lID;
+			}
+			catch(CDaoException *e)
+			{
+				ASSERT(FALSE);
+				e->Delete();
+			}			
+		break;
+		}
+	}
+}
+
+void CQPasteWnd::OnGetToolTipText(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	CQListToolTipText* pInfo = (CQListToolTipText*)pNMHDR;
+	if(!pInfo)
+		return;
+
+	try
+	{
+		CString cs;
+		
+		m_Recset.SetAbsolutePosition(pInfo->lItem);
+
+		cs = m_Recset.m_strText;
+		cs += "\n\n";
+		CTime time(m_Recset.m_lDate);
+		cs += time.Format("%m/%d/%Y %I:%M %p");
+
+		if(m_Recset.m_lDontAutoDelete)
+		{
+			cs += "\n";
+			cs += "Never Auto Delete";
+		}
+
+		if(m_Recset.m_lShortCut > 0)
+		{
+			cs += "\n";
+			
+			if( HIBYTE(m_Recset.m_lShortCut) & HOTKEYF_CONTROL )
+				cs += "Ctrl + ";
+			if( HIBYTE(m_Recset.m_lShortCut) & HOTKEYF_SHIFT )
+				cs += "Shift + ";
+			if( HIBYTE(m_Recset.m_lShortCut) & HOTKEYF_ALT )
+				cs += "Alt + ";
+
+			cs += LOBYTE(m_Recset.m_lShortCut);
+		}
+
+		strcpy(pInfo->cText, cs);
+
+	}
+	catch(CDaoException *e)
+	{
+		ASSERT(FALSE);
+		e->Delete();
+	}
+}
+
+void CQPasteWnd::OnFindItem(NMHDR* pNMHDR, LRESULT* pResult) 
+{
+	NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)pNMHDR;
+	LVFINDINFO    fndItem   = pFindInfo->lvfi;
+
+	if(fndItem.flags & LVFI_STRING)
+	{
+        int   nLength = strlen(fndItem.psz);
+        long lArraySize = m_Recset.GetRecordCount();
+
+		m_Recset.SetAbsolutePosition(pFindInfo->iStart);
+		// Search to end.
+		for(int i = pFindInfo->iStart; i < lArraySize; i++ )
+		{
+			if(m_Recset.IsEOF() == FALSE)
+			{
+				if(_strnicmp(fndItem.psz, m_Recset.m_strText, nLength) == 0)
+				{
+					*pResult = i;
+					return;
+				}
+				m_Recset.MoveNext();
+			}
+		}
+
+		m_Recset.MoveFirst();
+
+		// Search from 0 to start.
+		for( i = 0; i < pFindInfo->iStart; i++ )
+		{
+			if(m_Recset.IsEOF() == FALSE)
+			{
+				if(_strnicmp(fndItem.psz, m_Recset.m_strText, nLength) == 0)
+				{
+					*pResult = i;
+					return;
+				}
+
+				m_Recset.MoveNext();
+			}
+		}
+	}
+
+	*pResult = -1;	// Default action.
+}

+ 133 - 0
QPasteWnd.h

@@ -0,0 +1,133 @@
+#if !defined(AFX_QPASTEWND_H__65261F0F_FEFD_48CF_A0CD_01D8BFEB353B__INCLUDED_)
+#define AFX_QPASTEWND_H__65261F0F_FEFD_48CF_A0CD_01D8BFEB353B__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// QPasteWnd.h : header file
+//
+
+#include "QListCtrl.h"
+#include "ComboBoxSearch.h"
+#include "WndEx.h"
+
+#ifdef AFTER_98
+	#include "AlphaBlend.h"
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CQPasteWnd window
+
+class CQPasteWnd : public CWndEx
+{
+// Construction
+public:
+	CQPasteWnd();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CQPasteWnd)
+	public:
+	virtual BOOL Create(const POINT& ptStart, CWnd* pParentWnd);
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	protected:
+	//}}AFX_VIRTUAL
+
+// Implementation
+public:
+	void SetFocusWindow(HWND hWndFocus)	{ m_hWndFocus = hWndFocus;	}
+	bool Add(const CString &csHeader, const CString &csText, int nID);
+	virtual ~CQPasteWnd();
+
+protected:
+	CQListCtrl		m_lstHeader;
+	HWND			m_hWndFocus;
+
+	#ifdef AFTER_98
+		CAlphaBlend		m_Alpha;
+	#endif
+	
+	CFont			m_TitleFont;
+	CComboBoxSearch	m_cbSearch;
+	CFont			m_SearchFont;
+	CButton			m_btCancel;
+	bool			m_bHideWnd;
+	CMainTable		m_Recset;
+
+	BOOL FillList(CString csSQLSearch = "");
+	BOOL HideQPasteWindow();
+	BOOL ShowQPasteWindow(BOOL bFillList = TRUE);
+	void MoveControls();
+
+	void DeleteSelectedRows();
+
+	//Menu Items
+	void SetLinesPerRow(long lLines);
+	void SetTransparency(long lPercent);
+	void OnUpdateLinesPerRow(CCmdUI* pCmdUI, int nValue);
+	void OnUpdateTransparency(CCmdUI* pCmdUI, int nValue);
+	void SetMenuChecks(CMenu *pMenu);
+	
+	// Generated message map functions
+protected:
+	//{{AFX_MSG(CQPasteWnd)
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnSetFocus(CWnd* pOldWnd);
+	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
+	afx_msg void OnMenuLinesperrow1();
+	afx_msg void OnMenuLinesperrow2();
+	afx_msg void OnMenuLinesperrow3();
+	afx_msg void OnMenuLinesperrow4();
+	afx_msg void OnMenuLinesperrow5();
+	afx_msg void OnMenuTransparency10();
+	afx_msg void OnMenuTransparency15();
+	afx_msg void OnMenuTransparency20();
+	afx_msg void OnMenuTransparency25();
+	afx_msg void OnMenuTransparency30();
+	afx_msg void OnMenuTransparency40();
+	afx_msg void OnMenuTransparency5();
+	afx_msg void OnMenuTransparencyNone();
+	afx_msg void OnRclickQuickPaste(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnMenuDelete();
+	afx_msg void OnMenuPositioningAtcaret();
+	afx_msg void OnMenuPositioningAtcursor();
+	afx_msg void OnMenuPositioningAtpreviousposition();
+	afx_msg void OnMenuOptions();
+	afx_msg void OnCancelFilter();
+	afx_msg void OnMenuExitprogram();
+	afx_msg void OnMenuReconnecttoclipboardchain();
+	afx_msg void OnMenuProperties();
+	afx_msg void OnClose();
+	afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+	afx_msg void GetDispInfo(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnFindItem(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnMenuFirsttenhotkeysUsectrlnum();
+	afx_msg void OnMenuFirsttenhotkeysShowhotkeytext();
+	//}}AFX_MSG
+	afx_msg LRESULT OnListSelect(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnListEnd(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnSearch(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnDelete(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnProperties(WPARAM wParam, LPARAM lParam);
+	afx_msg void OnGetToolTipText(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg LRESULT OnListSelect_DB_ID(WPARAM wParam, LPARAM lParam);
+	DECLARE_MESSAGE_MAP()
+};
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_QPASTEWND_H__65261F0F_FEFD_48CF_A0CD_01D8BFEB353B__INCLUDED_)

+ 137 - 0
QuickPaste.cpp

@@ -0,0 +1,137 @@
+// QuickPaste.cpp: implementation of the CQuickPaste class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "QuickPaste.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+#define ID_QPASTE_WND			0x1001
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CQuickPaste::CQuickPaste()
+{
+	m_pwndPaste = NULL;
+
+}
+
+CQuickPaste::~CQuickPaste()
+{
+	if(m_pwndPaste)
+	{
+		delete m_pwndPaste;
+		m_pwndPaste = NULL;
+	}
+
+}
+
+BOOL CQuickPaste::CloseQPasteWnd()
+{
+	if(m_pwndPaste)
+	{
+		if(m_pwndPaste->IsWindowVisible())
+			return FALSE;
+
+		if(m_pwndPaste)
+			m_pwndPaste->SendMessage(WM_CLOSE, 0, 0);
+
+		delete m_pwndPaste;
+		m_pwndPaste = NULL;
+	}
+
+	return TRUE;
+}
+
+void CQuickPaste::ShowQPasteWnd(CWnd *pParent, BOOL bAtPrevPos)
+{
+	{
+		if((theApp.m_bShowingQuickPaste) || (theApp.m_bShowingOptions))
+			return;
+	}
+
+	int nPosition = CGetSetOptions::GetQuickPastePosition();
+
+	CPoint ptCaret;
+	HWND hWndActive = GetActiveWnd(&ptCaret);
+	ptCaret.Offset(-12, 12);
+
+	CPoint point;
+	CRect rcPrev;
+	CSize csSize;
+
+	if(!m_pwndPaste)
+		m_pwndPaste = new CQPasteWnd;
+
+	if(!m_pwndPaste)
+	{
+		ASSERT(FALSE);
+		return;
+	}
+
+	//If its  a window get the rect otherwise get the saved point and size
+	if (IsWindow(m_pwndPaste->m_hWnd))
+	{
+		m_pwndPaste->GetWindowRect(rcPrev);
+		csSize = rcPrev.Size();
+	}
+	else
+	{
+		CGetSetOptions::GetQuickPastePoint(point);
+		CGetSetOptions::GetQuickPasteSize(csSize);
+	}
+
+	if(bAtPrevPos)
+	{
+		CGetSetOptions::GetQuickPastePoint(point);
+		CGetSetOptions::GetQuickPasteSize(csSize);
+	}
+	else if(nPosition == POS_AT_CARET)
+		point = ptCaret;
+	else if(nPosition == POS_AT_CURSOR)
+		GetCursorPos(&point);
+	else if(nPosition == POS_AT_PREVIOUS)
+		CGetSetOptions::GetQuickPastePoint(point);
+		
+	if (!IsWindow(m_pwndPaste->m_hWnd))
+	{
+		// Create the window   
+		if (!m_pwndPaste->Create(point, pParent))
+			return;
+	}
+
+	if((nPosition == POS_AT_CARET) ||
+		(nPosition == POS_AT_CURSOR) ||
+		(bAtPrevPos))
+	{
+		m_pwndPaste->MoveWindow(CRect(point, csSize));
+	}
+		
+	//set the window that recieves the paste message
+	m_pwndPaste->SetFocusWindow(hWndActive);
+
+	// Show the window
+	m_pwndPaste->ShowWindow(SW_SHOW);
+
+	::SetForegroundWindow(m_pwndPaste->m_hWnd);
+	::SetFocus(m_pwndPaste->m_hWnd);
+
+}
+
+void CQuickPaste::HideQPasteWnd()
+{
+	// Hide the window
+	if(m_pwndPaste)
+	{
+		if (IsWindow(m_pwndPaste->m_hWnd))
+			m_pwndPaste->ShowWindow(SW_SHOW);
+	}
+}

+ 28 - 0
QuickPaste.h

@@ -0,0 +1,28 @@
+// QuickPaste.h: interface for the CQuickPaste class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_QUICKPASTE_H__1B4A98E6_B719_402C_BDD4_7F3F97CD0EB0__INCLUDED_)
+#define AFX_QUICKPASTE_H__1B4A98E6_B719_402C_BDD4_7F3F97CD0EB0__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "QPasteWnd.h"
+
+class CQuickPaste  
+{
+public:
+	CQuickPaste();
+	virtual ~CQuickPaste();
+
+	void ShowQPasteWnd(CWnd *pParent, BOOL bAtPrevPos = FALSE);
+	void HideQPasteWnd();
+	BOOL CloseQPasteWnd();
+
+protected:
+	CQPasteWnd *m_pwndPaste;
+};
+
+#endif // !defined(AFX_QUICKPASTE_H__1B4A98E6_B719_402C_BDD4_7F3F97CD0EB0__INCLUDED_)

+ 105 - 0
ReadMe.txt

@@ -0,0 +1,105 @@
+========================================================================
+       MICROSOFT FOUNDATION CLASS LIBRARY : CP_Main
+========================================================================
+
+
+AppWizard has created this CP_Main application for you.  This application
+not only demonstrates the basics of using the Microsoft Foundation classes
+but is also a starting point for writing your application.
+
+This file contains a summary of what you will find in each of the files that
+make up your CP_Main application.
+
+CP_Main.dsp
+    This file (the project file) contains information at the project level and
+    is used to build a single project or subproject. Other users can share the
+    project (.dsp) file, but they should export the makefiles locally.
+
+CP_Main.h
+    This is the main header file for the application.  It includes other
+    project specific headers (including Resource.h) and declares the
+    CCP_MainApp application class.
+
+CP_Main.cpp
+    This is the main application source file that contains the application
+    class CCP_MainApp.
+
+CP_Main.rc
+    This is a listing of all of the Microsoft Windows resources that the
+    program uses.  It includes the icons, bitmaps, and cursors that are stored
+    in the RES subdirectory.  This file can be directly edited in Microsoft
+	Visual C++.
+
+CP_Main.clw
+    This file contains information used by ClassWizard to edit existing
+    classes or add new classes.  ClassWizard also uses this file to store
+    information needed to create and edit message maps and dialog data
+    maps and to create prototype member functions.
+
+res\CP_Main.ico
+    This is an icon file, which is used as the application's icon.  This
+    icon is included by the main resource file CP_Main.rc.
+
+res\CP_Main.rc2
+    This file contains resources that are not edited by Microsoft 
+	Visual C++.  You should place all resources not editable by
+	the resource editor in this file.
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+For the main frame window:
+
+MainFrm.h, MainFrm.cpp
+    These files contain the frame class CMainFrame, which is derived from
+    CFrameWnd and controls all SDI frame features.
+
+res\Toolbar.bmp
+    This bitmap file is used to create tiled images for the toolbar.
+    The initial toolbar and status bar are constructed in the CMainFrame
+    class. Edit this toolbar bitmap using the resource editor, and
+    update the IDR_MAINFRAME TOOLBAR array in CP_Main.rc to add
+    toolbar buttons.
+/////////////////////////////////////////////////////////////////////////////
+
+AppWizard creates one document type and one view:
+
+CP_MainDoc.h, CP_MainDoc.cpp - the document
+    These files contain your CCP_MainDoc class.  Edit these files to
+    add your special document data and to implement file saving and loading
+    (via CCP_MainDoc::Serialize).
+
+CP_MainView.h, CP_MainView.cpp - the view of the document
+    These files contain your CCP_MainView class.
+    CCP_MainView objects are used to view CCP_MainDoc objects.
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named CP_Main.pch and a precompiled types file named StdAfx.obj.
+
+Resource.h
+    This is the standard header file, which defines new resource IDs.
+    Microsoft Visual C++ reads and updates this file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" to indicate parts of the source code you
+should add to or customize.
+
+If your application uses MFC in a shared DLL, and your application is 
+in a language other than the operating system's current language, you
+will need to copy the corresponding localized resources MFC42XXX.DLL
+from the Microsoft Visual C++ CD-ROM onto the system or system32 directory,
+and rename it to be MFCLOC.DLL.  ("XXX" stands for the language abbreviation.
+For example, MFC42DEU.DLL contains resources translated to German.)  If you
+don't do this, some of the UI elements of your application will remain in the
+language of the operating system.
+
+/////////////////////////////////////////////////////////////////////////////

+ 111 - 0
Resource.h

@@ -0,0 +1,111 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by CP_Main.rc
+//
+#define IDD_ABOUTBOX                    100
+#define IDR_MAINFRAME                   128
+#define IDR_CP_MAITYPE                  129
+#define IDR_MENU                        130
+#define IDD_SELECT_DB                   131
+#define IDD_OPTIONS_STATS               132
+#define IDD_ADD_TYPE                    134
+#define IDD_COPY_PROPERTIES             135
+#define IDD_ABOUT                       136
+#define IDC_PATH                        1000
+#define IDC_GET_PATH                    1001
+#define IDC_SELECT                      1003
+#define IDC_TRIP_COPIES                 1004
+#define IDC_TRIP_PASTES                 1005
+#define IDC_RESET_COUNTS                1006
+#define IDC_ALL_COPIES                  1007
+#define IDC_ALL_PASTES                  1008
+#define IDC_TRIP_DATE                   1009
+#define IDC_EDIT_ALL_DATE               1010
+#define IDC_SAVED_COPIES                1011
+#define IDC_SAVED_COPY_DATA             1012
+#define IDC_REMOVE_ALL                  1013
+#define IDC_DATABASE_SIZE               1014
+#define IDC_LIST1                       1014
+#define IDC_ADD                         1015
+#define IDC_DELETE                      1016
+#define IDC_EDIT1                       1017
+#define IDC_LIST2                       1018
+#define IDC_ADD_1                       1019
+#define IDC_ADD_2                       1020
+#define IDC_EDIT_DISPLAY_TEXT           1020
+#define IDC_ADD_3                       1021
+#define IDC_DELETE_COPY_DATA            1021
+#define IDC_DATE                        1022
+#define IDC_COPY_DATA                   1023
+#define IDC_NEVER_AUTO_DELETE           1025
+#define IDC_NAMED_COPY                  1026
+#define IDC_COMPACT_REPAIR              1027
+#define IDC_BT_COMPACT_AND_REPAIR       1028
+#define IDC_CHECK_UPDATES               1029
+#define IDC_CHECK_FOR_UPDATES           1030
+#define IDC_LIST                        1032
+#define IDC_CTRL_CLICK                  1033
+#define IDC_SET_DB_PATH                 1034
+#define IDC_SHOW_TEXT_FOR_FIRST_TEN_HOT_KEYS 1034
+#define IDC_USE_DEFAULT                 1035
+#define IDC_HYPER_LINK                  1036
+#define IDD_OPTIONS_KEYSTROKES          2001
+#define IDC_HOTKEY                      2002
+#define IDC_DISPLAY_IN_SYSTEMTRAY       2003
+#define IDD_OPTIONS_GENERAL             2003
+#define IDD_OPTIONS_TYPES               2004
+#define IDC_START_ON_STARTUP            2004
+#define IDR_QUICK_PASTE                 2005
+#define IDC_TRANSPARENCY                2006
+#define IDD_OPTIONS_QUICK_PASTE         2006
+#define IDD_OPTIONS_UTILITIES           2007
+#define IDC_TRANS_PERC                  2007
+#define IDC_MAXIMUM                     2008
+#define IDC_EXPIRE                      2009
+#define IDC_EXPIRE_AFTER                2010
+#define IDC_MAX_SAVED_COPIES            2012
+#define IDC_LINES_ROW                   2013
+#define IDC_AT_CARET                    2015
+#define IDC_AT_CURSOR                   2016
+#define IDC_AT_PREVIOUS                 2017
+#define IDC_COMPACT_DB                  2018
+#define IDC_REPAIR                      2019
+#define ID_FIRST_OPTION                 32771
+#define ID_FIRST_EXIT                   32772
+#define ID_FIRST_SHOWQUICKPASTE         32773
+#define ID_FIRST_RECONNECTTOCLIPBOARDCHAIN 32774
+#define ID_MENU_RECONNECTTOCLIPBOARDCHAIN 32775
+#define ID_MENU_PROPERTIES              32776
+#define ID_MENU_FIRSTTENHOTKEYS_USECTRLNUM 32778
+#define ID_MENU_FIRSTTENHOTKEYS_SHOWHOTKEYTEXT 32779
+#define ID_MENU_LINESPERROW_1           32786
+#define ID_MENU_LINESPERROW_2           32787
+#define ID_MENU_LINESPERROW_3           32788
+#define ID_MENU_LINESPERROW_4           32789
+#define ID_MENU_LINESPERROW_5           32790
+#define ID_MENU_TRANSPARENCY_5          32791
+#define ID_MENU_TRANSPARENCY_10         32792
+#define ID_MENU_TRANSPARENCY_15         32793
+#define ID_MENU_TRANSPARENCY_20         32794
+#define ID_MENU_TRANSPARENCY_25         32795
+#define ID_MENU_TRANSPARENCY_30         32796
+#define ID_MENU_TRANSPARENCY_40         32806
+#define ID_MENU_TRANSPARENCY_NONE       32807
+#define ID_MENU_DELETE                  32810
+#define ID_MENU_POSITIONING_ATCARET     32811
+#define ID_MENU_POSITIONING_ATCURSOR    32812
+#define ID_MENU_POSITIONING_ATPREVIOUSPOSITION 32813
+#define ID_MENU_OPTIONS                 32814
+#define ID_MENU_EXITPROGRAM             32816
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS                     1
+#define _APS_NEXT_RESOURCE_VALUE        138
+#define _APS_NEXT_COMMAND_VALUE         32780
+#define _APS_NEXT_CONTROL_VALUE         1037
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

+ 112 - 0
SelectDB.cpp

@@ -0,0 +1,112 @@
+// SelectDB.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "SelectDB.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CSelectDB dialog
+
+
+CSelectDB::CSelectDB(CWnd* pParent /*=NULL*/)
+	: CDialog(CSelectDB::IDD, pParent)
+{
+	//{{AFX_DATA_INIT(CSelectDB)
+	//}}AFX_DATA_INIT
+}
+
+
+void CSelectDB::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(CSelectDB)
+	DDX_Control(pDX, IDC_PATH, m_ePath);
+	//}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CSelectDB, CDialog)
+	//{{AFX_MSG_MAP(CSelectDB)
+	ON_BN_CLICKED(IDC_SELECT, OnSelect)
+	ON_BN_CLICKED(IDC_USE_DEFAULT, OnUseDefault)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSelectDB message handlers
+
+BOOL CSelectDB::OnInitDialog() 
+{
+	CDialog::OnInitDialog();
+	
+	m_ePath.SetWindowText(CGetSetOptions::GetDBPath(FALSE));
+	
+	m_ePath.SetFocus();
+	
+	return FALSE;
+}
+
+void CSelectDB::OnOK() 
+{
+	CString csPath;
+	m_ePath.GetWindowText(csPath);
+
+	CGetSetOptions::SetDBPath(csPath);
+		
+	CDialog::OnOK();
+}
+
+void CSelectDB::OnSelect() 
+{
+	OPENFILENAME	FileName;
+
+	char			szFileName[400];
+	char			szDir[400];
+
+	memset(&FileName, 0, sizeof(FileName));
+	memset(szFileName, 0, sizeof(szFileName));
+	memset(&szDir, 0, sizeof(szDir));
+
+	FileName.lStructSize = sizeof(FileName);
+
+	
+	FileName.lpstrTitle = "Open Database";
+	FileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST;
+	FileName.nMaxFile = 400;
+	FileName.lpstrFile = szFileName;
+	FileName.lpstrInitialDir = szDir;
+	FileName.lpstrFilter = "Database Files (.MDB)\0*.mdb";
+	FileName.lpstrDefExt = "mdb";
+
+	if(GetOpenFileName(&FileName) == 0)
+		return;
+
+	CString	csPath(FileName.lpstrFile);
+
+	if(ValidDB(csPath) == FALSE)
+	{
+		MessageBox("Invalid Database", "Ditto", MB_OK);
+		m_ePath.SetFocus();
+	}
+	else
+		m_ePath.SetWindowText(csPath);	
+}
+
+void CSelectDB::OnUseDefault() 
+{
+	CGetSetOptions::SetDBPath("");
+	CString csPath = CGetSetOptions::GetDBPath();
+
+	if(ValidDB(csPath) == FALSE)
+		DeleteFile(csPath);
+	
+	if(CheckDBExists(CGetSetOptions::GetDBPath()))
+		EndDialog(IDOK);
+}

+ 49 - 0
SelectDB.h

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

+ 8 - 0
StdAfx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+//	CP_Main.pch will be the pre-compiled header
+//	stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+

+ 31 - 0
StdAfx.h

@@ -0,0 +1,31 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__56F3D184_7208_47FE_AFE2_E270325F356A__INCLUDED_)
+#define AFX_STDAFX_H__56F3D184_7208_47FE_AFE2_E270325F356A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define _WIN32_WINNT 0x0500
+#define WINVER 0x0500
+
+#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h>         // MFC core and standard components
+#include <afxext.h>         // MFC extensions
+#include <afxdisp.h>        // MFC Automation classes
+#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
+#include <afxdao.h>
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>			// MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__56F3D184_7208_47FE_AFE2_E270325F356A__INCLUDED_)

+ 1117 - 0
SystemTray.cpp

@@ -0,0 +1,1117 @@
+/////////////////////////////////////////////////////////////////////////////
+// SystemTray.cpp : implementation file
+//
+// MFC VERSION
+//
+// This is a conglomeration of ideas from the MSJ "Webster" application,
+// sniffing round the online docs, and from other implementations such
+// as PJ Naughter's "CTrayNotifyIcon" (http://indigo.ie/~pjn/ntray.html)
+// especially the "CSystemTray::OnTrayNotification" member function.
+// Joerg Koenig suggested the icon animation stuff
+//
+// This class is a light wrapper around the windows system tray stuff. It
+// adds an icon to the system tray with the specified ToolTip text and 
+// callback notification value, which is sent back to the Parent window.
+//
+// The tray icon can be instantiated using either the constructor or by
+// declaring the object and creating (and displaying) it later on in the
+// program. eg.
+//
+//        CSystemTray m_SystemTray;    // Member variable of some class
+//        
+//        ... 
+//        // in some member function maybe...
+//        m_SystemTray.Create(pParentWnd, WM_MY_NOTIFY, "Click here", 
+//                          hIcon, nSystemTrayID);
+//
+// Written by Chris Maunder ([email protected])
+// Copyright (c) 1998.
+//
+// Updated: 25 Jul 1998 - Added icon animation, and derived class
+//                        from CWnd in order to handle messages. (CJM)
+//                        (icon animation suggested by Joerg Koenig.
+//                        Added API to set default menu item. Code provided
+//                        by Enrico Lelina.
+//
+// Updated: 6 June 1999 - SetIcon can now load non-standard sized icons (Chip Calvert)
+//                        Added "bHidden" parameter when creating icon
+//                        (Thanks to Michael Gombar for these suggestions)
+//                        Restricted tooltip text to 64 characters.
+//
+// Updated: 9 Nov 1999  - Now works in WindowsCE.
+//                        Fix for use in NT services (Thomas Mooney, TeleProc, Inc)
+//                        Added W2K stuff by Michael Dunn
+//
+// Updated: 1 Jan 2000  - Added tray minimisation stuff.
+// 
+// Updated: 21 Sep 2000 - Added GetDoWndAnimation - animation only occurs if the system
+//                        settings allow it (Matthew Ellis). Updated the GetTrayWndRect
+//                        function to include more fallback logic (Matthew Ellis)
+//                        NOTE: Signature of GetTrayWndRect has changed!
+//
+// Updated: 16 Jun 2002 - Fixed stupid errors so that it compiles clean on VC7
+//
+// This code may be used in compiled form in any way you desire. This
+// file may be redistributed unmodified by any means PROVIDING it is 
+// not sold for profit without the authors written consent, and 
+// providing that this notice and the authors name is included. If 
+// the source code in  this file is used in any commercial application 
+// then acknowledgement must be made to the author of this file 
+// (in whatever form you wish).
+//
+// This file is provided "as is" with no expressed or implied warranty.
+// The author accepts no liability for any damage caused through use.
+//
+// Expect bugs.
+// 
+// Please use and enjoy. Please let me know of any bugs/mods/improvements 
+// that you have found/implemented and I will fix/incorporate them into this
+// file. 
+//
+/////////////////////////////////////////////////////////////////////////////
+    
+#include "stdafx.h"
+#include "SystemTray.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#ifndef _WIN32_WCE  // Use C++ exception handling instead of structured.
+#undef TRY
+#undef CATCH
+#undef END_CATCH
+#define TRY try
+#define CATCH(ex_class, ex_object) catch(ex_class* ex_object)
+#define END_CATCH
+#endif  // _WIN32_WCE
+
+#ifndef _countof
+#define _countof(x) ( sizeof(x) / sizeof(x[0]) )
+#endif
+
+IMPLEMENT_DYNAMIC(CSystemTray, CWnd)
+
+const UINT CSystemTray::m_nTimerID    = 4567;
+UINT CSystemTray::m_nMaxTooltipLength  = 64;     // This may change...
+const UINT CSystemTray::m_nTaskbarCreatedMsg = ::RegisterWindowMessage(_T("TaskbarCreated"));
+CWnd  CSystemTray::m_wndInvisible;
+BOOL CSystemTray::m_bShowWndAnimation;
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray construction/creation/destruction
+
+CSystemTray::CSystemTray()
+{
+    Initialise();
+}
+
+CSystemTray::CSystemTray(CWnd* pParent,             // The window that will recieve tray notifications
+                         UINT uCallbackMessage,     // the callback message to send to parent
+                         LPCTSTR szToolTip,         // tray icon tooltip
+                         HICON icon,                // Handle to icon
+                         UINT uID,                  // Identifier of tray icon
+                         BOOL bHidden /*=FALSE*/,   // Hidden on creation?                  
+                         LPCTSTR szBalloonTip /*=NULL*/,    // Ballon tip (w2k only)
+                         LPCTSTR szBalloonTitle /*=NULL*/,  // Balloon tip title (w2k)
+                         DWORD dwBalloonIcon /*=NIIF_NONE*/,// Ballon tip icon (w2k)
+                         UINT uBalloonTimeout /*=10*/)      // Balloon timeout (w2k)
+{
+    Initialise();
+    Create(pParent, uCallbackMessage, szToolTip, icon, uID, bHidden,
+           szBalloonTip, szBalloonTitle, dwBalloonIcon, uBalloonTimeout);
+}
+
+void CSystemTray::Initialise()
+{
+    memset(&m_tnd, 0, sizeof(m_tnd));
+
+    m_bEnabled = FALSE;
+    m_bHidden  = TRUE;
+    m_bRemoved = TRUE;
+
+    m_DefaultMenuItemID    = 0;
+    m_DefaultMenuItemByPos = TRUE;
+
+    m_bShowIconPending = FALSE;
+
+    m_uIDTimer   = 0;
+    m_hSavedIcon = NULL;
+
+	m_pTargetWnd = NULL;
+	m_uCreationFlags = 0;
+
+	m_bShowWndAnimation = FALSE;
+
+#ifdef SYSTEMTRAY_USEW2K
+    OSVERSIONINFO os = { sizeof(os) };
+    GetVersionEx(&os);
+    m_bWin2K = ( VER_PLATFORM_WIN32_NT == os.dwPlatformId && os.dwMajorVersion >= 5 );
+#else
+    m_bWin2K = FALSE;
+#endif
+}
+
+// update by Michael Dunn, November 1999
+//
+//  New version of Create() that handles new features in Win 2K.
+//
+// Changes:
+//  szTip: Same as old, but can be 128 characters instead of 64.
+//  szBalloonTip: Text for a balloon tooltip that is shown when the icon
+//                is first added to the tray.  Pass "" if you don't want
+//                a balloon.
+//  szBalloonTitle: Title text for the balloon tooltip.  This text is shown
+//                  in bold above the szBalloonTip text.  Pass "" if you
+//                  don't want a title.
+//  dwBalloonIcon: Specifies which icon will appear in the balloon.  Legal
+//                 values are:
+//                     NIIF_NONE: No icon
+//                     NIIF_INFO: Information
+//                     NIIF_WARNING: Exclamation
+//                     NIIF_ERROR: Critical error (red circle with X)
+//  uBalloonTimeout: Number of seconds for the balloon to remain visible.
+//                   Must be between 10 and 30 inclusive.
+
+BOOL CSystemTray::Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szToolTip, 
+                         HICON icon, UINT uID, BOOL bHidden /*=FALSE*/,
+                         LPCTSTR szBalloonTip /*=NULL*/, 
+                         LPCTSTR szBalloonTitle /*=NULL*/,  
+                         DWORD dwBalloonIcon /*=NIIF_NONE*/,
+                         UINT uBalloonTimeout /*=10*/)
+{
+#ifdef _WIN32_WCE
+    m_bEnabled = TRUE;
+#else
+    // this is only for Windows 95 (or higher)
+    m_bEnabled = (GetVersion() & 0xff) >= 4;
+    if (!m_bEnabled) 
+    {
+        ASSERT(FALSE);
+        return FALSE;
+    }
+#endif
+
+    m_nMaxTooltipLength = _countof(m_tnd.szTip);
+    
+    // Make sure we avoid conflict with other messages
+    ASSERT(uCallbackMessage >= WM_APP);
+
+    // Tray only supports tooltip text up to m_nMaxTooltipLength) characters
+    ASSERT(AfxIsValidString(szToolTip));
+    ASSERT(_tcslen(szToolTip) <= m_nMaxTooltipLength);
+
+    // Create an invisible window
+    CWnd::CreateEx(0, AfxRegisterWndClass(0), _T(""), WS_POPUP, 0,0,0,0, NULL, 0);
+
+    // load up the NOTIFYICONDATA structure
+    m_tnd.cbSize = sizeof(NOTIFYICONDATA);
+    m_tnd.hWnd   = pParent->GetSafeHwnd()? pParent->GetSafeHwnd() : m_hWnd;
+    m_tnd.uID    = uID;
+    m_tnd.hIcon  = icon;
+    m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+    m_tnd.uCallbackMessage = uCallbackMessage;
+    _tcsncpy(m_tnd.szTip, szToolTip, m_nMaxTooltipLength-1);
+
+#ifdef SYSTEMTRAY_USEW2K
+    if (m_bWin2K && szBalloonTip)
+    {
+        // The balloon tooltip text can be up to 255 chars long.
+        ASSERT(AfxIsValidString(szBalloonTip));
+        ASSERT(lstrlen(szBalloonTip) < 256);
+
+        // The balloon title text can be up to 63 chars long.
+        if (szBalloonTitle)
+        {
+            ASSERT(AfxIsValidString(szBalloonTitle));
+            ASSERT(lstrlen(szBalloonTitle) < 64);
+        }
+
+        // dwBalloonIcon must be valid.
+        ASSERT(NIIF_NONE == dwBalloonIcon    || NIIF_INFO == dwBalloonIcon ||
+               NIIF_WARNING == dwBalloonIcon || NIIF_ERROR == dwBalloonIcon);
+
+        // The timeout must be between 10 and 30 seconds.
+        ASSERT(uBalloonTimeout >= 10 && uBalloonTimeout <= 30);
+
+        m_tnd.uFlags |= NIF_INFO;
+
+        _tcsncpy(m_tnd.szInfo, szBalloonTip, 255);
+        if (szBalloonTitle)
+            _tcsncpy(m_tnd.szInfoTitle, szBalloonTitle, 63);
+        else
+            m_tnd.szInfoTitle[0] = _T('\0');
+        m_tnd.uTimeout    = uBalloonTimeout * 1000; // convert time to ms
+        m_tnd.dwInfoFlags = dwBalloonIcon;
+    }
+#endif
+
+    m_bHidden = bHidden;
+
+#ifdef SYSTEMTRAY_USEW2K    
+    if (m_bWin2K && m_bHidden)
+    {
+        m_tnd.uFlags = NIF_STATE;
+        m_tnd.dwState = NIS_HIDDEN;
+        m_tnd.dwStateMask = NIS_HIDDEN;
+    }
+#endif
+
+	m_uCreationFlags = m_tnd.uFlags;	// Store in case we need to recreate in OnTaskBarCreate
+
+    BOOL bResult = TRUE;
+    if (!m_bHidden || m_bWin2K)
+    {
+        bResult = Shell_NotifyIcon(NIM_ADD, &m_tnd);
+        m_bShowIconPending = m_bHidden = m_bRemoved = !bResult;
+    }
+    
+#ifdef SYSTEMTRAY_USEW2K    
+    if (m_bWin2K && szBalloonTip)
+    {
+        // Zero out the balloon text string so that later operations won't redisplay
+        // the balloon.
+        m_tnd.szInfo[0] = _T('\0');
+    }
+#endif
+
+    return bResult;
+}
+
+CSystemTray::~CSystemTray()
+{
+    RemoveIcon();
+    m_IconList.RemoveAll();
+    DestroyWindow();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray icon manipulation
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:    SetFocus()
+//
+// Description:
+//  Sets the focus to the tray icon.  Microsoft's Win 2K UI guidelines
+//  say you should do this after the user dismisses the icon's context
+//  menu.
+//
+// Input:
+//  Nothing.
+//
+// Returns:
+//  Nothing.
+//
+//////////////////////////////////////////////////////////////////////////
+// Added by Michael Dunn, November, 1999
+//////////////////////////////////////////////////////////////////////////
+
+void CSystemTray::SetFocus()
+{
+#ifdef SYSTEMTRAY_USEW2K
+    Shell_NotifyIcon ( NIM_SETFOCUS, &m_tnd );
+#endif
+}
+
+BOOL CSystemTray::MoveToRight()
+{
+    RemoveIcon();
+    return AddIcon();
+}
+
+BOOL CSystemTray::AddIcon()
+{
+    if (!m_bRemoved)
+        RemoveIcon();
+
+    if (m_bEnabled)
+    {
+        m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+        if (!Shell_NotifyIcon(NIM_ADD, &m_tnd))
+            m_bShowIconPending = TRUE;
+        else
+            m_bRemoved = m_bHidden = FALSE;
+    }
+    return (m_bRemoved == FALSE);
+}
+
+BOOL CSystemTray::RemoveIcon()
+{
+    m_bShowIconPending = FALSE;
+
+    if (!m_bEnabled || m_bRemoved)
+        return TRUE;
+
+    m_tnd.uFlags = 0;
+    if (Shell_NotifyIcon(NIM_DELETE, &m_tnd))
+        m_bRemoved = m_bHidden = TRUE;
+
+    return (m_bRemoved == TRUE);
+}
+
+BOOL CSystemTray::HideIcon()
+{
+    if (!m_bEnabled || m_bRemoved || m_bHidden)
+        return TRUE;
+
+#ifdef SYSTEMTRAY_USEW2K
+    if (m_bWin2K)
+    {
+        m_tnd.uFlags = NIF_STATE;
+        m_tnd.dwState = NIS_HIDDEN;
+        m_tnd.dwStateMask = NIS_HIDDEN;
+
+        m_bHidden = Shell_NotifyIcon( NIM_MODIFY, &m_tnd);
+    }
+    else
+#endif
+        RemoveIcon();
+
+    return (m_bHidden == TRUE);
+}
+
+BOOL CSystemTray::ShowIcon()
+{
+    if (m_bRemoved)
+        return AddIcon();
+
+    if (!m_bHidden)
+        return TRUE;
+
+#ifdef SYSTEMTRAY_USEW2K
+    if (m_bWin2K)
+    {
+        m_tnd.uFlags = NIF_STATE;
+        m_tnd.dwState = 0;
+        m_tnd.dwStateMask = NIS_HIDDEN;
+        m_bHidden = !Shell_NotifyIcon ( NIM_MODIFY, &m_tnd );
+    }
+    else
+#endif
+        AddIcon();
+
+    return (m_bHidden == FALSE);
+}
+
+BOOL CSystemTray::SetIcon(HICON hIcon)
+{
+    if (!m_bEnabled)
+        return FALSE;
+
+    m_tnd.uFlags = NIF_ICON;
+    m_tnd.hIcon = hIcon;
+
+    if (m_bHidden)
+        return TRUE;
+    else
+        return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
+}
+
+BOOL CSystemTray::SetIcon(LPCTSTR lpszIconName)
+{
+    HICON hIcon = (HICON) ::LoadImage(AfxGetResourceHandle(), 
+                                      lpszIconName,
+                                      IMAGE_ICON, 
+                                      0, 0,
+                                      LR_DEFAULTCOLOR | LR_SHARED);
+
+    return SetIcon(hIcon);
+}
+
+BOOL CSystemTray::SetIcon(UINT nIDResource)
+{
+    return SetIcon(MAKEINTRESOURCE(nIDResource));
+}
+
+BOOL CSystemTray::SetStandardIcon(LPCTSTR lpIconName)
+{
+    HICON hIcon = LoadIcon(NULL, lpIconName);
+
+    return SetIcon(hIcon);
+}
+
+BOOL CSystemTray::SetStandardIcon(UINT nIDResource)
+{
+	return SetStandardIcon(MAKEINTRESOURCE(nIDResource));
+}
+ 
+HICON CSystemTray::GetIcon() const
+{
+    return (m_bEnabled)? m_tnd.hIcon : NULL;
+}
+
+BOOL CSystemTray::SetIconList(UINT uFirstIconID, UINT uLastIconID) 
+{
+	if (uFirstIconID > uLastIconID)
+        return FALSE;
+
+	const CWinApp* pApp = AfxGetApp();
+    if (!pApp)
+    {
+        ASSERT(FALSE);
+        return FALSE;
+    }
+
+    m_IconList.RemoveAll();
+    TRY {
+	    for (UINT i = uFirstIconID; i <= uLastIconID; i++)
+		    m_IconList.Add(pApp->LoadIcon(i));
+    }
+    CATCH(CMemoryException, e)
+    {
+        e->ReportError();
+        e->Delete();
+        m_IconList.RemoveAll();
+        return FALSE;
+    }
+    END_CATCH
+
+    return TRUE;
+}
+
+BOOL CSystemTray::SetIconList(HICON* pHIconList, UINT nNumIcons)
+{
+    m_IconList.RemoveAll();
+
+    TRY {
+	    for (UINT i = 0; i <= nNumIcons; i++)
+		    m_IconList.Add(pHIconList[i]);
+    }
+    CATCH (CMemoryException, e)
+    {
+        e->ReportError();
+        e->Delete();
+        m_IconList.RemoveAll();
+        return FALSE;
+    }
+    END_CATCH
+
+    return TRUE;
+}
+
+BOOL CSystemTray::Animate(UINT nDelayMilliSeconds, int nNumSeconds /*=-1*/)
+{
+    StopAnimation();
+
+    m_nCurrentIcon = 0;
+    m_StartTime = COleDateTime::GetCurrentTime();
+    m_nAnimationPeriod = nNumSeconds;
+    m_hSavedIcon = GetIcon();
+
+	// Setup a timer for the animation
+	m_uIDTimer = SetTimer(m_nTimerID, nDelayMilliSeconds, NULL);
+
+    return (m_uIDTimer != 0);
+}
+
+BOOL CSystemTray::StepAnimation()
+{
+    if (!m_IconList.GetSize())
+        return FALSE;
+
+    m_nCurrentIcon++;
+    if (m_nCurrentIcon >= m_IconList.GetSize())
+        m_nCurrentIcon = 0;
+
+    return SetIcon(m_IconList[m_nCurrentIcon]);
+}
+
+BOOL CSystemTray::StopAnimation()
+{
+    BOOL bResult = FALSE;
+
+    if (m_uIDTimer)
+	    bResult = KillTimer(m_uIDTimer);
+    m_uIDTimer = 0;
+
+    if (m_hSavedIcon)
+        SetIcon(m_hSavedIcon);
+    m_hSavedIcon = NULL;
+
+    return bResult;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray tooltip text manipulation
+
+BOOL CSystemTray::SetTooltipText(LPCTSTR pszTip)
+{
+    ASSERT(AfxIsValidString(pszTip)); // (md)
+    ASSERT(_tcslen(pszTip) < m_nMaxTooltipLength);
+
+    if (!m_bEnabled) 
+        return FALSE;
+
+    m_tnd.uFlags = NIF_TIP;
+    _tcsncpy(m_tnd.szTip, pszTip, m_nMaxTooltipLength-1);
+
+    if (m_bHidden)
+        return TRUE;
+    else
+        return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
+}
+
+BOOL CSystemTray::SetTooltipText(UINT nID)
+{
+    CString strText;
+    VERIFY(strText.LoadString(nID));
+
+    return SetTooltipText(strText);
+}
+
+CString CSystemTray::GetTooltipText() const
+{
+    CString strText;
+    if (m_bEnabled)
+        strText = m_tnd.szTip;
+
+    return strText;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray support for Win 2K features.
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:    ShowBalloon
+//
+// Description:
+//  Shows a balloon tooltip over the tray icon.
+//
+// Input:
+//  szText: [in] Text for the balloon tooltip.
+//  szTitle: [in] Title for the balloon.  This text is shown in bold above
+//           the tooltip text (szText).  Pass "" if you don't want a title.
+//  dwIcon: [in] Specifies an icon to appear in the balloon.  Legal values are:
+//                 NIIF_NONE: No icon
+//                 NIIF_INFO: Information
+//                 NIIF_WARNING: Exclamation
+//                 NIIF_ERROR: Critical error (red circle with X)
+//  uTimeout: [in] Number of seconds for the balloon to remain visible.  Can
+//            be between 10 and 30 inclusive.
+//
+// Returns:
+//  TRUE if successful, FALSE if not.
+//
+//////////////////////////////////////////////////////////////////////////
+// Added by Michael Dunn, November 1999
+//////////////////////////////////////////////////////////////////////////
+
+BOOL CSystemTray::ShowBalloon(LPCTSTR szText,
+                              LPCTSTR szTitle  /*=NULL*/,
+                              DWORD   dwIcon   /*=NIIF_NONE*/,
+                              UINT    uTimeout /*=10*/ )
+{
+#ifndef SYSTEMTRAY_USEW2K
+    return FALSE;
+#else
+    // Bail out if we're not on Win 2K.
+    if (!m_bWin2K)
+        return FALSE;
+
+    // Verify input parameters.
+
+    // The balloon tooltip text can be up to 255 chars long.
+    ASSERT(AfxIsValidString(szText));
+    ASSERT(lstrlen(szText) < 256);
+
+    // The balloon title text can be up to 63 chars long.
+    if (szTitle)
+    {
+        ASSERT(AfxIsValidString( szTitle));
+        ASSERT(lstrlen(szTitle) < 64);
+    }
+
+    // dwBalloonIcon must be valid.
+    ASSERT(NIIF_NONE == dwIcon    || NIIF_INFO == dwIcon ||
+           NIIF_WARNING == dwIcon || NIIF_ERROR == dwIcon);
+
+    // The timeout must be between 10 and 30 seconds.
+    ASSERT(uTimeout >= 10 && uTimeout <= 30);
+
+
+    m_tnd.uFlags = NIF_INFO;
+    _tcsncpy(m_tnd.szInfo, szText, 256);
+    if (szTitle)
+        _tcsncpy(m_tnd.szInfoTitle, szTitle, 64);
+    else
+        m_tnd.szInfoTitle[0] = _T('\0');
+    m_tnd.dwInfoFlags = dwIcon;
+    m_tnd.uTimeout = uTimeout * 1000;   // convert time to ms
+
+    BOOL bSuccess = Shell_NotifyIcon (NIM_MODIFY, &m_tnd);
+
+    // Zero out the balloon text string so that later operations won't redisplay
+    // the balloon.
+    m_tnd.szInfo[0] = _T('\0');
+
+    return bSuccess;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray notification window stuff
+
+BOOL CSystemTray::SetNotificationWnd(CWnd* pWnd)
+{
+    if (!m_bEnabled) 
+        return FALSE;
+
+    // Make sure Notification window is valid
+    if (!pWnd || !::IsWindow(pWnd->GetSafeHwnd()))
+    {
+        ASSERT(FALSE);
+        return FALSE;
+    }
+
+    m_tnd.hWnd = pWnd->GetSafeHwnd();
+    m_tnd.uFlags = 0;
+
+    if (m_bHidden)
+        return TRUE;
+    else
+        return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
+}
+
+CWnd* CSystemTray::GetNotificationWnd() const
+{
+    return CWnd::FromHandle(m_tnd.hWnd);
+}
+
+// Hatr added
+
+// Hatr added
+
+// Change or retrive the window to send menu commands to
+BOOL CSystemTray::SetTargetWnd(CWnd* pTargetWnd)
+{
+    m_pTargetWnd = pTargetWnd;
+    return TRUE;
+} // CSystemTray::SetTargetWnd()
+
+CWnd* CSystemTray::GetTargetWnd() const
+{
+    if (m_pTargetWnd)
+        return m_pTargetWnd;
+    else
+        return AfxGetMainWnd();
+} // CSystemTray::GetTargetWnd()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray notification message stuff
+
+BOOL CSystemTray::SetCallbackMessage(UINT uCallbackMessage)
+{
+    if (!m_bEnabled)
+        return FALSE;
+
+    // Make sure we avoid conflict with other messages
+    ASSERT(uCallbackMessage >= WM_APP);
+
+    m_tnd.uCallbackMessage = uCallbackMessage;
+    m_tnd.uFlags = NIF_MESSAGE;
+
+    if (m_bHidden)
+        return TRUE;
+    else
+        return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
+}
+
+UINT CSystemTray::GetCallbackMessage() const
+{
+    return m_tnd.uCallbackMessage;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray menu manipulation
+
+BOOL CSystemTray::SetMenuDefaultItem(UINT uItem, BOOL bByPos)
+{
+#ifdef _WIN32_WCE
+    return FALSE;
+#else
+    if ((m_DefaultMenuItemID == uItem) && (m_DefaultMenuItemByPos == bByPos)) 
+        return TRUE;
+
+    m_DefaultMenuItemID = uItem;
+    m_DefaultMenuItemByPos = bByPos;   
+
+    CMenu menu, *pSubMenu;
+
+    if (!menu.LoadMenu(m_tnd.uID))
+        return FALSE;
+
+    pSubMenu = menu.GetSubMenu(0);
+    if (!pSubMenu)
+        return FALSE;
+
+    ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);
+
+    return TRUE;
+#endif
+}
+
+void CSystemTray::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos)
+{
+    uItem = m_DefaultMenuItemID;
+    bByPos = m_DefaultMenuItemByPos;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray message handlers
+
+BEGIN_MESSAGE_MAP(CSystemTray, CWnd)
+	//{{AFX_MSG_MAP(CSystemTray)
+	ON_WM_TIMER()
+	//}}AFX_MSG_MAP
+#ifndef _WIN32_WCE
+	ON_WM_SETTINGCHANGE()
+#endif
+    ON_REGISTERED_MESSAGE(CSystemTray::m_nTaskbarCreatedMsg, OnTaskbarCreated)
+END_MESSAGE_MAP()
+
+void CSystemTray::OnTimer(UINT nIDEvent) 
+{
+    if (nIDEvent != m_uIDTimer)
+    {
+        ASSERT(FALSE);
+        return;
+    }
+
+    COleDateTime CurrentTime = COleDateTime::GetCurrentTime();
+    COleDateTimeSpan period = CurrentTime - m_StartTime;
+
+    if (m_nAnimationPeriod > 0 && m_nAnimationPeriod < period.GetTotalSeconds())
+    {
+        StopAnimation();
+        return;
+    }
+
+    StepAnimation();
+}
+
+// This is called whenever the taskbar is created (eg after explorer crashes
+// and restarts. Please note that the WM_TASKBARCREATED message is only passed
+// to TOP LEVEL windows (like WM_QUERYNEWPALETTE)
+LRESULT CSystemTray::OnTaskbarCreated(WPARAM /*wParam*/, LPARAM /*lParam*/) 
+{
+    InstallIconPending();
+	return 0L;
+}
+
+#ifndef _WIN32_WCE
+void CSystemTray::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) 
+{
+	CWnd::OnSettingChange(uFlags, lpszSection);
+
+    if (uFlags == SPI_SETWORKAREA)
+        InstallIconPending();	
+}
+#endif
+
+LRESULT CSystemTray::OnTrayNotification(UINT wParam, LONG lParam) 
+{
+    //Return quickly if its not for this tray icon
+    if (wParam != m_tnd.uID)
+        return 0L;
+
+    CMenu menu, *pSubMenu;
+    CWnd *pTargetWnd = GetTargetWnd();
+    if (!pTargetWnd)
+        return 0L;
+
+    // Clicking with right button brings up a context menu
+#if defined(_WIN32_WCE) //&& _WIN32_WCE < 211
+    BOOL bAltPressed = ((GetKeyState(VK_MENU) & (1 << (sizeof(SHORT)*8-1))) != 0);
+    if (LOWORD(lParam) == WM_LBUTTONUP && bAltPressed)
+#else
+    if (LOWORD(lParam) == WM_RBUTTONUP)
+#endif
+    {    
+        if (!menu.LoadMenu(m_tnd.uID))
+            return 0;
+        
+        pSubMenu = menu.GetSubMenu(0);
+        if (!pSubMenu)
+            return 0;
+
+#ifndef _WIN32_WCE
+        // Make chosen menu item the default (bold font)
+        ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);
+#endif
+
+        // Display and track the popup menu
+        CPoint pos;
+#ifdef _WIN32_WCE
+        pos = CPoint(GetMessagePos());
+#else
+        GetCursorPos(&pos);
+#endif
+
+        pTargetWnd->SetForegroundWindow(); 
+        
+#ifndef _WIN32_WCE
+        ::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0, 
+                         pTargetWnd->GetSafeHwnd(), NULL);
+#else
+        pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, pos.x, pos.y, pTargetWnd, NULL);
+#endif
+
+        // BUGFIX: See "PRB: Menus for Notification Icons Don't Work Correctly"
+        pTargetWnd->PostMessage(WM_NULL, 0, 0);
+
+        menu.DestroyMenu();
+    } 
+#if defined(_WIN32_WCE) //&& _WIN32_WCE < 211
+    if (LOWORD(lParam) == WM_LBUTTONDBLCLK && bAltPressed)
+#else
+    else if (LOWORD(lParam) == WM_LBUTTONDBLCLK) 
+#endif
+    {
+        // double click received, the default action is to execute default menu item
+        pTargetWnd->SetForegroundWindow();  
+
+        UINT uItem;
+        if (m_DefaultMenuItemByPos)
+        {
+            if (!menu.LoadMenu(m_tnd.uID))
+                return 0;
+            
+            pSubMenu = menu.GetSubMenu(0);
+            if (!pSubMenu)
+                return 0;
+            
+            uItem = pSubMenu->GetMenuItemID(m_DefaultMenuItemID);
+
+			menu.DestroyMenu();
+        }
+        else
+            uItem = m_DefaultMenuItemID;
+        
+        pTargetWnd->SendMessage(WM_COMMAND, uItem, 0);
+    }
+
+    return 1;
+}
+
+LRESULT CSystemTray::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
+{
+    if (message == m_tnd.uCallbackMessage)
+        return OnTrayNotification(wParam, lParam);
+	
+	return CWnd::WindowProc(message, wParam, lParam);
+}
+
+void CSystemTray::InstallIconPending()
+{
+    // Is the icon display pending, and it's not been set as "hidden"?
+    if (!m_bShowIconPending || m_bHidden)
+        return;
+
+	// Reset the flags to what was used at creation
+	m_tnd.uFlags = m_uCreationFlags;
+
+    // Try and recreate the icon
+    m_bHidden = !Shell_NotifyIcon(NIM_ADD, &m_tnd);
+
+    // If it's STILL hidden, then have another go next time...
+    m_bShowIconPending = !m_bHidden;
+
+    ASSERT(m_bHidden == FALSE);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// For minimising/maximising from system tray
+
+BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam)
+{
+    TCHAR szClassName[256];
+    GetClassName(hwnd, szClassName, 255);
+	
+    // Did we find the Main System Tray? If so, then get its size and keep going
+    if (_tcscmp(szClassName, _T("TrayNotifyWnd")) == 0)
+    {
+        CRect *pRect = (CRect*) lParam;
+        ::GetWindowRect(hwnd, pRect);
+        return TRUE;
+    }
+	
+    // Did we find the System Clock? If so, then adjust the size of the rectangle
+    // we have and quit (clock will be found after the system tray)
+    if (_tcscmp(szClassName, _T("TrayClockWClass")) == 0)
+    {
+        CRect *pRect = (CRect*) lParam;
+        CRect rectClock;
+        ::GetWindowRect(hwnd, rectClock);
+        // if clock is above system tray adjust accordingly
+        if (rectClock.bottom < pRect->bottom-5) // 10 = random fudge factor.
+            pRect->top = rectClock.bottom;
+        else
+            pRect->right = rectClock.left;
+        return FALSE;
+    }
+	
+    return TRUE;
+}
+ 
+#ifndef _WIN32_WCE
+// enhanced version by Matthew Ellis <[email protected]>
+void CSystemTray::GetTrayWndRect(LPRECT lprect)
+{
+#define DEFAULT_RECT_WIDTH 150
+#define DEFAULT_RECT_HEIGHT 30
+	
+    HWND hShellTrayWnd = ::FindWindow(_T("Shell_TrayWnd"), NULL);
+    if (hShellTrayWnd)
+    {
+        ::GetWindowRect(hShellTrayWnd, lprect);
+        EnumChildWindows(hShellTrayWnd, FindTrayWnd, (LPARAM)lprect);
+        return;
+    }
+    // OK, we failed to get the rect from the quick hack. Either explorer isn't
+    // running or it's a new version of the shell with the window class names
+    // changed (how dare Microsoft change these undocumented class names!) So, we
+    // try to find out what side of the screen the taskbar is connected to. We
+    // know that the system tray is either on the right or the bottom of the
+    // taskbar, so we can make a good guess at where to minimize to
+    APPBARDATA appBarData;
+    appBarData.cbSize=sizeof(appBarData);
+    if (SHAppBarMessage(ABM_GETTASKBARPOS,&appBarData))
+    {
+        // We know the edge the taskbar is connected to, so guess the rect of the
+        // system tray. Use various fudge factor to make it look good
+        switch(appBarData.uEdge)
+        {
+        case ABE_LEFT:
+        case ABE_RIGHT:
+            // We want to minimize to the bottom of the taskbar
+            lprect->top    = appBarData.rc.bottom-100;
+            lprect->bottom = appBarData.rc.bottom-16;
+            lprect->left   = appBarData.rc.left;
+            lprect->right  = appBarData.rc.right;
+            break;
+            
+        case ABE_TOP:
+        case ABE_BOTTOM:
+            // We want to minimize to the right of the taskbar
+            lprect->top    = appBarData.rc.top;
+            lprect->bottom = appBarData.rc.bottom;
+            lprect->left   = appBarData.rc.right-100;
+            lprect->right  = appBarData.rc.right-16;
+            break;
+        }
+        return;
+    }
+    
+    // Blimey, we really aren't in luck. It's possible that a third party shell
+    // is running instead of explorer. This shell might provide support for the
+    // system tray, by providing a Shell_TrayWnd window (which receives the
+    // messages for the icons) So, look for a Shell_TrayWnd window and work out
+    // the rect from that. Remember that explorer's taskbar is the Shell_TrayWnd,
+    // and stretches either the width or the height of the screen. We can't rely
+    // on the 3rd party shell's Shell_TrayWnd doing the same, in fact, we can't
+    // rely on it being any size. The best we can do is just blindly use the
+    // window rect, perhaps limiting the width and height to, say 150 square.
+    // Note that if the 3rd party shell supports the same configuraion as
+    // explorer (the icons hosted in NotifyTrayWnd, which is a child window of
+    // Shell_TrayWnd), we would already have caught it above
+    if (hShellTrayWnd)
+    {
+        ::GetWindowRect(hShellTrayWnd, lprect);
+        if (lprect->right - lprect->left > DEFAULT_RECT_WIDTH)
+            lprect->left = lprect->right - DEFAULT_RECT_WIDTH;
+        if (lprect->bottom - lprect->top > DEFAULT_RECT_HEIGHT)
+            lprect->top = lprect->bottom - DEFAULT_RECT_HEIGHT;
+        
+        return;
+    }
+    
+    // OK. Haven't found a thing. Provide a default rect based on the current work
+    // area
+    SystemParametersInfo(SPI_GETWORKAREA,0, lprect, 0);
+    lprect->left = lprect->right - DEFAULT_RECT_WIDTH;
+    lprect->top  = lprect->bottom - DEFAULT_RECT_HEIGHT;
+}
+
+// Check to see if the animation has been disabled (Matthew Ellis <[email protected]>)
+BOOL CSystemTray::GetDoWndAnimation()
+{
+	if(!m_bShowWndAnimation)
+		return FALSE;
+	
+	ANIMATIONINFO ai;
+	
+	ai.cbSize=sizeof(ai);
+	SystemParametersInfo(SPI_GETANIMATION,sizeof(ai),&ai,0);
+	
+	return ai.iMinAnimate?TRUE:FALSE;
+}
+#endif
+
+BOOL CSystemTray::RemoveTaskbarIcon(CWnd* pWnd)
+{
+    LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);
+	
+    // Create static invisible window
+    if (!::IsWindow(m_wndInvisible.m_hWnd))
+    {
+		if (!m_wndInvisible.CreateEx(0, pstrOwnerClass, _T(""), WS_POPUP,
+			CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+			NULL, 0))
+			return FALSE;
+    }
+	
+    pWnd->SetParent(&m_wndInvisible);
+	
+    return TRUE;
+}
+
+void CSystemTray::MinimiseToTray(CWnd* pWnd)
+{
+#ifndef _WIN32_WCE
+    if (GetDoWndAnimation())
+    {
+        CRect rectFrom, rectTo;
+		
+        pWnd->GetWindowRect(rectFrom);
+        GetTrayWndRect(rectTo);
+		
+		::DrawAnimatedRects(pWnd->m_hWnd, IDANI_CAPTION, rectFrom, rectTo);
+    }
+	
+    RemoveTaskbarIcon(pWnd);
+    pWnd->ModifyStyle(WS_VISIBLE, 0);
+#endif
+}
+
+void CSystemTray::MaximiseFromTray(CWnd* pWnd)
+{
+#ifndef _WIN32_WCE
+    if (GetDoWndAnimation())
+    {
+        CRect rectTo;
+        pWnd->GetWindowRect(rectTo);
+
+        CRect rectFrom;
+        GetTrayWndRect(rectFrom);
+
+        pWnd->SetParent(NULL);
+		::DrawAnimatedRects(pWnd->m_hWnd, IDANI_CAPTION, rectFrom, rectTo);
+    }
+    else
+        pWnd->SetParent(NULL);
+
+    pWnd->ModifyStyle(0, WS_VISIBLE);
+    pWnd->RedrawWindow(NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME |
+                                   RDW_INVALIDATE | RDW_ERASE);
+
+    // Move focus away and back again to ensure taskbar icon is recreated
+    if (::IsWindow(m_wndInvisible.m_hWnd))
+        m_wndInvisible.SetActiveWindow();
+    pWnd->SetActiveWindow();
+    pWnd->SetForegroundWindow();
+#endif
+}

+ 195 - 0
SystemTray.h

@@ -0,0 +1,195 @@
+/////////////////////////////////////////////////////////////////////////////
+// SystemTray.h : header file
+//
+// Written by Chris Maunder ([email protected])
+// Copyright (c) 1998.
+//
+// This code may be used in compiled form in any way you desire. This
+// file may be redistributed unmodified by any means PROVIDING it is 
+// not sold for profit without the authors written consent, and 
+// providing that this notice and the authors name is included. If 
+// the source code in  this file is used in any commercial application 
+// then acknowledgement must be made to the author of this file 
+// (in whatever form you wish).
+//
+// This file is provided "as is" with no expressed or implied warranty.
+//
+// Expect bugs.
+// 
+// Please use and enjoy. Please let me know of any bugs/mods/improvements 
+// that you have found/implemented and I will fix/incorporate them into this
+// file. 
+
+#ifndef _INCLUDED_SYSTEMTRAY_H_
+#define _INCLUDED_SYSTEMTRAY_H_
+
+#define ASSUME_IE5_OR_ABOVE
+
+#ifdef ASSUME_IE5_OR_ABOVE
+#	ifndef _WIN32_IE
+#		define _WIN32_IE 0x0500    // enable shell v5 features
+#	elif _WIN32_IE < 0x0500
+#		undef _WIN32_IE
+#		define _WIN32_IE 0x0500    // enable shell v5 features
+#	endif
+#	ifdef NOTIFYICONDATA_V1_SIZE   // If NOTIFYICONDATA_V1_SIZE, then we can use fun stuff
+#		define SYSTEMTRAY_USEW2K
+#	endif
+#endif
+
+#ifndef NIIF_NONE
+#define NIIF_NONE 0
+#endif
+
+// #include <afxwin.h>
+#include <afxtempl.h>
+#include <afxdisp.h>    // COleDateTime
+
+/////////////////////////////////////////////////////////////////////////////
+// CSystemTray window
+
+class CSystemTray : public CWnd
+{
+// Construction/destruction
+public:
+    CSystemTray();
+    CSystemTray(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID, 
+                BOOL bhidden = FALSE,
+                LPCTSTR szBalloonTip = NULL, LPCTSTR szBalloonTitle = NULL, 
+                DWORD dwBalloonIcon = NIIF_NONE, UINT uBalloonTimeout = 10);
+    virtual ~CSystemTray();
+
+    DECLARE_DYNAMIC(CSystemTray)
+
+// Operations
+public:
+    BOOL Enabled() { return m_bEnabled; }
+    BOOL Visible() { return !m_bHidden; }
+
+    // Create the tray icon
+    BOOL Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID,
+                BOOL bHidden = FALSE,
+                LPCTSTR szBalloonTip = NULL, LPCTSTR szBalloonTitle = NULL, 
+                DWORD dwBalloonIcon = NIIF_NONE, UINT uBalloonTimeout = 10);
+
+    // Change or retrieve the Tooltip text
+    BOOL    SetTooltipText(LPCTSTR pszTooltipText);
+    BOOL    SetTooltipText(UINT nID);
+    CString GetTooltipText() const;
+
+    // Change or retrieve the icon displayed
+    BOOL  SetIcon(HICON hIcon);
+    BOOL  SetIcon(LPCTSTR lpszIconName);
+    BOOL  SetIcon(UINT nIDResource);
+    BOOL  SetStandardIcon(LPCTSTR lpIconName);
+    BOOL  SetStandardIcon(UINT nIDResource);
+    HICON GetIcon() const;
+
+    void  SetFocus();
+    BOOL  HideIcon();
+    BOOL  ShowIcon();
+    BOOL  AddIcon();
+    BOOL  RemoveIcon();
+    BOOL  MoveToRight();
+
+    BOOL ShowBalloon(LPCTSTR szText, LPCTSTR szTitle = NULL,
+                     DWORD dwIcon = NIIF_NONE, UINT uTimeout = 10);
+
+    // For icon animation
+    BOOL  SetIconList(UINT uFirstIconID, UINT uLastIconID); 
+    BOOL  SetIconList(HICON* pHIconList, UINT nNumIcons); 
+    BOOL  Animate(UINT nDelayMilliSeconds, int nNumSeconds = -1);
+    BOOL  StepAnimation();
+    BOOL  StopAnimation();
+
+    // Change menu default item
+    void GetMenuDefaultItem(UINT& uItem, BOOL& bByPos);
+    BOOL SetMenuDefaultItem(UINT uItem, BOOL bByPos);
+
+    // Change or retrieve the window to send notification messages to
+    BOOL  SetNotificationWnd(CWnd* pNotifyWnd);
+    CWnd* GetNotificationWnd() const;
+
+    // Change or retrieve the window to send menu commands to
+    BOOL  SetTargetWnd(CWnd* pTargetWnd);
+    CWnd* GetTargetWnd() const;
+
+    // Change or retrieve  notification messages sent to the window
+    BOOL  SetCallbackMessage(UINT uCallbackMessage);
+    UINT  GetCallbackMessage() const;
+
+    UINT  GetTimerID() const   { return m_nTimerID; }
+
+// Static functions
+public:
+    static void MinimiseToTray(CWnd* pWnd);
+    static void MaximiseFromTray(CWnd* pWnd);
+
+public:
+    // Default handler for tray notification message
+    virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
+
+// Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CSystemTray)
+	protected:
+	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+    void Initialise();
+    void InstallIconPending();
+
+// Implementation
+protected:
+    NOTIFYICONDATA  m_tnd;
+    BOOL            m_bEnabled;         // does O/S support tray icon?
+    BOOL            m_bHidden;          // Has the icon been hidden?
+    BOOL            m_bRemoved;         // Has the icon been removed?
+    BOOL            m_bShowIconPending; // Show the icon once tha taskbar has been created
+    BOOL            m_bWin2K;           // Use new W2K features?
+	CWnd*           m_pTargetWnd;       // Window that menu commands are sent
+
+    CArray<HICON, HICON> m_IconList;
+    UINT         m_uIDTimer;
+    int          m_nCurrentIcon;
+    COleDateTime m_StartTime;
+    int          m_nAnimationPeriod;
+    HICON        m_hSavedIcon;
+    UINT         m_DefaultMenuItemID;
+    BOOL         m_DefaultMenuItemByPos;
+	UINT         m_uCreationFlags;
+	
+// Static data
+protected:
+    static BOOL RemoveTaskbarIcon(CWnd* pWnd);
+
+    static const UINT m_nTimerID;
+    static UINT  m_nMaxTooltipLength;
+    static const UINT m_nTaskbarCreatedMsg;
+    static CWnd  m_wndInvisible;
+	static BOOL	 m_bShowWndAnimation;
+
+    static BOOL GetW2K();
+#ifndef _WIN32_WCE
+    static void GetTrayWndRect(LPRECT lprect);
+    static BOOL GetDoWndAnimation();
+#endif
+
+// Generated message map functions
+protected:
+	//{{AFX_MSG(CSystemTray)
+	afx_msg void OnTimer(UINT nIDEvent);
+	//}}AFX_MSG
+#ifndef _WIN32_WCE
+	afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
+#endif
+    LRESULT OnTaskbarCreated(WPARAM wParam, LPARAM lParam);
+    DECLARE_MESSAGE_MAP()
+};
+
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////

+ 89 - 0
TypesTable.cpp

@@ -0,0 +1,89 @@
+// TypesTable.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "cp_main.h"
+#include "TypesTable.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTypesTable
+
+IMPLEMENT_DYNAMIC(CTypesTable, CDaoRecordset)
+
+CTypesTable::CTypesTable(CDaoDatabase* pdb)
+	: CDaoRecordset(pdb)
+{
+	//{{AFX_FIELD_INIT(CTypesTable)
+	m_ID = 0;
+	m_TypeText = _T("");
+	m_nFields = 2;
+	//}}AFX_FIELD_INIT
+	m_nDefaultType = dbOpenDynaset;
+}
+
+
+CString CTypesTable::GetDefaultDBName()
+{
+	return _T("C:\\Projects\\Ditto\\CP_Shared\\Release_DLL\\97.mdb");
+}
+
+CString CTypesTable::GetDefaultSQL()
+{
+	return _T("[Types]");
+}
+
+void CTypesTable::DoFieldExchange(CDaoFieldExchange* pFX)
+{
+	//{{AFX_FIELD_MAP(CTypesTable)
+	pFX->SetFieldType(CDaoFieldExchange::outputColumn);
+	DFX_Long(pFX, _T("[ID]"), m_ID);
+	DFX_Text(pFX, _T("[TypeText]"), m_TypeText);
+	//}}AFX_FIELD_MAP
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CTypesTable diagnostics
+
+#ifdef _DEBUG
+void CTypesTable::AssertValid() const
+{
+	CDaoRecordset::AssertValid();
+}
+
+void CTypesTable::Dump(CDumpContext& dc) const
+{
+	CDaoRecordset::Dump(dc);
+}
+#endif //_DEBUG
+
+
+BOOL CTypesTable::DeleteAll()
+{
+	BOOL bRet = FALSE;
+	try
+	{
+		theApp.EnsureOpenDB();
+		theApp.m_pDatabase->Execute("DELETE * FROM Types", dbFailOnError);
+		bRet = TRUE;
+	}
+	catch(CDaoException* e)
+	{
+		AfxMessageBox(e->m_pErrorInfo->m_strDescription);
+		e->Delete();
+	}
+
+	return bRet;
+}
+
+void CTypesTable::Open(int nOpenType, LPCTSTR lpszSql, int nOptions) 
+{
+	m_pDatabase = theApp.EnsureOpenDB();
+	
+	CDaoRecordset::Open(nOpenType, lpszSql, nOptions);
+}

+ 48 - 0
TypesTable.h

@@ -0,0 +1,48 @@
+#if !defined(AFX_TYPESTABLE_H__41C712E1_75EC_4385_ABA3_9749852F63FD__INCLUDED_)
+#define AFX_TYPESTABLE_H__41C712E1_75EC_4385_ABA3_9749852F63FD__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// TypesTable.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CTypesTable DAO recordset
+
+class CTypesTable : public CDaoRecordset
+{
+public:
+	CTypesTable(CDaoDatabase* pDatabase = NULL);
+	DECLARE_DYNAMIC(CTypesTable)
+
+// Field/Param Data
+	//{{AFX_FIELD(CTypesTable, CDaoRecordset)
+	long	m_ID;
+	CString	m_TypeText;
+	//}}AFX_FIELD
+	
+public:
+	BOOL DeleteAll();
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CTypesTable)
+	public:
+	virtual CString GetDefaultDBName();		// Default database name
+	virtual CString GetDefaultSQL();		// Default SQL for Recordset
+	virtual void DoFieldExchange(CDaoFieldExchange* pFX);  // RFX support
+	virtual void Open(int nOpenType = AFX_DAO_USE_DEFAULT_TYPE, LPCTSTR lpszSql = NULL, int nOptions = 0);
+	//}}AFX_VIRTUAL
+
+// Implementation
+#ifdef _DEBUG
+	virtual void AssertValid() const;
+	virtual void Dump(CDumpContext& dc) const;
+#endif
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TYPESTABLE_H__41C712E1_75EC_4385_ABA3_9749852F63FD__INCLUDED_)

BIN
Version.Lib


+ 418 - 0
WndEx.cpp

@@ -0,0 +1,418 @@
+// WndEx.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "WndEx.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CWndEx
+
+CWndEx::CWndEx()
+{
+	m_bResizable = true;
+	m_bMouseDownOnClose = false;
+	m_bMouseOverClose = false;
+	m_bMouseDownOnCaption = false;
+}
+
+CWndEx::~CWndEx()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CWndEx, CWnd)
+	//{{AFX_MSG_MAP(CWndEx)
+	ON_WM_CREATE()
+	ON_WM_NCPAINT()
+	ON_WM_NCCALCSIZE()
+	ON_WM_NCHITTEST()
+	ON_WM_NCLBUTTONDOWN()
+	ON_WM_NCMOUSEMOVE()
+	ON_WM_NCLBUTTONUP()
+	ON_WM_ERASEBKGND()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CWndEx message handlers
+
+BOOL CWndEx::Create(const CRect& crStart, CWnd* pParentWnd)
+{
+	WNDCLASS wc;	
+	wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+	wc.lpfnWndProc = AfxWndProc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hInstance = AfxGetInstanceHandle();
+	wc.hIcon = NULL;
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+	wc.lpszMenuName =  NULL;
+	wc.lpszClassName = "QPasteClass";
+
+	// Create the QPaste window class
+	if (!AfxRegisterClass(&wc))
+		return FALSE;
+	
+	return CWndEx::CreateEx(0, "QPasteClass", "Quick Paste", WS_POPUP,
+		crStart, pParentWnd, 0);
+}
+
+int CWndEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
+{
+	if (CWnd::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	m_TitleFont.CreateFont(14,0,-900,0,400,FALSE,FALSE,0,ANSI_CHARSET,
+	OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
+	DEFAULT_PITCH|FF_SWISS,"Arial");
+	
+	return 0;
+}
+
+void CWndEx::OnNcPaint()
+{
+	CWindowDC dc(this);
+
+	CRect rcFrame;
+	GetWindowRect(rcFrame);
+
+	ScreenToClient(rcFrame);
+
+	CRect rc;
+	GetClientRect(rc);
+
+	ClientToScreen(rc);
+
+	long lWidth = rcFrame.Width();
+
+	// Draw the window border
+	CRect rcBorder(0, 0, lWidth, rcFrame.Height());
+
+	COLORREF left = GetSysColor(COLOR_ACTIVECAPTION);
+	COLORREF right = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
+
+	dc.Draw3dRect(rcBorder, left, left);
+	rcBorder.DeflateRect(1, 1, 1, 1);
+	dc.Draw3dRect(rcBorder, left, left);
+
+	rcBorder.left = rcBorder.right - RIGHT_CAPTION - BORDER + 1;
+	rcBorder.bottom += BORDER;
+	rcBorder.top -= BORDER;
+
+	float gR = 0; 
+	float gG = 0; 
+	float gB = 0; 
+
+	float sR = GetRValue(left);
+	float sG = GetGValue(left);
+	float sB = GetBValue(left);
+
+	float eR = GetRValue(right);
+	float eG = GetGValue(right);
+	float eB = GetBValue(right);
+
+	// calculate the slope for color gradient 
+	gR = (eR - sR) / rcBorder.Height();
+	gG = (eG - sG) / rcBorder.Height(); 
+	gB = (eB - sB) / rcBorder.Height(); 
+	
+	HBRUSH color;
+	
+	long lHeight = rcBorder.Height();
+	CRect cr = rcBorder;
+	
+	for(int i = 0; i < lHeight; i++) 
+	{ 
+		cr.top = i;
+		cr.bottom = i + 1;
+
+		color = CreateSolidBrush(RGB(int(gR * (float) i + gR),
+									int(gG * (float) i + sG),
+									int(gB * (float) i + sB)));
+
+		::FillRect(dc, &cr, color);
+		DeleteObject(color);
+	}
+	
+	/*
+	HBRUSH color;
+	color = CreateSolidBrush(left);
+	::FillRect(dc, &rcBorder, color);
+	DeleteObject(color);
+	*/
+
+	int nOldBKMode = dc.SetBkMode(TRANSPARENT);
+	COLORREF oldColor = dc.SetTextColor(RGB(255, 255, 255));
+	CFont* pOldFont=dc.SelectObject(&m_TitleFont);
+
+	CString csText;
+	GetWindowText(csText);
+	dc.TextOut(rcBorder.right-1, 22, csText);
+
+	DrawCloseBtn(dc, lWidth, left);
+	
+	dc.SelectObject(pOldFont);
+	dc.SetTextColor(oldColor);
+	dc.SetBkMode(nOldBKMode);
+}
+
+void CWndEx::DrawCloseBtn(CWindowDC &dc, long lRight, COLORREF left)
+{
+	if(lRight == -1)
+	{
+		CRect cr;
+		GetWindowRect(cr);
+		lRight = cr.Width();
+	}
+
+	if(left == 0)
+		left = GetSysColor(COLOR_ACTIVECAPTION);
+
+	//rows first then columns
+	int Points[5][6] =
+	{
+		1,1,0,0,1,1,
+		0,1,1,1,1,0,
+		0,0,1,1,0,0,
+		0,1,1,1,1,0,
+		1,1,0,0,1,1
+	};
+
+	CPoint ptShift(lRight - 15, 7);
+	m_crCloseBT.SetRect(ptShift, ptShift+CPoint(12, 11));
+	ptShift.Offset(3, 3);
+
+	COLORREF shaddow = RGB(GetRValue(left) * 1.16, 
+							GetGValue(left) * 1.12,
+							GetBValue(left) * 1.12);
+
+	if(m_bMouseDownOnClose)
+		dc.Draw3dRect(m_crCloseBT, RGB(0, 0, 0), shaddow);
+	else if(m_bMouseOverClose)
+		dc.Draw3dRect(m_crCloseBT, shaddow, RGB(0, 0, 0));
+
+	for (int iRow = 0; iRow < 5; iRow++)
+	{
+		for (int iCol = 0; iCol < 6; iCol++)
+		{
+			if (Points[iRow][iCol] == 1)
+				dc.SetPixel(ptShift+CPoint(iCol, iRow), RGB(255, 255, 255));
+		}
+	}
+}
+
+void CWndEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
+{
+	CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
+
+	//Decrease the client area
+	lpncsp->rgrc[0].left+= BORDER;
+	lpncsp->rgrc[0].top+= BORDER;
+	lpncsp->rgrc[0].right-= BORDER;
+	lpncsp->rgrc[0].bottom-= BORDER;
+	lpncsp->rgrc[0].right-= RIGHT_CAPTION;
+}
+
+UINT CWndEx::OnNcHitTest(CPoint point) 
+{
+	if(!m_bResizable)
+		return CWnd::OnNcHitTest(point);
+
+	//Hit the close button
+//	CPoint clPoint(point);
+//	ScreenToClient(&clPoint);
+//	if(m_crCloseBT.PtInRect(clPoint))
+//		return HTCLOSE;
+	
+
+	CRect crWindow;
+	GetWindowRect(crWindow);
+
+	if ((point.y < crWindow.top + BORDER * 2) &&
+		(point.x < crWindow.left + BORDER * 2))
+		return HTTOPLEFT;
+	else if ((point.y < crWindow.top + BORDER * 2) &&
+		(point.x > crWindow.right - RIGHT_CAPTION))
+		return HTTOPRIGHT;
+	else if ((point.y > crWindow.bottom - BORDER * 7) &&
+		(point.x > crWindow.right - RIGHT_CAPTION))
+		return HTBOTTOMRIGHT;
+	else if ((point.y > crWindow.bottom - BORDER * 2) &&
+		(point.x < crWindow.left + BORDER * 2))
+		return HTBOTTOMLEFT;
+	else if (point.y < crWindow.top + BORDER * 2)
+		return HTTOP;
+	else if (point.x > crWindow.right - BORDER * 2)
+		return HTRIGHT;
+	else if (point.x < crWindow.left + BORDER * 2)
+		return HTLEFT;
+	else if (point.y > crWindow.bottom - BORDER * 2)
+		return HTBOTTOM;
+	else if (point.x > crWindow.right - RIGHT_CAPTION)
+		return HTCAPTION;
+	else
+		return CWnd::OnNcHitTest(point); // The default handler
+}
+
+void CWndEx::OnNcLButtonDown(UINT nHitTest, CPoint point) 
+{
+	CPoint clPoint(point);
+	ScreenToClient(&clPoint);
+	if(m_crCloseBT.PtInRect(clPoint))
+	{
+		SetCapture();
+
+		m_bMouseDownOnClose = true;
+
+		CWindowDC dc(this);
+		DrawCloseBtn(dc);
+	}
+	
+	CWnd::OnNcLButtonDown(nHitTest, point);
+}
+
+void CWndEx::OnNcLButtonUp(UINT nHitTest, CPoint point) 
+{
+	if(m_bMouseDownOnClose)
+	{
+		ReleaseCapture();
+		m_bMouseDownOnClose = false;
+		m_bMouseOverClose = false;
+		
+		OnNcPaint();
+		
+		CPoint clPoint(point);
+		if(m_crCloseBT.PtInRect(point))
+			SendMessage(WM_CLOSE, 0, 0);
+	}
+	
+	CWnd::OnNcLButtonUp(nHitTest, point);
+}
+
+void CWndEx::OnNcMouseMove(UINT nHitTest, CPoint point) 
+{
+	CPoint clPoint(point);
+	ScreenToClient(&clPoint);
+	if(m_crCloseBT.PtInRect(clPoint))
+	{
+		m_bMouseOverClose = true;
+		CWindowDC dc(this);
+		DrawCloseBtn(dc);
+	}
+	else if(m_bMouseOverClose)
+	{
+		m_bMouseOverClose = false;
+		OnNcPaint();
+	}
+	
+	
+	CWnd::OnNcMouseMove(nHitTest, point);
+}
+
+BOOL CWndEx::PreTranslateMessage(MSG* pMsg) 
+{
+	if (pMsg->message == WM_NCLBUTTONDOWN)
+		m_bMouseDownOnCaption = true;
+
+	if ((pMsg->message == WM_LBUTTONUP) && (m_bMouseDownOnCaption)) 
+	{
+		m_bMouseDownOnCaption = false;
+		pMsg->message = WM_NCLBUTTONUP;
+	}
+
+	
+	return CWnd::PreTranslateMessage(pMsg);
+}
+
+
+/*
+
+  CBitmap			m_bitmap;
+	CDC				dcMem;
+	
+	void			MakeBitmap();
+
+
+  CDC dcMem;
+   dcMem.CreateCompatibleDC(&dc);
+    
+    CBitmap *pOldBmp = (CBitmap *)(dcMem.SelectObject(&m_bitmap));
+
+	dc.BitBlt(rcBorder.left, 0, rcBorder.Width(), rcBorder.Height(), &dcMem, 0, 0, SRCCOPY);
+
+	dcMem.SelectObject(pOldBmp);
+    
+    dcMem.DeleteDC();
+
+
+void CWndEx::MakeBitmap()
+{
+    CWindowDC dc(this);
+    CRect rect;
+    GetWindowRect(&rect);
+
+	CRect rcBorder(0, 0, rect.Width(), rect.Height());
+	rcBorder.left = rcBorder.right - RIGHT_CAPTION - BORDER + 1;
+
+	rect = rcBorder;
+
+    int r1=245,g1=190,b1=240;
+    int r2=130,g2=0,b2=0;
+
+    int x1=0,y1=0;
+    int x2=0,y2=0;
+
+    CDC dc2;
+    dc2.CreateCompatibleDC(&dc);
+
+    if(m_bitmap.m_hObject)
+        m_bitmap.DeleteObject();
+    m_bitmap.CreateCompatibleBitmap(&dc,rect.Width(),
+        rect.Height());
+
+    CBitmap *oldbmap=dc2.SelectObject(&m_bitmap);
+
+    while(x1 < rect.Width() && y1 < rect.Height())
+    {
+        if(y1 < rect.Height()-1)
+            y1++;
+        else
+            x1++;
+
+        if(x2 < rect.Width()-1)
+            x2++;
+        else
+            y2++;
+
+        int r,g,b;
+        int i = x1+y1;
+        r = r1 + (i * (r2-r1) / (rect.Width()+rect.Height()));
+        g = g1 + (i * (g2-g1) / (rect.Width()+rect.Height()));
+        b = b1 + (i * (b2-b1) / (rect.Width()+rect.Height()));
+
+        CPen p(PS_SOLID,1,RGB(r,g,b));
+        CPen *oldpen = dc2.SelectObject(&p); 
+
+        dc2.MoveTo(x1,y1);
+        dc2.LineTo(x2,y2);
+
+        dc2.SelectObject(oldpen);
+    } 
+
+    dc2.SelectObject(oldbmap);
+}
+*/
+
+BOOL CWndEx::OnEraseBkgnd(CDC* pDC) 
+{
+	return CWnd::OnEraseBkgnd(pDC);
+}

+ 71 - 0
WndEx.h

@@ -0,0 +1,71 @@
+#if !defined(AFX_WNDEX_H__E14EA019_CE71_469A_AEB4_3D3CB271C531__INCLUDED_)
+#define AFX_WNDEX_H__E14EA019_CE71_469A_AEB4_3D3CB271C531__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// WndEx.h : header file
+//
+
+#define RIGHT_CAPTION			15
+#define BORDER					2
+
+class CWndEx : public CWnd
+{
+// Construction
+public:
+	CWndEx();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CWndEx)
+	public:
+	virtual BOOL Create(const CRect& crStart, CWnd* pParentWnd);
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	//}}AFX_VIRTUAL
+
+public:
+	void	SetResizable(bool bVal)	{ m_bResizable = bVal;	}
+
+protected:
+	CFont			m_TitleFont;
+	bool			m_bResizable;
+	CRect			m_crCloseBT;
+	bool			m_bMouseOverClose;
+	bool			m_bMouseDownOnClose;
+	bool			m_bMouseDownOnCaption;
+	
+	void			DrawCloseBtn(CWindowDC &dc, long lRight = -1, COLORREF left = 0);
+
+	
+// Implementation
+public:
+	virtual ~CWndEx();
+
+	// Generated message map functions
+protected:
+	//{{AFX_MSG(CWndEx)
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnNcPaint();
+	afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);
+	afx_msg UINT OnNcHitTest(CPoint point);
+	afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
+	afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
+	afx_msg void OnNcLButtonUp(UINT nHitTest, CPoint point);
+	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_WNDEX_H__E14EA019_CE71_469A_AEB4_3D3CB271C531__INCLUDED_)

BIN
res/CP_Main.ico


+ 13 - 0
res/CP_Main.rc2

@@ -0,0 +1,13 @@
+//
+// CP_MAIN.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+	#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////

BIN
res/CP_MainDoc.ico


BIN
res/Ditto.ico


BIN
res/Toolbar.bmp


BIN
res/bitmap1.bmp