From 4268349bf04861528414612c1b1460e03c2ce1ae Mon Sep 17 00:00:00 2001 From: Don Ho Date: Wed, 11 May 2016 02:18:04 +0200 Subject: [PATCH] Fix crash bug in Log Monitoring while monitoring a large file --- PowerEditor/src/Notepad_plus.cpp | 17 +++++++++++ PowerEditor/src/Notepad_plus.h | 9 +++--- PowerEditor/src/NppBigSwitch.cpp | 7 +++++ PowerEditor/src/NppCommands.cpp | 2 +- PowerEditor/src/NppIO.cpp | 19 ++----------- PowerEditor/src/ScitillaComponent/Buffer.cpp | 30 +++++++++++++------- PowerEditor/src/ScitillaComponent/Buffer.h | 10 ++++--- PowerEditor/src/resource.h | 2 +- 8 files changed, 58 insertions(+), 38 deletions(-) diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index 94ba8b052..aed326278 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -4784,6 +4784,23 @@ void Notepad_plus::notifyBufferChanged(Buffer * buffer, int mask) } break; } + case DOC_NEEDRELOAD: // by log monitoring + { + doReload(buffer->getID(), false); + + // not only test main view + if (buffer == _mainEditView.getCurrentBuffer()) + { + _mainEditView.execute(SCI_GOTOLINE, _mainEditView.execute(SCI_GETLINECOUNT) - 1); + } + // but also test sub-view, because the buffer could be clonned + if (buffer == _subEditView.getCurrentBuffer()) + { + _subEditView.execute(SCI_GOTOLINE, _subEditView.execute(SCI_GETLINECOUNT) - 1); + } + + break; + } case DOC_DELETED: //ask for keep { SCNotification scnN; diff --git a/PowerEditor/src/Notepad_plus.h b/PowerEditor/src/Notepad_plus.h index 78790e83e..676867f26 100644 --- a/PowerEditor/src/Notepad_plus.h +++ b/PowerEditor/src/Notepad_plus.h @@ -447,7 +447,7 @@ private: bool reloadLang(); bool loadStyles(); - int currentView(){ + int currentView() { return _activeView; } @@ -645,11 +645,10 @@ private: static DWORD WINAPI monitorFileOnChange(void * params); struct MonitorInfo final { - MonitorInfo(Buffer *buf, ScintillaEditView *mainEditorView, ScintillaEditView *subEditorView) : - _buffer(buf), _mainEditorView(mainEditorView), _subEditorView(subEditorView) {}; + MonitorInfo(Buffer *buf, HWND nppHandle) : + _buffer(buf), _nppHandle(nppHandle) {}; Buffer *_buffer = nullptr; - ScintillaEditView *_mainEditorView = nullptr; - ScintillaEditView *_subEditorView = nullptr; + HWND _nppHandle = nullptr; }; }; diff --git a/PowerEditor/src/NppBigSwitch.cpp b/PowerEditor/src/NppBigSwitch.cpp index 53932c618..1018438c2 100644 --- a/PowerEditor/src/NppBigSwitch.cpp +++ b/PowerEditor/src/NppBigSwitch.cpp @@ -1409,6 +1409,13 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa return FALSE; } + case NPPM_INTERNAL_RELOADSCROLLTOEND: + { + Buffer *buf = (Buffer *)wParam; + buf->reload(); + return TRUE; + } + case NPPM_INTERNAL_GETCHECKDOCOPT: { return (LRESULT)((NppGUI &)(pNppParam->getNppGUI()))._fileAutoDetection; diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp index a51181e67..12e84d3fa 100644 --- a/PowerEditor/src/NppCommands.cpp +++ b/PowerEditor/src/NppCommands.cpp @@ -1781,7 +1781,7 @@ void Notepad_plus::command(int id) curBuf->startMonitoring(); // monitoring firstly for making monitoring icon curBuf->setUserReadOnly(true); - MonitorInfo *monitorInfo = new MonitorInfo(curBuf, &_mainEditView, &_subEditView); + MonitorInfo *monitorInfo = new MonitorInfo(curBuf, _pPublicInterface->getHSelf()); hThread = ::CreateThread(NULL, 0, monitorFileOnChange, (void *)monitorInfo, 0, NULL); // will be deallocated while quitting thread checkMenuItem(IDM_VIEW_MONITORING, true); _toolBar.setCheck(IDM_VIEW_MONITORING, true); diff --git a/PowerEditor/src/NppIO.cpp b/PowerEditor/src/NppIO.cpp index 9fa3b3196..3b683a3ab 100644 --- a/PowerEditor/src/NppIO.cpp +++ b/PowerEditor/src/NppIO.cpp @@ -43,8 +43,7 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params) { MonitorInfo *monitorInfo = (MonitorInfo *)params; Buffer *buf = monitorInfo->_buffer; - ScintillaEditView *mainEditorView = monitorInfo->_mainEditorView; - ScintillaEditView *subEditorView = monitorInfo->_subEditorView; + HWND h = monitorInfo->_nppHandle; const TCHAR *fullFileName = (const TCHAR *)buf->getFullPathName(); @@ -91,21 +90,7 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params) if (dwAction == FILE_ACTION_MODIFIED && lstrcmp(fullFileName, wstrFilename.GetString()) == 0) { - MainFileManager->reloadBuffer(buf->getID()); - buf->updateTimeStamp(); - - // not only test main view - if (buf == mainEditorView->getCurrentBuffer()) - { - int lastLineToShow = mainEditorView->execute(SCI_GETLINECOUNT); - mainEditorView->scroll(0, lastLineToShow); - } - // but also test sub-view, because the buffer could be clonned - if (buf == subEditorView->getCurrentBuffer()) - { - int lastLineToShow = subEditorView->execute(SCI_GETLINECOUNT); - subEditorView->scroll(0, lastLineToShow); - } + ::PostMessage(h, NPPM_INTERNAL_RELOADSCROLLTOEND, (WPARAM)buf, 0); } } } diff --git a/PowerEditor/src/ScitillaComponent/Buffer.cpp b/PowerEditor/src/ScitillaComponent/Buffer.cpp index b7827f5f8..5a4dd28f5 100644 --- a/PowerEditor/src/ScitillaComponent/Buffer.cpp +++ b/PowerEditor/src/ScitillaComponent/Buffer.cpp @@ -238,14 +238,14 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c bool isWow64Off = false; NppParameters *pNppParam = NppParameters::getInstance(); - if (!PathFileExists(_fullPathName.c_str())) + if (not PathFileExists(_fullPathName.c_str())) { pNppParam->safeWow64EnableWow64FsRedirection(FALSE); isWow64Off = true; } bool isOK = false; - if (_currentStatus != DOC_DELETED && !PathFileExists(_fullPathName.c_str())) //document has been deleted + if (_currentStatus != DOC_DELETED && not PathFileExists(_fullPathName.c_str())) //document has been deleted { _currentStatus = DOC_DELETED; _isFileReadOnly = false; @@ -256,7 +256,7 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c } else if (_currentStatus == DOC_DELETED && PathFileExists(_fullPathName.c_str())) { //document has returned from its grave - if (!generic_stat(_fullPathName.c_str(), &buf)) + if (not generic_stat(_fullPathName.c_str(), &buf)) { _isFileReadOnly = (bool)(!(buf.st_mode & _S_IWRITE)); @@ -266,10 +266,10 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c isOK = true; } } - else if (!generic_stat(_fullPathName.c_str(), &buf)) + else if (not generic_stat(_fullPathName.c_str(), &buf)) { int mask = 0; //status always 'changes', even if from modified to modified - bool isFileReadOnly = (bool)(!(buf.st_mode & _S_IWRITE)); + bool isFileReadOnly = (bool)(not(buf.st_mode & _S_IWRITE)); if (isFileReadOnly != _isFileReadOnly) { _isFileReadOnly = isFileReadOnly; @@ -294,11 +294,20 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c if (isWow64Off) { pNppParam->safeWow64EnableWow64FsRedirection(TRUE); - //isWow64Off = false; } return isOK; } +void Buffer::reload() +{ + struct _stat buf; + if (PathFileExists(_fullPathName.c_str()) && not generic_stat(_fullPathName.c_str(), &buf)) + { + _timeStamp = buf.st_mtime; + _currentStatus = DOC_NEEDRELOAD; + doNotify(BufferChangeTimestamp | BufferChangeStatus); + } +} int Buffer::getFileLength() const { @@ -1341,10 +1350,10 @@ LangType FileManager::detectLanguageFromTextBegining(const unsigned char *data, return L_TEXT; } -inline bool FileManager::loadFileData(Document doc, const TCHAR * filename, char* data, Utf8_16_Read * unicodeConvertor, LangType & language, int & encoding, EolType & eolFormat) +bool FileManager::loadFileData(Document doc, const TCHAR * filename, char* data, Utf8_16_Read * unicodeConvertor, LangType & language, int & encoding, EolType & eolFormat) { FILE *fp = generic_fopen(filename, TEXT("rb")); - if (!fp) + if (not fp) return false; //Get file size @@ -1354,9 +1363,9 @@ inline bool FileManager::loadFileData(Document doc, const TCHAR * filename, char // size/6 is the normal room Scintilla keeps for editing, but here we limit it to 1MiB when loading (maybe we want to load big files without editing them too much) unsigned __int64 bufferSizeRequested = fileSize + min(1<<20,fileSize/6); // As a 32bit application, we cannot allocate 2 buffer of more than INT_MAX size (it takes the whole address space) - if(bufferSizeRequested > INT_MAX) + if (bufferSizeRequested > INT_MAX) { - ::MessageBox(NULL, TEXT("File is too big to be opened by Notepad++"), TEXT("File open problem"), MB_OK|MB_APPLMODAL); + ::MessageBox(NULL, TEXT("File is too big to be opened by Notepad++"), TEXT("File size problem"), MB_OK|MB_APPLMODAL); /* _nativeLangSpeaker.messageBox("NbFileToOpenImportantWarning", _pPublicInterface->getHSelf(), @@ -1503,6 +1512,7 @@ inline bool FileManager::loadFileData(Document doc, const TCHAR * filename, char _pscratchTilla->execute(SCI_SETREADONLY, true); _pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault); + return success; } diff --git a/PowerEditor/src/ScitillaComponent/Buffer.h b/PowerEditor/src/ScitillaComponent/Buffer.h index 460d8a455..95c5b257c 100644 --- a/PowerEditor/src/ScitillaComponent/Buffer.h +++ b/PowerEditor/src/ScitillaComponent/Buffer.h @@ -38,10 +38,11 @@ typedef sptr_t Document; enum DocFileStatus { - DOC_REGULAR = 0x01, // should not be combined with anything - DOC_UNNAMED = 0x02, // not saved (new ##) - DOC_DELETED = 0x04, // doesn't exist in environment anymore, but not DOC_UNNAMED - DOC_MODIFIED = 0x08 // File in environment has changed + DOC_REGULAR = 0x01, // should not be combined with anything + DOC_UNNAMED = 0x02, // not saved (new ##) + DOC_DELETED = 0x04, // doesn't exist in environment anymore, but not DOC_UNNAMED + DOC_MODIFIED = 0x08, // File in environment has changed + DOC_NEEDRELOAD = 0x10 // File is modified & needed to be reload (by log monitoring) }; enum BufferStatusInfo @@ -354,6 +355,7 @@ public: bool isMonitoringOn() const { return _isMonitoringOn; }; void updateTimeStamp(); + void reload(); private: int indexOfReference(const ScintillaEditView * identifier) const; diff --git a/PowerEditor/src/resource.h b/PowerEditor/src/resource.h index edc356450..5b900e994 100644 --- a/PowerEditor/src/resource.h +++ b/PowerEditor/src/resource.h @@ -405,7 +405,7 @@ #define NPPM_INTERNAL_SAVECURRENTSESSION (NOTEPADPLUS_USER_INTERNAL + 39) #define NPPM_INTERNAL_FINDINFINDERDLG (NOTEPADPLUS_USER_INTERNAL + 40) #define NPPM_INTERNAL_REMOVEFINDER (NOTEPADPLUS_USER_INTERNAL + 41) - + #define NPPM_INTERNAL_RELOADSCROLLTOEND (NOTEPADPLUS_USER_INTERNAL + 42) // Used by Monitoring feature //wParam: 0 //lParam: document new index