pull/3/head
chen 1 year ago
parent f378694a32
commit 2eb8ad44d1

@ -16,31 +16,31 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//该cpp文件实现了处理崩溃的类MiniDumper.h
#include <shlwapi.h>
#include "MiniDumper.h"
//消息标题
LPCTSTR msgTitle = TEXT("Notepad++ crash analysis");
MiniDumper::MiniDumper()
{
}
//写入崩溃转储的函数
bool MiniDumper::writeDump(EXCEPTION_POINTERS * pExceptionInfo)
{
TCHAR szDumpPath[MAX_PATH];
TCHAR szScratch[MAX_PATH];
LPCTSTR szResult = NULL;
bool retval = false;
//加载动态链接库
HMODULE hDll = ::LoadLibraryEx(TEXT("DBGHELP.DLL"), nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); //that wont work on older windows version than XP, #care :)
if (hDll)
{
MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
if (pDump)
{
{//获取当前模块的文件路径
::GetModuleFileName(NULL, szDumpPath, MAX_PATH);
::PathRemoveFileSpec(szDumpPath);
wcscat_s(szDumpPath, TEXT("\\NppDump.dmp"));
@ -93,7 +93,7 @@ bool MiniDumper::writeDump(EXCEPTION_POINTERS * pExceptionInfo)
{
szResult = TEXT("Unable to load the debugging DLL,\r\nfind a recent copy of dbghelp.dll and install it.");
}
//弹出消息框显示结果
if (szResult)
::MessageBox(NULL, szResult, msgTitle, MB_OK);

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//fileBrowser类的具体实现
#include "fileBrowser.h"
#include "resource.h"
#include "tinyxml.h"
@ -41,7 +41,7 @@
#define FB_CMD_FOLDALL 2
#define FB_CMD_EXPANDALL 3
//停止所有文件监视器
FileBrowser::~FileBrowser()
{
for (const auto folder : _folderUpdaters)
@ -55,7 +55,7 @@ FileBrowser::~FileBrowser()
delete cd;
}
}
//将一个字符串分割成多个子字符串函数使用了for循环依次检查字符串中的每个字符当找到等于`sep`或者空字符的字符时,就把这之前的字符作为一个子字符串存储在`splitedStrings`向量中。
vector<generic_string> split(const generic_string & string2split, TCHAR sep)
{
vector<generic_string> splitedStrings;
@ -71,7 +71,7 @@ vector<generic_string> split(const generic_string & string2split, TCHAR sep)
}
return splitedStrings;
}
//检查子文件夹是否与根文件相关
bool isRelatedRootFolder(const generic_string & relatedRoot, const generic_string & subFolder)
{
if (relatedRoot.empty())
@ -91,11 +91,11 @@ bool isRelatedRootFolder(const generic_string & relatedRoot, const generic_strin
return relatedRootArray[index2Compare] == subFolderArray[index2Compare];
}
//消息处理
intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
{//会话框初始化,包括创建工具条,树状视图的初始化等。
case WM_INITDIALOG :
{
NppParameters& nppParam = NppParameters::getInstance();
@ -175,7 +175,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
return TRUE;
}
//处理黑暗模式刷新的消息
case NPPM_INTERNAL_REFRESHDARKMODE:
{
if (static_cast<BOOL>(lParam) != TRUE)
@ -185,7 +185,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
NppDarkMode::setTreeViewStyle(_treeView.getHSelf());
return TRUE;
}
//鼠标消息
case WM_MOUSEMOVE:
if (_treeView.isDragging())
_treeView.dragItem(_hSelf, LOWORD(lParam), HIWORD(lParam));
@ -197,13 +197,13 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
}
break;
//通知消息
case WM_NOTIFY:
{
notified((LPNMHDR)lParam);
}
return TRUE;
//得到窗体的新宽度和高度,然后调整工具条和树形视图的位置和大小。
case WM_SIZE:
{
int width = LOWORD(lParam);
@ -220,28 +220,28 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
::MoveWindow(hwnd, 0, toolbarMenuRect.bottom + extraValue, width, height - toolbarMenuRect.bottom - extraValue, TRUE);
break;
}
//文本菜单
case WM_CONTEXTMENU:
if (!_treeView.isDragging())
showContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return TRUE;
//来自菜单的选择
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
{//选择当前正在编辑的文件。
case FB_CMD_AIMFILE:
{
selectCurrentEditingFile();
break;
}
//折叠
case FB_CMD_FOLDALL:
{
_treeView.foldAll();
break;
}
//展开
case FB_CMD_EXPANDALL:
{
_treeView.expandAll();
@ -253,7 +253,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
}
break;
}
//销毁
case WM_DESTROY:
{
::DestroyWindow(_hToolbarMenu);
@ -261,7 +261,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
destroyMenus();
break;
}
//添加
case FB_ADDFILE:
{
@ -274,7 +274,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
break;
}
//移除
case FB_RMFILE:
{
@ -287,7 +287,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
break;
}
//重命名
case FB_RNFILE:
{
const std::vector<generic_string> file2Change = *(std::vector<generic_string> *)lParam;
@ -324,7 +324,7 @@ intptr_t CALLBACK FileBrowser::run_dlgProc(UINT message, WPARAM wParam, LPARAM l
}
return DockingDlgInterface::run_dlgProc(message, wParam, lParam);
}
//创建一个文件浏览器的时候,初始化弹出菜单。首先收集各种与菜单项相关的字符串,然后创建三种不同的菜单:全局菜单、根菜单、文件夹菜单和文件菜单,向这些菜单中插入各种菜单项。
void FileBrowser::initPopupMenus()
{
NativeLangSpeaker* pNativeSpeaker = NppParameters::getInstance().getNativeLangSpeaker();
@ -370,7 +370,7 @@ void FileBrowser::initPopupMenus()
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_EXPLORERHERE, explorerHere.c_str());
::InsertMenu(_hFileMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_CMDHERE, cmdHere.c_str());
}
//通过一个给定的路径选中文件浏览器中的一个项目。它首先检查路径是否为空,然后通过遍历所有的文件夹来寻找对应的项目。
bool FileBrowser::selectItemFromPath(const generic_string& itemPath) const
{
if (itemPath.empty())
@ -409,7 +409,7 @@ bool FileBrowser::selectItemFromPath(const generic_string& itemPath) const
}
return false;
}
//选择当前正在编辑的文件。
bool FileBrowser::selectCurrentEditingFile() const
{
TCHAR currentDocPath[MAX_PATH] = { '\0' };
@ -418,7 +418,7 @@ bool FileBrowser::selectCurrentEditingFile() const
return selectItemFromPath(currentDocPathStr);
}
//摧毁创建的菜单
void FileBrowser::destroyMenus()
{
::DestroyMenu(_hGlobalMenu);
@ -426,7 +426,7 @@ void FileBrowser::destroyMenus()
::DestroyMenu(_hFolderMenu);
::DestroyMenu(_hFileMenu);
}
//返回一个给定节点的完整路径。
generic_string FileBrowser::getNodePath(HTREEITEM node) const
{
if (!node) return TEXT("");
@ -460,12 +460,12 @@ generic_string FileBrowser::getNodePath(HTREEITEM node) const
return fullPath;
}
//返回一个给定节点的名称。
generic_string FileBrowser::getNodeName(HTREEITEM node) const
{
return node ? _treeView.getItemDisplayName(node) : TEXT("");
}
//打开选定的文件。如果选定的项目是一个文件,那么就打开它;否则,不执行任何操作。
void FileBrowser::openSelectFile()
{
// Get the selected item
@ -483,7 +483,7 @@ void FileBrowser::openSelectFile()
::PostMessage(_hParent, NPPM_DOOPEN, 0, reinterpret_cast<LPARAM>(_selectedNodeFullPath.c_str()));
}
//处理各种菜单操作的事件。例如,如果一个菜单项被双击,那么就调用函数进行对应的处理;如果一个节点标签被编辑,那么函数就保存新的标签。
void FileBrowser::notified(LPNMHDR notification)
{
if (notification->code == DMN_CLOSE)
@ -673,7 +673,7 @@ void FileBrowser::notified(LPNMHDR notification)
}
}
}
//获取给定项目(`hItem`)的节点类型。函数首先获取项目的索引(`iImage`),如果索引为`INDEX_LEAF`,则节点类型为文件;如果项目的参数(`lParam`)不为空并且`SortingData4lParam`类中`_rootPath`成员不为空,那么节点类型为根;否则,节点类型为文件夹。
BrowserNodeType FileBrowser::getNodeType(HTREEITEM hItem)
{
TVITEM tvItem;
@ -697,7 +697,7 @@ BrowserNodeType FileBrowser::getNodeType(HTREEITEM hItem)
return browserNodeType_folder;
}
}
//(x, y)位置显示上下文菜单。函数首先检测给定位置是否在一个元素上,如果是的话就选中该元素,并获取该元素的节点类型,然后根据节点类型显示相应的上下文菜单。
void FileBrowser::showContextMenu(int x, int y)
{
TVHITTESTINFO tvHitInfo{};
@ -735,7 +735,7 @@ void FileBrowser::showContextMenu(int x, int y)
x, y, 0, _hSelf, NULL);
}
}
//执行与给定命令ID(`cmdID`)关联的上下文菜单命令。例如如果命令ID为`IDM_FILEBROWSER_REMOVEROOTFOLDER`,则函数将删除选定的根文件夹。
void FileBrowser::popupMenuCmd(int cmdID)
{
// get selected item handle
@ -872,7 +872,7 @@ void FileBrowser::popupMenuCmd(int cmdID)
}
//在目录`dir`中获取符合`patterns`模式的所有文件和子目录的结构信息,并将其保存到`directoryStructure`中。`isRecursive`参数指定是否递归遍历子目录,`isInHiddenDir`参数指示当前目录是否为隐藏目录。
void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<generic_string> & patterns, FolderInfo & directoryStructure, bool isRecursive, bool isInHiddenDir)
{
if (directoryStructure._parent == nullptr) // Root!
@ -954,12 +954,13 @@ void FileBrowser::getDirectoryStructure(const TCHAR *dir, const std::vector<gene
}
::FindClose(hFile);
}
//添加根文件夹
void FileBrowser::addRootFolder(generic_string rootFolderPath)
{
{//检查根文件夹路径是否存在
if (!::PathFileExists(rootFolderPath.c_str()))
return;
// 检查根文件夹路径是否是一个目录
if (!::PathIsDirectory(rootFolderPath.c_str()))
return;
@ -968,13 +969,13 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
{
rootFolderPath = rootFolderPath.substr(0, rootFolderPath.length() - 1);
}
// 遍历已添加的根文件夹更新器
for (const auto f : _folderUpdaters)
{
{ // 检查是否已经添加相同路径的根文件夹
if (f->_rootFolder._rootPath == rootFolderPath)
return;
else
{
{ // 检查是否存在相关的根文件夹,以便选择目录
if (isRelatedRootFolder(f->_rootFolder._rootPath, rootFolderPath))
{
//do nothing, go down to select the dir
@ -987,9 +988,9 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
_treeView.selectItem(foundItem);
return;
}
// 检查是否存在相对于要添加的根文件夹的子文件夹
if (isRelatedRootFolder(rootFolderPath, f->_rootFolder._rootPath))
{
{// 显示消息框,指示存在子文件夹,需要先移除
NppParameters::getInstance().getNativeLangSpeaker()->messageBox("FolderAsWorspaceSubfolderExists",
_hParent,
TEXT("A sub-folder of the folder you want to add exists.\rPlease remove its root from the panel before you add folder \"$STR_REPLACE$\"."),
@ -1001,10 +1002,10 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
}
}
}
// 设置要匹配的文件模式
std::vector<generic_string> patterns2Match;
patterns2Match.push_back(TEXT("*.*"));
// 获取根文件夹的名称并创建相应的文件夹信息对象
TCHAR *label = ::PathFindFileName(rootFolderPath.c_str());
TCHAR rootLabel[MAX_PATH] = {'\0'};
wcscpy_s(rootLabel, label);
@ -1019,10 +1020,11 @@ void FileBrowser::addRootFolder(generic_string rootFolderPath)
_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] = { '\0' };
@ -1033,14 +1035,14 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con
SortingData4lParam* customData = new SortingData4lParam(rootPath, TEXT(""), true);
sortingDataArray.push_back(customData);
// 添加根节点到树视图
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), TVI_ROOT, INDEX_CLOSE_ROOT, reinterpret_cast<LPARAM>(customData));
}
else
{
SortingData4lParam* customData = new SortingData4lParam(TEXT(""), directoryStructure._name, true);
sortingDataArray.push_back(customData);
// 添加节点到树视图
hFolderItem = _treeView.addItem(directoryStructure._name.c_str(), hParentItem, INDEX_CLOSE_NODE, reinterpret_cast<LPARAM>(customData));
}
@ -1053,7 +1055,7 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con
{
SortingData4lParam* customData = new SortingData4lParam(TEXT(""), file._name, false);
sortingDataArray.push_back(customData);
// 添加文件节点到树视图
_treeView.addItem(file._name.c_str(), hFolderItem, INDEX_LEAF, reinterpret_cast<LPARAM>(customData));
}
@ -1061,7 +1063,7 @@ HTREEITEM FileBrowser::createFolderItemsFromDirStruct(HTREEITEM hParentItem, con
return hFolderItem;
}
//根据路径找到根目录
HTREEITEM FileBrowser::getRootFromFullPath(const generic_string & rootPath) const
{
HTREEITEM node = nullptr;
@ -1080,7 +1082,7 @@ HTREEITEM FileBrowser::getRootFromFullPath(const generic_string & rootPath) cons
}
return node;
}
//在指定父节点下查找具有特定名称的子节点。
HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, const generic_string& label) const
{
for (HTREEITEM hItemNode = _treeView.getChildFrom(parent);
@ -1102,7 +1104,7 @@ HTREEITEM FileBrowser::findChildNodeFromName(HTREEITEM parent, const generic_str
}
return nullptr;
}
//得到所有根节点的路径
vector<generic_string> FileBrowser::getRoots() const
{
vector<generic_string> roots;
@ -1121,7 +1123,7 @@ vector<generic_string> FileBrowser::getRoots() const
}
return roots;
}
//获取选中文件的路径
generic_string FileBrowser::getSelectedItemPath() const
{
generic_string itemPath;
@ -1132,7 +1134,7 @@ generic_string FileBrowser::getSelectedItemPath() const
}
return itemPath;
}
//将传递的文件路径信息分组,按照共同路径和根路径进行分类。
std::vector<FileBrowser::FilesToChange> FileBrowser::getFilesFromParam(LPARAM lParam) const
{
const std::vector<generic_string> filesToChange = *(std::vector<generic_string>*)lParam;
@ -1189,7 +1191,7 @@ std::vector<FileBrowser::FilesToChange> FileBrowser::getFilesFromParam(LPARAM lP
return groupedFiles;
}
//将文件组添加到树中,根据文件类型在树中创建相应的节点。
bool FileBrowser::addToTree(FilesToChange & group, HTREEITEM node)
{
if (node == nullptr) // it's a root. Search the right root with rootPath
@ -1266,7 +1268,7 @@ bool FileBrowser::addToTree(FilesToChange & group, HTREEITEM node)
}
}
//在树中查找并删除指定的文件组。
bool FileBrowser::deleteFromTree(FilesToChange & group)
{
std::vector<HTREEITEM> foundItems = findInTree(group, nullptr);
@ -1283,7 +1285,7 @@ bool FileBrowser::deleteFromTree(FilesToChange & group)
return true;
}
//在树形结构中查找指定路径,首先判断当前节点是否为根节点,若是则根据根路径查找对应的根节点。然后根据路径数组的大小,判断是否继续查找子节点或者返回当前节点。
HTREEITEM FileBrowser::findInTree(const generic_string& rootPath, HTREEITEM node, std::vector<generic_string> linarPathArray) const
{
if (node == nullptr) // it's a root. Search the right root with rootPath
@ -1326,7 +1328,7 @@ HTREEITEM FileBrowser::findInTree(const generic_string& rootPath, HTREEITEM node
return nullptr;
}
}
//该函数也用于在树形结构中查找指定路径但参数不同。参数group是一个包含文件信息和路径的对象node表示当前节点。函数首先判断当前节点是否为根节点若是则根据路径信息查找对应的根节点。然后根据路径信息的大小判断是否继续查找子节点或者返回找到的节点集合。
std::vector<HTREEITEM> FileBrowser::findInTree(FilesToChange & group, HTREEITEM node) const
{
if (node == nullptr) // it's a root. Search the right root with rootPath
@ -1367,7 +1369,7 @@ std::vector<HTREEITEM> FileBrowser::findInTree(FilesToChange & group, HTREEITEM
return {};
}
}
//找到指定父节点的子节点
std::vector<HTREEITEM> FileBrowser::findChildNodesFromNames(HTREEITEM parent, std::vector<generic_string> & labels) const
{
std::vector<HTREEITEM> itemNodes;
@ -1394,6 +1396,7 @@ std::vector<HTREEITEM> FileBrowser::findChildNodesFromNames(HTREEITEM parent, st
}
return itemNodes;
}
//移除已经在父节点中的名字。它遍历父节点的所有子节点,并将与给定标签集合中名字相匹配的标签清除。
void FileBrowser::removeNamesAlreadyInNode(HTREEITEM parent, std::vector<generic_string> & labels) const
{
@ -1418,7 +1421,7 @@ void FileBrowser::removeNamesAlreadyInNode(HTREEITEM parent, std::vector<generic
}
}
}
//在树形结构中重命名节点,找到匹配给定线性路径数组的节点,并将其重新命名为指定的字符串。
bool FileBrowser::renameInTree(const generic_string& rootPath, HTREEITEM node, const std::vector<generic_string>& linarPathArrayFrom, const generic_string & renameTo)
{
HTREEITEM foundItem = findInTree(rootPath, node, linarPathArrayFrom);
@ -1433,7 +1436,7 @@ bool FileBrowser::renameInTree(const generic_string& rootPath, HTREEITEM node, c
return true;
}
//排序回调函数,按照文件夹和文件名进行排序。首先是文件夹,然后是文件。如果两者都是文件夹或文件,那么比较它们的名字。
int CALLBACK FileBrowser::categorySortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM /*lParamSort*/)
{
SortingData4lParam* item1 = reinterpret_cast<SortingData4lParam*>(lParam1);
@ -1449,7 +1452,7 @@ int CALLBACK FileBrowser::categorySortFunc(LPARAM lParam1, LPARAM lParam2, LPARA
else
return lstrcmpi(item1->_label.c_str(), item2->_label.c_str());
}
//将给定的完整路径添加到文件夹信息结构中。该路径可能是文件或目录如果该路径已经存在于结构中则返回false如果成功添加则返回true。
bool FolderInfo::addToStructure(generic_string & fullpath, std::vector<generic_string> linarPathArray)
{
if (linarPathArray.size() == 1) // could be file or folder
@ -1494,7 +1497,7 @@ bool FolderInfo::addToStructure(generic_string & fullpath, std::vector<generic_s
return false;
}
}
//从文件夹信息结构中删除给定的线性路径数组。成功删除返回true否则返回false。
bool FolderInfo::removeFromStructure(std::vector<generic_string> linarPathArray)
{
if (linarPathArray.size() == 1) // could be file or folder
@ -1532,7 +1535,7 @@ bool FolderInfo::removeFromStructure(std::vector<generic_string> linarPathArray)
}
return false;
}
//在文件夹信息结构中重命名给定的线性路径。它将 "linarPathArrayFrom" 指定的路径的名字更改为 "linarPathArrayTo" 指定的名字。
bool FolderInfo::renameInStructure(std::vector<generic_string> linarPathArrayFrom, std::vector<generic_string> linarPathArrayTo)
{
if (linarPathArrayFrom.size() == 1) // could be file or folder
@ -1572,6 +1575,7 @@ bool FolderInfo::renameInStructure(std::vector<generic_string> linarPathArrayFro
return false;
}
}
//打开监视器,创建一个事件对象并开启一个新的线程,线程开始运行 `watching` 函数。
void FolderUpdater::startWatcher()
{
@ -1579,6 +1583,7 @@ void FolderUpdater::startWatcher()
_EventHandle = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
_watchThreadHandle = ::CreateThread(NULL, 0, watching, this, 0, NULL);
}
//停止监视器。它通过设定事件和关闭对应的线程实现。
void FolderUpdater::stopWatcher()
{
@ -1586,6 +1591,7 @@ void FolderUpdater::stopWatcher()
::CloseHandle(_watchThreadHandle);
::CloseHandle(_EventHandle);
}
//根据动作类型的代码返回相应的动作名字。
LPCWSTR explainAction(DWORD dwAction)
{
@ -1606,6 +1612,7 @@ LPCWSTR explainAction(DWORD dwAction)
}
}
//负责监视目录下的文件变化。当有文件被创建、删除、重命名等操作时,就会将这个改动放入改动队列,并通过事件提醒主线程进行处理。
DWORD WINAPI FolderUpdater::watching(void *params)
{
@ -1704,6 +1711,7 @@ DWORD WINAPI FolderUpdater::watching(void *params)
//printStr(L"Quit watching thread");
return EXIT_SUCCESS;
}
//根据改动的类型,调用不同的文件浏览器的方法,例如文件创建、删除、重命名等。
void FolderUpdater::processChange(DWORD dwAction, std::vector<generic_string> filesToChange, FolderUpdater* thisFolderUpdater)
{

Loading…
Cancel
Save