From b3daf0a98220ffc6e206133aa645d5a2d1d63a4f Mon Sep 17 00:00:00 2001 From: Alan Kilborn Date: Sat, 15 Jun 2024 08:22:15 -0400 Subject: [PATCH] Add plugin command NPPM_SETUNTITLEDNAME to rename untitled tab Fix #8916, close #15291 --- .../MISC/PluginsManager/Notepad_plus_msgs.h | 6 ++ PowerEditor/src/Notepad_plus.h | 1 + PowerEditor/src/NppBigSwitch.cpp | 20 ++--- PowerEditor/src/NppIO.cpp | 80 +++++++++++++++++-- PowerEditor/src/resource.h | 8 -- 5 files changed, 87 insertions(+), 28 deletions(-) diff --git a/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h b/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h index ff9fdead1..216de6494 100644 --- a/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h +++ b/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h @@ -973,6 +973,12 @@ enum Platform { PF_UNKNOWN, PF_X86, PF_X64, PF_IA64, PF_ARM64 }; // // Note: there's no symetric command NPPM_SETTABCOLORID. Plugins can use NPPM_MENUCOMMAND to set current tab color with the desired tab color ID. + #define NPPM_SETUNTITLEDNAME (NPPMSG + 115) + // int NPPM_SETUNTITLEDNAME(BufferID id, const TCHAR* newName) + // Rename the tab name for an untitled tab. + // wParam[in]: id - BufferID of the tab. -1 for currently active tab + // lParam[in]: newName - the desired new name of the tab + // Return TRUE upon success; FALSE upon failure // For RUNCOMMAND_USER #define VAR_NOT_RECOGNIZED 0 diff --git a/PowerEditor/src/Notepad_plus.h b/PowerEditor/src/Notepad_plus.h index 6aa236aa1..3bcb3ac50 100644 --- a/PowerEditor/src/Notepad_plus.h +++ b/PowerEditor/src/Notepad_plus.h @@ -190,6 +190,7 @@ public: bool fileSaveAs(BufferID id = BUFFER_INVALID, bool isSaveCopy = false); bool fileDelete(BufferID id = BUFFER_INVALID); bool fileRename(BufferID id = BUFFER_INVALID); + bool fileRenameUntitled(BufferID id, const wchar_t* tabNewName); bool switchToFile(BufferID buffer); //find buffer in active view then in other view. //@} diff --git a/PowerEditor/src/NppBigSwitch.cpp b/PowerEditor/src/NppBigSwitch.cpp index 0a0fa1201..e6ea9682f 100644 --- a/PowerEditor/src/NppBigSwitch.cpp +++ b/PowerEditor/src/NppBigSwitch.cpp @@ -553,20 +553,6 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa break; } - case NPPM_INTERNAL_SETFILENAME: - { - if (!lParam && !wParam) - return FALSE; - BufferID id = (BufferID)wParam; - Buffer * b = MainFileManager.getBufferByID(id); - if (b && b->getStatus() == DOC_UNNAMED) - { - b->setFileName(reinterpret_cast(lParam)); - return TRUE; - } - return FALSE; - } - case NPPM_GETBUFFERLANGTYPE: { if (!wParam) @@ -3142,6 +3128,12 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa return colorId; } + case NPPM_SETUNTITLEDNAME: + { + if (!wParam || !lParam) return FALSE; + return fileRenameUntitled(reinterpret_cast(wParam), reinterpret_cast(lParam)); + } + case NPPM_GETBOOKMARKID: { return MARK_BOOKMARK; diff --git a/PowerEditor/src/NppIO.cpp b/PowerEditor/src/NppIO.cpp index 51ba2e13f..fa65fb7b0 100644 --- a/PowerEditor/src/NppIO.cpp +++ b/PowerEditor/src/NppIO.cpp @@ -32,6 +32,11 @@ using namespace std; +// https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file +// Reserved characters: < > : " / \ | ? * tab +// ("tab" is not in the official list, but it is good to avoid it) +const std::wstring filenameReservedChars = TEXT("<>:\"/\\|\?*\t"); + DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params) { MonitorInfo *monitorInfo = static_cast(params); @@ -1904,16 +1909,11 @@ bool Notepad_plus::fileRename(BufferID id) // We are just going to rename the tab nothing else // So just rename the tab and rename the backup file too if applicable - // https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file - // Reserved characters: < > : " / \ | ? * tab - // ("tab" is not in the official list, but it is good to avoid it) - std::wstring reservedChars = TEXT("<>:\"/\\|\?*\t"); - std::wstring staticName = _nativeLangSpeaker.getLocalizedStrFromID("tabrename-newname", L"New name"); StringDlg strDlg; std::wstring title = _nativeLangSpeaker.getLocalizedStrFromID("tabrename-title", L"Rename Current Tab"); - strDlg.init(_pPublicInterface->getHinst(), _pPublicInterface->getHSelf(), title.c_str(), staticName.c_str(), buf->getFileName(), langNameLenMax - 1, reservedChars.c_str(), true); + strDlg.init(_pPublicInterface->getHinst(), _pPublicInterface->getHSelf(), title.c_str(), staticName.c_str(), buf->getFileName(), langNameLenMax - 1, filenameReservedChars.c_str(), true); wchar_t *tabNewName = reinterpret_cast(strDlg.doDialog()); if (tabNewName) @@ -1975,6 +1975,74 @@ bool Notepad_plus::fileRename(BufferID id) return success; } +bool Notepad_plus::fileRenameUntitled(BufferID id, const wchar_t* tabNewName) +{ + BufferID bufferID = id; + if (id == BUFFER_INVALID) + { + bufferID = _pEditView->getCurrentBufferID(); + } + Buffer* buf = MainFileManager.getBufferByID(bufferID); + + bool isFileExisting = PathFileExists(buf->getFullPathName()) != FALSE; + if (isFileExisting) return false; + + // We are just going to rename the tab nothing else + // So just rename the tab and rename the backup file too if applicable + + if (!tabNewName) return false; + + std::wstring tabNewNameStr = tabNewName; + + trim(tabNewNameStr); // No leading and tailing space allowed + + if (tabNewNameStr.empty()) return false; + + if (tabNewNameStr.length() > langNameLenMax - 1) return false; + + if (tabNewNameStr.find_first_of(filenameReservedChars) != std::wstring::npos) return false; + + BufferID sameNamedBufferId = _pDocTab->findBufferByName(tabNewNameStr.c_str()); + if (sameNamedBufferId == BUFFER_INVALID) + { + sameNamedBufferId = _pNonDocTab->findBufferByName(tabNewNameStr.c_str()); + } + + if (sameNamedBufferId == BUFFER_INVALID) + { + SCNotification scnN{}; + scnN.nmhdr.code = NPPN_FILEBEFORERENAME; + scnN.nmhdr.hwndFrom = _pPublicInterface->getHSelf(); + scnN.nmhdr.idFrom = (uptr_t)bufferID; + _pluginsManager.notify(&scnN); + + buf->setFileName(tabNewNameStr.c_str()); + + scnN.nmhdr.code = NPPN_FILERENAMED; + _pluginsManager.notify(&scnN); + + bool isSnapshotMode = NppParameters::getInstance().getNppGUI().isSnapshotMode(); + if (isSnapshotMode) + { + std::wstring oldBackUpFile = buf->getBackupFileName(); + + // Change the backup file name and let MainFileManager decide the new filename + buf->setBackupFileName(TEXT("")); + + // Create new backup + buf->setModifiedStatus(true); + bool bRes = MainFileManager.backupCurrentBuffer(); + + // Delete old backup + if (bRes) + { + ::DeleteFile(oldBackUpFile.c_str()); + } + } + } + + return true; +} bool Notepad_plus::fileDelete(BufferID id) { diff --git a/PowerEditor/src/resource.h b/PowerEditor/src/resource.h index 6da80e228..51721c24f 100644 --- a/PowerEditor/src/resource.h +++ b/PowerEditor/src/resource.h @@ -688,14 +688,6 @@ #define CHECKDOCOPT_UPDATESILENTLY 1 #define CHECKDOCOPT_UPDATEGO2END 2 - // - // Used by netnote plugin - // - #define NPPM_INTERNAL_SETFILENAME (NPPMSG + 63) - //wParam: BufferID to rename - //lParam: name to set (TCHAR*) - //Buffer must have been previously unnamed (eg "new 1" document types) - #define SCINTILLA_USER (WM_USER + 2000)