04 Aug 31
---------
! Fixed "Corrupted QuickPaste position when closing Ditto while minimized /
  rolled-up" bug.
  . Reported By: Anthony Ford - tonyforduk 2004-08-27 14:08
    http://sourceforge.net/forum/message.php?msg_id=2732759
  * CWndEx::GetWindowRectEx() was not properly copying m_crFullSizeWindow
    when m_bMinimized was true.


04 May 30
---------
+ Toggle Connect to Clipboard to Connect or Disconnect the
  Clipboard Viewer from the chain.
  - removed "Reconnect to Clipboad Chain"

+ focus.dll and system-wide focus tracking implementation to correct
  mouse tray activation.

+ Sending clips across a network.


04 Jan 20
---------
! Fixed "multiple repaints on first show" bug.
  * CQuickPaste::ShowQPasteWnd:
    - m_pwndPaste->ShowWindow(SW_SHOW)
      . This caused premature drawing and activation of the window.
        It was replaced by a call to:
    + m_pwndPaste->ShowQPasteWindow()
    
  * CQPasteWnd:
    + bool m_bAllowRepaintImmediately:
      . This acts as an override for RefreshNc's bRepaintImmediately parameter,
        thereby stopping the status (titlebar) from being repeatedly redrawn
        during ShowQPasteWindow.

* Misc. Painting Improvements:
  ! CWndEx::InvalidateNc(): redraw with RDW_NOCHILDREN
    . The client area was being invalidated without this.
  * CQListCtrl::OnEraseBkgnd(): faster when shift-scrolling.
  * CQListCtrl::OnSelectionChange(): delayed SetStatus for faster selection.


03 Sept 22
----------
+ Shared Data: Data can now be shared amongst multiple Clips.
  + DittoDB.mdb: Main.lDataID, Data.lDataID
  * SQL statements, e.g. INNER JOIN through Main.lID
  
+ Groups:
  + DittoDB.mdb: Main.bIsGroup, Main.lParentID, Main.dOrder
  * CCP_MainApp:
    + long    m_GroupDefaultID; // new clips are saved to this group
    + long    m_GroupID;        // current group
    + long    m_GroupParentID;  // current group's parent
    + CString m_GroupText;      // current group's description
    +	BOOL EnterGroupID( long lID );
    + long GetValidGroupID(); // returns a valid id (not negative)
    + void SetGroupDefaultID( long lID ); // sets a valid id

+ Internal Clipboard for cut/copy/paste items between Groups
  CCP_MainApp:
  + bool      m_IC_bCopy; // true to copy the items, false to move them
  + CClipIDs  m_IC_IDs;   // buffer
  + void IC_Cut( ARRAY* pIDs = NULL ); // if NULL, use current QPaste selection
  + void IC_Copy( ARRAY* pIDs = NULL ); // if NULL, use current QPaste selection
  + void IC_Paste();

+ Persistent QPasteWnd focus item
  + CCP_MainApp: long m_FocusID; // the ID given focus by CQPasteWnd::FillList
	* CQPasteWnd::FillList

+ Item Description: Show Leading WhiteSpace
  + CString CMainTable::GetDisplayText()
  * void CQPasteWnd::OnGetToolTipText()
  * CGetSetOptions:
    + static BOOL    m_bDescShowLeadingWhiteSpace;
    + static void SetDescShowLeadingWhiteSpace(BOOL bVal);
    + static BOOL GetDescShowLeadingWhiteSpace();

+ QListCtrl Keys:
  +        F7: Create a New Group
  +   Ctrl-F7: Create a New Group of Selected Elements
  + Backspace: Go to parent group
  +     Enter: Enter group or paste if clip
  +  Alt-Home: Go to History Group
  +   Alt-End: List all top level Groups
  +    Ctrl-X: Move selection (establishes the source)
  +    Ctrl-C: Copy selection (establishes the source)
  +    Ctrl-V: Paste selection (Move or Copy)


03 Sept 14
----------
+ View caption on all sides (top, right, bottom, left)
+ Roll up window by button on caption or by auto roll up (rolls up when it looses focus)


03 Sept 10
----------
+ HistoryStartTop - History can be shown top-down or bottom-up
  + CGetSetOptions::m_bHistoryStartTop, SetHistoryStartTop, GetHistoryStartTop
  + BOOL CQPasteWnd::m_bAscending - sort ascending (true) or descending (false)
  * OptionsQuickPaste - added checkbox
  * CQListCtrl::
    + BOOL m_bStartTop - start at the top (true) or the bottom (false)
    + BOOL SetListPos( int index ) - moves cursor to a single index position
    + int GetFirstTenNum( int index ) - convert index to number
    + int GetFirstTenIndex( int num ) - convert number to index
    * OnCustomdrawList() - draws FirstTen block top or bottom
    * PreTranslateMessage() - handles FirstTen block (1-9,0) accelerators
    
+ CPopup - Manually display tooltips (Misc.h/.cpp)

+ View Full Description by pressing F3 using CPopup
  CQListCtrl::
    + CPopup m_Popup
    + OnKillFocus - removes Popup
    * PreTranslateMessage - handles F3 key

* CopyProperties
  + CTokenizer (ASCII only) (Misc.h/.cpp)
  * Multiple delimiter characters are used rather than a single separator string.
  * Defaults to Focus on Description when not a NamedCopy
  * Uses CPopup for status


03 Sept 8
---------
+ static bool CDataTable::DeleteParent( long lParentID )
  . Deletes all records in Data Table with the given "lParentID"
  
+ Show Target Name in Status (TitleBar)

+ Ensure Connected to Clipboard Viewer Chain using dummy WM_DRAWCLIPBOARD
  CClipboardViewer:
  * OnCreate: SetTimer(TIMER_ENSURE_VIEWER_IN_CHAIN, ONE_MINUTE, 0);
  * WM_CV_RECONNECT - force reconnect if not in chain.
  * WM_CV_IS_CONNECTED - performs a ping of chain.

+ Custom Accelerators
  + Misc.h/.cpp: CAccel and CAccels
  ! fixes bug "can't use accelerators with clip IDs > 65535 (USHRT_MAX)"
    . this was due to win32 ACCEL only capable of handling a WORD cmd

* Moved SendPaste to CCP_Main to implicitly use Target


03 Sept 5
---------
+ Snap to window now works on multiple monitors


03 Sept 4
---------
+ Ditto window snaps to window sides


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()

! fixed bad connect / disconnect logic in CClipboardViewer


03 Sept 2
---------
+ ShowPersistent: always-on-top "persistent show"
  . Toggled by double clicking the titlebar or <Ctrl>-<Space>
  + theApp.ShowPersistent( bool bVal )
  * required modification of Target window tracking system.

+ Misc.h/.cpp
  + Utility functions (HGLOBAL funcs, IsAppWnd, StrF)
  + Debug functions (Log, SetThreadName)

* ProcessCopy - redesigned to fix the fast copy bugs.
  . The same source object is used for the description as is stored in the db.
  . Actual copying from the clipboard is (usually) not interrupted.
  + CClip - For managing a Clip (copy of the clipboard) as a single unit.
  + CCopyThread - handles copying the clipboard when the clipboard changes and
      safely communicating with the Main thread.
  + CClipboardViewer - the Clipboard Viewer window (code factored out from
      MainWnd)
  + uses AllowDuplicates (non-sequential duplicates) flag

* ProcessPaste - redesigned for delayed rendering during drag and drop and
  immediate rendering otherwise.
  + uses UpdateTimeOnPaste flag
  + uses SaveMultiPaste flag
    
* CCP_MainApp Copy and Paste Management
  + bool EnableCbCopy(bool bState); // copy clipboad when it changes
  + long SaveAllClips();  // saves all clips copied by CCopyThread
  + void ReloadTypes();   // reloads the Types Table on demand
  + void Delayed_RemoveOldEntries( UINT delay ); // based on timer
  + void RefreshView();   // refreshes the view if it is visible
  + void OnCopyCompleted( long lLastID, int count = 1 );
  + void OnPasteCompleted();
  + void SetStatus(char*) // for displaying status in the titlebar.

* Targeting the previous focus window
  + CCP_MainApp::
    + HWND m_hTargetWnd;
    + HWND TargetActiveWindow();
    + bool ActivateTarget();
    + bool ReleaseFocus(); // activate the target only if we are foreground
  * The foreground window is tracked rather than the focus window.
    . I think SetFocus doesn't do anything unless the hWnd is associated
      with our thread's message queue.  
  + Targeting the previous focus window is handled properly when
    Ditto is activated by:
      1. Mouse (in CMainFrame::PreTranslateMessage) OR
      2. HotKey (in CQuickPaste::ShowQPasteWnd)
 !! Problems with Targeting still exist when Ditto is activated by a
    separate application (e.g. <Alt>-<Tab> or Taskbar Tray).  This may
    eventually be fixed by using a system hook.
    . See source comment preceding TargetActiveWindow() in CP_Main.cpp
  
* Streamlined <Ctrl> 0-9 Accelerators - now handled entirely in
  CQListCtrl::PreTranslateMessage
  - removed HACCEL m_acFirstTen in CQListCtrl

* WndEx
  ! fixed the close "x" button display
  + bool SetCaptionColors( COLORREF left, COLORREF right );
  + bool SetCaptionColorActive( bool bVal );

* Startup / Shutdown 
  + CCP_MainApp::
    + bool m_bAppRunning;
    + bool m_bAppExiting;
    + CMainFrame* m_pMainFrame; // for quick access
    + void AfterMainCreate();  // called after main window creation
    + void BeforeMainClose();  // called before main window close

* CGetSetOptions  
  + Accessible through new global g_Opt
  + Some local flag variables so that always getting from Profile (registry)
    is not necessary (flags loaded on construction of g_Opt).

* System HotKeys - Consolidated code in order to make adding and removing
  HotKeys programmatically easier. 
  + class CHotKey and CHotKeys (g_HotKeys) in Misc.h/.cpp
  + CCP_MainApp
    + CHotKey*  m_pDittoHotKey; // activate ditto's qpaste window
    + CHotKey*  m_pCopyHotKey;  // named copy
  . HotKey Management:
    . Create in CCP_MainApp::AfterMainCreate()
    . Handle in CMainFrame::OnHotKey()
    . Control user input in OptionsKeyBoard.


03 Aug 8
--------
+ Implemented Multi-Selection Paste for CF_TEXT clips by "\r\n" concatenation
  * CQPasteWnd::OnListSelect()
  + BOOL CProcessPaste::MultiPaste( int numIDs, int* pIDs, HWND hWnd );
  + BOOL CProcessPaste::MultiDrag( int numIDs, int* pIDs, HWND hWnd );
  + CString CProcessPaste::AggregateText(int numIDs, int* pIDs, UINT uiPastType, char* pSeparator);
  + bool CopyToGlobal( HGLOBAL hGlobal, LPVOID pBuf, ULONG ulBufLen )
  + HGLOBAL NewGlobal( LPVOID pBuf, ULONG ulBufLen )

* After a delete, position caret at first item deleted.
  * void CQPasteWnd::DeleteSelectedRows()

! Fixed Error "query too complex" when deleting large number of Clips
  * void CQPasteWnd::DeleteSelectedRows()
  + static BOOL CMainTable::DeleteAllClips();
  + static BOOL CMainTable::DeleteClip( int id );
  + static BOOL CMainTable::DeleteClips(ARRAY &IDs); (was called DeleteRows)


03 Aug 16
---------
! Perform GlobalUnlock after memcmp.
  * CDataTable::DataEqual

! Fixed "random" termination.
  * CMainFrame::OnTimer: added breaks to cases of switch.


03 Aug 11
---------
! Fixed string error in processcopy.cpp


Legend:
+ = added
- = removed
* = modified
! = fixed
. = info
