Browse Source

Text Item Parser in CopyProperties

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@16 595ec19a-5cb4-439b-94a8-42fb3063c22c
ingenuus 22 years ago
parent
commit
8408a097c9
14 changed files with 433 additions and 162 deletions
  1. 7 53
      CP_Main.cpp
  2. 1 3
      CP_Main.h
  3. 85 82
      CP_Main.rc
  4. 22 0
      Changes.txt
  5. 92 0
      CopyProperties.cpp
  6. 5 0
      CopyProperties.h
  7. 3 1
      DataTable.cpp
  8. 1 1
      MainFrm.cpp
  9. 57 10
      Misc.cpp
  10. 4 0
      Misc.h
  11. 124 7
      ProcessCopy.cpp
  12. 27 3
      ProcessCopy.h
  13. 1 0
      ProcessPaste.cpp
  14. 4 2
      Resource.h

+ 7 - 53
CP_Main.cpp

@@ -205,7 +205,7 @@ void CCP_MainApp::StopCopyThread()
 {
 	EnableCbCopy(false);
 	m_CopyThread.Quit();
-	SaveAllClips();
+	SaveCopyClips();
 }
 
 // Allocates a new CClipTypes
@@ -246,68 +246,22 @@ CClipTypes* pTypes = LoadTypesFromDB();
 		m_CopyThread.SetSupportedTypes( pTypes );
 }
 
-// ensures that pClip's time is not older than the last clip added
-// old times can happen on fast copies (<1 sec).
-void CCP_MainApp::FixTime( CClip* pClip )
-{
-long lDate;
-	try
-	{
-	CMainTable recset;
-
-		recset.m_strSort = "lDate DESC";
-		recset.Open("SELECT * FROM Main");
-		recset.MoveFirst();
-
-		lDate = (long) pClip->m_Time.GetTime();
-		if( lDate <= recset.m_lDate )
-		{
-			lDate = recset.m_lDate + 1;
-			pClip->m_Time = lDate;
-		}
-
-		recset.Close();
-	}
-	CATCHDAO
-}
-
-long CCP_MainApp::SaveAllClips()
+long CCP_MainApp::SaveCopyClips()
 {
 long lID = 0;
-int savedCount = 0;
-int nRemaining = 0;
+int count;
 
 	CClipList* pClips = m_CopyThread.GetClips(); // we now own pClips
 	if( !pClips )
 		return 0;
 
-	CClip* pClip;
-	bool bResult;
-	nRemaining = pClips->GetCount();
-	while( pClips->GetCount() > 0 )
+	count = pClips->AddToDB( true );
+	if( count > 0 )
 	{
-		SetStatus( StrF("%d",nRemaining) );
-		nRemaining--;
-
-		pClip = pClips->RemoveHead();
-		ASSERT( pClip );
-
-		FixTime( pClip );
-
-		bResult = pClip->AddToDB();
-		if( bResult )
-		{
-			lID = pClip->m_ID;
-			savedCount++;
-		}
-		delete pClip;
+		OnCopyCompleted( lID, count );
+		lID = pClips->GetTail()->m_ID;
 	}
 
-	SetStatus();
-
-	if( savedCount > 0 )
-		OnCopyCompleted( lID, savedCount );
-
 	delete pClips;
 
 	return lID;

+ 1 - 3
CP_Main.h

@@ -73,11 +73,9 @@ public:
 	bool IsClipboardViewerConnected() { return m_CopyThread.IsClipboardViewerConnected(); }
 
 //	CClipList	m_SaveClipQueue; 
-	// ensures that pClip's time is not older than the last clip added
-	void FixTime( CClip* pClip );
 	// Retrieves all clips from CopyThread and Saves them.
 	// returns the ID of the last Clip saved (or 0 if none)
-	long SaveAllClips(); 
+	long SaveCopyClips(); 
 
 	CClipTypes* LoadTypesFromDB(); // returns a "new" allocated object
 	void ReloadTypes();

+ 85 - 82
CP_Main.rc

@@ -1,4 +1,4 @@
-//Microsoft Developer Studio generated resource script.
+// Microsoft Visual C++ generated resource script.
 //
 #include "resource.h"
 
@@ -27,18 +27,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 // TEXTINCLUDE
 //
 
-1 TEXTINCLUDE DISCARDABLE 
+1 TEXTINCLUDE 
 BEGIN
     "resource.h\0"
 END
 
-2 TEXTINCLUDE DISCARDABLE 
+2 TEXTINCLUDE 
 BEGIN
     "#include ""afxres.h""\r\n"
     "\0"
 END
 
-3 TEXTINCLUDE DISCARDABLE 
+3 TEXTINCLUDE 
 BEGIN
     "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
     "#define _AFX_NO_OLE_RESOURCES\r\n"
@@ -67,22 +67,22 @@ END
 
 // 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"
+IDR_MAINFRAME           ICON                    "res\\Ditto.ico"
+IDR_CP_MAITYPE          ICON                    "res\\CP_MainDoc.ico"
 
 /////////////////////////////////////////////////////////////////////////////
 //
 // Bitmap
 //
 
-IDR_MAINFRAME           BITMAP  MOVEABLE PURE   "res\\Toolbar.bmp"
+IDR_MAINFRAME           BITMAP                  "res\\Toolbar.bmp"
 
 /////////////////////////////////////////////////////////////////////////////
 //
 // Toolbar
 //
 
-IDR_MAINFRAME TOOLBAR DISCARDABLE  16, 15
+IDR_MAINFRAME TOOLBAR  16, 15
 BEGIN
     BUTTON      ID_FILE_NEW
     BUTTON      ID_FILE_OPEN
@@ -103,7 +103,7 @@ END
 // Menu
 //
 
-IDR_MAINFRAME MENU PRELOAD DISCARDABLE 
+IDR_MAINFRAME MENU 
 BEGIN
     POPUP "&File"
     BEGIN
@@ -139,7 +139,7 @@ BEGIN
     END
 END
 
-IDR_MENU MENU DISCARDABLE 
+IDR_MENU MENU 
 BEGIN
     POPUP "First"
     BEGIN
@@ -153,7 +153,7 @@ BEGIN
     END
 END
 
-IDR_QUICK_PASTE MENU DISCARDABLE 
+IDR_QUICK_PASTE MENU 
 BEGIN
     POPUP "Menu"
     BEGIN
@@ -213,7 +213,7 @@ END
 // Accelerator
 //
 
-IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE 
+IDR_MAINFRAME ACCELERATORS 
 BEGIN
     "N",            ID_FILE_NEW,            VIRTKEY, CONTROL
     "O",            ID_FILE_OPEN,           VIRTKEY, CONTROL
@@ -237,8 +237,8 @@ END
 // Dialog
 //
 
-IDD_ABOUTBOX DIALOG DISCARDABLE  0, 0, 235, 55
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_ABOUTBOX DIALOG  0, 0, 235, 55
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "About CP_Main"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -248,8 +248,8 @@ BEGIN
     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
+IDD_OPTIONS_UTILITIES DIALOG  0, 0, 241, 137
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Database"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -260,8 +260,8 @@ BEGIN
     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
+IDD_OPTIONS_TYPES DIALOG  0, 0, 230, 172
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Supported Types"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -271,38 +271,41 @@ BEGIN
     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
+IDD_OPTIONS_QUICK_PASTE DIALOGEX 0, 0, 256, 159
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Quick Paste"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
 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
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,46,122,10
+    EDITTEXT        IDC_TRANS_PERC,140,45,19,12,ES_AUTOHSCROLL
+    LTEXT           "%",IDC_STATIC,162,48,8,8
+    LTEXT           "Text Lines per Row",IDC_STATIC,18,61,62,8
+    EDITTEXT        IDC_LINES_ROW,82,59,19,12,ES_AUTOHSCROLL
+    GROUPBOX        "Positioning",IDC_STATIC,11,74,196,41
     CONTROL         "At Caret",IDC_AT_CARET,"Button",BS_AUTORADIOBUTTON,22,
-                    66,41,10
+                    83,41,10
     CONTROL         "At Cursor",IDC_AT_CURSOR,"Button",BS_AUTORADIOBUTTON,22,
-                    76,45,10
+                    93,45,10
     CONTROL         "At Previous Position",IDC_AT_PREVIOUS,"Button",
-                    BS_AUTORADIOBUTTON,22,86,79,10
+                    BS_AUTORADIOBUTTON,22,103,79,10
     CONTROL         "Use Ctrl - Num for first ten copy hot keys",
                     IDC_CTRL_CLICK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,
-                    7,142,10
+                    24,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
+                    BS_AUTOCHECKBOX | WS_TABSTOP,18,34,128,10
     LTEXT           "** befere text  = text has a hot key assigned to it.",
-                    IDC_STATIC,18,105,153,8
+                    IDC_STATIC,18,122,153,8
     LTEXT           "* before text = text will never be auto deleted.",
-                    IDC_STATIC,18,116,143,8
+                    IDC_STATIC,18,133,143,8
+    CONTROL         "Use Ctrl - Num for first ten copy hot keys",
+                    IDC_CTRL_CLICK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,
+                    14,142,10
 END
 
-IDD_OPTIONS_KEYSTROKES DIALOG DISCARDABLE  0, 0, 186, 90
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_OPTIONS_KEYSTROKES DIALOG  0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Keyboard Shortcuts"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -314,10 +317,10 @@ BEGIN
     LTEXT           "Named Copy",IDC_STATIC,19,42,42,8
 END
 
-IDD_OPTIONS_GENERAL DIALOG DISCARDABLE  0, 0, 294, 166
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_OPTIONS_GENERAL DIALOGEX 0, 0, 294, 178
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "General"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
 BEGIN
     CONTROL         "Display Icon in System Tray",IDC_DISPLAY_IN_SYSTEMTRAY,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,28,103,10
@@ -342,10 +345,16 @@ BEGIN
                     BS_AUTOCHECKBOX | WS_TABSTOP,23,79,76,10
     EDITTEXT        IDC_PATH,23,89,248,12,ES_AUTOHSCROLL
     PUSHBUTTON      "....",IDC_GET_PATH,273,89,14,12
+    CONTROL         "Allow Duplicates",IDC_ALLOW_DUPLICATES,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,23,125,68,10
+    CONTROL         "Update Clip Time On Paste",IDC_UPDATE_TIME_ON_PASTE,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,138,101,10
+    CONTROL         "Save Multi-Pastes",IDC_SAVE_MULTIPASTE,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,23,151,73,10
 END
 
-IDD_SELECT_DB DIALOG DISCARDABLE  0, 0, 276, 46
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
+IDD_SELECT_DB DIALOG  0, 0, 276, 46
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
 CAPTION "Select Database"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -356,8 +365,8 @@ BEGIN
     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
+IDD_OPTIONS_STATS DIALOG  0, 0, 272, 163
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Stats"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -383,8 +392,8 @@ BEGIN
     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
+IDD_ADD_TYPE DIALOG  0, 0, 276, 230
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Add Supported Type"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -402,15 +411,15 @@ BEGIN
     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
+IDD_COPY_PROPERTIES DIALOGEX 0, 0, 244, 211
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Copy Properties"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
 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
+                    BS_AUTOCHECKBOX | WS_TABSTOP,8,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 | 
@@ -424,10 +433,12 @@ BEGIN
     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
+    EDITTEXT        IDC_PARSE_EDIT,177,24,30,14,ES_AUTOHSCROLL
+    PUSHBUTTON      "Parse",IDC_PARSE_BUTTON,212,24,25,14
 END
 
-IDD_ABOUT DIALOG DISCARDABLE  0, 0, 292, 124
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+IDD_ABOUT DIALOG  0, 0, 292, 124
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "About"
 FONT 8, "MS Sans Serif"
 BEGIN
@@ -437,7 +448,6 @@ BEGIN
 END
 
 
-#ifndef _MAC
 /////////////////////////////////////////////////////////////////////////////
 //
 // Version
@@ -460,18 +470,13 @@ BEGIN
     BEGIN
         BLOCK "040904b0"
         BEGIN
-            VALUE "Comments", "\0"
-            VALUE "CompanyName", "\0"
-            VALUE "FileDescription", "Ditto\0"
-            VALUE "FileVersion", "1, 50, 0, 0\0"
-            VALUE "InternalName", "CP_Main\0"
-            VALUE "LegalCopyright", "Copyright (C) 2003\0"
-            VALUE "LegalTrademarks", "\0"
-            VALUE "OriginalFilename", "Ditto\0"
-            VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Ditto\0"
-            VALUE "ProductVersion", "1, 50, 0, 0\0"
-            VALUE "SpecialBuild", "\0"
+            VALUE "FileDescription", "Ditto"
+            VALUE "FileVersion", "1, 50, 0, 0"
+            VALUE "InternalName", "CP_Main"
+            VALUE "LegalCopyright", "Copyright (C) 2003"
+            VALUE "OriginalFilename", "Ditto"
+            VALUE "ProductName", "Ditto"
+            VALUE "ProductVersion", "1, 50, 0, 0"
         END
     END
     BLOCK "VarFileInfo"
@@ -480,8 +485,6 @@ BEGIN
     END
 END
 
-#endif    // !_MAC
-
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -489,7 +492,7 @@ END
 //
 
 #ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO DISCARDABLE 
+GUIDELINES DESIGNINFO 
 BEGIN
     IDD_ABOUTBOX, DIALOG
     BEGIN
@@ -520,7 +523,7 @@ BEGIN
         LEFTMARGIN, 7
         RIGHTMARGIN, 249
         TOPMARGIN, 7
-        BOTTOMMARGIN, 131
+        BOTTOMMARGIN, 152
     END
 
     IDD_OPTIONS_KEYSTROKES, DIALOG
@@ -536,7 +539,7 @@ BEGIN
         LEFTMARGIN, 7
         RIGHTMARGIN, 287
         TOPMARGIN, 7
-        BOTTOMMARGIN, 158
+        BOTTOMMARGIN, 170
     END
 
     IDD_SELECT_DB, DIALOG
@@ -587,18 +590,18 @@ END
 // String Table
 //
 
-STRINGTABLE PRELOAD DISCARDABLE 
+STRINGTABLE 
 BEGIN
     IDR_MAINFRAME           "CP_Main\n\nCP_Mai\n\n\nCPMain.Document\nCP_Mai Document"
 END
 
-STRINGTABLE PRELOAD DISCARDABLE 
+STRINGTABLE 
 BEGIN
     AFX_IDS_APP_TITLE       "CP_Main"
     AFX_IDS_IDLEMESSAGE     "Ready"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 BEGIN
     ID_INDICATOR_EXT        "EXT"
     ID_INDICATOR_CAPS       "CAP"
@@ -608,7 +611,7 @@ BEGIN
     ID_INDICATOR_REC        "REC"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 BEGIN
     ID_FILE_NEW             "Create a new document\nNew"
     ID_FILE_OPEN            "Open an existing document\nOpen"
@@ -621,13 +624,13 @@ BEGIN
     ID_FILE_PRINT_PREVIEW   "Display full pages\nPrint Preview"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 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 
+STRINGTABLE 
 BEGIN
     ID_FILE_MRU_FILE1       "Open this document"
     ID_FILE_MRU_FILE2       "Open this document"
@@ -647,18 +650,18 @@ BEGIN
     ID_FILE_MRU_FILE16      "Open this document"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 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 
+STRINGTABLE 
 BEGIN
     ID_WINDOW_SPLIT         "Split the active window into panes\nSplit"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 BEGIN
     ID_EDIT_CLEAR           "Erase the selection\nErase"
     ID_EDIT_CLEAR_ALL       "Erase everything\nErase All"
@@ -673,13 +676,13 @@ BEGIN
     ID_EDIT_REDO            "Redo the previously undone action\nRedo"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 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 
+STRINGTABLE 
 BEGIN
     AFX_IDS_SCSIZE          "Change the window size"
     AFX_IDS_SCMOVE          "Change the window position"
@@ -690,13 +693,13 @@ BEGIN
     AFX_IDS_SCCLOSE         "Close the active window and prompts to save the documents"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 BEGIN
     AFX_IDS_SCRESTORE       "Restore the window to normal size"
     AFX_IDS_SCTASKLIST      "Activate Task List"
 END
 
-STRINGTABLE DISCARDABLE 
+STRINGTABLE 
 BEGIN
     AFX_IDS_PREVIEW_CLOSE   "Close print preview mode\nCancel Preview"
 END

+ 22 - 0
Changes.txt

@@ -1,3 +1,25 @@
+03 Sept 3
+---------
++ Text Item Parser in CopyProperties - parses a CF_TEXT item into multiple
+  CF_TEXT items based upon a given separator string.
+  + CEdit m_ParseEdit
+  + CButton m_ParseButton
+  + void OnBnClickedParseButton()
+  + Misc 
+    + BYTE GetEscapeChar( BYTE ch );
+    + CString RemoveEscapes( const char* str );
+
++ CClip::AddFormat
+
++ CClipList::AddToDB( bool bLatestTime = false, bool bShowStatus = true )
+
+* CClipFormat frees m_hgData on destruction
+
+* changed CCP_MainApp::SaveAllClips to CCP_MainApp::SaveCopyClips
+
+* changed CCP_MainApp::FixTime to CClip::MakeLatestTime()
+
+
 03 Sept 2
 ---------
 * ProcessCopy - redesigned to fix the fast copy bugs.

+ 92 - 0
CopyProperties.cpp

@@ -4,6 +4,7 @@
 #include "stdafx.h"
 #include "cp_main.h"
 #include "CopyProperties.h"
+#include ".\copyproperties.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -42,6 +43,8 @@ void CCopyProperties::DoDataExchange(CDataExchange* pDX)
 	DDX_Text(pDX, IDC_DATE, m_eDate);
 	DDX_Check(pDX, IDC_NEVER_AUTO_DELETE, m_bNeverAutoDelete);
 	//}}AFX_DATA_MAP
+	DDX_Control(pDX, IDC_PARSE_EDIT, m_ParseEdit);
+	DDX_Control(pDX, IDC_PARSE_BUTTON, m_ParseButton);
 }
 
 
@@ -50,6 +53,7 @@ BEGIN_MESSAGE_MAP(CCopyProperties, CDialog)
 	ON_BN_CLICKED(IDC_DELETE_COPY_DATA, OnDeleteCopyData)
 	ON_WM_ACTIVATE()
 	//}}AFX_MSG_MAP
+	ON_BN_CLICKED(IDC_PARSE_BUTTON, OnBnClickedParseButton)
 END_MESSAGE_MAP()
 
 /////////////////////////////////////////////////////////////////////////////
@@ -59,6 +63,8 @@ BOOL CCopyProperties::OnInitDialog()
 {
 	CDialog::OnInitDialog();
 
+	m_ParseEdit.SetWindowText("\\r\\n");
+
 	m_MainTable.Open("SELECT * FROM Main WHERE lID = %d", m_lCopyID);
 	if(!m_MainTable.IsEOF())
 	{
@@ -255,3 +261,89 @@ void CCopyProperties::OnCancel()
 		
 	CDialog::OnCancel();
 }
+
+void CCopyProperties::OnBnClickedParseButton()
+{
+CString sep;
+	m_ParseEdit.GetWindowText(sep);
+	sep = RemoveEscapes( sep );
+
+int nSep = sep.GetLength();
+	if( nSep <= 0 )
+	{
+		::MessageBox( m_hWnd, "Token Separator is not valid.", "Parse Failure", MB_OK|MB_ICONINFORMATION );
+		return;
+	}
+
+HGLOBAL hGlobal = CClip::LoadFormat( m_lCopyID, CF_TEXT );
+	if( !hGlobal )
+	{
+		::MessageBox( m_hWnd, "No CF_TEXT Format Data could be found.", "Parse Failure", MB_OK|MB_ICONINFORMATION );
+		return;
+	}
+
+int nDataSize = ::GlobalSize( hGlobal );
+char* pData = (char*) ::GlobalLock( hGlobal );
+char* pDataEnd = pData + nDataSize;
+int nDataLen = 0;
+char* p = pData;
+	ASSERT( pData != NULL && nDataSize > 0 );
+	// Find the terminating NULL
+	while( *p != '\0' && p < pDataEnd ) { p++; }
+	// there was no NULL in the string!
+	if( p >= pDataEnd )
+	{
+		ASSERT(0);
+		return;
+	}
+	// set pDataEnd to the terminating NULL
+	pDataEnd = p;
+	
+CStringArray tokens;
+char* pToken = pData;
+	p = pData;
+	while( p = strstr( pToken, sep ) )
+	{
+		// null out the separator string
+		for( int i=0; i < nSep; i++, p++ ) { *p = '\0'; }
+		// add the substring token
+		tokens.Add( pToken );
+		pToken = p; // start the next token after the separator
+	}
+
+	// if we found at least one occurrence of sep, then get the last token
+	if( tokens.GetCount() > 0 )
+		tokens.Add( pToken );
+
+	::GlobalUnlock( hGlobal );
+	::GlobalFree(hGlobal);
+
+CClip clip;
+int len;
+long lDate = (long) CTime::GetCurrentTime().GetTime();
+int count = tokens.GetCount();
+	// add in reverse order so that right to left corresponds to top to bottom
+	//  in the Ditto window (ditto sorts by time).
+	for( int i = count - 1; i >= 0; i-- )
+	{
+		theApp.SetStatus( StrF("%d",i+1) );
+		len = tokens[i].GetLength();
+		if( len <= 0 )
+			continue;
+		clip.AddFormat( CF_TEXT, (void*) (LPCTSTR) tokens[i], len+1 );
+		clip.m_Time = lDate;
+		clip.AddToDB();
+		clip.Clear();
+		lDate++; // make sure they are sequential
+	}
+	theApp.SetStatus();
+
+	if( count <= 0 )
+		::MessageBox( m_hWnd, "No new tokens found by parsing", "Parse Failed", MB_OK|MB_ICONINFORMATION );
+	else
+	{
+		::MessageBox( m_hWnd, StrF("Successfully parsed %d tokens.", tokens.GetCount()), "Parse Completed", MB_OK|MB_ICONINFORMATION );
+		theApp.RefreshView();
+	}
+}
+

+ 5 - 0
CopyProperties.h

@@ -1,3 +1,4 @@
+#include "afxwin.h"
 #if !defined(AFX_COPYPROPERTIES_H__129FE1CD_D305_487A_B88C_BB01CD9C1BB7__INCLUDED_)
 #define AFX_COPYPROPERTIES_H__129FE1CD_D305_487A_B88C_BB01CD9C1BB7__INCLUDED_
 
@@ -60,6 +61,10 @@ protected:
 	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
 	//}}AFX_MSG
 	DECLARE_MESSAGE_MAP()
+public:
+	CEdit m_ParseEdit;
+	CButton m_ParseButton;
+	afx_msg void OnBnClickedParseButton();
 };
 
 //{{AFX_INSERT_LOCATION}}

+ 3 - 1
DataTable.cpp

@@ -92,7 +92,9 @@ HGLOBAL CDataTable::TakeData()
 // This should be faster than making a copy, but is this SAFE ?????
 BOOL CDataTable::ReplaceData( HGLOBAL hgData, UINT len )
 {
-	if( m_ooData.m_hData && (m_ooData.m_hData = GlobalFree( m_ooData.m_hData )) )
+	if( m_ooData.m_hData && 
+		m_ooData.m_dwDataLength &&
+		(m_ooData.m_hData = ::GlobalFree( m_ooData.m_hData )) )
 	{
 		ASSERT(FALSE);
 		return FALSE;

+ 1 - 1
MainFrm.cpp

@@ -319,7 +319,7 @@ LRESULT CMainFrame::OnClipboardCopied(WPARAM wParam, LPARAM lParam)
 {
 	// if the delay is undesirable, this could be altered to save one at a time,
 	//  allowing the processing of other messages between saving clips.
-	theApp.SaveAllClips();
+	theApp.SaveCopyClips();
 	return TRUE;
 }
 

+ 57 - 10
Misc.cpp

@@ -7,16 +7,7 @@
 	#include "AlphaBlend.h"
 #endif
 
-CString StrF(const char * pszFormat, ...)
-{
-	ASSERT( AtlIsValidString( pszFormat ) );
-CString str;
-	va_list argList;
-	va_start( argList, pszFormat );
-	str.FormatV( pszFormat, argList );
-	va_end( argList );
-	return str;
-}
+// Debug Functions
 
 void AppendToFile( const char* fn, const char* msg )
 {
@@ -77,6 +68,62 @@ void SetThreadName(DWORD dwThreadID, LPCTSTR szThreadName)
     }
 } 
 
+// Utility Functions
+
+CString StrF(const char * pszFormat, ...)
+{
+	ASSERT( AtlIsValidString( pszFormat ) );
+CString str;
+	va_list argList;
+	va_start( argList, pszFormat );
+	str.FormatV( pszFormat, argList );
+	va_end( argList );
+	return str;
+}
+
+BYTE GetEscapeChar( BYTE ch )
+{
+	switch(ch)
+	{
+	case '\'':	return '\''; // Single quotation mark (') = 39 or 0x27
+	case '\"':	return '\"'; // Double quotation mark (") = 34 or 0x22
+	case '?':	return '\?'; // Question mark (?) = 63 or 0x3f
+	case '\\':	return '\\'; // Backslash (\) = 92 or 0x5c
+	case 'a':	return '\a'; // Alert (BEL) = 7
+	case 'b':	return '\b'; // Backspace (BS) = 8
+	case 'f':	return '\f'; // Formfeed (FF) = 12 or 0x0c
+	case 'n':	return '\n'; // Newline (NL or LF) = 10 or 0x0a
+	case 'r':	return '\r'; // Carriage Return (CR) = 13 or 0x0d
+	case 't':	return '\t'; // Horizontal tab (HT) = 9
+	case 'v':	return '\v'; // Vertical tab (VT) = 11 or 0x0b
+	case '0':	return '\0'; // Null character (NUL) = 0
+	}
+	return 0; // invalid
+}
+
+CString RemoveEscapes( const char* str )
+{
+	ASSERT( str );
+CString ret;
+char* pSrc = (char*) str;
+char* pDest = ret.GetBuffer( strlen(pSrc) );
+char* pStart = pDest;
+	while( *pSrc != '\0' )
+	{
+		if( *pSrc == '\\' )
+		{
+			pSrc++;
+			*pDest = GetEscapeChar( *pSrc );
+		}
+		else
+			*pDest = *pSrc;
+		pSrc++;
+		pDest++;
+	}
+	ret.ReleaseBuffer( pDest - pStart );
+	return ret;
+}
+
 CString GetWndText( HWND hWnd )
 {
 CString text;

+ 4 - 0
Misc.h

@@ -45,6 +45,10 @@ void SetThreadName(DWORD dwThreadID, LPCTSTR szThreadName);
 
 // Utility Functions
 CString StrF(const char * pszFormat, ...);
+// called after determining that the preceding character is a backslash
+BYTE GetEscapeChar( BYTE ch );
+CString RemoveEscapes( const char* str );
+
 CString GetWndText( HWND hWnd );
 // returns true if the given window is owned by this process
 bool IsAppWnd( HWND hWnd );

+ 124 - 7
ProcessCopy.cpp

@@ -106,16 +106,54 @@ int count = m_Formats.GetCount();
 	EmptyFormats();
 }
 
+void CClip::Clear()
+{
+	m_ID = 0;
+	m_Time = 0;
+	m_Desc = "";
+	m_lTotalCopySize = 0;
+	EmptyFormats();
+}
+
 void CClip::EmptyFormats()
 {
 	// free global memory in m_Formats
 	for( int i = m_Formats.GetCount()-1; i >= 0; i-- )
 	{
-		::GlobalFree( m_Formats[i].m_hgData );
+		m_Formats[i].Free();
 		m_Formats.RemoveAt( i );
 	}
 }
 
+// Adds a new Format to this Clip by copying the given data.
+bool CClip::AddFormat( CLIPFORMAT cfType, void* pData, UINT nLen )
+{
+	ASSERT( pData && nLen );
+HGLOBAL hGlobal = ::NewGlobalP( pData, nLen );
+	ASSERT( hGlobal );
+	// update the Clip statistics
+	m_Time = m_Time.GetCurrentTime();
+	m_lTotalCopySize += nLen;
+	if( !SetDescFromText( hGlobal ) )
+		SetDescFromType();
+
+CClipFormat format(cfType,hGlobal);
+CClipFormat *pFormat;
+
+	pFormat = m_Formats.FindFormat(cfType);
+	// if the format type already exists as part of this clip, replace the data
+	if( pFormat )
+	{
+		pFormat->Free();
+		pFormat->m_hgData = format.m_hgData;
+	}
+	else
+		m_Formats.Add(format);
+
+	format.m_hgData = 0; // now owned by m_Formats
+	return true;
+}
+
 #define EXIT_LoadFromClipboard(ret)	{ oleData.Release(); g_bCopyingClipboard = false; return(ret); }
 bool g_bCopyingClipboard = false; // for debugging reentrance
 // Fills this CClip with the contents of the clipboard.
@@ -211,8 +249,9 @@ int numTypes = pTypes->GetCount();
 			else
 			{
 				ASSERT(FALSE); // a valid GlobalMem with 0 size is strange
-				GlobalFree( cf.m_hgData );
+				cf.Free();
 			}
+			cf.m_hgData = 0; // m_Formats owns it now
 		}
 	}
 
@@ -224,7 +263,7 @@ int numTypes = pTypes->GetCount();
 	// if the description was in a type that is not supported,
 	//	we have to free it since it wasn't added to m_Formats
 	if( cfDesc.m_hgData )
-		GlobalFree( cfDesc.m_hgData );
+		cfDesc.Free();
 
 	if( m_Formats.GetSize() == 0 )
 		EXIT_LoadFromClipboard( false );
@@ -454,6 +493,32 @@ bool CClip::AddToDataTable()
 	return false;
 }
 
+// changes m_Time to be later than the latest clip entry in the db
+// ensures that pClip's time is not older than the last clip added
+// old times can happen on fast copies (<1 sec).
+void CClip::MakeLatestTime()
+{
+long lDate;
+	try
+	{
+	CMainTable recset;
+
+		recset.m_strSort = "lDate DESC";
+		recset.Open("SELECT * FROM Main");
+		recset.MoveFirst();
+
+		lDate = (long) m_Time.GetTime();
+		if( lDate <= recset.m_lDate )
+		{
+			lDate = recset.m_lDate + 1;
+			m_Time = lDate;
+		}
+
+		recset.Close();
+	}
+	CATCHDAO
+}
+
 // STATICS
 
 // deletes from both Main and Data Tables
@@ -551,12 +616,12 @@ HGLOBAL hGlobal = 0;
 	return hGlobal;
 }
 
-bool CClip::LoadFormats( long lID, CClipFormats& format )
+bool CClip::LoadFormats( long lID, CClipFormats& formats )
 {
 CClipFormat cf;
 HGLOBAL hGlobal = 0;
 
-	format.RemoveAll();
+	formats.RemoveAll();
 
 	try
 	{
@@ -581,15 +646,16 @@ HGLOBAL hGlobal = 0;
 			}
 			cf.m_cfType = GetFormatID( recset.m_strClipBoardFormat );
 			cf.m_hgData = hGlobal;
-			format.Add( cf );
+			formats.Add( cf );
 			recset.MoveNext();
 		}
+		cf.m_hgData = 0; // formats owns all the data
 
 		recset.Close();
 	}
 	CATCHDAO
 
-	return format.GetCount() > 0;
+	return formats.GetCount() > 0;
 }
 
 void CClip::LoadTypes( long lID, CClipTypes& types )
@@ -616,6 +682,57 @@ void CClip::LoadTypes( long lID, CClipTypes& types )
 }
 
 
+/*----------------------------------------------------------------------------*\
+	CClipList
+\*----------------------------------------------------------------------------*/
+
+CClipList::~CClipList()
+{
+CClip* pClip;
+	while( GetCount() )
+	{
+		pClip = RemoveHead();
+		DELETE_PTR( pClip );
+	}
+}
+
+// returns the number of clips actually saved
+// while this does empty the Format Data, it does not delete the Clips.
+int CClipList::AddToDB( bool bLatestTime, bool bShowStatus )
+{
+int savedCount = 0;
+int nRemaining = 0;
+CClip* pClip;
+POSITION pos;
+bool bResult;
+
+	nRemaining = GetCount();
+	pos = GetHeadPosition();
+	while( pos )
+	{
+		if( bShowStatus )
+		{
+			theApp.SetStatus( StrF("%d",nRemaining) );
+			nRemaining--;
+		}
+
+		pClip = GetNext( pos );
+		ASSERT( pClip );
+
+		if( bLatestTime )
+			pClip->MakeLatestTime();
+
+		bResult = pClip->AddToDB();
+		if( bResult )
+			savedCount++;
+	}
+
+	if( bShowStatus )
+		theApp.SetStatus();
+
+	return savedCount;
+}
+
 
 /*----------------------------------------------------------------------------*\
 	CClipboardViewer

+ 27 - 3
ProcessCopy.h

@@ -18,7 +18,6 @@ class CClip;
 class CCopyThread;
 
 typedef CArray<CLIPFORMAT, CLIPFORMAT> CClipTypes;
-typedef CList<CClip*,CClip*> CClipList;
 
 /*----------------------------------------------------------------------------*\
 	COleDataObjectEx
@@ -39,7 +38,12 @@ public:
 	CLIPFORMAT	m_cfType;
     HGLOBAL		m_hgData;
 
-	CClipFormat() : m_cfType(0), m_hgData(0) {}
+	CClipFormat( CLIPFORMAT cfType = 0, HGLOBAL hgData = 0 )
+		{ m_cfType = cfType; m_hgData = hgData; }
+	~CClipFormat() { Free(); }
+
+	void Clear() { m_cfType = 0;  m_hgData = 0; }
+	void Free() { if( m_hgData ) m_hgData = ::GlobalFree( m_hgData ); }
 };
 
 /*----------------------------------------------------------------------------*\
@@ -72,8 +76,11 @@ public:
 	CClip();
 	~CClip();
 
+	void Clear();
 	void EmptyFormats();
-
+	
+	// Adds a new Format to this Clip by copying the given data.
+	bool AddFormat( CLIPFORMAT cfType, void* pData, UINT nLen );
 	// Fills this CClip with the contents of the clipboard.
 	bool LoadFromClipboard( CClipTypes* pClipTypes );
 	bool SetDescFromText( HGLOBAL hgData );
@@ -88,6 +95,9 @@ public:
 	bool FindDuplicate( CMainTable& recset, BOOL bCheckLastOnly = FALSE );
 	int  CompareFormatDataTo( long lID );
 
+	// changes m_Time to be later than the latest clip entry in the db
+	void MakeLatestTime();
+
 // STATICS
 	// deletes from both Main and Data Tables
 	static BOOL Delete( int id );
@@ -103,6 +113,20 @@ public:
 };
 
 
+/*----------------------------------------------------------------------------*\
+	CClipList
+\*----------------------------------------------------------------------------*/
+
+class CClipList : public CList<CClip*,CClip*>
+{
+public:
+	~CClipList();
+	// returns the number of clips actually saved
+	// while this does empty the Format Data, it does not delete the Clips.
+	int AddToDB( bool bLatestTime = false, bool bShowStatus = true );
+};
+
+
 /*----------------------------------------------------------------------------*\
 	CClipboardViewer
 \*----------------------------------------------------------------------------*/

+ 1 - 0
ProcessPaste.cpp

@@ -193,6 +193,7 @@ int count = m_ClipIDs.GetCount();
 		{
 			pCF = &formats[i];
 			CacheGlobalData( pCF->m_cfType, pCF->m_hgData );
+			pCF->m_hgData = 0; // OLE owns it now
 		}
 		formats.RemoveAll();
 		return count;

+ 4 - 2
Resource.h

@@ -52,8 +52,10 @@
 #define IDC_HYPER_LINK                  1036
 #define IDC_ALLOW_DUPLICATES            1037
 #define IDC_UPDATE_TIME_ON_PASTE        1038
-#define IDC_CHECK3                      1039
 #define IDC_SAVE_MULTIPASTE             1039
+#define IDC_BUTTON1                     1040
+#define IDC_PARSE_BUTTON                1040
+#define IDC_PARSE_EDIT                  1041
 #define IDD_OPTIONS_KEYSTROKES          2001
 #define IDC_HOTKEY                      2002
 #define IDC_DISPLAY_IN_SYSTEMTRAY       2003
@@ -110,7 +112,7 @@
 #define _APS_3D_CONTROLS                     1
 #define _APS_NEXT_RESOURCE_VALUE        138
 #define _APS_NEXT_COMMAND_VALUE         32780
-#define _APS_NEXT_CONTROL_VALUE         1040
+#define _APS_NEXT_CONTROL_VALUE         1042
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif