Don HO 64d7535be1 x64 ready
1. Remove all warning while compiling in x64
2. Treat warning as error (W4) while compiling in x64
2016-06-05 20:30:22 +02:00

1550 lines
46 KiB
C++

// This file is part of Notepad++ project
// Copyright (C)2003 Don HO <don.h@free.fr>
//
// 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.
//
// Note that the GPL places important restrictions on "derived works", yet
// it does not provide a detailed definition of that term. To avoid
// misunderstandings, we consider an application to constitute a
// "derivative work" for the purpose of this license if it does any of the
// following:
// 1. Integrates source code from Notepad++.
// 2. Integrates/includes/aggregates Notepad++ into a proprietary executable
// installer, such as those produced by InstallShield.
// 3. Links to a library or executes a program that does any of the above.
//
// 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.
#include "fileBrowser.h"
#include "resource.h"
#include "tinyxml.h"
#include "FileDialog.h"
#include "localization.h"
#include "Parameters.h"
#include "RunDlg.h"
#include "ReadDirectoryChanges.h"
#include "menuCmdID.h"
#define CX_BITMAP 16
#define CY_BITMAP 16
#define INDEX_OPEN_ROOT 0
#define INDEX_CLOSE_ROOT 1
#define INDEX_OPEN_NODE 2
#define INDEX_CLOSE_NODE 3
#define INDEX_LEAF 4
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
#define FB_ADDFILE (WM_USER + 1024)
#define FB_RMFILE (WM_USER + 1025)
#define FB_RNFILE (WM_USER + 1026)
FileBrowser::~FileBrowser()
{
for (size_t i = 0; i < _folderUpdaters.size(); ++i)
{
_folderUpdaters[i]->stopWatcher();
delete _folderUpdaters[i];
}
}
vector<generic_string> split(const generic_string & string2split, TCHAR sep)
{
vector<generic_string> splitedStrings;
size_t len = string2split.length();
size_t beginPos = 0;
for (size_t i = 0; i < len + 1; ++i)
{
if (string2split[i] == sep || string2split[i] == '\0')
{
splitedStrings.push_back(string2split.substr(beginPos, i - beginPos));
beginPos = i + 1;
}
}
return splitedStrings;
};
INT_PTR CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG :
{
FileBrowser::initPopupMenus();
_treeView.init(_hInst, _hSelf, ID_FILEBROWSERTREEVIEW);
setImageList(IDI_FB_ROOTOPEN, IDI_FB_ROOTCLOSE, IDI_PROJECT_FOLDEROPEN, IDI_PROJECT_FOLDERCLOSE, IDI_PROJECT_FILE);
_treeView.addCanNotDropInList(INDEX_OPEN_ROOT);
_treeView.addCanNotDropInList(INDEX_CLOSE_ROOT);
_treeView.addCanNotDropInList(INDEX_OPEN_NODE);
_treeView.addCanNotDropInList(INDEX_CLOSE_NODE);
_treeView.addCanNotDropInList(INDEX_LEAF);
_treeView.addCanNotDragOutList(INDEX_OPEN_ROOT);
_treeView.addCanNotDragOutList(INDEX_CLOSE_ROOT);
_treeView.addCanNotDragOutList(INDEX_OPEN_NODE);
_treeView.addCanNotDragOutList(INDEX_CLOSE_NODE);
_treeView.addCanNotDragOutList(INDEX_LEAF);
_treeView.makeLabelEditable(false);
_treeView.display();
return TRUE;
}
case WM_MOUSEMOVE:
if (_treeView.isDragging())
_treeView.dragItem(_hSelf, LOWORD(lParam), HIWORD(lParam));
break;
case WM_LBUTTONUP:
if (_treeView.isDragging())
if (_treeView.dropItem())
{
}
break;
case WM_NOTIFY:
{
notified((LPNMHDR)lParam);
}
return TRUE;
case WM_SIZE:
{
int width = LOWORD(lParam);
int height = HIWORD(lParam);
HWND hwnd = _treeView.getHSelf();
if (hwnd)
::MoveWindow(hwnd, 0, 0, width, height, TRUE);
break;
}
case WM_CONTEXTMENU:
if (!_treeView.isDragging())
showContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return TRUE;
case WM_COMMAND:
{
popupMenuCmd(LOWORD(wParam));
break;
}
case WM_DESTROY:
{
_treeView.destroy();
destroyMenus();
break;
}
case FB_ADDFILE:
{
const std::vector<generic_string> file2Change = *(std::vector<generic_string> *)lParam;
generic_string separator = TEXT("\\\\");
size_t sepPos = file2Change[0].find(separator);
if (sepPos == generic_string::npos)
return false;
generic_string pathSuffix = file2Change[0].substr(sepPos + separator.length(), file2Change[0].length() - 1);
// remove prefix of file/folder in changeInfo, splite the remained path
vector<generic_string> linarPathArray = split(pathSuffix, '\\');
generic_string rootPath = file2Change[0].substr(0, sepPos);
generic_string path = rootPath;
generic_string addedFilePath = file2Change[0].substr(0, sepPos + 1);
addedFilePath += pathSuffix;
bool isAdded = addInTree(rootPath, addedFilePath, nullptr, linarPathArray);
if (not isAdded)
{
//MessageBox(NULL, addedFilePath.c_str(), TEXT("file/folder is not added"), MB_OK);
}
break;
}
case FB_RMFILE:
{
const std::vector<generic_string> file2Change = *(std::vector<generic_string> *)lParam;
generic_string separator = TEXT("\\\\");
size_t sepPos = file2Change[0].find(separator);
if (sepPos == generic_string::npos)
return false;
generic_string pathSuffix = file2Change[0].substr(sepPos + separator.length(), file2Change[0].length() - 1);
// remove prefix of file/folder in changeInfo, splite the remained path
vector<generic_string> linarPathArray = split(pathSuffix, '\\');
generic_string rootPath = file2Change[0].substr(0, sepPos);
// search recursively and modify the tree structure
bool isRemoved = deleteFromTree(rootPath, nullptr, linarPathArray);
if (not isRemoved)
{
//MessageBox(NULL, file2Change[0].c_str(), TEXT("file/folder is not removed"), MB_OK);
}
break;
}
case FB_RNFILE:
{
const std::vector<generic_string> file2Change = *(std::vector<generic_string> *)lParam;
generic_string separator = TEXT("\\\\");
size_t sepPos = file2Change[0].find(separator);
if (sepPos == generic_string::npos)
return false;
generic_string pathSuffix = file2Change[0].substr(sepPos + separator.length(), file2Change[0].length() - 1);
// remove prefix of file/folder in changeInfo, splite the remained path
vector<generic_string> linarPathArray = split(pathSuffix, '\\');
generic_string rootPath = file2Change[0].substr(0, sepPos);
size_t sepPos2 = file2Change[1].find(separator);
if (sepPos2 == generic_string::npos)
return false;
generic_string pathSuffix2 = file2Change[1].substr(sepPos2 + separator.length(), file2Change[1].length() - 1);
vector<generic_string> linarPathArray2 = split(pathSuffix2, '\\');
bool isRenamed = renameInTree(rootPath, nullptr, linarPathArray, linarPathArray2[linarPathArray2.size() - 1]);
if (not isRenamed)
{
//MessageBox(NULL, file2Change[0].c_str(), TEXT("file/folder is not removed"), MB_OK);
}
break;
}
default :
return DockingDlgInterface::run_dlgProc(message, wParam, lParam);
}
return DockingDlgInterface::run_dlgProc(message, wParam, lParam);
}
void FileBrowser::initPopupMenus()
{
//NativeLangSpeaker *pNativeSpeaker = (NppParameters::getInstance())->getNativeLangSpeaker();
/*
generic_string removeFolderFromFileBrowser = pNativeSpeaker->getProjectPanelLangMenuStr("FileBrowserContextMenu", IDM_FILEBROWSER_REMOVEROOTFOLDER, FB_REMOVEROOT);
generic_string edit_rename = pNativeSpeaker->getProjectPanelLangMenuStr("ProjectMenu", IDM_FILEBROWSER_RENAME, PM_EDITRENAME);
generic_string edit_addfolder = pNativeSpeaker->getProjectPanelLangMenuStr("ProjectMenu", IDM_FILEBROWSER_NEWFOLDER, PM_EDITNEWFOLDER);
generic_string edit_addfiles = pNativeSpeaker->getProjectPanelLangMenuStr("ProjectMenu", IDM_FILEBROWSER_ADDFILES, PM_EDITADDFILES);
edit_rename = pNativeSpeaker->getProjectPanelLangMenuStr("FolderMenu", IDM_FILEBROWSER_RENAME, PM_EDITRENAME);
edit_addfolder = pNativeSpeaker->getProjectPanelLangMenuStr("FolderMenu", IDM_FILEBROWSER_NEWFOLDER, PM_EDITNEWFOLDER);
edit_addfiles = pNativeSpeaker->getProjectPanelLangMenuStr("FolderMenu", IDM_FILEBROWSER_ADDFILES, PM_EDITADDFILES);
edit_remove = pNativeSpeaker->getProjectPanelLangMenuStr("FolderMenu", IDM_FILEBROWSER_DELETEFOLDER, PM_EDITREMOVE);
*/
_hGlobalMenu = ::CreatePopupMenu();
::InsertMenu(_hGlobalMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_ADDROOT, TEXT("Add"));
::InsertMenu(_hGlobalMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_REMOVEALLROOTS, TEXT("Remove All"));
_hRootMenu = ::CreatePopupMenu();
::InsertMenu(_hRootMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_REMOVEROOTFOLDER, TEXT("Remove"));
::InsertMenu(_hRootMenu, 0, MF_BYCOMMAND, (UINT)-1, 0);
::InsertMenu(_hRootMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_COPYEPATH, TEXT("Copy path"));
::InsertMenu(_hRootMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_FINDINFILES, TEXT("Find in Files..."));
::InsertMenu(_hRootMenu, 0, MF_BYCOMMAND, (UINT)-1, 0);
::InsertMenu(_hRootMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_EXPLORERHERE, TEXT("Explorer here"));
::InsertMenu(_hRootMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_CMDHERE, TEXT("CMD here"));
_hFolderMenu = ::CreatePopupMenu();
::InsertMenu(_hFolderMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_COPYEPATH, TEXT("Copy path"));
::InsertMenu(_hFolderMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_FINDINFILES, TEXT("Find in Files..."));
::InsertMenu(_hFolderMenu, 0, MF_BYCOMMAND, (UINT)-1, 0);
::InsertMenu(_hFolderMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_EXPLORERHERE, TEXT("Explorer here"));
::InsertMenu(_hFolderMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_CMDHERE, TEXT("CMD here"));
//::InsertMenu(_hFolderMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_NEWFOLDER, edit_addfolder.c_str());
//::InsertMenu(_hFolderMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_ADDFILES, edit_addfiles.c_str());
_hFileMenu = ::CreatePopupMenu();
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_OPENINNPP, TEXT("Open"));
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, (UINT)-1, 0);
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_COPYEPATH, TEXT("Copy path"));
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_SHELLEXECUTE, TEXT("Run by system"));
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, (UINT)-1, 0);
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_EXPLORERHERE, TEXT("Explorer here"));
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_CMDHERE, TEXT("CMD here"));
//::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_DELETEFILE, edit_remove.c_str());
//::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_MODIFYFILEPATH, edit_modifyfile.c_str());
}
BOOL FileBrowser::setImageList(int root_clean_id, int root_dirty_id, int open_node_id, int closed_node_id, int leaf_id)
{
HBITMAP hbmp;
COLORREF maskColour = RGB(192, 192, 192);
const int nbBitmaps = 5;
// Creation of image list
if ((_hImaLst = ImageList_Create(CX_BITMAP, CY_BITMAP, ILC_COLOR32 | ILC_MASK, nbBitmaps, 0)) == NULL)
return FALSE;
// Add the bmp in the list
hbmp = LoadBitmap(_hInst, MAKEINTRESOURCE(root_clean_id));
if (hbmp == NULL)
return FALSE;
ImageList_AddMasked(_hImaLst, hbmp, maskColour);
DeleteObject(hbmp);
hbmp = LoadBitmap(_hInst, MAKEINTRESOURCE(root_dirty_id));
if (hbmp == NULL)
return FALSE;
ImageList_AddMasked(_hImaLst, hbmp, maskColour);
DeleteObject(hbmp);
hbmp = LoadBitmap(_hInst, MAKEINTRESOURCE(open_node_id));
if (hbmp == NULL)
return FALSE;
ImageList_AddMasked(_hImaLst, hbmp, maskColour);
DeleteObject(hbmp);
hbmp = LoadBitmap(_hInst, MAKEINTRESOURCE(closed_node_id));
if (hbmp == NULL)
return FALSE;
ImageList_AddMasked(_hImaLst, hbmp, maskColour);
DeleteObject(hbmp);
hbmp = LoadBitmap(_hInst, MAKEINTRESOURCE(leaf_id));
if (hbmp == NULL)
return FALSE;
ImageList_AddMasked(_hImaLst, hbmp, maskColour);
DeleteObject(hbmp);
if (ImageList_GetImageCount(_hImaLst) < nbBitmaps)
return FALSE;
// Set image list to the tree view
TreeView_SetImageList(_treeView.getHSelf(), _hImaLst, TVSIL_NORMAL);
return TRUE;
}
void FileBrowser::destroyMenus()
{
::DestroyMenu(_hGlobalMenu);
::DestroyMenu(_hRootMenu);
::DestroyMenu(_hFolderMenu);
::DestroyMenu(_hFileMenu);
}
generic_string FileBrowser::getNodePath(HTREEITEM node) const
{
if (not node) return TEXT("");
vector<generic_string> fullPathArray;
generic_string fullPath;
// go up until to root, then get the full path
HTREEITEM parent = node;
for (; parent != nullptr;)
{
generic_string folderName = _treeView.getItemDisplayName(parent);
HTREEITEM temp = _treeView.getParent(parent);
if (temp == nullptr)
{
LPARAM param = _treeView.getItemParam(parent);
folderName = (param == 0) ? TEXT("") : *((generic_string *)param);
}
parent = temp;
fullPathArray.push_back(folderName);
}
for (int i = int(fullPathArray.size()) - 1; i >= 0; --i)
{
fullPath += fullPathArray[i];
if (i != 0)
fullPath += TEXT("\\");
}
return fullPath;
}
void FileBrowser::openSelectFile()
{
// Get the selected item
HTREEITEM selectedNode = _treeView.getSelection();
if (not selectedNode) return;
generic_string fullPath = getNodePath(selectedNode);
// test the path - if it's a file, open it, otherwise just fold or unfold it
if (not ::PathFileExists(fullPath.c_str()))
return;
if (::PathIsDirectory(fullPath.c_str()))
return;
::SendMessage(_hParent, NPPM_DOOPEN, 0, (LPARAM)(fullPath.c_str()));
}
void FileBrowser::notified(LPNMHDR notification)
{
if (notification->code == DMN_CLOSE)
{
::SendMessage(_hParent, WM_COMMAND, IDM_VIEW_FILEBROWSER, 0);
}
else if ((notification->hwndFrom == _treeView.getHSelf()))
{
TCHAR textBuffer[MAX_PATH];
TVITEM tvItem;
tvItem.mask = TVIF_TEXT | TVIF_PARAM;
tvItem.pszText = textBuffer;
tvItem.cchTextMax = MAX_PATH;
switch (notification->code)
{
case NM_DBLCLK:
{
openSelectFile();
}
break;
case TVN_ENDLABELEDIT:
{
LPNMTVDISPINFO tvnotif = (LPNMTVDISPINFO)notification;
if (!tvnotif->item.pszText)
return;
if (getNodeType(tvnotif->item.hItem) == browserNodeType_root)
return;
// Processing for only File case
if (tvnotif->item.lParam)
{
// Get the old label
tvItem.hItem = _treeView.getSelection();
::SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0,(LPARAM)&tvItem);
size_t len = lstrlen(tvItem.pszText);
// Find the position of old label in File path
generic_string *filePath = (generic_string *)tvnotif->item.lParam;
size_t found = filePath->rfind(tvItem.pszText);
// If found the old label, replace it with the modified one
if (found != generic_string::npos)
filePath->replace(found, len, tvnotif->item.pszText);
// Check the validity of modified file path
tvItem.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
if (::PathFileExists(filePath->c_str()))
{
tvItem.iImage = INDEX_LEAF;
tvItem.iSelectedImage = INDEX_LEAF;
}
else
{
//TODO: remove it
}
TreeView_SetItem(_treeView.getHSelf(), &tvItem);
}
// For File, Folder and Project
::SendMessage(_treeView.getHSelf(), TVM_SETITEM, 0,(LPARAM)(&(tvnotif->item)));
}
break;
case TVN_GETINFOTIP:
{
LPNMTVGETINFOTIP lpGetInfoTip = (LPNMTVGETINFOTIP)notification;
static generic_string tipStr;
BrowserNodeType nType = getNodeType(lpGetInfoTip->hItem);
if (nType == browserNodeType_root)
{
tipStr = *((generic_string *)lpGetInfoTip->lParam);
}
else if (nType == browserNodeType_file)
{
tipStr = getNodePath(lpGetInfoTip->hItem);
}
else
return;
lpGetInfoTip->pszText = (LPTSTR)tipStr.c_str();
lpGetInfoTip->cchTextMax = static_cast<int>(tipStr.size());
}
break;
case TVN_KEYDOWN:
{
LPNMTVKEYDOWN ptvkd = (LPNMTVKEYDOWN)notification;
if (ptvkd->wVKey == VK_RETURN)
{
HTREEITEM hItem = _treeView.getSelection();
BrowserNodeType nType = getNodeType(hItem);
if (nType == browserNodeType_file)
openSelectFile();
else
_treeView.toggleExpandCollapse(hItem);
}
/*
else if (ptvkd->wVKey == VK_DELETE)
{
HTREEITEM hItem = _treeView.getSelection();
BrowserNodeType nType = getNodeType(hItem);
if (nType == browserNodeType_folder)
popupMenuCmd(IDM_FILEBROWSER_DELETEFOLDER);
else if (nType == browserNodeType_file)
popupMenuCmd(IDM_FILEBROWSER_DELETEFILE);
}
else if (ptvkd->wVKey == VK_UP)
{
if (0x80 & GetKeyState(VK_CONTROL))
{
popupMenuCmd(IDM_FILEBROWSER_MOVEUP);
}
}
else if (ptvkd->wVKey == VK_DOWN)
{
if (0x80 & GetKeyState(VK_CONTROL))
{
popupMenuCmd(IDM_FILEBROWSER_MOVEDOWN);
}
}
else if (ptvkd->wVKey == VK_F2)
popupMenuCmd(IDM_FILEBROWSER_RENAME);
*/
}
break;
case TVN_ITEMEXPANDED:
{
LPNMTREEVIEW nmtv = (LPNMTREEVIEW)notification;
tvItem.hItem = nmtv->itemNew.hItem;
tvItem.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
if (getNodeType(nmtv->itemNew.hItem) == browserNodeType_folder)
{
if (nmtv->action == TVE_COLLAPSE)
{
_treeView.setItemImage(nmtv->itemNew.hItem, INDEX_CLOSE_NODE, INDEX_CLOSE_NODE);
}
else if (nmtv->action == TVE_EXPAND)
{
_treeView.setItemImage(nmtv->itemNew.hItem, INDEX_OPEN_NODE, INDEX_OPEN_NODE);
}
}
else if (getNodeType(nmtv->itemNew.hItem) == browserNodeType_root)
{
if (nmtv->action == TVE_COLLAPSE)
{
_treeView.setItemImage(nmtv->itemNew.hItem, INDEX_CLOSE_ROOT, INDEX_CLOSE_ROOT);
}
else if (nmtv->action == TVE_EXPAND)
{
_treeView.setItemImage(nmtv->itemNew.hItem, INDEX_OPEN_ROOT, INDEX_OPEN_ROOT);
}
}
}
break;
case TVN_BEGINDRAG:
{
//printStr(TEXT("hello"));
_treeView.beginDrag((LPNMTREEVIEW)notification);
}
break;
}
}
}
BrowserNodeType FileBrowser::getNodeType(HTREEITEM hItem)
{
TVITEM tvItem;
tvItem.hItem = hItem;
tvItem.mask = TVIF_IMAGE | TVIF_PARAM;
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0,(LPARAM)&tvItem);
// File
if (tvItem.iImage == INDEX_LEAF)
{
return browserNodeType_file;
}
// Root
else if (tvItem.lParam != NULL)
{
return browserNodeType_root;
}
// Folder
else
{
return browserNodeType_folder;
}
}
void FileBrowser::showContextMenu(int x, int y)
{
TVHITTESTINFO tvHitInfo;
HTREEITEM hTreeItem;
// Detect if the given position is on the element TVITEM
tvHitInfo.pt.x = x;
tvHitInfo.pt.y = y;
tvHitInfo.flags = 0;
ScreenToClient(_treeView.getHSelf(), &(tvHitInfo.pt));
hTreeItem = TreeView_HitTest(_treeView.getHSelf(), &tvHitInfo);
if (tvHitInfo.hItem == nullptr)
{
TrackPopupMenu(_hGlobalMenu, TPM_LEFTALIGN, x, y, 0, _hSelf, NULL);
}
else
{
// Make item selected
_treeView.selectItem(tvHitInfo.hItem);
// get clicked item type
BrowserNodeType nodeType = getNodeType(tvHitInfo.hItem);
HMENU hMenu = NULL;
if (nodeType == browserNodeType_root)
hMenu = _hRootMenu;
else if (nodeType == browserNodeType_folder)
hMenu = _hFolderMenu;
else //nodeType_file
hMenu = _hFileMenu;
TrackPopupMenu(hMenu, TPM_LEFTALIGN, x, y, 0, _hSelf, NULL);
}
}
void FileBrowser::popupMenuCmd(int cmdID)
{
// get selected item handle
HTREEITEM selectedNode = _treeView.getSelection();
switch (cmdID)
{
//
// Toolbar menu commands
//
case IDM_FILEBROWSER_REMOVEROOTFOLDER:
{
if (not selectedNode) return;
generic_string *rootPath = (generic_string *)_treeView.getItemParam(selectedNode);
if (_treeView.getParent(selectedNode) != nullptr || rootPath == nullptr)
return;
size_t nbFolderUpdaters = _folderUpdaters.size();
for (size_t i = 0; i < nbFolderUpdaters; ++i)
{
if (_folderUpdaters[i]->_rootFolder._rootPath == *rootPath)
{
_folderUpdaters[i]->stopWatcher();
_folderUpdaters.erase(_folderUpdaters.begin() + i);
_treeView.removeItem(selectedNode);
break;
}
}
}
break;
case IDM_FILEBROWSER_EXPLORERHERE:
{
if (not selectedNode) return;
generic_string path = getNodePath(selectedNode);
if (::PathFileExists(path.c_str()))
{
TCHAR cmdStr[1024];
wsprintf(cmdStr, TEXT("explorer /select,%s"), path.c_str());
Command cmd(cmdStr);
cmd.run(nullptr);
}
}
break;
case IDM_FILEBROWSER_CMDHERE:
{
if (not selectedNode) return;
if (getNodeType(selectedNode) == browserNodeType_file)
selectedNode = _treeView.getParent(selectedNode);
generic_string path = getNodePath(selectedNode);
if (::PathFileExists(path.c_str()))
{
TCHAR cmdStr[1024];
wsprintf(cmdStr, TEXT("cmd /K cd /d %s"), path.c_str());
Command cmd(cmdStr);
cmd.run(nullptr);
}
}
break;
case IDM_FILEBROWSER_COPYEPATH:
{
if (not selectedNode) return;
generic_string path = getNodePath(selectedNode);
str2Clipboard(path, _hParent);
}
break;
case IDM_FILEBROWSER_FINDINFILES:
{
if (not selectedNode) return;
generic_string path = getNodePath(selectedNode);
::SendMessage(_hParent, NPPM_LAUNCHFINDINFILESDLG, (WPARAM)path.c_str(), 0);
}
break;
case IDM_FILEBROWSER_OPENINNPP:
{
openSelectFile();
}
break;
case IDM_FILEBROWSER_REMOVEALLROOTS:
{
for (int i = (int)_folderUpdaters.size() - 1; i >= 0; --i)
{
_folderUpdaters[i]->stopWatcher();
HTREEITEM root = getRootFromFullPath(_folderUpdaters[i]->_rootFolder._rootPath);
if (root)
_treeView.removeItem(root);
_folderUpdaters.erase(_folderUpdaters.begin() + i);
}
}
break;
case IDM_FILEBROWSER_ADDROOT:
{
generic_string folderPath = folderBrowser(_hParent, TEXT("Select a folder to add in Folder as Workspace panel"));
if (not folderPath.empty())
{
addRootFolder(folderPath);
}
}
break;
case IDM_FILEBROWSER_SHELLEXECUTE:
{
if (not selectedNode) return;
generic_string path = getNodePath(selectedNode);
if (::PathFileExists(path.c_str()))
::ShellExecute(NULL, TEXT("open"), path.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
break;
/*
case IDM_FILEBROWSER_RENAME :
TreeView_EditLabel(_treeView.getHSelf(), hTreeItem);
break;
case IDM_FILEBROWSER_DELETEFOLDER :
{
HTREEITEM parent = _treeView.getParent(hTreeItem);
if (_treeView.getChildFrom(hTreeItem) != NULL)
{
TCHAR str2display[MAX_PATH] = TEXT("All the sub-items will be removed.\rAre you sure you want to remove this folder from the project?");
if (::MessageBox(_hSelf, str2display, TEXT("Remove folder from project"), MB_YESNO) == IDYES)
{
_treeView.removeItem(hTreeItem);
//_folderUpdaters[0].stopWatcher();
}
}
else
{
_treeView.removeItem(hTreeItem);
}
if (getNodeType(parent) == browserNodeType_folder)
_treeView.setItemImage(parent, INDEX_CLOSED_NODE, INDEX_CLOSED_NODE);
}
break;
case IDM_FILEBROWSER_DELETEFILE :
{
HTREEITEM parent = _treeView.getParent(hTreeItem);
TCHAR str2display[MAX_PATH] = TEXT("Are you sure you want to remove this file from the project?");
if (::MessageBox(_hSelf, str2display, TEXT("Remove file from project"), MB_YESNO) == IDYES)
{
_treeView.removeItem(hTreeItem);
if (getNodeType(parent) == browserNodeType_folder)
_treeView.setItemImage(parent, INDEX_CLOSED_NODE, INDEX_CLOSED_NODE);
}
}
break;
*/
}
}
void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<generic_string> & patterns, FolderInfo & directoryStructure, bool isRecursive, bool isInHiddenDir)
{
if (directoryStructure._parent == nullptr) // Root!
directoryStructure.setRootPath(dir);
generic_string dirFilter(dir);
if (dirFilter[dirFilter.length() - 1] != '\\')
dirFilter += TEXT("\\");
dirFilter += TEXT("*.*");
WIN32_FIND_DATA foundData;
HANDLE hFile = ::FindFirstFile(dirFilter.c_str(), &foundData);
if (hFile != INVALID_HANDLE_VALUE)
{
if (foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (!isInHiddenDir && (foundData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
{
// do nothing
}
else if (isRecursive)
{
if ((lstrcmp(foundData.cFileName, TEXT("."))) && (lstrcmp(foundData.cFileName, TEXT(".."))))
{
generic_string pathDir(dir);
if (pathDir[pathDir.length() - 1] != '\\')
pathDir += TEXT("\\");
pathDir += foundData.cFileName;
pathDir += TEXT("\\");
FolderInfo subDirectoryStructure(foundData.cFileName, &directoryStructure);
getDirectoryStructure(pathDir.c_str(), patterns, subDirectoryStructure, isRecursive, isInHiddenDir);
directoryStructure.addSubFolder(subDirectoryStructure);
}
}
}
else
{
if (matchInList(foundData.cFileName, patterns))
{
directoryStructure.addFile(foundData.cFileName);
}
}
}
while (::FindNextFile(hFile, &foundData))
{
if (foundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (!isInHiddenDir && (foundData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
{
// do nothing
}
else if (isRecursive)
{
if ((lstrcmp(foundData.cFileName, TEXT("."))) && (lstrcmp(foundData.cFileName, TEXT(".."))))
{
generic_string pathDir(dir);
if (pathDir[pathDir.length() - 1] != '\\')
pathDir += TEXT("\\");
pathDir += foundData.cFileName;
pathDir += TEXT("\\");
FolderInfo subDirectoryStructure(foundData.cFileName, &directoryStructure);
getDirectoryStructure(pathDir.c_str(), patterns, subDirectoryStructure, isRecursive, isInHiddenDir);
directoryStructure.addSubFolder(subDirectoryStructure);
}
}
}
else
{
if (matchInList(foundData.cFileName, patterns))
{
directoryStructure.addFile(foundData.cFileName);
}
}
}
::FindClose(hFile);
}
bool isRelatedRootFolder(const generic_string & relatedRoot, const generic_string & subFolder)
{
if (relatedRoot.empty())
return false;
if (subFolder.empty())
return false;
size_t pos = subFolder.find(relatedRoot);
if (pos != 0) // pos == 0 is the necessary condition, but not enough
return false;
vector<generic_string> relatedRootArray = split(relatedRoot, '\\');
vector<generic_string> subFolderArray = split(subFolder, '\\');
size_t index2Compare = relatedRootArray.size() - 1;
return relatedRootArray[index2Compare] == subFolderArray[index2Compare];
}
void FileBrowser::addRootFolder(generic_string rootFolderPath)
{
if (not ::PathFileExists(rootFolderPath.c_str()))
return;
// make sure there's no '\' at the end
if (rootFolderPath[rootFolderPath.length() - 1] == '\\')
{
rootFolderPath = rootFolderPath.substr(0, rootFolderPath.length() - 1);
}
size_t nbFolderUpdaters = _folderUpdaters.size();
for (size_t i = 0; i < nbFolderUpdaters; ++i)
{
if (_folderUpdaters[i]->_rootFolder._rootPath == rootFolderPath)
return;
else
{
if (isRelatedRootFolder(_folderUpdaters[i]->_rootFolder._rootPath, rootFolderPath))
{
//do nothing, go down to select the dir
generic_string rootPath = _folderUpdaters[i]->_rootFolder._rootPath;
generic_string pathSuffix = rootFolderPath.substr(rootPath.size() + 1, rootFolderPath.size() - rootPath.size());
vector<generic_string> linarPathArray = split(pathSuffix, '\\');
HTREEITEM foundItem = findInTree(rootPath, nullptr, linarPathArray);
if (foundItem)
_treeView.selectItem(foundItem);
return;
}
if (isRelatedRootFolder(rootFolderPath, _folderUpdaters[i]->_rootFolder._rootPath))
{
::MessageBox(_hParent, TEXT("A sub-folder of the folder you want to open exists.\rPlease remove it from the panel before you add this one."), rootFolderPath.c_str(), MB_OK);
return;
}
}
}
std::vector<generic_string> patterns2Match;
patterns2Match.push_back(TEXT("*.*"));
TCHAR *label = ::PathFindFileName(rootFolderPath.c_str());
TCHAR rootLabel[MAX_PATH];
lstrcpy(rootLabel, label);
size_t len = lstrlen(rootLabel);
if (rootLabel[len - 1] == '\\')
rootLabel[len - 1] = '\0';
FolderInfo directoryStructure(rootLabel, nullptr);
getDirectoryStructure(rootFolderPath.c_str(), patterns2Match, directoryStructure, true, false);
HTREEITEM hRootItem = createFolderItemsFromDirStruct(nullptr, directoryStructure);
_treeView.expand(hRootItem);
_folderUpdaters.push_back(new FolderUpdater(directoryStructure, this));
_folderUpdaters[_folderUpdaters.size() - 1]->startWatcher();
}
HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, const FolderInfo & directoryStructure)
{
HTREEITEM hFolderItem = nullptr;
if (directoryStructure._parent == nullptr && hParentItem == nullptr)
{
TCHAR rootPath[MAX_PATH];
lstrcpy(rootPath, directoryStructure._rootPath.c_str());
size_t len = lstrlen(rootPath);
if (rootPath[len - 1] == '\\')
rootPath[len - 1] = '\0';
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), TVI_ROOT, INDEX_CLOSE_ROOT, rootPath);
}
else
{
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), hParentItem, INDEX_CLOSE_NODE);
}
for (size_t i = 0; i < directoryStructure._subFolders.size(); ++i)
{
createFolderItemsFromDirStruct(hFolderItem, directoryStructure._subFolders[i]);
}
for (size_t i = 0; i < directoryStructure._files.size(); ++i)
{
_treeView.addItem(directoryStructure._files[i]._name.c_str(), hFolderItem, INDEX_LEAF);
}
_treeView.fold(hParentItem);
return hFolderItem;
}
HTREEITEM FileBrowser::getRootFromFullPath(const generic_string & rootPath) const
{
HTREEITEM node = nullptr;
for (HTREEITEM hItemNode = _treeView.getRoot();
hItemNode != nullptr && node == nullptr;
hItemNode = _treeView.getNextSibling(hItemNode))
{
TVITEM tvItem;
tvItem.mask = TVIF_PARAM;
tvItem.cchTextMax = MAX_PATH;
tvItem.hItem = hItemNode;
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
if (tvItem.lParam != 0 && rootPath == *((generic_string *)tvItem.lParam))
node = hItemNode;
}
return node;
}
HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, generic_string label)
{
HTREEITEM childNodeFound = nullptr;
for (HTREEITEM hItemNode = _treeView.getChildFrom(parent);
hItemNode != NULL && childNodeFound == nullptr;
hItemNode = _treeView.getNextSibling(hItemNode))
{
TCHAR textBuffer[MAX_PATH];
TVITEM tvItem;
tvItem.mask = TVIF_TEXT;
tvItem.pszText = textBuffer;
tvItem.cchTextMax = MAX_PATH;
tvItem.hItem = hItemNode;
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
if (label == tvItem.pszText)
{
childNodeFound = hItemNode;
}
}
return childNodeFound;
}
vector<generic_string> FileBrowser::getRoots() const
{
vector<generic_string> roots;
HTREEITEM node = nullptr;
for (HTREEITEM hItemNode = _treeView.getRoot();
hItemNode != nullptr && node == nullptr;
hItemNode = _treeView.getNextSibling(hItemNode))
{
TVITEM tvItem;
tvItem.mask = TVIF_PARAM;
tvItem.cchTextMax = MAX_PATH;
tvItem.hItem = hItemNode;
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
roots.push_back(*((generic_string *)tvItem.lParam));
}
return roots;
}
generic_string FileBrowser::getSelectedItemPath() const
{
generic_string itemPath;
HTREEITEM hItemNode = _treeView.getSelection();
if (hItemNode)
{
itemPath = getNodePath(hItemNode);
}
return itemPath;
}
bool FileBrowser::addInTree(generic_string rootPath, generic_string addItemFullPath, HTREEITEM node, vector<generic_string> linarPathArray)
{
if (node == nullptr) // it's a root. Search the right root with rootPath
{
// Search
if ((node = getRootFromFullPath(rootPath)) == nullptr)
return false;
}
if (linarPathArray.size() == 1)
{
// Of course item to add should be exist on the disk
if (not::PathFileExists(addItemFullPath.c_str()))
return false;
// Search : if no found, add
HTREEITEM childNodeFound = findChildNodeFromName(node, linarPathArray[0]);
if (childNodeFound != nullptr)
return false;
// No found, good - Action
if (::PathIsDirectory(addItemFullPath.c_str()))
{
_treeView.addItem(linarPathArray[0].c_str(), node, INDEX_CLOSE_NODE);
}
else
{
_treeView.addItem(linarPathArray[0].c_str(), node, INDEX_LEAF);
}
return true;
}
else
{
HTREEITEM childNodeFound = nullptr;
for (HTREEITEM hItemNode = _treeView.getChildFrom(node);
hItemNode != NULL && childNodeFound == nullptr;
hItemNode = _treeView.getNextSibling(hItemNode))
{
TCHAR textBuffer[MAX_PATH];
TVITEM tvItem;
tvItem.mask = TVIF_TEXT;
tvItem.pszText = textBuffer;
tvItem.cchTextMax = MAX_PATH;
tvItem.hItem = hItemNode;
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
if (linarPathArray[0] == tvItem.pszText)
{
// search recursively the node for an action
linarPathArray.erase(linarPathArray.begin());
return addInTree(rootPath, addItemFullPath, hItemNode, linarPathArray);
}
}
return false;
}
}
HTREEITEM FileBrowser::findInTree(generic_string rootPath, HTREEITEM node, std::vector<generic_string> linarPathArray)
{
if (node == nullptr) // it's a root. Search the right root with rootPath
{
// Search
if ((node = getRootFromFullPath(rootPath)) == nullptr)
return nullptr;
}
if (linarPathArray.size() == 1)
{
// Search
return findChildNodeFromName(node, linarPathArray[0]);
}
else
{
HTREEITEM childNodeFound = nullptr;
for (HTREEITEM hItemNode = _treeView.getChildFrom(node);
hItemNode != NULL && childNodeFound == nullptr;
hItemNode = _treeView.getNextSibling(hItemNode))
{
TCHAR textBuffer[MAX_PATH];
TVITEM tvItem;
tvItem.mask = TVIF_TEXT;
tvItem.pszText = textBuffer;
tvItem.cchTextMax = MAX_PATH;
tvItem.hItem = hItemNode;
SendMessage(_treeView.getHSelf(), TVM_GETITEM, 0, (LPARAM)&tvItem);
if (linarPathArray[0] == tvItem.pszText)
{
// search recursively the node for an action
linarPathArray.erase(linarPathArray.begin());
return findInTree(rootPath, hItemNode, linarPathArray);
}
}
return nullptr;
}
}
bool FileBrowser::deleteFromTree(generic_string rootPath, HTREEITEM node, std::vector<generic_string> linarPathArray)
{
HTREEITEM foundItem = findInTree(rootPath, node, linarPathArray);
if (foundItem == nullptr)
return false;
// found it, delete it
_treeView.removeItem(foundItem);
return true;
}
bool FileBrowser::renameInTree(generic_string rootPath, HTREEITEM node, std::vector<generic_string> linarPathArrayFrom, const generic_string & renameTo)
{
HTREEITEM foundItem = findInTree(rootPath, node, linarPathArrayFrom);
if (foundItem == nullptr)
return false;
// found it, rename it
_treeView.renameItem(foundItem, renameTo.c_str());
return true;
}
bool FolderInfo::addToStructure(generic_string & fullpath, std::vector<generic_string> linarPathArray)
{
if (linarPathArray.size() == 1) // could be file or folder
{
fullpath += TEXT("\\");
fullpath += linarPathArray[0];
if (PathIsDirectory(fullpath.c_str()))
{
// search in folders, if found - no good
size_t nbFolder = _subFolders.size();
for (size_t i = 0; i < nbFolder; ++i)
{
if (linarPathArray[0] == _subFolders[i].getName())
return false; // Maybe already added?
}
_subFolders.push_back(FolderInfo(linarPathArray[0], this));
return true;
}
else
{
// search in files, if found - no good
size_t nbFile = _files.size();
for (size_t i = 0; i < nbFile; ++i)
{
if (linarPathArray[0] == _files[i].getName())
return false; // Maybe already added?
}
_files.push_back(FileInfo(linarPathArray[0], this));
return true;
}
}
else // folder
{
size_t nbFolder = _subFolders.size();
for (size_t i = 0; i < nbFolder; ++i)
{
if (_subFolders[i].getName() == linarPathArray[0])
{
fullpath += TEXT("\\");
fullpath += linarPathArray[0];
linarPathArray.erase(linarPathArray.begin());
return _subFolders[i].addToStructure(fullpath, linarPathArray);
}
}
return false;
}
}
bool FolderInfo::removeFromStructure(std::vector<generic_string> linarPathArray)
{
if (linarPathArray.size() == 1) // could be file or folder
{
for (size_t i = 0; i < _files.size(); ++i)
{
if (_files[i].getName() == linarPathArray[0])
{
// remove this file
_files.erase(_files.begin() + i);
return true;
}
}
for (size_t i = 0; i < _subFolders.size(); ++i)
{
if (_subFolders[i].getName() == linarPathArray[0])
{
// remove this folder
_subFolders.erase(_subFolders.begin() + i);
return true;
}
}
}
else // folder
{
for (size_t i = 0; i < _subFolders.size(); ++i)
{
if (_subFolders[i].getName() == linarPathArray[0])
{
linarPathArray.erase(linarPathArray.begin());
return _subFolders[i].removeFromStructure(linarPathArray);
}
}
}
return false;
}
bool FolderInfo::renameInStructure(std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo)
{
if (linarPathArrayFrom.size() == 1) // could be file or folder
{
for (size_t i = 0; i < _files.size(); ++i)
{
if (_files[i].getName() == linarPathArrayFrom[0])
{
// rename this file
_files[i].setName(linarPathArrayTo[0]);
return true;
}
}
for (size_t i = 0; i < _subFolders.size(); ++i)
{
if (_subFolders[i].getName() == linarPathArrayFrom[0])
{
// rename this folder
_subFolders[i].setName(linarPathArrayTo[0]);
return true;
}
}
return false;
}
else // folder
{
for (size_t i = 0; i < _subFolders.size(); ++i)
{
if (_subFolders[i].getName() == linarPathArrayFrom[0])
{
linarPathArrayFrom.erase(linarPathArrayFrom.begin());
linarPathArrayTo.erase(linarPathArrayTo.begin());
return _subFolders[i].renameInStructure(linarPathArrayFrom, linarPathArrayTo);
}
}
return false;
}
}
void FolderUpdater::startWatcher()
{
// no thread yet, create a event with non-signaled, to block all threads
_EventHandle = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
_watchThreadHandle = ::CreateThread(NULL, 0, watching, this, 0, NULL);
}
void FolderUpdater::stopWatcher()
{
::SetEvent(_EventHandle);
::CloseHandle(_watchThreadHandle);
::CloseHandle(_EventHandle);
}
LPCWSTR explainAction(DWORD dwAction)
{
switch (dwAction)
{
case FILE_ACTION_ADDED:
return L"Added";
case FILE_ACTION_REMOVED:
return L"Deleted";
case FILE_ACTION_MODIFIED:
return L"Modified";
case FILE_ACTION_RENAMED_OLD_NAME:
return L"Renamed From";
case FILE_ACTION_RENAMED_NEW_NAME:
return L"Renamed ";
default:
return L"BAD DATA";
}
};
/*
bool FolderUpdater::updateTree(DWORD action, const std::vector<generic_string> & file2Change)
{
// TCHAR msg2show[1024];
// switch (action)
// {
// case FILE_ACTION_ADDED:
// swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str());
// printStr(msg2show);
//::PostMessage(thisFolderUpdater->_hFileBrowser, FB_ADDFILE, nullptr, (LPARAM)wstrFilename.GetString());
// break;
// case FILE_ACTION_REMOVED:
// swprintf(msg2show, L"%s %s\n", explainAction(action), file2Change[0].c_str());
// printStr(msg2show);
// break;
// case FILE_ACTION_RENAMED_NEW_NAME:
// swprintf(msg2show, L"%s from %s \rto %s", explainAction(action), file2Change[0].c_str(), file2Change[1].c_str());
// printStr(msg2show);
// break;
// default:
// break;
// }
generic_string separator = TEXT("\\\\");
size_t sepPos = file2Change[0].find(separator);
if (sepPos == generic_string::npos)
return false;
generic_string pathSuffix = file2Change[0].substr(sepPos + separator.length(), file2Change[0].length() - 1);
// remove prefix of file/folder in changeInfo, splite the remained path
vector<generic_string> linarPathArray = split(pathSuffix, '\\');
if (action == FILE_ACTION_ADDED)
{
generic_string rootPath = file2Change[0].substr(0, sepPos);
generic_string path = rootPath;
// search recursively and modify the tree structure
//bool foundAndModified = _rootFolder.addToStructure(path, linarPathArray);
bool foundAndModified = true;
if (foundAndModified)
{
generic_string addedFilePath = file2Change[0].substr(0, sepPos + 1);
addedFilePath += pathSuffix;
bool isAdded = _pFileBrowser->addInTree(rootPath, addedFilePath, nullptr, linarPathArray);
if (not isAdded)
MessageBox(NULL, addedFilePath.c_str(), TEXT("file/folder is not added"), MB_OK);
}
else
printStr(TEXT("addToStructure pb"));
}
else if (action == FILE_ACTION_REMOVED)
{
generic_string rootPath = file2Change[0].substr(0, sepPos);
// search recursively and modify the tree structure
//bool foundAndModified = _rootFolder.removeFromStructure(linarPathArray);
bool foundAndModified = true;
if (foundAndModified)
{
bool isRemoved = _pFileBrowser->deleteFromTree(rootPath, nullptr, linarPathArray);
if (not isRemoved)
MessageBox(NULL, file2Change[0].c_str(), TEXT("file/folder is not removed"), MB_OK);
}
else
printStr(TEXT("removeFromStructure pb"));
}
else if (action == FILE_ACTION_RENAMED_NEW_NAME)
{
generic_string rootPath = file2Change[0].substr(0, sepPos);
size_t sepPos2 = file2Change[1].find(separator);
if (sepPos2 == generic_string::npos)
return false;
generic_string pathSuffix2 = file2Change[1].substr(sepPos2 + separator.length(), file2Change[1].length() - 1);
vector<generic_string> linarPathArray2 = split(pathSuffix2, '\\');
//bool foundAndModified = _rootFolder.renameInStructure(linarPathArray, linarPathArray2);
bool foundAndModified = true;
if (foundAndModified)
{
bool isRenamed = _pFileBrowser->renameInTree(rootPath, nullptr, linarPathArray, linarPathArray2);
if (not isRenamed)
MessageBox(NULL, file2Change[0].c_str(), TEXT("file/folder is not removed"), MB_OK);
}
else
printStr(TEXT("removeFromStructure pb"));
}
return true;
}
*/
DWORD WINAPI FolderUpdater::watching(void *params)
{
FolderUpdater *thisFolderUpdater = (FolderUpdater *)params;
generic_string dir2Watch = (thisFolderUpdater->_rootFolder)._rootPath;
if (dir2Watch[dir2Watch.length() - 1] != '\\')
dir2Watch += TEXT("\\"); // CReadDirectoryChanges will add another '\' so we will get "\\" as a separator (of monitored root) in the notification
const DWORD dwNotificationFlags = FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME;
// Create the monitor and add directory to watch.
CReadDirectoryChanges changes;
changes.AddDirectory(dir2Watch.c_str(), true, dwNotificationFlags);
HANDLE changeHandles[] = { thisFolderUpdater->_EventHandle, changes.GetWaitHandle() };
bool toBeContinued = true;
while (toBeContinued)
{
DWORD waitStatus = ::WaitForMultipleObjects(_countof(changeHandles), changeHandles, FALSE, INFINITE);
switch (waitStatus)
{
case WAIT_OBJECT_0 + 0:
// Mutex was signaled. User removes this folder or file browser is closed
toBeContinued = false;
break;
case WAIT_OBJECT_0 + 1:
// We've received a notification in the queue.
{
DWORD dwAction;
CStringW wstrFilename;
if (changes.CheckOverflow())
printStr(L"Queue overflowed.");
else
{
changes.Pop(dwAction, wstrFilename);
static generic_string oldName;
static std::vector<generic_string> file2Change;
file2Change.clear();
switch (dwAction)
{
case FILE_ACTION_ADDED:
file2Change.push_back(wstrFilename.GetString());
//thisFolderUpdater->updateTree(dwAction, file2Change);
::SendMessage((thisFolderUpdater->_pFileBrowser)->getHSelf(), FB_ADDFILE, (WPARAM)nullptr, (LPARAM)&file2Change);
oldName = TEXT("");
break;
case FILE_ACTION_REMOVED:
file2Change.push_back(wstrFilename.GetString());
//thisFolderUpdater->updateTree(dwAction, file2Change);
::SendMessage((thisFolderUpdater->_pFileBrowser)->getHSelf(), FB_RMFILE, (WPARAM)nullptr, (LPARAM)&file2Change);
oldName = TEXT("");
break;
case FILE_ACTION_MODIFIED:
oldName = TEXT("");
break;
case FILE_ACTION_RENAMED_OLD_NAME:
oldName = wstrFilename.GetString();
break;
case FILE_ACTION_RENAMED_NEW_NAME:
if (not oldName.empty())
{
file2Change.push_back(oldName);
file2Change.push_back(wstrFilename.GetString());
//thisFolderUpdater->updateTree(dwAction, file2Change);
::SendMessage((thisFolderUpdater->_pFileBrowser)->getHSelf(), FB_RNFILE, (WPARAM)nullptr, (LPARAM)&file2Change);
}
oldName = TEXT("");
break;
default:
oldName = TEXT("");
break;
}
}
}
break;
case WAIT_IO_COMPLETION:
// Nothing to do.
break;
}
}
// Just for sample purposes. The destructor will
// call Terminate() automatically.
changes.Terminate();
//printStr(L"Quit watching thread");
return EXIT_SUCCESS;
}