Migrate timestamps from time_t to FILETIME and store them in UTC universally
Fixes #4491, #3969, #2535 and #215.
This commit is contained in:
parent
08eb29e3d6
commit
9cb8fce854
@ -4952,7 +4952,7 @@ void Notepad_plus::getCurrentOpenedFiles(Session & session, bool includUntitledD
|
|||||||
|
|
||||||
generic_string languageName = getLangFromMenu(buf);
|
generic_string languageName = getLangFromMenu(buf);
|
||||||
const TCHAR *langName = languageName.c_str();
|
const TCHAR *langName = languageName.c_str();
|
||||||
sessionFileInfo sfi(buf->getFullPathName(), langName, buf->getEncoding(), buf->getPosition(editView), buf->getBackupFileName().c_str(), int(buf->getLastModifiedTimestamp()), buf->getMapPosition());
|
sessionFileInfo sfi(buf->getFullPathName(), langName, buf->getEncoding(), buf->getPosition(editView), buf->getBackupFileName().c_str(), buf->getLastModifiedTimestamp(), buf->getMapPosition());
|
||||||
|
|
||||||
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, buf->getDocument());
|
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, buf->getDocument());
|
||||||
size_t maxLine = static_cast<size_t>(_invisibleEditView.execute(SCI_GETLINECOUNT));
|
size_t maxLine = static_cast<size_t>(_invisibleEditView.execute(SCI_GETLINECOUNT));
|
||||||
|
@ -174,7 +174,7 @@ public:
|
|||||||
//! \name File Operations
|
//! \name File Operations
|
||||||
//@{
|
//@{
|
||||||
//The doXXX functions apply to a single buffer and dont need to worry about views, with the excpetion of doClose, since closing one view doesnt have to mean the document is gone
|
//The doXXX functions apply to a single buffer and dont need to worry about views, with the excpetion of doClose, since closing one view doesnt have to mean the document is gone
|
||||||
BufferID doOpen(const generic_string& fileName, bool isRecursive = false, bool isReadOnly = false, int encoding = -1, const TCHAR *backupFileName = NULL, time_t fileNameTimestamp = 0);
|
BufferID doOpen(const generic_string& fileName, bool isRecursive = false, bool isReadOnly = false, int encoding = -1, const TCHAR *backupFileName = NULL, FILETIME fileNameTimestamp = {});
|
||||||
bool doReload(BufferID id, bool alert = true);
|
bool doReload(BufferID id, bool alert = true);
|
||||||
bool doSave(BufferID, const TCHAR * filename, bool isSaveCopy = false);
|
bool doSave(BufferID, const TCHAR * filename, bool isSaveCopy = false);
|
||||||
void doClose(BufferID, int whichOne, bool doDeleteBackup = false);
|
void doClose(BufferID, int whichOne, bool doDeleteBackup = false);
|
||||||
|
@ -121,7 +121,7 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, bool isReadOnly, int encoding, const TCHAR *backupFileName, time_t fileNameTimestamp)
|
BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, bool isReadOnly, int encoding, const TCHAR *backupFileName, FILETIME fileNameTimestamp)
|
||||||
{
|
{
|
||||||
const rsize_t longFileNameBufferSize = MAX_PATH; // TODO stop using fixed-size buffer
|
const rsize_t longFileNameBufferSize = MAX_PATH; // TODO stop using fixed-size buffer
|
||||||
if (fileName.size() >= longFileNameBufferSize - 1) // issue with all other sub-routines
|
if (fileName.size() >= longFileNameBufferSize - 1) // issue with all other sub-routines
|
||||||
|
@ -2050,8 +2050,9 @@ bool NppParameters::getSessionFromXmlTree(TiXmlDocument *pSessionDoc, Session *p
|
|||||||
const TCHAR *encStr = (childNode->ToElement())->Attribute(TEXT("encoding"), &encoding);
|
const TCHAR *encStr = (childNode->ToElement())->Attribute(TEXT("encoding"), &encoding);
|
||||||
const TCHAR *backupFilePath = (childNode->ToElement())->Attribute(TEXT("backupFilePath"));
|
const TCHAR *backupFilePath = (childNode->ToElement())->Attribute(TEXT("backupFilePath"));
|
||||||
|
|
||||||
int fileModifiedTimestamp = 0;
|
FILETIME fileModifiedTimestamp;
|
||||||
(childNode->ToElement())->Attribute(TEXT("originalFileLastModifTimestamp"), &fileModifiedTimestamp);
|
(childNode->ToElement())->Attribute(TEXT("originalFileLastModifTimestamp"), reinterpret_cast<int32_t*>(&fileModifiedTimestamp.dwLowDateTime));
|
||||||
|
(childNode->ToElement())->Attribute(TEXT("originalFileLastModifTimestampHigh"), reinterpret_cast<int32_t*>(&fileModifiedTimestamp.dwHighDateTime));
|
||||||
|
|
||||||
sessionFileInfo sfi(fileName, langName, encStr?encoding:-1, position, backupFilePath, fileModifiedTimestamp, mapPosition);
|
sessionFileInfo sfi(fileName, langName, encStr?encoding:-1, position, backupFilePath, fileModifiedTimestamp, mapPosition);
|
||||||
|
|
||||||
@ -2985,7 +2986,8 @@ void NppParameters::writeSession(const Session & session, const TCHAR *fileName)
|
|||||||
(fileNameNode->ToElement())->SetAttribute(TEXT("encoding"), viewSessionFiles[i]._encoding);
|
(fileNameNode->ToElement())->SetAttribute(TEXT("encoding"), viewSessionFiles[i]._encoding);
|
||||||
(fileNameNode->ToElement())->SetAttribute(TEXT("filename"), viewSessionFiles[i]._fileName.c_str());
|
(fileNameNode->ToElement())->SetAttribute(TEXT("filename"), viewSessionFiles[i]._fileName.c_str());
|
||||||
(fileNameNode->ToElement())->SetAttribute(TEXT("backupFilePath"), viewSessionFiles[i]._backupFilePath.c_str());
|
(fileNameNode->ToElement())->SetAttribute(TEXT("backupFilePath"), viewSessionFiles[i]._backupFilePath.c_str());
|
||||||
(fileNameNode->ToElement())->SetAttribute(TEXT("originalFileLastModifTimestamp"), static_cast<int32_t>(viewSessionFiles[i]._originalFileLastModifTimestamp));
|
(fileNameNode->ToElement())->SetAttribute(TEXT("originalFileLastModifTimestamp"), static_cast<int32_t>(viewSessionFiles[i]._originalFileLastModifTimestamp.dwLowDateTime));
|
||||||
|
(fileNameNode->ToElement())->SetAttribute(TEXT("originalFileLastModifTimestampHigh"), static_cast<int32_t>(viewSessionFiles[i]._originalFileLastModifTimestamp.dwHighDateTime));
|
||||||
|
|
||||||
// docMap
|
// docMap
|
||||||
(fileNameNode->ToElement())->SetAttribute(TEXT("mapFirstVisibleDisplayLine"), viewSessionFiles[i]._mapPos._firstVisibleDisplayLine);
|
(fileNameNode->ToElement())->SetAttribute(TEXT("mapFirstVisibleDisplayLine"), viewSessionFiles[i]._mapPos._firstVisibleDisplayLine);
|
||||||
|
@ -162,7 +162,7 @@ private:
|
|||||||
|
|
||||||
struct sessionFileInfo : public Position
|
struct sessionFileInfo : public Position
|
||||||
{
|
{
|
||||||
sessionFileInfo(const TCHAR *fn, const TCHAR *ln, int encoding, Position pos, const TCHAR *backupFilePath, int originalFileLastModifTimestamp, const MapPosition & mapPos) :
|
sessionFileInfo(const TCHAR *fn, const TCHAR *ln, int encoding, Position pos, const TCHAR *backupFilePath, FILETIME originalFileLastModifTimestamp, const MapPosition & mapPos) :
|
||||||
_encoding(encoding), Position(pos), _originalFileLastModifTimestamp(originalFileLastModifTimestamp), _mapPos(mapPos)
|
_encoding(encoding), Position(pos), _originalFileLastModifTimestamp(originalFileLastModifTimestamp), _mapPos(mapPos)
|
||||||
{
|
{
|
||||||
if (fn) _fileName = fn;
|
if (fn) _fileName = fn;
|
||||||
@ -179,7 +179,7 @@ struct sessionFileInfo : public Position
|
|||||||
int _encoding = -1;
|
int _encoding = -1;
|
||||||
|
|
||||||
generic_string _backupFilePath;
|
generic_string _backupFilePath;
|
||||||
time_t _originalFileLastModifTimestamp = 0;
|
FILETIME _originalFileLastModifTimestamp = {};
|
||||||
|
|
||||||
MapPosition _mapPos;
|
MapPosition _mapPos;
|
||||||
};
|
};
|
||||||
|
@ -144,10 +144,14 @@ void Buffer::setLangType(LangType lang, const TCHAR* userLangName)
|
|||||||
|
|
||||||
void Buffer::updateTimeStamp()
|
void Buffer::updateTimeStamp()
|
||||||
{
|
{
|
||||||
struct _stat buf;
|
FILETIME timeStamp = {};
|
||||||
time_t timeStamp = (generic_stat(_fullPathName.c_str(), &buf)==0)?buf.st_mtime:0;
|
WIN32_FILE_ATTRIBUTE_DATA attributes;
|
||||||
|
if (GetFileAttributesEx(_fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
|
||||||
|
{
|
||||||
|
timeStamp = attributes.ftLastWriteTime;
|
||||||
|
}
|
||||||
|
|
||||||
if (timeStamp != _timeStamp)
|
if (CompareFileTime(&_timeStamp, &timeStamp) != 0)
|
||||||
{
|
{
|
||||||
_timeStamp = timeStamp;
|
_timeStamp = timeStamp;
|
||||||
doNotify(BufferChangeTimestamp);
|
doNotify(BufferChangeTimestamp);
|
||||||
@ -222,7 +226,7 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c
|
|||||||
if (_currentStatus == DOC_UNNAMED) //unsaved document cannot change by environment
|
if (_currentStatus == DOC_UNNAMED) //unsaved document cannot change by environment
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct _stat buf;
|
WIN32_FILE_ATTRIBUTE_DATA attributes;
|
||||||
bool isWow64Off = false;
|
bool isWow64Off = false;
|
||||||
NppParameters *pNppParam = NppParameters::getInstance();
|
NppParameters *pNppParam = NppParameters::getInstance();
|
||||||
|
|
||||||
@ -238,18 +242,18 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c
|
|||||||
_currentStatus = DOC_DELETED;
|
_currentStatus = DOC_DELETED;
|
||||||
_isFileReadOnly = false;
|
_isFileReadOnly = false;
|
||||||
_isDirty = true; //dirty sicne no match with filesystem
|
_isDirty = true; //dirty sicne no match with filesystem
|
||||||
_timeStamp = 0;
|
_timeStamp = {};
|
||||||
doNotify(BufferChangeStatus | BufferChangeReadonly | BufferChangeTimestamp);
|
doNotify(BufferChangeStatus | BufferChangeReadonly | BufferChangeTimestamp);
|
||||||
isOK = true;
|
isOK = true;
|
||||||
}
|
}
|
||||||
else if (_currentStatus == DOC_DELETED && PathFileExists(_fullPathName.c_str()))
|
else if (_currentStatus == DOC_DELETED && PathFileExists(_fullPathName.c_str()))
|
||||||
{ //document has returned from its grave
|
{ //document has returned from its grave
|
||||||
if (not generic_stat(_fullPathName.c_str(), &buf))
|
if (GetFileAttributesEx(_fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
|
||||||
{
|
{
|
||||||
_isFileReadOnly = (bool)(!(buf.st_mode & _S_IWRITE));
|
_isFileReadOnly = attributes.dwFileAttributes & FILE_ATTRIBUTE_READONLY;
|
||||||
|
|
||||||
_currentStatus = DOC_MODIFIED;
|
_currentStatus = DOC_MODIFIED;
|
||||||
_timeStamp = buf.st_mtime;
|
_timeStamp = attributes.ftLastWriteTime;
|
||||||
|
|
||||||
if (_reloadFromDiskRequestGuard.try_lock())
|
if (_reloadFromDiskRequestGuard.try_lock())
|
||||||
{
|
{
|
||||||
@ -259,18 +263,18 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c
|
|||||||
isOK = true;
|
isOK = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (not generic_stat(_fullPathName.c_str(), &buf))
|
else if (GetFileAttributesEx(_fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
|
||||||
{
|
{
|
||||||
int mask = 0; //status always 'changes', even if from modified to modified
|
int mask = 0; //status always 'changes', even if from modified to modified
|
||||||
bool isFileReadOnly = (bool)(not(buf.st_mode & _S_IWRITE));
|
bool isFileReadOnly = attributes.dwFileAttributes & FILE_ATTRIBUTE_READONLY;
|
||||||
if (isFileReadOnly != _isFileReadOnly)
|
if (isFileReadOnly != _isFileReadOnly)
|
||||||
{
|
{
|
||||||
_isFileReadOnly = isFileReadOnly;
|
_isFileReadOnly = isFileReadOnly;
|
||||||
mask |= BufferChangeReadonly;
|
mask |= BufferChangeReadonly;
|
||||||
}
|
}
|
||||||
if (_timeStamp != buf.st_mtime)
|
if (CompareFileTime(&_timeStamp, &attributes.ftLastWriteTime) != 0)
|
||||||
{
|
{
|
||||||
_timeStamp = buf.st_mtime;
|
_timeStamp = attributes.ftLastWriteTime;
|
||||||
mask |= BufferChangeTimestamp;
|
mask |= BufferChangeTimestamp;
|
||||||
_currentStatus = DOC_MODIFIED;
|
_currentStatus = DOC_MODIFIED;
|
||||||
mask |= BufferChangeStatus; //status always 'changes', even if from modified to modified
|
mask |= BufferChangeStatus; //status always 'changes', even if from modified to modified
|
||||||
@ -300,10 +304,10 @@ bool Buffer::checkFileState() //eturns true if the status has been changed (it c
|
|||||||
|
|
||||||
void Buffer::reload()
|
void Buffer::reload()
|
||||||
{
|
{
|
||||||
struct _stat buf;
|
WIN32_FILE_ATTRIBUTE_DATA attributes;
|
||||||
if (PathFileExists(_fullPathName.c_str()) && not generic_stat(_fullPathName.c_str(), &buf))
|
if (GetFileAttributesEx(_fullPathName.c_str(), GetFileExInfoStandard, &attributes) != 0)
|
||||||
{
|
{
|
||||||
_timeStamp = buf.st_mtime;
|
_timeStamp = attributes.ftLastWriteTime;
|
||||||
_currentStatus = DOC_NEEDRELOAD;
|
_currentStatus = DOC_NEEDRELOAD;
|
||||||
doNotify(BufferChangeTimestamp | BufferChangeStatus);
|
doNotify(BufferChangeTimestamp | BufferChangeStatus);
|
||||||
}
|
}
|
||||||
@ -552,7 +556,7 @@ void FileManager::closeBuffer(BufferID id, ScintillaEditView * identifier)
|
|||||||
|
|
||||||
|
|
||||||
// backupFileName is sentinel of backup mode: if it's not NULL, then we use it (load it). Otherwise we use filename
|
// backupFileName is sentinel of backup mode: if it's not NULL, then we use it (load it). Otherwise we use filename
|
||||||
BufferID FileManager::loadFile(const TCHAR * filename, Document doc, int encoding, const TCHAR *backupFileName, time_t fileNameTimestamp)
|
BufferID FileManager::loadFile(const TCHAR * filename, Document doc, int encoding, const TCHAR *backupFileName, FILETIME fileNameTimestamp)
|
||||||
{
|
{
|
||||||
bool ownDoc = false;
|
bool ownDoc = false;
|
||||||
if (doc == NULL)
|
if (doc == NULL)
|
||||||
@ -593,7 +597,8 @@ BufferID FileManager::loadFile(const TCHAR * filename, Document doc, int encodin
|
|||||||
newBuf->_currentStatus = DOC_UNNAMED;
|
newBuf->_currentStatus = DOC_UNNAMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileNameTimestamp != 0)
|
const FILETIME zeroTime = {};
|
||||||
|
if (CompareFileTime(&fileNameTimestamp, &zeroTime) != 0)
|
||||||
newBuf->_timeStamp = fileNameTimestamp;
|
newBuf->_timeStamp = fileNameTimestamp;
|
||||||
|
|
||||||
_buffers.push_back(newBuf);
|
_buffers.push_back(newBuf);
|
||||||
|
@ -87,7 +87,7 @@ public:
|
|||||||
|
|
||||||
void addBufferReference(BufferID id, ScintillaEditView * identifer); //called by Scintilla etc indirectly
|
void addBufferReference(BufferID id, ScintillaEditView * identifer); //called by Scintilla etc indirectly
|
||||||
|
|
||||||
BufferID loadFile(const TCHAR * filename, Document doc = NULL, int encoding = -1, const TCHAR *backupFileName = NULL, time_t fileNameTimestamp = 0); //ID == BUFFER_INVALID on failure. If Doc == NULL, a new file is created, otherwise data is loaded in given document
|
BufferID loadFile(const TCHAR * filename, Document doc = NULL, int encoding = -1, const TCHAR *backupFileName = NULL, FILETIME fileNameTimestamp = {}); //ID == BUFFER_INVALID on failure. If Doc == NULL, a new file is created, otherwise data is loaded in given document
|
||||||
BufferID newEmptyDocument();
|
BufferID newEmptyDocument();
|
||||||
//create Buffer from existing Scintilla, used from new Scintillas. If dontIncrease = true, then the new document number isnt increased afterwards.
|
//create Buffer from existing Scintilla, used from new Scintillas. If dontIncrease = true, then the new document number isnt increased afterwards.
|
||||||
//usefull for temporary but neccesary docs
|
//usefull for temporary but neccesary docs
|
||||||
@ -321,7 +321,7 @@ public:
|
|||||||
void setModifiedStatus(bool isModified) { _isModified = isModified; }
|
void setModifiedStatus(bool isModified) { _isModified = isModified; }
|
||||||
generic_string getBackupFileName() const { return _backupFileName; }
|
generic_string getBackupFileName() const { return _backupFileName; }
|
||||||
void setBackupFileName(generic_string fileName) { _backupFileName = fileName; }
|
void setBackupFileName(generic_string fileName) { _backupFileName = fileName; }
|
||||||
time_t getLastModifiedTimestamp() const { return _timeStamp; }
|
FILETIME getLastModifiedTimestamp() const { return _timeStamp; }
|
||||||
|
|
||||||
bool isLoadedDirty() const
|
bool isLoadedDirty() const
|
||||||
{
|
{
|
||||||
@ -394,7 +394,7 @@ private:
|
|||||||
|
|
||||||
//Environment properties
|
//Environment properties
|
||||||
DocFileStatus _currentStatus;
|
DocFileStatus _currentStatus;
|
||||||
time_t _timeStamp = 0; // 0 if it's a new doc
|
FILETIME _timeStamp = {}; // 0 if it's a new doc
|
||||||
|
|
||||||
bool _isFileReadOnly = false;
|
bool _isFileReadOnly = false;
|
||||||
generic_string _fullPathName;
|
generic_string _fullPathName;
|
||||||
|
Loading…
Reference in New Issue
Block a user