Skip to content

Commit

Permalink
Copy file names from Windows dialog
Browse files Browse the repository at this point in the history
Ctrl+C copies selected path names.
Context menu allows to copy either name or path.

Fix notepad-plus-plus#10123
  • Loading branch information
mere-human committed Jul 19, 2021
1 parent ce07fff commit f792504
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 9 deletions.
2 changes: 2 additions & 0 deletions PowerEditor/installer/nativeLang/english.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,8 @@ You can re-activate this dialog in Preferences dialog later." /> <!-- HowToRepro
<ColumnType name="Type"/>
<ColumnSize name="Size"/>
<NbDocsTotal name="total documents:"/>
<MenuCopyName name="Copy Name(s)"/>
<MenuCopyPath name="Copy Pathname(s)"/>
</WindowsDlg>
<AsciiInsertion>
<PanelTitle name="ASCII Codes Insertion Panel"/>
Expand Down
111 changes: 102 additions & 9 deletions PowerEditor/src/WinControls/WindowsDlg/WindowsDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ using namespace std;
#define WD_CLMNTYPE "ColumnType"
#define WD_CLMNSIZE "ColumnSize"
#define WD_NBDOCSTOTAL "NbDocsTotal"
#define WD_MENUCOPYNAME "MenuCopyName"
#define WD_MENUCOPYPATH "MenuCopyPath"

static const TCHAR *readonlyString = TEXT(" [Read Only]");
const UINT WDN_NOTIFY = RegisterWindowMessage(TEXT("WDN_NOTIFY"));
Expand Down Expand Up @@ -313,6 +315,22 @@ INT_PTR CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lPa
doColumnSort();
break;
}

default:
if (HIWORD(wParam) == 0)
{
// Menu
switch (LOWORD(wParam))
{
case IDM_WINDOW_COPY_NAME:
putItemsToClipboard(false);
break;
case IDM_WINDOW_COPY_PATH:
putItemsToClipboard(true);
break;
}
}
break;
}
break;
}
Expand All @@ -335,14 +353,9 @@ INT_PTR CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lPa
if (pLvdi->item.mask & LVIF_TEXT)
{
pLvdi->item.pszText[0] = 0;
size_t index = pLvdi->item.iItem;
if (index >= _pTab->nbItem() || index >= _idxMap.size())
Buffer* buf = getBuffer(pLvdi->item.iItem);
if (!buf)
return FALSE;
index = _idxMap[index];

//const Buffer& buffer = _pView->getBufferAt(index);
BufferID bufID = _pTab->getBufferByIndex(index);
Buffer * buf = MainFileManager.getBufferByID(bufID);
generic_string text;
if (pLvdi->item.iSubItem == 0) // file name
{
Expand Down Expand Up @@ -426,20 +439,49 @@ INT_PTR CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lPa
else if (pNMHDR->code == LVN_KEYDOWN)
{
NMLVKEYDOWN *lvkd = (NMLVKEYDOWN *)pNMHDR;
// Ctrl+A
short ctrl = GetKeyState(VK_CONTROL);
short alt = GetKeyState(VK_MENU);
short shift = GetKeyState(VK_SHIFT);
if (lvkd->wVKey == 0x41/*a*/ && ctrl<0 && alt>=0 && shift>=0)
if (lvkd->wVKey == 'A' && ctrl<0 && alt>=0 && shift>=0)
{
// Ctrl + A
for (int i=0, n=ListView_GetItemCount(_hList); i<n; ++i)
ListView_SetItemState(_hList, i, LVIS_SELECTED, LVIS_SELECTED);
}
else if (lvkd->wVKey == 'C' && ctrl & 0x80)
{
// Ctrl + C
if (ListView_GetSelectedCount(_hList) != 0)
putItemsToClipboard(true);
}
return TRUE;
}
}
break;
}

case WM_CONTEXTMENU:
{
if (!_listMenu.isCreated())
{
NativeLangSpeaker* pNativeSpeaker = (NppParameters::getInstance()).getNativeLangSpeaker();
const std::vector<MenuItemUnit> itemUnitArray
{
{IDM_WINDOW_COPY_NAME, pNativeSpeaker->getAttrNameStr(TEXT("Copy Name(s)"), WD_ROOTNODE, WD_MENUCOPYNAME)},
{IDM_WINDOW_COPY_PATH, pNativeSpeaker->getAttrNameStr(TEXT("Copy Pathname(s)"), WD_ROOTNODE, WD_MENUCOPYPATH)}
};
_listMenu.create(_hSelf, itemUnitArray);
}

const bool enableMenu = ListView_GetSelectedCount(_hList) != 0;
_listMenu.enableItem(IDM_WINDOW_COPY_NAME, enableMenu);
_listMenu.enableItem(IDM_WINDOW_COPY_PATH, enableMenu);

POINT p = {};
::GetCursorPos(&p);
_listMenu.display(p);
}
return TRUE;
}
return MyBaseClass::run_dlgProc(message, wParam, lParam);
}
Expand Down Expand Up @@ -895,6 +937,57 @@ void WindowsDlg::doSortToTabs()
delete[] nmdlg.Items;
}

void WindowsDlg::putItemsToClipboard(bool isFullPath)
{
constexpr int nameColumn = 0;
constexpr int pathColumn = 1;

TCHAR str[MAX_PATH] = {};

generic_string selection;
for (int i = -1, j = 0; ; ++j)
{
i = ListView_GetNextItem(_hList, i, LVNI_SELECTED);
if (i < 0)
break;
if (isFullPath)
{
// Get the directory path (2nd column).
ListView_GetItemText(_hList, i, pathColumn, str, sizeof(str));
if (str[0])
selection += str;
}

// Get the file name.
// Do not use ListView_GetItemText() because 1st column may contain "*" or "[Read Only]".
Buffer* buf = getBuffer(i);
if (buf)
{
const TCHAR* fileName = buf->getFileName();
if (fileName)
selection += fileName;
}

if (!selection.empty() && selection.back() != '\n')
selection += '\n';
}
if (!selection.empty())
str2Clipboard(selection, _hList);
}

Buffer* WindowsDlg::getBuffer(int index) const
{
if (index < 0 || index >= _idxMap.size())
return nullptr;

index = _idxMap[index];
if (index < 0 || !_pTab || index >= _pTab->nbItem())
return nullptr;

BufferID bufID = _pTab->getBufferByIndex(index);
return MainFileManager.getBufferByID(bufID);
}

WindowsMenu::WindowsMenu()
{}

Expand Down
5 changes: 5 additions & 0 deletions PowerEditor/src/WinControls/WindowsDlg/WindowsDlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@

#include "SizeableDlg.h"
#include "Common.h"
#include "ContextMenu.h"

class DocTabView;
class Buffer;

typedef enum {
WDT_ACTIVATE = 1,
Expand Down Expand Up @@ -73,6 +75,8 @@ protected :
void activateCurrent();
void doColumnSort();
void doCount();
void putItemsToClipboard(bool isFullPath);
Buffer* getBuffer(int index) const;

HWND _hList = nullptr;
static RECT _lastKnownLocation;
Expand All @@ -83,6 +87,7 @@ protected :
int _currentColumn = -1;
int _lastSort = -1;
bool _reverseSort = false;
ContextMenu _listMenu;

private:
virtual void init(HINSTANCE hInst, HWND parent);
Expand Down
2 changes: 2 additions & 0 deletions PowerEditor/src/WinControls/WindowsDlg/WindowsDlgRc.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,6 @@
#define IDM_WINDOW_WINDOWS (IDR_WINDOWS_MENU + 1)
#define IDM_WINDOW_MRU_FIRST (IDR_WINDOWS_MENU + 20)
#define IDM_WINDOW_MRU_LIMIT (IDR_WINDOWS_MENU + 29)
#define IDM_WINDOW_COPY_NAME (IDM_WINDOW_MRU_LIMIT + 1)
#define IDM_WINDOW_COPY_PATH (IDM_WINDOW_MRU_LIMIT + 2)

0 comments on commit f792504

Please sign in to comment.