// WinMerge: an interactive diff/merge utility
// Copyright (C) 1997-2000 Thingamahoochie Software
// Author: Dean Grimm
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-//
+// SPDX-License-Identifier: GPL-2.0-or-later
/////////////////////////////////////////////////////////////////////////////
/**
* @file FilePathEdit.cpp
*
* @brief Implementation of the CFilepathEdit class.
*/
-// ID line follows -- this is updated by SVN
-// $Id: FilepathEdit.cpp 6500 2009-02-25 13:36:26Z kimmov $
#include "stdafx.h"
+#include "FilepathEdit.h"
#include "Merge.h"
#include "BCMenu.h"
-#include "FilepathEdit.h"
#include "ClipBoard.h"
#include "Shlwapi.h"
#include "paths.h"
-#include <algorithm>
#ifdef _DEBUG
#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
#endif
-static int FormatFilePathForDisplayWidth(CDC * pDC, int maxWidth, CString & sFilepath);
+static int FormatFilePathForDisplayWidth(CDC * pDC, int maxWidth, String & sFilepath);
BEGIN_MESSAGE_MAP(CFilepathEdit, CEdit)
ON_WM_CONTEXTMENU()
ON_WM_CTLCOLOR_REFLECT()
+ ON_WM_NCPAINT()
+ ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
END_MESSAGE_MAP()
* - out: formatted string
* @return Number of lines path is splitted to.
*/
-int FormatFilePathForDisplayWidth(CDC * pDC, int maxWidth, String & sFilepath)
+static int FormatFilePathForDisplayWidth(CDC * pDC, int maxWidth, String & sFilepath)
{
- int iBegin = 0;
+ size_t iBegin = 0;
int nLines = 1;
- while (1)
+ while (true)
{
String line;
// find the next truncation point
- int iEndMin = 0;
- int iEndMax = sFilepath.length() - iBegin + 1;
+ size_t iEndMin = 0;
+ size_t iEndMax = sFilepath.length() - iBegin + 1;
while(1)
{
- int iEnd = (iEndMin + iEndMax) / 2;
+ size_t iEnd = (iEndMin + iEndMax) / 2;
if (iEnd == iEndMin)
break;
line = sFilepath.substr(iBegin, iEnd);
// truncate the text to the previous "\" if possible
line = sFilepath.substr(iBegin, iEndMin);
- int lastSlash = line.rfind('\\');
+ size_t lastSlash = line.rfind('\\');
if (lastSlash != String::npos)
iEndMin = lastSlash + 1;
CFilepathEdit::CFilepathEdit()
: m_crBackGnd(RGB(255, 255, 255))
, m_crText(RGB(0,0,0))
- , m_bActive(FALSE)
+ , m_bActive(false)
{
}
* @brief Subclass the control.
* @param [in] nID ID of the control to subclass.
* @param [in] pParent Parent control of the control to subclass.
- * @return TRUE if succeeded, FALSE otherwise.
+ * @return `true` if succeeded, `false` otherwise.
*/
-BOOL CFilepathEdit::SubClassEdit(UINT nID, CWnd* pParent)
+bool CFilepathEdit::SubClassEdit(UINT nID, CWnd* pParent)
{
- m_bActive = FALSE;
+ m_bActive = false;
return SubclassDlgItem(nID, pParent);
};
/**
- * @brief Return the control's original text.
- * @return Control's original text.
- */
-void CFilepathEdit::GetOriginalText(String& rString) const
-{
- rString = m_sOriginalText;
-}
-
-/**
* @brief Set the text to show in the control.
* This function sets the text (original text) to show in the control.
* The control may modify the text for displaying in the GUI.
CRect rect;
GetRect(rect);
// take GetBuffer (lenght +3) to count for ellipsis
- std::vector<TCHAR> tmp(line.length() + 3);
+ std::vector<TCHAR> tmp(line.length() + 4);
std::copy(line.begin(), line.end(), tmp.begin());
PathCompactPath(lDC.GetSafeHdc(), &tmp[0], rect.Width());
line = &tmp[0];
*
* @note The standard Copy function works with the (compacted) windowText
*/
-void CFilepathEdit::CustomCopy(int iBegin, int iEnd /*=-1*/)
+void CFilepathEdit::CustomCopy(size_t iBegin, size_t iEnd /*=-1*/)
{
- if (iEnd == -1)
+ if (iEnd == String::npos)
iEnd = m_sOriginalText.length();
PutToClipboard(m_sOriginalText.substr(iBegin, iEnd - iBegin), m_hWnd);
VERIFY(menu.LoadMenu(IDR_POPUP_EDITOR_HEADERBAR));
theApp.TranslateMenu(menu.m_hMenu);
- BCMenu* pPopup = (BCMenu *) menu.GetSubMenu(0);
- ASSERT(pPopup != NULL);
+ BCMenu* pPopup = static_cast<BCMenu *>(menu.GetSubMenu(0));
+ ASSERT(pPopup != nullptr);
- if (paths_EndsWithSlash(m_sOriginalText))
+ DWORD sel = GetSel();
+ if (HIWORD(sel) == LOWORD(sel))
+ pPopup->EnableMenuItem(ID_EDITOR_COPY, MF_GRAYED);
+ if (paths::EndsWithSlash(m_sOriginalText))
// no filename, we have to disable the unwanted menu entry
pPopup->EnableMenuItem(ID_EDITOR_COPY_FILENAME, MF_GRAYED);
// and handle the command after TrackPopupMenu
int command = pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON |
TPM_NONOTIFY | TPM_RETURNCMD, point.x, point.y, AfxGetMainWnd());
- if (command != ID_EDITOR_COPY_FILENAME && command != ID_EDITOR_COPY_PATH)
- return;
// compute the beginning of the text to copy (in OriginalText)
- int iBegin = 0;
+ size_t iBegin = 0;
switch (command)
{
+ case ID_EDITOR_COPY:
+ Copy();
+ return;
case ID_EDITOR_COPY_FILENAME:
{
size_t lastSlash = m_sOriginalText.rfind('\\');
else
iBegin = 0;
break;
+ default:
+ return;
}
CustomCopy(iBegin);
}
}
+static COLORREF GetDarkenColor(COLORREF a, double r)
+{
+ const int R = static_cast<int>(GetRValue(a) * r);
+ const int G = static_cast<int>(GetGValue(a) * r);
+ const int B = static_cast<int>(GetBValue(a) * r);
+ return RGB(R, G, B);
+}
+
+void CFilepathEdit::OnNcPaint()
+{
+ CWindowDC dc(this);
+ CRect rect;
+ const int margin = 4;
+ GetWindowRect(rect);
+ rect.OffsetRect(-rect.TopLeft());
+ dc.FillSolidRect(CRect(rect.left, rect.top, rect.left + margin, rect.bottom), GetDarkenColor(m_crBackGnd, 0.98));
+ dc.FillSolidRect(CRect(rect.left, rect.top, rect.left + 1, rect.bottom), GetDarkenColor(m_crBackGnd, 0.96));
+ dc.FillSolidRect(CRect(rect.right - margin, rect.top, rect.right, rect.bottom), m_crBackGnd);
+ dc.FillSolidRect(CRect(rect.left + 1, rect.top, rect.right, rect.top + margin), GetDarkenColor(m_crBackGnd, 0.98));
+ dc.FillSolidRect(CRect(rect.left, rect.top, rect.right, rect.top + 1), GetDarkenColor(m_crBackGnd, 0.96));
+ dc.FillSolidRect(CRect(rect.left + margin, rect.bottom - margin, rect.right, rect.bottom), m_crBackGnd);
+}
+
+void CFilepathEdit::OnEditCopy()
+{
+ int nStartChar, nEndChar;
+ GetSel(nStartChar, nEndChar);
+ if (nStartChar == nEndChar)
+ SetSel(0, -1);
+ Copy();
+ if (nStartChar == nEndChar)
+ SetSel(nStartChar, nEndChar);
+}
+
+BOOL CFilepathEdit::PreTranslateMessage(MSG *pMsg)
+{
+ if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
+ {
+ if (::TranslateAccelerator (m_hWnd, static_cast<CFrameWnd *>(AfxGetMainWnd())->GetDefaultAccelerator(), pMsg))
+ return TRUE;
+ }
+ return CEdit::PreTranslateMessage(pMsg);
+}
+
/**
* @brief Set the control to look active/inactive.
* This function sets control to look like an active control. We don't
* have real focus on this control, but editor pane below it. However
* for user this active look informs which editor pane is active.
- * @param [in] bActive If TRUE set control look like active control.
+ * @param [in] bActive If `true` set control look like active control.
*/
void CFilepathEdit::SetActive(bool bActive)
{
m_bActive = bActive;
- if (m_hWnd == NULL)
+ if (m_hWnd == nullptr)
return;
CRect rcWnd;
SetTextColor(::GetSysColor(COLOR_INACTIVECAPTIONTEXT));
SetBackColor(::GetSysColor(COLOR_INACTIVECAPTION));
}
+ RedrawWindow(nullptr, nullptr, RDW_FRAME | RDW_INVALIDATE);
}
/**
HBRUSH CFilepathEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
UNUSED_ALWAYS(nCtlColor);
- // Return a non-NULL brush if the parent's
+ // Return a non-`nullptr` brush if the parent's
//handler should not be called
//set text color