<commit_before>/*
* Copyright (c) 2003-2016 <NAME> <<EMAIL>>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

#include "stdafx.h"
#include "PWTreeCtrl.h"
#include "DboxMain.h"
#include "ThisMfcApp.h"
#include "DDSupport.h"
#include "SecString.h"
#include "SMemFile.h"
#include "GeneralMsgBox.h"

#include "core/ItemData.h"
#include "core/Util.h"
#include "core/Pwsprefs.h"

#include "os/debug.h"

#include <algorithm>

using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Hover time of 1.5 seconds before expanding a group during D&D
#define HOVERTIME 1500

extern const wchar_t GROUP_SEP = L'.';
extern const wchar_t *GROUP_SEP2 = L".";

// following header for D&D data passed over OLE:
// Process ID of sender (to determine if src == tgt)
// Type of data
// Length of actual payload, in bytes.
static const char *OLE_HDR_FMT = "%08x%02x%08x";
static const int OLE_HDR_LEN = 18;

/*
* Following classes are used to "Fake" multiple inheritance:
* Ideally, CPWTreeCtrl should derive from CTreeCtrl, COleDropTarget
* and COleDropSource. However, since m'soft, in their infinite
* wisdom, couldn't get this common use-case straight,
* we use the following classes as proxies: CPWTreeCtrl
* has a member var for each, registers said member appropriately
* for D&D, and member calls parent's method to do the grunt work.
*/

class CPWTDropTarget : public COleDropTarget
{
public:
  CPWTDropTarget(CPWTreeCtrl *parent) : m_tree(*parent) {}

  DROPEFFECT OnDragEnter(CWnd* pWnd , COleDataObject* pDataObject,
                         DWORD dwKeyState, CPoint point)
  {return m_tree.OnDragEnter(pWnd, pDataObject, dwKeyState, point);}

  DROPEFFECT OnDragOver(CWnd* pWnd , COleDataObject* pDataObject,
                        DWORD dwKeyState, CPoint point)
  {return m_tree.OnDragOver(pWnd, pDataObject, dwKeyState, point);}

  void OnDragLeave(CWnd*)
  {m_tree.OnDragLeave();}

  BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject,
              DROPEFFECT dropEffect, CPoint point)
  {return m_tree.OnDrop(pWnd, pDataObject, dropEffect, point);}

private:
  CPWTreeCtrl &m_tree;
};

class CPWTDropSource : public COleDropSource
{
public:
  CPWTDropSource(CPWTreeCtrl *parent) : m_tree(*parent) {}

  virtual SCODE QueryContinueDrag(BOOL bEscapePressed, DWORD dwKeyState)
  {
    // To prevent processing in multiple calls to CStaticDataSource::OnRenderGlobalData
    //  Only process the request if data has been dropped.
    SCODE sCode = COleDropSource::QueryContinueDrag(bEscapePressed, dwKeyState);
    if (sCode == DRAGDROP_S_DROP) {
      m_tree.EndDrop();
    }
    return sCode;
  }

  virtual SCODE GiveFeedback(DROPEFFECT dropEffect)
  {return m_tree.GiveFeedback(dropEffect);}

private:
  CPWTreeCtrl &m_tree;
};

class CPWTDataSource : public COleDataSource
{
public:
  CPWTDataSource(CPWTreeCtrl *parent, COleDropSource *ds)
    : m_tree(*parent), m_DropSource(ds) {}

  DROPEFFECT StartDragging(CLIPFORMAT cpfmt, LPCRECT rClient)
  {
    DelayRenderData(cpfmt);
    DelayRenderData(CF_UNICODETEXT);
    DelayRenderData(CF_TEXT);

    m_tree.m_cfdropped = 0;
    DROPEFFECT de = DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE,
                               rClient, m_DropSource);
    // Cleanup:
    // Standard processing is for the recipient to do this!!!
    if (de == DROPEFFECT_NONE) {
      if (m_tree.m_hgDataALL != NULL) {
        LPVOID lpData = GlobalLock(m_tree.m_hgDataALL);
        SIZE_T memsize = GlobalSize(m_tree.m_hgDataALL);
        if (lpData != NULL && memsize > 0) {
          trashMemory(lpData, memsize);
        }
        GlobalUnlock(m_tree.m_hgDataALL);
        GlobalFree(m_tree.m_hgDataALL);
        m_tree.m_hgDataALL = NULL;
      }
      if (m_tree.m_hgDataTXT != NULL) {
        LPVOID lpData = GlobalLock(m_tree.m_hgDataTXT);
        SIZE_T memsize = GlobalSize(m_tree.m_hgDataTXT);
        if (lpData != NULL && memsize > 0) {
          trashMemory(lpData, memsize);
        }
        GlobalUnlock(m_tree.m_hgDataTXT);
        GlobalFree(m_tree.m_hgDataTXT);
        m_tree.m_hgDataTXT = NULL;
      }
      if (m_tree.m_hgDataUTXT != NULL) {
        LPVOID lpData = GlobalLock(m_tree.m_hgDataUTXT);
        SIZE_T memsize = GlobalSize(m_tree.m_hgDataUTXT);
        if (lpData != NULL && memsize > 0) {
          trashMemory(lpData, memsize);
        }
        GlobalUnlock(m_tree.m_hgDataUTXT);
        GlobalFree(m_tree.m_hgDataUTXT);
        m_tree.m_hgDataUTXT = NULL;
      }
    }
    return de;
  }

  virtual BOOL OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
  {return m_tree.OnRenderGlobalData(lpFormatEtc, phGlobal);}

private:
  CPWTreeCtrl &m_tree;
  COleDropSource *m_DropSource;
};

/**
* Implementation of CPWTreeCtrl begins here
*/

CPWTreeCtrl::CPWTreeCtrl()
  : m_isRestoring(false), m_bWithinThisInstance(true),
  m_bMouseInWindow(false), m_nHoverNDTimerID(0), m_nShowNDTimerID(0),
  m_hgDataALL(NULL), m_hgDataTXT(NULL), m_hgDataUTXT(NULL),
  m_bFilterActive(false), m_bUseHighLighting(false)
{
  // Register a clipboard format for column drag & drop.
  // Note that it's OK to register same format more than once:
  // "If a registered format with the specified name already exists,
  // a new format is not registered and the return value identifies the existing format."

  CString cs_CPF(MAKEINTRESOURCE(IDS_CPF_TVDD));
  m_tcddCPFID = (CLIPFORMAT)RegisterClipboardFormat(cs_CPF);
  ASSERT(m_tcddCPFID != 0);

  // instantiate "proxy" objects for D&D.
  // The members are currently pointers mainly to hide
  // their implementation from the header file. If this changes,
  // e.g., if we make them nested classes, then they should
  // be non-pointers.
  m_DropTarget = new CPWTDropTarget(this);
  m_DropSource = new CPWTDropSource(this);
  m_DataSource = new CPWTDataSource(this, m_DropSource);
}

CPWTreeCtrl::~CPWTreeCtrl()
{
  // see comment in constructor re these member variables
  delete m_DropTarget;
  delete m_DropSource;
  delete m_DataSource;
}

BEGIN_MESSAGE_MAP(CPWTreeCtrl, CTreeCtrl)
  //{{AFX_MSG_MAP(CPWTreeCtrl)
  ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginLabelEdit)
  ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndLabelEdit)
  ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
  ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, OnBeginDrag)
  ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnExpandCollapse)
  ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelectionChanged)
  ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteItem)
  ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)<commit_msg>Fix bizarre error in the internals of MFC D&D<commit_after>/*
* Copyright (c) 2003-2016 <NAME> <<EMAIL>>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

#include "stdafx.h"
#include "PWTreeCtrl.h"
#include "DboxMain.h"
#include "ThisMfcApp.h"
#include "DDSupport.h"
#include "SecString.h"
#include "SMemFile.h"
#include "GeneralMsgBox.h"

#include "core/ItemData.h"
#include "core/Util.h"
#include "core/Pwsprefs.h"

#include "os/debug.h"

#include <algorithm>

using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Hover time of 1.5 seconds before expanding a group during D&D
#define HOVERTIME 1500

extern const wchar_t GROUP_SEP = L'.';
extern const wchar_t *GROUP_SEP2 = L".";

// following header for D&D data passed over OLE:
// Process ID of sender (to determine if src == tgt)
// Type of data
// Length of actual payload, in bytes.
static const char *OLE_HDR_FMT = "%08x%02x%08x";
static const int OLE_HDR_LEN = 18;

/*
* Following classes are used to "Fake" multiple inheritance:
* Ideally, CPWTreeCtrl should derive from CTreeCtrl, COleDropTarget
* and COleDropSource. However, since m'soft, in their infinite
* wisdom, couldn't get this common use-case straight,
* we use the following classes as proxies: CPWTreeCtrl
* has a member var for each, registers said member appropriately
* for D&D, and member calls parent's method to do the grunt work.
*/

class CPWTDropTarget : public COleDropTarget
{
public:
  CPWTDropTarget(CPWTreeCtrl *parent) : m_tree(*parent) {}

  DROPEFFECT OnDragEnter(CWnd* pWnd , COleDataObject* pDataObject,
                         DWORD dwKeyState, CPoint point)
  {return m_tree.OnDragEnter(pWnd, pDataObject, dwKeyState, point);}

  DROPEFFECT OnDragOver(CWnd* pWnd , COleDataObject* pDataObject,
                        DWORD dwKeyState, CPoint point)
  {return m_tree.OnDragOver(pWnd, pDataObject, dwKeyState, point);}

  void OnDragLeave(CWnd*)
  {m_tree.OnDragLeave();}

  BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject,
              DROPEFFECT dropEffect, CPoint point)
  {return m_tree.OnDrop(pWnd, pDataObject, dropEffect, point);}

private:
  CPWTreeCtrl &m_tree;
};

class CPWTDropSource : public COleDropSource
{
public:
  CPWTDropSource(CPWTreeCtrl *parent) : m_tree(*parent) {}

  virtual SCODE QueryContinueDrag(BOOL bEscapePressed, DWORD dwKeyState)
  {
    // To prevent processing in multiple calls to CStaticDataSource::OnRenderGlobalData
    //  Only process the request if data has been dropped.
    SCODE sCode = COleDropSource::QueryContinueDrag(bEscapePressed, dwKeyState);
    if (sCode == DRAGDROP_S_DROP) {
      m_tree.EndDrop();
    }
    return sCode;
  }

  virtual SCODE GiveFeedback(DROPEFFECT dropEffect)
  {return m_tree.GiveFeedback(dropEffect);}

private:
  CPWTreeCtrl &m_tree;
};

class CPWTDataSource : public COleDataSource
{
public:
  CPWTDataSource(CPWTreeCtrl *parent, COleDropSource *ds)
    : m_tree(*parent), m_DropSource(ds) {}

  DROPEFFECT StartDragging(CLIPFORMAT cpfmt, LPCRECT rClient)
  {
    DelayRenderData(cpfmt);
    DelayRenderData(CF_UNICODETEXT);
    DelayRenderData(CF_TEXT);

    m_tree.m_cfdropped = 0;
    DROPEFFECT de = DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE,
                               rClient, m_DropSource);
    // Cleanup:
    // Standard processing is for the recipient to do this!!!
    if (de == DROPEFFECT_NONE) {
      if (m_tree.m_hgDataALL != NULL) {
        LPVOID lpData = GlobalLock(m_tree.m_hgDataALL);
        SIZE_T memsize = GlobalSize(m_tree.m_hgDataALL);
        if (lpData != NULL && memsize > 0) {
          trashMemory(lpData, memsize);
        }
        GlobalUnlock(m_tree.m_hgDataALL);
        GlobalFree(m_tree.m_hgDataALL);
        m_tree.m_hgDataALL = NULL;
      }
      if (m_tree.m_hgDataTXT != NULL) {
        LPVOID lpData = GlobalLock(m_tree.m_hgDataTXT);
        SIZE_T memsize = GlobalSize(m_tree.m_hgDataTXT);
        if (lpData != NULL && memsize > 0) {
          trashMemory(lpData, memsize);
        }
        GlobalUnlock(m_tree.m_hgDataTXT);
        GlobalFree(m_tree.m_hgDataTXT);
        m_tree.m_hgDataTXT = NULL;
      }
      if (m_tree.m_hgDataUTXT != NULL) {
        LPVOID lpData = GlobalLock(m_tree.m_hgDataUTXT);
        SIZE_T memsize = GlobalSize(m_tree.m_hgDataUTXT);
        if (lpData != NULL && memsize > 0) {
          trashMemory(lpData, memsize);
        }
        GlobalUnlock(m_tree.m_hgDataUTXT);
        GlobalFree(m_tree.m_hgDataUTXT);
        m_tree.m_hgDataUTXT = NULL;
      }
    }
    return de;
  }

  virtual BOOL OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
  {return m_tree.OnRenderGlobalData(lpFormatEtc, phGlobal);}

private:
  CPWTreeCtrl &m_tree;
  COleDropSource *m_DropSource;
};

/**
* Implementation of CPWTreeCtrl begins here
*/

CPWTreeCtrl::CPWTreeCtrl()
  : m_isRestoring(false), m_bWithinThisInstance(true),
  m_bMouseInWindow(false), m_nHoverNDTimerID(0), m_nShowNDTimerID(0),
  m_hgDataALL(NULL), m_hgDataTXT(NULL), m_hgDataUTXT(NULL),
  m_bFilterActive(false), m_bUseHighLighting(false)
{
  // Register a clipboard format for column drag & drop.
  // Note that it's OK to register same format more than once:
  // "If a registered format with the specified name already exists,
  // a new format is not registered and the return value identifies the existing format."

  CString cs_CPF(MAKEINTRESOURCE(IDS_CPF_TVDD));
  m_tcddCPFID = (CLIPFORMAT)RegisterClipboardFormat(cs_CPF);
  ASSERT(m_tcddCPFID != 0);

  // Instantiate "proxy" objects for D&D.

  // The members are currently pointers mainly to hide
  // their implementation from the header file. If this changes,
  // e.g., if we make them nested classes, then they should
  // be non-pointers.
  m_DropTarget = new CPWTDropTarget(this);
  m_DropSource = new CPWTDropSource(this);
  m_DataSource = new CPWTDataSource(this, m_DropSource);
}

CPWTreeCtrl::~CPWTreeCtrl()
{
  // See comment in constructor re these member variables

  // Don't delete m_Data Source but first release all references and
  // this routine will delete it when the references get to 0.
  m_DataSource->ExternalRelease();

  // delete the Drop Target & Source
  delete m_DropTarget;
  delete m_DropSource;
}

BEGIN_MESSAGE_MAP(CPWTreeCtrl, CTreeCtrl)
  //{{AFX_MSG_MAP(CPWTreeCtrl)
  ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginLabelEdit)
  ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndLabelEdit)
  ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
  ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, OnBeginDrag)
  ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnExpandCollapse)
  ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelectionChanged)
  ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteItem)
  ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
{'fraction_non_alphanumeric': 0.09680258140217073, 'fraction_numerical': 0.005060134936931651, 'mean_word_length': 3.971563981042654, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1757782', 'n_tokens_mistral': 4939, 'n_tokens_neox': 4741, 'n_words': 1154}