Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Commit [c97342] Maximize Restore History

checkpoint - merge with branches/dk200703 1337:1382 -compiles cleanly but crashes upon item rename.

git-svn-id: svn://svn.code.sf.net/p/passwordsafe/code/trunk/pwsafe/pwsafe@1407 1f79f812-37fb-46fe-a122-30589dd2bf55

Rony Shapiro Rony Shapiro 2007-05-07

1 2 > >> (Page 1 of 2)
added DDSupport.cpp
added DDSupport.h
added corelib/SMemFile.cpp
added corelib/SMemFile.h
changed ColumnChooserLC.cpp
changed ColumnChooserLC.h
changed DboxMain.cpp
changed DboxMain.h
changed DropSource.cpp
changed LVHdrCtrl.cpp
changed LVHdrCtrl.h
changed MainEdit.cpp
changed MainView.cpp
changed OptionsMisc.cpp
changed PasswordSafe.h
changed ThisMfcApp.cpp
changed ThisMfcApp.h
changed corelib
changed corelib/PWSprefs.cpp
changed corelib/UUIDGen.cpp
changed corelib/UUIDGen.h
changed corelib/Util.cpp
changed corelib/Util.h
changed corelib/corelib.vcproj
changed docs
changed docs/ReleaseNotes.txt
changed pwsafe.vcproj
changed res
changed res/PasswordSafe3.rc2
changed resource3.h
changed version.in
copied MyTreeCtrl.cpp -> TVTreeCtrl.cpp
copied MyTreeCtrl.h -> TVTreeCtrl.h
DDSupport.cpp Diff Switch to side-by-side view
Loading...
DDSupport.h Diff Switch to side-by-side view
Loading...
corelib/SMemFile.cpp Diff Switch to side-by-side view
Loading...
corelib/SMemFile.h Diff Switch to side-by-side view
Loading...
ColumnChooserLC.cpp Diff Switch to side-by-side view
Loading...
ColumnChooserLC.h Diff Switch to side-by-side view
Loading...
DboxMain.cpp Diff Switch to side-by-side view
Loading...
DboxMain.h Diff Switch to side-by-side view
Loading...
DropSource.cpp Diff Switch to side-by-side view
Loading...
LVHdrCtrl.cpp Diff Switch to side-by-side view
Loading...
LVHdrCtrl.h Diff Switch to side-by-side view
Loading...
MainEdit.cpp Diff Switch to side-by-side view
Loading...
MainView.cpp Diff Switch to side-by-side view
Loading...
OptionsMisc.cpp Diff Switch to side-by-side view
Loading...
PasswordSafe.h Diff Switch to side-by-side view
Loading...
ThisMfcApp.cpp Diff Switch to side-by-side view
Loading...
ThisMfcApp.h Diff Switch to side-by-side view
Loading...
corelib
Directory.
corelib/PWSprefs.cpp Diff Switch to side-by-side view
Loading...
corelib/UUIDGen.cpp Diff Switch to side-by-side view
Loading...
corelib/UUIDGen.h Diff Switch to side-by-side view
Loading...
corelib/Util.cpp Diff Switch to side-by-side view
Loading...
corelib/Util.h Diff Switch to side-by-side view
Loading...
corelib/corelib.vcproj Diff Switch to side-by-side view
Loading...
docs
Directory.
docs/ReleaseNotes.txt Diff Switch to side-by-side view
Loading...
pwsafe.vcproj Diff Switch to side-by-side view
Loading...
res
Directory.
res/PasswordSafe3.rc2 Diff Switch to side-by-side view
Loading...
resource3.h Diff Switch to side-by-side view
Loading...
version.in Diff Switch to side-by-side view
Loading...
MyTreeCtrl.cpp to TVTreeCtrl.cpp
--- a/MyTreeCtrl.cpp
+++ b/TVTreeCtrl.cpp
@@ -5,11 +5,6 @@
  * distributed with this code, or available from
  * http://www.opensource.org/licenses/artistic-license.php
  */
-/*
- * Silly subclass of CTreeCtrl just to implement Drag&Drop.
- *
- * Based on MFC sample code from CMNCTRL1
- */
 
 // Need a set to keep track of what nodes are expanded, to re-expand
 // after minimize
@@ -18,12 +13,21 @@
 using namespace std ;
 
 #include "stdafx.h"
-#include "MyTreeCtrl.h"
+#include "TVTreeCtrl.h"
 #include "DboxMain.h"
 #include "corelib/ItemData.h"
 #include "corelib/MyString.h"
 #include "corelib/Util.h"
 #include "corelib/Pwsprefs.h"
+#include "corelib/SMemFile.h"
+#include "corelib/PWSrand.h"
+#include <afxole.h>         // MFC OLE classes
+#include <afxodlgs.h>       // MFC OLE dialog classes
+#include <afxdisp.h >       // MFC OLE automation classes
+#include "PasswordSafe.h"   // for access to external gbl_tcddCPFID
+#include "DropSource.h"
+#include "DropTarget.h"
+#include "DDSupport.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -37,33 +41,27 @@
 
 static const TCHAR GROUP_SEP = TCHAR('.');
 
-CMyTreeCtrl::CMyTreeCtrl() : m_bDragging(false), m_pimagelist(NULL)
+CTVTreeCtrl::CTVTreeCtrl() : m_pimagelist(NULL), m_pDragImage(NULL), m_isRestoring(false),
+m_uiSendingSession(0), m_uiReceivingSession(0)
 {
   m_expandedItems = new SetTreeItem_t;
-  m_isRestoring = false;
-}
-
-CMyTreeCtrl::~CMyTreeCtrl()
+}
+
+CTVTreeCtrl::~CTVTreeCtrl()
 {
   delete m_pimagelist;
   delete (SetTreeItem_t *)m_expandedItems;
 }
 
-
-BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)
-	//{{AFX_MSG_MAP(CMyTreeCtrl)
-	ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginLabelEdit)
-	ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndLabelEdit)
-	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
-	ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnExpandCollapse)
-	ON_WM_MOUSEMOVE()
-	ON_WM_DESTROY()
-	ON_WM_LBUTTONUP()
-	ON_WM_TIMER()
-	//}}AFX_MSG_MAP
+BEGIN_MESSAGE_MAP(CTVTreeCtrl, CTreeCtrl)
+  //{{AFX_MSG_MAP(CTVTreeCtrl)
+  ON_WM_DESTROY()
+  ON_WM_LBUTTONDOWN()
+  ON_WM_LBUTTONDBLCLK()
+  //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
-void CMyTreeCtrl::OnDestroy()
+void CTVTreeCtrl::OnDestroy()
 {
   CImageList  *pimagelist;
 
@@ -72,9 +70,11 @@
     pimagelist->DeleteImageList();
     delete pimagelist;
   }
-}
-
-BOOL CMyTreeCtrl::PreTranslateMessage(MSG* pMsg) 
+
+  m_TCDropTarget.Revoke();
+}
+
+BOOL CTVTreeCtrl::PreTranslateMessage(MSG* pMsg)
 {
   // When an item is being edited make sure the edit control
   // receives certain important key strokes
@@ -84,13 +84,8 @@
     return TRUE; // DO NOT process further
   }
 
-  //Hitting the Escape key, Cancelling drag & drop
-  if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE && m_bDragging) {
-    EndDragging(TRUE);
-    return TRUE;
-  }
   //hitting the F2 key, being in-place editing of an item
-  else if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F2) {
+  if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F2) {
     HTREEITEM hItem = GetSelectedItem();
     if (hItem != NULL && !((DboxMain *)GetParent())->IsReadOnly())
       EditLabel(hItem);
@@ -101,21 +96,96 @@
   return CTreeCtrl::PreTranslateMessage(pMsg);
 }
 
-
-void CMyTreeCtrl::SetNewStyle(long lStyleMask, BOOL bSetBits)
+DROPEFFECT CTVTreeCtrl::OnDragEnter(CWnd* pWnd , COleDataObject* pDataObject,
+                  DWORD dwKeyState, CPoint point)
+{
+  return CDropTarget::OnDragEnter(pWnd, pDataObject, dwKeyState, point);
+}
+
+#define SCROLL_BORDER 25
+#define SCROLL_SPEED_ZONE_WIDTH 20
+
+DROPEFFECT CTVTreeCtrl::OnDragOver(CWnd* pWnd , COleDataObject* /* pDataObject */,
+                  DWORD dwKeyState, CPoint point)
+{
+  CTVTreeCtrl *pDestTreeCtrl;
+
+  DROPEFFECT dropeffectRet = DROPEFFECT_COPY;
+  if ((dwKeyState & MK_SHIFT) == MK_SHIFT)
+    dropeffectRet = DROPEFFECT_MOVE;
+
+  // Doesn't matter that we didn't initialize m_calls
+  m_calls++;
+
+  // Expand and highlight the item under the mouse and 
+  pDestTreeCtrl = (CTVTreeCtrl *)pWnd;
+  HTREEITEM hTItem = pDestTreeCtrl->HitTest(point);
+  // Use m_calls to slow down expanding nodes
+  if (hTItem != NULL && (m_calls % 32 == 0)) {
+    pDestTreeCtrl->Expand(hTItem, TVE_EXPAND);
+    pDestTreeCtrl->SelectDropTarget(hTItem);
+  }  
+
+  CRect rectClient;
+  pWnd->GetClientRect(&rectClient);
+  pWnd->ClientToScreen(rectClient);
+  pWnd->ClientToScreen(&point);
+
+  int slowscroll_up = 6 - (rectClient.top + SCROLL_BORDER - point.y) / SCROLL_SPEED_ZONE_WIDTH;
+  int slowscroll_down = 6 - (point.y - rectClient.bottom + SCROLL_BORDER ) / SCROLL_SPEED_ZONE_WIDTH;
+
+  // Scroll Tree control depending on mouse position
+  int iMaxV = GetScrollLimit(SB_VERT);
+  int iPosV = GetScrollPos(SB_VERT);
+
+  int nScrollDir = -1;
+  if ((point.y > rectClient.bottom - SCROLL_BORDER) && (iPosV != iMaxV) &&
+      (m_calls % (slowscroll_down > 0 ? slowscroll_down : 1)) == 0)
+    nScrollDir = SB_LINEDOWN;
+  else
+  if ((point.y < rectClient.top + SCROLL_BORDER) && (iPosV != 0) &&
+      (m_calls % (slowscroll_up > 0 ? slowscroll_up : 1)) == 0)
+    nScrollDir = SB_LINEUP;
+
+  if (nScrollDir != -1) {
+    int nScrollPos = pWnd->GetScrollPos(SB_VERT);
+    WPARAM wParam = MAKELONG(nScrollDir, nScrollPos);
+    pWnd->SendMessage(WM_VSCROLL, wParam);
+  }
+  
+  int iPosH = GetScrollPos(SB_HORZ);
+  int iMaxH = GetScrollLimit(SB_HORZ);
+
+  nScrollDir = -1;
+  if ((point.x < rectClient.left + SCROLL_BORDER) && (iPosH != 0))
+    nScrollDir = SB_LINELEFT;
+  else
+  if ((point.x > rectClient.right - SCROLL_BORDER) && (iPosH != iMaxH))
+    nScrollDir = SB_LINERIGHT;
+  
+  if (nScrollDir != -1) {
+    int nScrollPos = pWnd->GetScrollPos(SB_VERT);
+    WPARAM wParam = MAKELONG(nScrollDir, nScrollPos);
+    pWnd->SendMessage(WM_HSCROLL, wParam);
+  }
+  
+  return dropeffectRet;  
+}
+
+void CTVTreeCtrl::SetNewStyle(long lStyleMask, BOOL bSetBits)
 {
   long        lStyleOld;
 
-  lStyleOld = GetWindowLong(m_hWnd, GWL_STYLE);
+  lStyleOld = GetWindowLong(CWnd::m_hWnd, GWL_STYLE);
   lStyleOld &= ~lStyleMask;
   if (bSetBits)
     lStyleOld |= lStyleMask;
 
-  SetWindowLong(m_hWnd, GWL_STYLE, lStyleOld);
+  SetWindowLong(CWnd::m_hWnd, GWL_STYLE, lStyleOld);
   SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
 }
 
-void CMyTreeCtrl::UpdateLeafsGroup(HTREEITEM hItem, CString prefix)
+void CTVTreeCtrl::UpdateLeafsGroup(HTREEITEM hItem, CString prefix)
 {
   // Starting with hItem, update the Group field of all of hItem's
   // children. Called after a label has been edited.
@@ -135,9 +205,9 @@
   }
 }
 
-void CMyTreeCtrl::OnBeginLabelEdit(LPNMHDR , LRESULT *pLResult)
-{
-  //TV_DISPINFO *ptvinfo = (TV_DISPINFO *)pnmhdr;
+void CTVTreeCtrl::BeginLabelEdit(NMHDR * /* pNotifyStruct */, LRESULT * &pLResult)
+{
+  //TV_DISPINFO *ptvinfo = (TV_DISPINFO *)pNotifyStruct;
   *pLResult = FALSE; // TRUE cancels label editing
 }
 
@@ -160,12 +230,12 @@
   }
 }
 
-void CMyTreeCtrl::OnEndLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult)
+void CTVTreeCtrl::EndLabelEdit(NMHDR *pNotifyStruct, LRESULT * &pLResult)
 {
   if (((DboxMain *)GetParent())->IsReadOnly())
     return; // don't drag in read-only mode
 
-  NMTVDISPINFO *ptvinfo = (NMTVDISPINFO *)pnmhdr;
+  NMTVDISPINFO *ptvinfo = (NMTVDISPINFO *)pNotifyStruct;
   HTREEITEM ti = ptvinfo->item.hItem;
   if (ptvinfo->item.pszText != NULL && // NULL if edit cancelled,
       ptvinfo->item.pszText[0] != TCHAR('\0')) { // empty if text deleted - not allowed
@@ -186,37 +256,37 @@
       if (newUser.IsEmpty())
         newUser = CString(ci->GetUser());
       CString treeDispString;
-	  treeDispString = newTitle;
-	  treeDispString += _T(" [");
-	  treeDispString += newUser;
-	  treeDispString += _T("]");
-
-      PWSprefs *prefs = PWSprefs::GetInstance();
-      bool bShowPasswordInList = prefs->GetPref(PWSprefs::ShowPWInList);
-
-	  if (bShowPasswordInList) {
-		  CString newPassword = CString(ci->GetPassword());
-		  treeDispString += _T(" [");
-		  treeDispString += newPassword;
-		  treeDispString += _T("]");
-	  }
-
-      // Update corresponding Tree mode text with the new display text (ie: in case 
+    treeDispString = newTitle;
+    treeDispString += _T(" [");
+    treeDispString += newUser;
+    treeDispString += _T("]");
+
+    PWSprefs *prefs = PWSprefs::GetInstance();
+    bool bShowPasswordInList = prefs->GetPref(PWSprefs::ShowPWInList);
+
+    if (bShowPasswordInList) {
+      CString newPassword = CString(ci->GetPassword());
+      treeDispString += _T(" [");
+      treeDispString += newPassword;
+      treeDispString += _T("]");
+    }
+
+      // Update corresponding Tree mode text with the new display text (ie: in case
       // the username was removed and had to be normalized back in).  Note that
       // we cannot do "SetItemText(ti, treeDispString)" here since Windows will
-      // automatically overwrite and update the item text with the contents from 
+      // automatically overwrite and update the item text with the contents from
       // the "ptvinfo->item.pszText" buffer.
       PWSUtil::strCopy(ptvinfo->item.pszText, ptvinfo->item.cchTextMax,
                       treeDispString, ptvinfo->item.cchTextMax);
-      ptvinfo->item.pszText[ptvinfo->item.cchTextMax - 1] = TCHAR('\0');
 
       // update the password database record.
       ci->SetTitle(newTitle); ci->SetUser(newUser);
+
       // update corresponding List mode text
       DisplayInfo *di = (DisplayInfo *)ci->GetDisplayInfo();
       ASSERT(di != NULL);
       int lindex = di->list_index;
-	  ((DboxMain *)m_parent)->UpdateListItemTitle(lindex, newTitle);
+      ((DboxMain *)m_parent)->UpdateListItemTitle(lindex, newTitle);
       ((DboxMain *)m_parent)->UpdateListItemUser(lindex, newUser);
     } else {
       // Update all leaf children with new path element
@@ -246,35 +316,7 @@
   }
 }
 
-void CMyTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
-{
-  if (m_nHoverTimerID) {
-  	KillTimer( m_nHoverTimerID );
-  	m_nHoverTimerID = 0;
-  }
-
-  if (m_bDragging) {
-    UINT                flags;
-
-    ASSERT(m_pimagelist != NULL);
-    m_pimagelist->DragMove(point);
-
-	m_nHoverTimerID = SetTimer(2, 750, NULL);
-	m_HoverPoint = point;
-
-    HTREEITEM hitem = HitTest(point, &flags);
-    if (hitem != NULL) {
-      m_pimagelist->DragLeave(this);
-      SelectDropTarget(hitem);
-      m_hitemDrop = hitem;
-      m_pimagelist->DragEnter(this, point);
-    }
-    m_pimagelist->DragShowNolock(TRUE);
-  }
-  CTreeCtrl::OnMouseMove(nFlags, point);
-}
-
-bool CMyTreeCtrl::IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent)
+bool CTVTreeCtrl::IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent)
 {
   do {
     if (hitemChild == hitemSuspectedParent)
@@ -284,7 +326,7 @@
   return (hitemChild != NULL);
 }
 
-bool CMyTreeCtrl::IsLeafNode(HTREEITEM hItem)
+bool CTVTreeCtrl::IsLeafNode(HTREEITEM hItem)
 {
   // ItemHasChildren() won't work in the general case
   BOOL status;
@@ -294,7 +336,7 @@
   return (i != NODE);
 }
 
-void CMyTreeCtrl::DeleteWithParents(HTREEITEM hItem)
+void CTVTreeCtrl::DeleteWithParents(HTREEITEM hItem)
 {
   // We don't want nodes that have no children to remain
   HTREEITEM p;
@@ -307,7 +349,7 @@
   } while (p != TVI_ROOT && p != NULL);
 }
 
-void CMyTreeCtrl::DeleteFromSet(HTREEITEM hItem)
+void CTVTreeCtrl::DeleteFromSet(HTREEITEM hItem)
 {
   SetTreeItemP_t pSet = SetTreeItemP_t(m_expandedItems);
   DWORD itemData = GetItemData(hItem);
@@ -318,7 +360,7 @@
 
 // Return the full path leading up to a given item, but
 // not including the name of the item itself.
-CString CMyTreeCtrl::GetGroup(HTREEITEM hItem)
+CString CTVTreeCtrl::GetGroup(HTREEITEM hItem)
 {
   CString retval;
   CString nodeText;
@@ -353,11 +395,11 @@
 }
 
 static bool ExistsInTree(CTreeCtrl &Tree, HTREEITEM node,
-			 const CMyString &s, HTREEITEM &si)
+       const CMyString &s, HTREEITEM &si)
 {
   // returns true iff s is a direct descendant of node
   HTREEITEM ti = Tree.GetChildItem(node);
-  
+
   while (ti != NULL) {
     const CMyString itemText = Tree.GetItemText(ti);
     if (itemText == s) {
@@ -369,7 +411,7 @@
   return false;
 }
 
-HTREEITEM CMyTreeCtrl::AddGroup(const CString &group)
+HTREEITEM CTVTreeCtrl::AddGroup(const CString &group)
 {
   // Add a group at the end of path
   HTREEITEM ti = TVI_ROOT;
@@ -381,7 +423,7 @@
       s = GetPathElem(path);
       if (!ExistsInTree(*this, ti, s, si)) {
         ti = InsertItem(s, ti, TVI_SORT);
-        SetItemImage(ti, CMyTreeCtrl::NODE, CMyTreeCtrl::NODE);
+        SetItemImage(ti, CTVTreeCtrl::NODE, CTVTreeCtrl::NODE);
       } else
         ti = si;
     } while (!path.IsEmpty());
@@ -389,7 +431,7 @@
   return ti;
 }
 
-bool CMyTreeCtrl::TransferItem(HTREEITEM hitemDrag, HTREEITEM hitemDrop)
+bool CTVTreeCtrl::TransferItem(HTREEITEM hitemDrag, HTREEITEM hitemDrop)
 {
   TV_INSERTSTRUCT     tvstruct;
   TCHAR               sztBuffer[260];  // max visible
@@ -403,11 +445,13 @@
   tvstruct.item.mask = (TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE
                         | TVIF_SELECTEDIMAGE | TVIF_TEXT);
   GetItem(&tvstruct.item);  // get information of the dragged element
+
   tvstruct.hParent = hitemDrop;
   if (((DboxMain *)GetParent())->IsExplorerTree())
     tvstruct.hInsertAfter = TVI_LAST;
   else
     tvstruct.hInsertAfter = TVI_SORT;
+
   tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
   hNewItem = InsertItem(&tvstruct);
   if (itemData != 0) { // Non-NULL itemData implies Leaf
@@ -429,39 +473,30 @@
     // Get information from current selected entry
     CMyString ci_user = ci->GetUser();
     CMyString ci_title0 = ci->GetTitle();
-    CMyString ci_title = ci_title0;
-    if (((DboxMain *)m_parent)->Find(path, ci_title0, ci_user) != NULL) {
-        // Find a unique "Title"
-        POSITION listpos = NULL;
-        int i = 0;
-        CString s_copy;
-        do {
-            i++;
-            s_copy.Format(IDS_DRAGNUMBER, i);
-            ci_title = ci_title0 + CMyString(s_copy);
-            listpos = ((DboxMain *)m_parent)->Find(path, ci_title, ci_user);
-        } while (listpos != NULL);
-    }
+    CMyString ci_title;
+    ci_title = ((DboxMain *)m_parent)->GetUniqueTitle(path, 
+                           ci_title0, ci_user, IDS_DRAGNUMBER);
+
     ci->SetGroup(path);
     DisplayInfo *di = (DisplayInfo *)ci->GetDisplayInfo();
     ASSERT(di != NULL);
     if (ci_title.Compare(ci_title0) != 0) {
-        ci->SetTitle(ci_title);
-        CMyString treeDispString;
-	    treeDispString = ci_title;
-	    treeDispString += _T(" [");
-	    treeDispString += ci_user;
-	    treeDispString += _T("]");
-        if( PWSprefs::GetInstance()->GetPref(PWSprefs::ShowPWInList)) {
-		    CMyString ci_Password = ci->GetPassword();
-		    treeDispString += _T(" [");
-		    treeDispString += ci_Password;
-		    treeDispString += _T("]");
-	    }
-        // Update tree label
-        SetItemText(hNewItem, treeDispString);
-        // Update list field
-        ((DboxMain *)GetParent())->UpdateListItemTitle(di->list_index, (CString)ci_title);
+      ci->SetTitle(ci_title);
+      CMyString treeDispString;
+      treeDispString = ci_title;
+      treeDispString += _T(" [");
+      treeDispString += ci_user;
+      treeDispString += _T("]");
+      if( PWSprefs::GetInstance()->GetPref(PWSprefs::ShowPWInList)) {
+        CMyString ci_Password = ci->GetPassword();
+        treeDispString += _T(" [");
+        treeDispString += ci_Password;
+        treeDispString += _T("]");
+      }
+      // Update tree label
+      SetItemText(hNewItem, treeDispString);
+      // Update list field
+      ((DboxMain *)GetParent())->UpdateListItemTitle(di->list_index, (CString)ci_title);
     }
     // Mark database as modified!
     ((DboxMain *)GetParent())->SetChanged(DboxMain::Data);
@@ -481,102 +516,75 @@
   return true;
 }
 
-void CMyTreeCtrl::EndDragging(BOOL bCancel)
-{
-  if (m_bDragging) {
-    ASSERT(m_pimagelist != NULL);
-    m_pimagelist->DragLeave(this);
-    m_pimagelist->EndDrag();
-    delete m_pimagelist;
-    m_pimagelist = NULL;
-    HTREEITEM parent = GetParentItem(m_hitemDrag);
-    if (IsLeafNode(m_hitemDrop))
-        m_hitemDrop = GetParentItem(m_hitemDrop);
-
-    if (!bCancel &&
-        m_hitemDrag != m_hitemDrop &&
-        !IsChildNodeOf(m_hitemDrop, m_hitemDrag) &&
-        parent != m_hitemDrop)
-      {
-        // drag operation completed successfully.
-        TransferItem(m_hitemDrag, m_hitemDrop);
-        DeleteItem(m_hitemDrag);
-        while (parent != NULL && !ItemHasChildren(parent)) {
-          HTREEITEM grandParent = GetParentItem(parent);
-          DeleteItem(parent);
-          parent = grandParent;
-        }
-        SelectItem(m_hitemDrop);
-      } else {
-        // drag failed or cancelled, revert to last selected
-        SelectItem(m_hitemDrag);
-      }
-    ReleaseCapture();
-    m_bDragging = FALSE;
-    SelectDropTarget(NULL);
-
-  }
-  KillTimer(m_nTimerID);
-  KillTimer(m_nHoverTimerID);
-}
-
-
-void CMyTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
-{
-  if (m_bDragging) {
-    // Dragging operation should be ended, but first check to see
-    // if the mouse is outside the window to decide if the 
-    // drag operation should be aborted.
-    CRect clientRect;
-    GetClientRect(&clientRect);
-    if (clientRect.PtInRect(point))
-      EndDragging(FALSE);
-    else
-      EndDragging(TRUE);
-  }
-  CTreeCtrl::OnLButtonUp(nFlags, point);
-}
-
-
-void CMyTreeCtrl::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) 
-{
-  CPoint      ptAction;
-
-  NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
-  *pResult = 0;
-
-  if (((DboxMain *)GetParent())->IsReadOnly())
-      return; // don't drag in read-only mode
-
-  GetCursorPos(&ptAction);
-  ScreenToClient(&ptAction);
-  ASSERT(!m_bDragging);
-  m_bDragging = TRUE;
-  m_hitemDrag = pNMTreeView->itemNew.hItem;
-  m_hitemDrop = NULL;
-  SelectItem(m_hitemDrag);
-
-  ASSERT(m_pimagelist == NULL);
-  m_pimagelist = CreateDragImage(m_hitemDrag);
-  m_pimagelist->DragShowNolock(TRUE);
-  m_pimagelist->SetDragCursorImage(0, CPoint(0, 0));
-  m_pimagelist->BeginDrag(0, CPoint(0,0));
-  m_pimagelist->DragMove(ptAction);
-  m_pimagelist->DragEnter(this, ptAction);
-  SetCapture();
-  
-  // Set up the timer
-  m_nTimerID = SetTimer(1, 75, NULL);
-}
-
-
-void CMyTreeCtrl::OnExpandCollapse(NMHDR *pNotifyStruct, LRESULT *)
+bool CTVTreeCtrl::CopyItem(HTREEITEM hitemDrag, HTREEITEM hitemDrop)
+{
+  HTREEITEM hFirstChild;
+  DWORD itemData = GetItemData(hitemDrag);
+
+  if (itemData != 0) { // Non-NULL itemData implies Leaf
+    CItemData *ci = (CItemData *)itemData;
+    CItemData temp(*ci);
+
+    // Update Group
+    CMyString path, elem;
+    path = CMyString(GetItemText(hitemDrop));
+    HTREEITEM p, q = hitemDrop;
+    do {
+      p = GetParentItem(q);
+      if (p != NULL) {
+        elem = CMyString(GetItemText(p));
+        if (!path.IsEmpty())
+          elem += GROUP_SEP;
+        path = elem + path;
+        q = p;
+      } else
+        break;
+    } while (1);
+
+    // Get information from current selected entry
+    CMyString ci_user = ci->GetUser();
+    CMyString ci_title0 = ci->GetTitle();
+    CMyString ci_title;
+    ci_title = ((DboxMain *)m_parent)->GetUniqueTitle(path, ci_title0,
+                            ci_user, IDS_DRAGNUMBER);
+
+    temp.CreateUUID();
+    temp.SetGroup(path);
+    temp.SetTitle(ci_title);
+    DisplayInfo *di = (DisplayInfo *)ci->GetDisplayInfo();
+    ASSERT(di != NULL);
+    DisplayInfo *ndi = new DisplayInfo;
+    ndi->list_index = -1; // so that insertItem will set new values
+    ndi->tree_item = 0;
+    temp.SetDisplayInfo(ndi);
+
+    ((DboxMain *)m_parent)->AddEntry(temp);
+
+    // Mark database as modified!
+    ((DboxMain *)GetParent())->SetChanged(DboxMain::Data);
+  }
+
+  if (((DboxMain *)GetParent())->IsExplorerTree())
+    ((DboxMain *)GetParent())->SortTree(hitemDrop);
+  else
+    SortChildren(hitemDrop);
+
+  while ((hFirstChild = GetChildItem(hitemDrag)) != NULL) {
+    CopyItem(hFirstChild, hitemDrop);  // recursively copy all the items
+  }
+
+  return true;
+}
+
+void CTVTreeCtrl::ExpandCollapse(NMHDR *pNotifyStruct, LRESULT * &pLResult)
 {
   // The hItem that is expanded isn't the one that will be restored,
   // since the tree is rebuilt in DboxMain::RefreshList. Therefore, we
   // need to store the corresponding elements. But groups have none, so
   // we store the first (or any) child element, and upon restore, expand
   // the parent. Ugh++.
+
+  *pLResult = FALSE;
 
   if (!m_isRestoring) {
     SetTreeItemP_t pSet = SetTreeItemP_t(m_expandedItems);
@@ -590,7 +598,7 @@
       }
       child = GetNextSiblingItem(child);
     } while (child != NULL);
-    
+
     if (child == NULL) {
       // case where expanded node has only tree subnodes,
       // nothing to get a CItemData from. This borderline
@@ -610,7 +618,7 @@
   }
 }
 
-void CMyTreeCtrl::RestoreExpanded()
+void CTVTreeCtrl::RestoreExpanded()
 {
   m_isRestoring = true;
   SetTreeItemP_t pSet = SetTreeItemP_t(m_expandedItems);
@@ -625,13 +633,13 @@
   m_isRestoring = false;
 }
 
-void CMyTreeCtrl::ClearExpanded()
+void CTVTreeCtrl::ClearExpanded()
 {
   SetTreeItemP_t pSet = SetTreeItemP_t(m_expandedItems);
   pSet->clear();
 }
 
-void CMyTreeCtrl::OnExpandAll() 
+void CTVTreeCtrl::OnExpandAll()
 {
   // Updated to test for zero entries!
   HTREEITEM hItem = this->GetRootItem();
@@ -647,7 +655,7 @@
   SetRedraw();
 }
 
-void CMyTreeCtrl::OnCollapseAll() 
+void CTVTreeCtrl::OnCollapseAll()
 {
   // Courtesy of Zafir Anjum from www.codeguru.com
   // Updated to test for zero entries!
@@ -656,149 +664,431 @@
     return;
   SetRedraw(FALSE);
   do {
-	  CollapseBranch(hItem);
+    CollapseBranch(hItem);
   }
   while((hItem = this->GetNextSiblingItem(hItem)) != NULL);
   SetRedraw();
 }
 
-void CMyTreeCtrl::CollapseBranch(HTREEITEM hItem)
-{
-	// Courtesy of Zafir Anjumfrom www.codeguru.com
-	if(this->ItemHasChildren(hItem)) {
-		this->Expand(hItem, TVE_COLLAPSE);
-		hItem = this->GetChildItem(hItem);
-		do {
-			CollapseBranch(hItem);
-		}
-		while((hItem = this->GetNextSiblingItem(hItem)) != NULL);
-	}
-}
-
-void CMyTreeCtrl::OnTimer(UINT nIDEvent)
-{
-  const int SCROLL_BORDER = 10;
-  const int SCROLL_SPEED_ZONE_WIDTH = 20;
-
-  if (nIDEvent == m_nHoverTimerID) {
-    KillTimer(m_nHoverTimerID);
-    m_nHoverTimerID = 0;
-
-    HTREEITEM	trItem	= 0;
-    UINT		uFlag	= 0;
-
-    trItem = HitTest(m_HoverPoint, &uFlag);
-
-    if (trItem) {
-      SelectItem(trItem);
-      Expand(trItem,TVE_EXPAND);
-    }
+void CTVTreeCtrl::CollapseBranch(HTREEITEM hItem)
+{
+  // Courtesy of Zafir Anjumfrom www.codeguru.com
+  if(this->ItemHasChildren(hItem)) {
+    this->Expand(hItem, TVE_COLLAPSE);
+    hItem = this->GetChildItem(hItem);
+    do {
+      CollapseBranch(hItem);
+    }
+    while((hItem = this->GetNextSiblingItem(hItem)) != NULL);
+  }
+}
+
+HTREEITEM
+CTVTreeCtrl::GetNextTreeItem(HTREEITEM hItem)
+{
+  if (NULL == hItem)
+    return this->GetRootItem();
+
+    // First, try to go to this item's 1st child
+    HTREEITEM hReturn = this->GetChildItem(hItem);
+
+    // If no more child items...
+    while (hItem && !hReturn) {
+        // Get this item's next sibling
+        hReturn = this->GetNextSiblingItem(hItem);
+
+        // If hReturn is NULL, then there are no
+        // sibling items, and we're on a leaf node.
+        // Backtrack up the tree one level, and
+        // we'll look for a sibling on the next
+        // iteration (or we'll reach the root and
+        // quit).
+        hItem = this->GetParentItem(hItem);
+    }
+    return hReturn;
+}
+
+void CTVTreeCtrl::OnLButtonDblClk(UINT /* nFlags */, CPoint /* point */)
+{
+  ((DboxMain *)m_parent)->DoItemDoubleClick();
+}
+
+void CTVTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point)
+{
+  CTreeCtrl::OnLButtonDown(nFlags, point);
+
+  // Can drag in read-only mode as it might be to someone else
+  // Can't allow drop in read-only mode
+
+  UINT uFlags;
+  m_hitemDrag = HitTest(point, &uFlags);
+  if ((m_hitemDrag == NULL) || !(TVHT_ONITEM & uFlags)) {
     return;
   }
 
-  if (nIDEvent != m_nTimerID) {
-    CTreeCtrl::OnTimer(nIDEvent);
+  SelectItem(m_hitemDrag);
+
+  long lBufLen;
+  BYTE * buffer(NULL);
+  CString cs_text;
+
+  // Start of Drag of entries.....
+  // CollectData allocates buffer - need to free later
+  if (!CollectData(buffer, lBufLen))
     return;
-  }
-
-  // Doesn't matter that we didn't initialize m_timerticks
-  m_timerticks++;
-
-  POINT pt;
-  GetCursorPos(&pt);
-  CRect rect;
-  GetClientRect(&rect);
-  ClientToScreen(&rect);
-
-  // NOTE: Screen coordinate is being used because the call
-  // to DragEnter had used the Desktop window.
-  POINT pttemp = POINT(pt);
-  ClientToScreen(&pttemp);
-  CImageList::DragMove(pttemp);
-
-  int iMaxV = GetScrollLimit(SB_VERT);
-  int iPosV = GetScrollPos(SB_VERT);
-  HTREEITEM hitem = GetFirstVisibleItem();
-
-  // The cursor must not only be SOMEWHERE above/beneath the tree control
-  // BUT RIGHT above or beneath it
-  // i.e. the x-coordinates must be those of the control (+/- SCROLL_BORDER)
-  if ( pt.x < rect.left - SCROLL_BORDER )
-    ; // Too much to the left
-  else if ( pt.x > rect.right + SCROLL_BORDER )
-    ; // Too much to the right
-  else if( (pt.y < rect.top + SCROLL_BORDER) && iPosV ) {
-    // We need to scroll up
-    // Scroll slowly if cursor near the treeview control
-    int slowscroll = 6 - (rect.top + SCROLL_BORDER - pt.y) / SCROLL_SPEED_ZONE_WIDTH;
-    if (0 == (m_timerticks % (slowscroll > 0 ? slowscroll : 1)))
-      {
-        CImageList::DragShowNolock(FALSE);
-        SendMessage(WM_VSCROLL, SB_LINEUP);
-        SelectDropTarget(hitem);
-        m_hitemDrop = hitem;
-        CImageList::DragShowNolock(TRUE);
+
+  cs_text.Format(_T("%s%02x%08x"), gbl_classname, FROMTREE, lBufLen);
+
+  CMemFile mf;
+  mf.Write(cs_text, sizeof(gbl_classname) - 1 + 10);
+  mf.Write(buffer, lBufLen);
+
+  // Finished with (encrypted) buffer - free it
+  free(buffer);
+
+  DWORD dw_mflen = (DWORD)mf.GetLength();
+  LPCTSTR mf_buffer = LPCTSTR(mf.Detach());
+
+  ASSERT(m_pDragImage == NULL);
+  m_pDragImage = CreateDragImage(m_hitemDrag);
+
+  // Get client rectangle
+  RECT rClient;
+  GetClientRect(&rClient);
+
+  // Set our session numbers (should be different!)
+  m_uiSendingSession = PWSrand::GetInstance()->RandUInt();
+  m_uiReceivingSession = PWSrand::GetInstance()->RandUInt();
+
+  // Start dragging
+  StartDragging(mf_buffer, dw_mflen, gbl_tcddCPFID, &rClient, &point);
+
+  // Cleanup
+  free((void *)mf_buffer);
+
+// End dragging image
+  m_pDragImage->DragLeave(GetDesktopWindow());
+  m_pDragImage->EndDrag();
+
+  delete m_pDragImage;
+  m_pDragImage = NULL;
+}
+
+BOOL CTVTreeCtrl::OnDrop(CWnd* /* pWnd */, COleDataObject* pDataObject,
+                              DROPEFFECT dropEffect, CPoint point)
+{
+  if (((DboxMain *)GetParent())->IsReadOnly())
+    return FALSE; // don't drop in read-only mode
+
+  if (!pDataObject->IsDataAvailable(gbl_tcddCPFID, NULL))
+    return FALSE;
+
+  UINT uFlags;
+  m_hitemDrop = HitTest(point, &uFlags);
+
+  bool bForceRoot(false);
+  switch (uFlags) {
+    case TVHT_ABOVE:
+    case TVHT_BELOW:
+    case TVHT_TOLEFT:
+    case TVHT_TORIGHT:
+      return FALSE;
+    case TVHT_NOWHERE:
+      if (m_hitemDrop == NULL) {
+        // Treat as drop in root
+        m_hitemDrop = GetRootItem();
+        bForceRoot = true;
+      } else
+        return FALSE;
+      break;
+    case TVHT_ONITEM:
+    case TVHT_ONITEMBUTTON:
+    case TVHT_ONITEMICON:
+    case TVHT_ONITEMINDENT:
+    case TVHT_ONITEMLABEL:
+    case TVHT_ONITEMRIGHT:
+    case TVHT_ONITEMSTATEICON:
+      if (m_hitemDrop == NULL)
+        return FALSE;
+      break;
+    default :
+      return FALSE;
+  }
+
+  m_uiReceivingSession = m_uiSendingSession;
+
+  BOOL retval(FALSE);
+
+  // On Drop of data from one tree to another
+  HGLOBAL hGlobal;
+
+  hGlobal = pDataObject->GetGlobalData(gbl_tcddCPFID);
+  LPCTSTR pData = (LPCTSTR)GlobalLock(hGlobal);
+  ASSERT(pData != NULL);
+
+  SIZE_T memsize = GlobalSize(hGlobal);
+
+  if (memsize < DD_MEMORY_MINSIZE)
+    goto exit;
+
+  memset(m_sending_classname, 0, sizeof(gbl_classname));
+  memcpy(m_sending_classname, pData, sizeof(gbl_classname) - 1);
+  bool our_data = memcmp(gbl_classname, m_sending_classname, sizeof(gbl_classname) - 1) == 0;
+
+  int iDDType;
+  long lBufLen;
+
+#if _MSC_VER >= 1400
+  _stscanf_s(pData + sizeof(gbl_classname) - 1, _T("%02x%08x"), &iDDType, &lBufLen);
+#else
+  _stscanf(pData + sizeof(gbl_classname) - 1, _T("%02x%08x"), &iDDType, &lBufLen);
+#endif
+
+  // Check if it is from another TreeCtrl?
+  // - we don't accept drop from anything else
+  if (iDDType != FROMTREE || ((long)memsize < (DD_MEMORY_MINSIZE + lBufLen)))
+    goto exit;
+
+  if (m_hitemDrop == NULL && GetCount() == 0) {
+    // Dropping on to an empty database
+    CMyString DropGroup (_T(""));
+    ProcessData((BYTE *)(pData + sizeof(gbl_classname) - 1 + 10), lBufLen, DropGroup);
+    SelectItem(GetRootItem());
+    retval = TRUE;
+    goto exit;
+  }
+
+  if (IsLeafNode(m_hitemDrop) || bForceRoot)
+    m_hitemDrop = GetParentItem(m_hitemDrop);
+
+  if (our_data) {
+    // from me! - easy
+    HTREEITEM parent = GetParentItem(m_hitemDrag);
+    if (m_hitemDrag != m_hitemDrop &&
+      !IsChildNodeOf(m_hitemDrop, m_hitemDrag) &&
+      parent != m_hitemDrop) {
+      // drag operation completed successfully.
+      if (dropEffect == DROPEFFECT_MOVE) {
+        // Transfer them & delete
+        TransferItem(m_hitemDrag, m_hitemDrop);
+        DeleteItem(m_hitemDrag);
+      } else if (dropEffect == DROPEFFECT_COPY) {
+        CopyItem(m_hitemDrag, m_hitemDrop);
       }
-  }
-  else if( (pt.y > rect.bottom - SCROLL_BORDER) && (iPosV!=iMaxV) )
-	{
-      // We need to scroll down
-      // Scroll slowly if cursor near the treeview control
-      int slowscroll = 6 - (pt.y - rect.bottom + SCROLL_BORDER ) / SCROLL_SPEED_ZONE_WIDTH;
-      if (0 == (m_timerticks % (slowscroll > 0 ? slowscroll : 1)))
-		{
-          CImageList::DragShowNolock(FALSE);
-          SendMessage(WM_VSCROLL, SB_LINEDOWN);
-          int nCount = GetVisibleCount();
-          for (int i=0; i<nCount-1; ++i)
-            hitem = GetNextVisibleItem(hitem);
-          if(hitem)
-            SelectDropTarget(hitem);
-          m_hitemDrop = hitem;
-          CImageList::DragShowNolock(TRUE);
-		}
-	}
-
-  // The cursor must be in a small zone IN the treecontrol at the left/right
-  int iPosH = GetScrollPos(SB_HORZ);
-  int iMaxH = GetScrollLimit(SB_HORZ);
-
-  if (!rect.PtInRect(pt)) return; // not in TreeCtrl
-  else if ((pt.x < rect.left + SCROLL_BORDER) && (iPosH != 0)) {
-    // We need to scroll to the left
-    CImageList::DragShowNolock(FALSE);
-    SendMessage(WM_HSCROLL, SB_LINELEFT);
-    CImageList::DragShowNolock(TRUE);
-  }
-  else if ((pt.x > rect.right - SCROLL_BORDER) && (iPosH != iMaxH)) {
-    // We need to scroll to the right
-    CImageList::DragShowNolock(FALSE);
-    SendMessage(WM_HSCROLL, SB_LINERIGHT);
-    CImageList::DragShowNolock(TRUE);
-  }
-}
-
-HTREEITEM
-CMyTreeCtrl::GetNextTreeItem(HTREEITEM hItem) 
-{
-	if (NULL == hItem)
-		return this->GetRootItem(); 
-
-    // First, try to go to this item's 1st child 
-    HTREEITEM hReturn = this->GetChildItem(hItem); 
-
-    // If no more child items... 
-    while (hItem && !hReturn) { 
-        // Get this item's next sibling 
-        hReturn = this->GetNextSiblingItem(hItem); 
-
-        // If hReturn is NULL, then there are no 
-        // sibling items, and we're on a leaf node. 
-        // Backtrack up the tree one level, and 
-        // we'll look for a sibling on the next 
-        // iteration (or we'll reach the root and 
-        // quit). 
-        hItem = this->GetParentItem(hItem); 
-    }
-    return hReturn;
-} 
+      SelectItem(m_hitemDrop);
+      retval = TRUE;
+    } else {
+      // drag failed or cancelled, revert to last selected
+      SelectItem(m_hitemDrag);
+    }
+  } else {
+    // from someone else!
+    // Now add it
+    CMyString DropGroup = CMyString(GetGroup(m_hitemDrop));
+    ProcessData((BYTE *)(pData + sizeof(gbl_classname) - 1 + 10), lBufLen, DropGroup);
+    SelectItem(m_hitemDrop);
+    retval = TRUE;
+  }
+
+  GetParent()->SetFocus();
+
+exit:
+  GlobalUnlock(hGlobal);
+
+  if (retval == TRUE)
+    ((DboxMain *)m_parent)->SetChanged(DboxMain::Data);
+
+  return retval;
+}
+
+void CTVTreeCtrl::CompleteMove()
+{
+  // If drag within instance - we have already done ths
+  if (m_uiReceivingSession == m_uiSendingSession)
+    return;
+
+  // If drag to another instance, ignore in Read-only mode
+  if (((DboxMain *)GetParent())->IsReadOnly())
+    return;
+
+  // After we have dragged successfully from our Tree to another Tree
+  ((DboxMain *)m_parent)->Delete();
+  ((DboxMain *)m_parent)->RefreshList();
+  return;
+}
+
+bool CTVTreeCtrl::CollectData(BYTE * &out_buffer, long &outLen)
+{
+  DWORD itemData = GetItemData(m_hitemDrag);
+  CItemData *ci = (CItemData *)itemData;
+
+  CDDObList out_oblist;
+
+  if (IsLeafNode(m_hitemDrag)) {
+    ASSERT(itemData != NULL);
+    m_nDragPathLen = 0;
+    GetEntryData(out_oblist, ci);
+    out_oblist.m_bDragNode = false;
+  } else {
+    m_nDragPathLen = GetGroup(GetParentItem(m_hitemDrag)).GetLength();
+    GetGroupEntriesData(out_oblist, m_hitemDrag);
+    out_oblist.m_bDragNode = true;
+  }
+
+  CSMemFile outDDmemfile;
+  CArchive ar_out (&outDDmemfile, CArchive::store);
+  out_oblist.Serialize(ar_out);
+  ar_out.Flush();
+  ar_out.Close();
+
+  DWORD dw_outmflen = (DWORD)outDDmemfile.GetLength();
+  unsigned char * outddmemfile_buffer = (unsigned char *)outDDmemfile.Detach();
+  EncryptSendingData(outddmemfile_buffer, dw_outmflen, out_buffer, outLen);
+
+  while (!out_oblist.IsEmpty()) {
+    delete (CDDObject *)out_oblist.RemoveHead();
+  } 
+
+  trashMemory(outddmemfile_buffer, dw_outmflen);
+  free(outddmemfile_buffer);
+
+  return (outLen > 0);
+}
+
+bool CTVTreeCtrl::ProcessData(BYTE *in_buffer, const long &inLen, const CMyString DropGroup)
+{
+  unsigned char * clear_buffer(NULL);
+  long clearLen(0);
+
+  DecryptReceivedData(in_buffer, inLen, clear_buffer, clearLen);
+
+  if (clearLen <= 0)
+    return false;
+
+  CDDObList in_oblist;
+
+  CSMemFile *pinDDmemfile;
+  pinDDmemfile = new CSMemFile;
+  pinDDmemfile->Attach((BYTE *)clear_buffer, clearLen);
+
+  CArchive ar_in (pinDDmemfile, CArchive::load);
+  in_oblist.Serialize(ar_in);
+  ar_in.Close();
+
+  pinDDmemfile->Detach();
+  trashMemory(clear_buffer, clearLen);
+  free(clear_buffer);
+  delete pinDDmemfile;
+
+  if (!in_oblist.IsEmpty()) {
+    ((DboxMain *)m_parent)->AddEntries(in_oblist, DropGroup);
+
+    while (!in_oblist.IsEmpty()) {
+      delete (CDDObject *)in_oblist.RemoveHead();
+    }
+  }
+
+  return (clearLen > 0);
+}
+
+void CTVTreeCtrl::DecryptReceivedData(BYTE * &in_buffer, const long &inLen,
+                                      unsigned char * &out_buffer, long &outLen)
+{
+  CSMemFile *pinMemFile;
+  CMyString passwd;
+
+  out_buffer = NULL;
+  outLen = 0;
+
+  // Create a memory file
+  pinMemFile = new CSMemFile;
+
+  // Point to data
+  pinMemFile->Attach((BYTE *)in_buffer, inLen, 0);
+
+  // Generate password from their classname and the CLIPFORMAT
+  passwd.Format(_T("%s%04x"), m_sending_classname, gbl_tcddCPFID);
+
+  // Decrypt it
+  DecryptMemory(out_buffer, outLen, passwd, pinMemFile);
+
+  pinMemFile->Detach();
+  delete pinMemFile;
+}
+
+void CTVTreeCtrl::EncryptSendingData(unsigned char * &in_buffer, const long &inLen,
+                                     BYTE * &out_buffer, long &outLen)
+{
+  CSMemFile *poutMemFile;
+  CMyString passwd;
+
+  // Create a memory file
+  poutMemFile = new CSMemFile;
+
+  // Generate password from our classname and the CLIPFORMAT
+  passwd.Format(_T("%s%04x"), gbl_classname, gbl_tcddCPFID);
+
+  // Encrypt it
+  EncryptMemory(in_buffer, inLen, passwd, poutMemFile);
+
+  outLen = (long)poutMemFile->GetLength();
+  if (outLen > 0) {
+    // Create buffer for clipboard
+    out_buffer = (BYTE *)poutMemFile->Detach();
+  }
+
+  delete poutMemFile;
+}
+
+void
+CTVTreeCtrl::GetGroupEntriesData(CDDObList &out_oblist, HTREEITEM hItem)
+{
+  if (IsLeafNode(hItem)) {
+    DWORD itemData = GetItemData(hItem);
+    ASSERT(itemData != NULL);
+    CItemData *ci = (CItemData *)itemData;
+    GetEntryData(out_oblist, ci);
+  } else {
+    HTREEITEM child;
+    for (child = GetChildItem(hItem);
+      child != NULL;
+      child = GetNextSiblingItem(child)) {
+      GetGroupEntriesData(out_oblist, child);
+    }
+  }
+}
+
+void
+CTVTreeCtrl::GetEntryData(CDDObList &out_oblist, CItemData *ci)
+{
+  CDDObject *pDDObject;
+
+  pDDObject = new CDDObject;
+
+  uuid_array_t uuid_array;
+  ci->GetUUID(uuid_array);
+
+  memcpy(pDDObject->m_DD_UUID, uuid_array, sizeof(uuid_array));
+
+  const CMyString cs_Group = ci->GetGroup();
+  if (out_oblist.m_bDragNode && m_nDragPathLen > 0)
+    pDDObject->m_DD_Group = cs_Group.Right(cs_Group.GetLength() - m_nDragPathLen - 1);
+  else
+    pDDObject->m_DD_Group = cs_Group;
+
+  pDDObject->m_DD_Title= ci->GetTitle();
+  pDDObject->m_DD_User= ci->GetUser();
+  pDDObject->m_DD_Notes = ci->GetNotes();
+  pDDObject->m_DD_Password = ci->GetPassword();
+  pDDObject->m_DD_URL = ci->GetURL();
+  pDDObject->m_DD_AutoType= ci->GetAutoType();
+  pDDObject->m_DD_PWHistory = ci->GetPWHistory();
+
+  ci->GetCTime(pDDObject->m_DD_CTime);
+  ci->GetPMTime(pDDObject->m_DD_PMTime);
+  ci->GetATime(pDDObject->m_DD_ATime);
+  ci->GetLTime(pDDObject->m_DD_LTime);
+  ci->GetRMTime(pDDObject->m_DD_RMTime);
+
+  out_oblist.AddTail(pDDObject);
+}
MyTreeCtrl.h to TVTreeCtrl.h
--- a/MyTreeCtrl.h
+++ b/TVTreeCtrl.h
@@ -1,82 +1,101 @@
-/*
- * Copyright (c) 2003-2007 Rony Shapiro <ronys@users.sourceforge.net>.
- * All rights reserved. Use of the code is allowed under the
- * Artistic License terms, as specified in the LICENSE file
- * distributed with this code, or available from
- * http://www.opensource.org/licenses/artistic-license.php
- */
-#pragma once
-
-/*
- * Silly subclass of CTreeCtrl just to implement Drag&Drop.
- *
- * Based on MFC sample code from CMNCTRL1
- */
-
-#include <Afxcmn.h>
-
-class CMyTreeCtrl : public CTreeCtrl
-{
-public:
-  CMyTreeCtrl();
-  ~CMyTreeCtrl();
-
-   // indices of bitmaps in ImageList
-  enum {NODE=0, LEAF=1, EXPIRED_LEAF = 2, WARNEXPIRED_LEAF = 3};
-
-  void DeleteWithParents(HTREEITEM hItem); // if a parent node becomes a leaf
-  void DeleteFromSet(HTREEITEM hItem);
-  CString GetGroup(HTREEITEM hItem); // get group path to hItem
-  HTREEITEM AddGroup(const CString &path);
-  bool IsLeafNode(HTREEITEM hItem);
-  void RestoreExpanded();
-  void ClearExpanded(); // use when items will be invalid
-  void OnCollapseAll();
-  void OnExpandAll();
-  void SetDboxPointer(void *parent) {m_parent = parent;}
-  HTREEITEM GetNextTreeItem(HTREEITEM hItem);
-
- protected:
-  //{{AFX_MSG(CMyTreeCtrl)
-  afx_msg void OnBeginLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult);
-  afx_msg void OnEndLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult);
-  afx_msg void OnExpandCollapse(NMHDR *pNotifyStruct, LRESULT *result);
-  afx_msg void OnBeginDrag(LPNMHDR pnmhdr, LRESULT *pLResult);
-  afx_msg void OnMouseMove(UINT nFlags, CPoint point);
-  afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
-  afx_msg void OnDestroy();
-  afx_msg void OnTimer(UINT nIDEvent);
-  //
-  //afx_msg void OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult);
-  //}}AFX_MSG
-
-  void EndDragging(BOOL bCancel);
-  BOOL PreTranslateMessage(MSG* pMsg);
-
-  DECLARE_MESSAGE_MAP()
-
-private:
-  bool        m_bDragging;
-  HTREEITEM   m_hitemDrag;
-  HTREEITEM   m_hitemDrop;
-  CImageList  *m_pimagelist;
-  void *m_parent;
-  void *m_expandedItems; // Internally this is a SetTreeItem_t, don't want to include stl file here...
-
-  bool m_isRestoring; // don't repopulate m_expandedItems in restore
-  
-  void SetNewStyle(long lStyleMask, BOOL bSetBits);
-  bool TransferItem(HTREEITEM hitem, HTREEITEM hNewParent);
-  bool IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent);
-  void UpdateLeafsGroup(HTREEITEM hItem, CString prefix);
-  void CollapseBranch(HTREEITEM hItem);
-  
-protected:
-	UINT    m_nTimerID;
-	UINT    m_timerticks;
-	UINT	m_nHoverTimerID;
-	POINT	m_HoverPoint;
-
-};
-
-
+/*
+ * Copyright (c) 2003-2007 Rony Shapiro <ronys@users.sourceforge.net>.
+ * All rights reserved. Use of the code is allowed under the
+ * Artistic License terms, as specified in the LICENSE file
+ * distributed with this code, or available from
+ * http://www.opensource.org/licenses/artistic-license.php
+ */
+#pragma once
+
+#include <Afxcmn.h>
+#include "DropTarget.h"
+#include "DropSource.h"
+#include "corelib/ItemData.h"
+#include "corelib/MyString.h"
+#include "DDSupport.h"
+
+class CTVTreeCtrl : public CTreeCtrl, public CDropTarget, public CDropSource
+{
+public:
+  CTVTreeCtrl();
+  ~CTVTreeCtrl();
+
+  BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject,
+    DROPEFFECT dropEffect, CPoint point);
+  DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject,
+    DWORD dwKeyState, CPoint point);
+  DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject,
+    DWORD dwKeyState, CPoint point);
+
+   void operator delete(void* p)
+        { CDropTarget::operator delete(p); }
+
+   // indices of bitmaps in ImageList
+  enum {NODE=0, LEAF=1, EXPIRED_LEAF = 2, WARNEXPIRED_LEAF = 3};
+  enum {REQUEST_INFO = 0, SEND_INFO = 1};
+
+  void DeleteWithParents(HTREEITEM hItem); // if a parent node becomes a leaf
+  void DeleteFromSet(HTREEITEM hItem);
+  CString GetGroup(HTREEITEM hItem); // get group path to hItem
+  HTREEITEM AddGroup(const CString &path);
+  bool IsLeafNode(HTREEITEM hItem);
+  void RestoreExpanded();
+  void ClearExpanded(); // use when items will be invalid
+  void OnCollapseAll();
+  void OnExpandAll();
+  void SetDboxPointer(void *parent) {m_parent = parent;}
+  void SetListPointer(CListCtrl *pList) {m_pctlItemList = pList;}
+  HTREEITEM GetNextTreeItem(HTREEITEM hItem);
+  void BeginLabelEdit(NMHDR *pNotifyStruct, LRESULT * &pLResult);
+  void EndLabelEdit(NMHDR *pNotifyStruct, LRESULT * &pLResult);
+  void ExpandCollapse(NMHDR *pNotifyStruct, LRESULT * &pLresult);
+
+ protected:
+  virtual void CompleteMove();
+
+  //{{AFX_MSG(CTVTreeCtrl)
+  afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+  afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
+  afx_msg void OnDestroy();
+  //}}AFX_MSG
+
+  BOOL PreTranslateMessage(MSG* pMsg);
+
+  DECLARE_MESSAGE_MAP()
+
+private:
+  CImageList *m_pimagelist;
+  void *m_parent;
+  void *m_expandedItems; // Internally this is a SetTreeItem_t, don't want to include stl file here...
+
+  bool m_isRestoring; // don't repopulate m_expandedItems in restore
+
+  void SetNewStyle(long lStyleMask, BOOL bSetBits);
+  bool TransferItem(HTREEITEM hitem, HTREEITEM hNewParent);
+  bool CopyItem(HTREEITEM hitem, HTREEITEM hNewParent);
+  bool IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent);
+  void UpdateLeafsGroup(HTREEITEM hItem, CString prefix);
+  void CollapseBranch(HTREEITEM hItem);
+  void GetGroupEntriesData(CDDObList &out_oblist, HTREEITEM hItem);
+  void GetEntryData(CDDObList &out_oblist, CItemData *ci);
+  bool CollectData(BYTE * &out_buffer, long &outLen);
+  bool ProcessData(BYTE *in_buffer, const long &inLen, const CMyString DropGroup);
+  void DecryptReceivedData(BYTE * &in_buffer, const long &inLen,
+                           unsigned char * &out_buffer, long &outLen);
+  void EncryptSendingData(unsigned char * &in_buffer, const long &inLen,
+                          BYTE * &out_buffer, long &outLen);
+  CDropSource m_TCDropSource;
+  CDropTarget m_TCDropTarget;
+  CImageList* m_pDragImage;
+  HTREEITEM m_iItem;
+
+protected:
+  CListCtrl *m_pctlItemList;
+  HTREEITEM m_hitemDrag;
+  HTREEITEM m_hitemDrop;
+  unsigned char m_sending_classname[40];
+  int m_nDragPathLen;
+  unsigned int  m_uiSendingSession;
+  unsigned int  m_uiReceivingSession;
+  int m_calls;
+};
1 2 > >> (Page 1 of 2)