mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-28 16:24:27 +02:00
Fix NUL file-corruption issue after system shutting down brutally
Uses native Win32 IO API (CreateFile, ReadFile, WriteFile, CloseHandle) instead of POSIX ones (fopen, fread, fwrite, fclose) for remedying NUL file-corruption problem due to system shutting down brutally. Fix #6133, close #10598
This commit is contained in:
parent
49c3e5d553
commit
9aa9ecb664
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include "StaticDialog.h"
|
#include "StaticDialog.h"
|
||||||
#include "CustomFileDialog.h"
|
#include "CustomFileDialog.h"
|
||||||
|
|
||||||
|
#include "FileInterface.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Utf8.h"
|
#include "Utf8.h"
|
||||||
#include <Parameters.h>
|
#include <Parameters.h>
|
||||||
@ -113,20 +115,19 @@ generic_string relativeFilePathToFullFilePath(const TCHAR *relativeFilePath)
|
|||||||
|
|
||||||
void writeFileContent(const TCHAR *file2write, const char *content2write)
|
void writeFileContent(const TCHAR *file2write, const char *content2write)
|
||||||
{
|
{
|
||||||
FILE *f = generic_fopen(file2write, TEXT("w+c"));
|
CFile file(file2write, CFile::Mode::WRITE);
|
||||||
fwrite(content2write, sizeof(content2write[0]), strlen(content2write), f);
|
|
||||||
fflush(f);
|
if (file.IsOpened())
|
||||||
fclose(f);
|
file.Write(content2write, static_cast<unsigned long>(strlen(content2write)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void writeLog(const TCHAR *logFileName, const char *log2write)
|
void writeLog(const TCHAR *logFileName, const char *log2write)
|
||||||
{
|
{
|
||||||
FILE *f = generic_fopen(logFileName, TEXT("a+c"));
|
CFile file(logFileName, CFile::Mode::APPEND);
|
||||||
fwrite(log2write, sizeof(log2write[0]), strlen(log2write), f);
|
|
||||||
fputc('\n', f);
|
if (file.IsOpened())
|
||||||
fflush(f);
|
file.Write(log2write, static_cast<unsigned long>(strlen(log2write)));
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
142
PowerEditor/src/MISC/Common/FileInterface.cpp
Normal file
142
PowerEditor/src/MISC/Common/FileInterface.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// This file is part of Notepad++ project
|
||||||
|
// Copyright (C)2021 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 3 of the License, or
|
||||||
|
// at your option any later version.
|
||||||
|
//
|
||||||
|
// 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, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#include "FileInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
CFile::CFile(const char *fname, Mode fmode) : _hMode(fmode)
|
||||||
|
{
|
||||||
|
if (fname)
|
||||||
|
{
|
||||||
|
DWORD access, share, disp, attrib;
|
||||||
|
fillCreateParams(access, share, disp, attrib);
|
||||||
|
|
||||||
|
_hFile = ::CreateFileA(fname, access, share, NULL, disp, attrib, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_hFile != INVALID_HANDLE_VALUE) && (_hMode == Mode::APPEND))
|
||||||
|
{
|
||||||
|
LARGE_INTEGER offset;
|
||||||
|
offset.QuadPart = 0;
|
||||||
|
|
||||||
|
::SetFilePointerEx(_hFile, offset, NULL, FILE_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CFile::CFile(const wchar_t *fname, Mode fmode) : _hMode(fmode)
|
||||||
|
{
|
||||||
|
if (fname)
|
||||||
|
{
|
||||||
|
DWORD access, share, disp, attrib;
|
||||||
|
fillCreateParams(access, share, disp, attrib);
|
||||||
|
|
||||||
|
_hFile = ::CreateFileW(fname, access, share, NULL, disp, attrib, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_hFile != INVALID_HANDLE_VALUE) && (_hMode == Mode::APPEND))
|
||||||
|
{
|
||||||
|
LARGE_INTEGER offset;
|
||||||
|
offset.QuadPart = 0;
|
||||||
|
|
||||||
|
::SetFilePointerEx(_hFile, offset, NULL, FILE_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CFile::Close()
|
||||||
|
{
|
||||||
|
if (IsOpened())
|
||||||
|
{
|
||||||
|
if (_written)
|
||||||
|
{
|
||||||
|
::SetEndOfFile(_hFile);
|
||||||
|
::FlushFileBuffers(_hFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
::CloseHandle(_hFile);
|
||||||
|
|
||||||
|
_hFile = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int_fast64_t CFile::GetSize()
|
||||||
|
{
|
||||||
|
LARGE_INTEGER r;
|
||||||
|
r.QuadPart = -1;
|
||||||
|
|
||||||
|
if (IsOpened())
|
||||||
|
::GetFileSizeEx(_hFile, &r);
|
||||||
|
|
||||||
|
return static_cast<int_fast64_t>(r.QuadPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long CFile::Read(void *rbuf, unsigned long buf_size)
|
||||||
|
{
|
||||||
|
if (!IsOpened() || (rbuf == nullptr) || (buf_size == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
DWORD bytes_read = 0;
|
||||||
|
|
||||||
|
if (::ReadFile(_hFile, rbuf, buf_size, &bytes_read, NULL) == FALSE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CFile::Write(const void *wbuf, unsigned long buf_size)
|
||||||
|
{
|
||||||
|
if (!IsOpened() || (wbuf == nullptr) || (buf_size == 0) || ((_hMode != Mode::WRITE) && (_hMode != Mode::APPEND)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DWORD bytes_written = 0;
|
||||||
|
|
||||||
|
if (::WriteFile(_hFile, wbuf, buf_size, &bytes_written, NULL) == FALSE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_written && (bytes_written != 0))
|
||||||
|
_written = true;
|
||||||
|
|
||||||
|
return (bytes_written == buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function to auto-fill CreateFile params optimized for Notepad++ usage.
|
||||||
|
void CFile::fillCreateParams(DWORD &access, DWORD &share, DWORD &disp, DWORD &attrib)
|
||||||
|
{
|
||||||
|
access = GENERIC_READ;
|
||||||
|
attrib = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_POSIX_SEMANTICS; // Distinguish between upper/lower case in name
|
||||||
|
|
||||||
|
if (_hMode == Mode::READ)
|
||||||
|
{
|
||||||
|
share = FILE_SHARE_READ;
|
||||||
|
disp = OPEN_EXISTING; // Open only if file exists and is not locked by other process
|
||||||
|
|
||||||
|
attrib |= FILE_FLAG_SEQUENTIAL_SCAN; // Optimize caching for sequential read
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
share = 0;
|
||||||
|
disp = OPEN_ALWAYS; // Open existing file for writing without destroying it or create new
|
||||||
|
|
||||||
|
access |= GENERIC_WRITE;
|
||||||
|
attrib |= FILE_FLAG_WRITE_THROUGH; // Write cached data directly to disk (no lazy writer)
|
||||||
|
}
|
||||||
|
}
|
64
PowerEditor/src/MISC/Common/FileInterface.h
Normal file
64
PowerEditor/src/MISC/Common/FileInterface.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// This file is part of Notepad++ project
|
||||||
|
// Copyright (C)2021 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 3 of the License, or
|
||||||
|
// at your option any later version.
|
||||||
|
//
|
||||||
|
// 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, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
|
class CFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Mode
|
||||||
|
{
|
||||||
|
READ,
|
||||||
|
WRITE,
|
||||||
|
APPEND
|
||||||
|
};
|
||||||
|
|
||||||
|
CFile(const char *fname, Mode fmode = Mode::READ);
|
||||||
|
CFile(const wchar_t *fname, Mode fmode = Mode::READ);
|
||||||
|
|
||||||
|
~CFile()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOpened()
|
||||||
|
{
|
||||||
|
return (_hFile != INVALID_HANDLE_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
int_fast64_t GetSize();
|
||||||
|
|
||||||
|
unsigned long Read(void *rbuf, unsigned long buf_size);
|
||||||
|
bool Write(const void *wbuf, unsigned long buf_size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CFile(const CFile&) = delete;
|
||||||
|
CFile& operator=(const CFile&) = delete;
|
||||||
|
|
||||||
|
void fillCreateParams(DWORD &access, DWORD &share, DWORD &disp, DWORD &attrib);
|
||||||
|
|
||||||
|
HANDLE _hFile {INVALID_HANDLE_VALUE};
|
||||||
|
Mode _hMode {Mode::READ};
|
||||||
|
bool _written {false};
|
||||||
|
};
|
@ -25,6 +25,7 @@
|
|||||||
#include "ScintillaEditView.h"
|
#include "ScintillaEditView.h"
|
||||||
#include "EncodingMapper.h"
|
#include "EncodingMapper.h"
|
||||||
#include "uchardet.h"
|
#include "uchardet.h"
|
||||||
|
#include "FileInterface.h"
|
||||||
|
|
||||||
static const int blockSize = 128 * 1024 + 4;
|
static const int blockSize = 128 * 1024 + 4;
|
||||||
static const int CR = 0x0D;
|
static const int CR = 0x0D;
|
||||||
@ -868,15 +869,14 @@ bool FileManager::backupCurrentBuffer()
|
|||||||
::SetFileAttributes(fullpath, dwFileAttribs);
|
::SetFileAttributes(fullpath, dwFileAttribs);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *fp = UnicodeConvertor.fopen(fullpath, TEXT("wbc"));
|
if (UnicodeConvertor.fopen(fullpath))
|
||||||
if (fp)
|
|
||||||
{
|
{
|
||||||
int lengthDoc = _pNotepadPlus->_pEditView->getCurrentDocLen();
|
int lengthDoc = _pNotepadPlus->_pEditView->getCurrentDocLen();
|
||||||
char* buf = (char*)_pNotepadPlus->_pEditView->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer
|
char* buf = (char*)_pNotepadPlus->_pEditView->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer
|
||||||
size_t items_written = 0;
|
long items_written = 0;
|
||||||
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
|
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
|
||||||
{
|
{
|
||||||
items_written = UnicodeConvertor.fwrite(buf, lengthDoc);
|
items_written = UnicodeConvertor.fwrite(buf, static_cast<unsigned long>(lengthDoc));
|
||||||
if (lengthDoc == 0)
|
if (lengthDoc == 0)
|
||||||
items_written = 1;
|
items_written = 1;
|
||||||
}
|
}
|
||||||
@ -894,7 +894,7 @@ bool FileManager::backupCurrentBuffer()
|
|||||||
int incompleteMultibyteChar = 0;
|
int incompleteMultibyteChar = 0;
|
||||||
const char *newData = wmc.encode(SC_CP_UTF8, encoding, buf+i, grabSize, &newDataLen, &incompleteMultibyteChar);
|
const char *newData = wmc.encode(SC_CP_UTF8, encoding, buf+i, grabSize, &newDataLen, &incompleteMultibyteChar);
|
||||||
grabSize -= incompleteMultibyteChar;
|
grabSize -= incompleteMultibyteChar;
|
||||||
items_written = UnicodeConvertor.fwrite(newData, newDataLen);
|
items_written = UnicodeConvertor.fwrite(newData, static_cast<unsigned long>(newDataLen));
|
||||||
}
|
}
|
||||||
if (lengthDoc == 0)
|
if (lengthDoc == 0)
|
||||||
items_written = 1;
|
items_written = 1;
|
||||||
@ -993,22 +993,16 @@ SavingStatus FileManager::saveBuffer(BufferID id, const TCHAR * filename, bool i
|
|||||||
|
|
||||||
int encoding = buffer->getEncoding();
|
int encoding = buffer->getEncoding();
|
||||||
|
|
||||||
FILE *fp = UnicodeConvertor.fopen(fullpath, TEXT("wbc"));
|
if (UnicodeConvertor.fopen(fullpath))
|
||||||
|
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
return SavingStatus::SaveOpenFailed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, buffer->_doc); //generate new document
|
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, buffer->_doc); //generate new document
|
||||||
|
|
||||||
int lengthDoc = _pscratchTilla->getCurrentDocLen();
|
int lengthDoc = _pscratchTilla->getCurrentDocLen();
|
||||||
char* buf = (char*)_pscratchTilla->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer
|
char* buf = (char*)_pscratchTilla->execute(SCI_GETCHARACTERPOINTER); //to get characters directly from Scintilla buffer
|
||||||
size_t items_written = 0;
|
long items_written = 0;
|
||||||
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
|
if (encoding == -1) //no special encoding; can be handled directly by Utf8_16_Write
|
||||||
{
|
{
|
||||||
items_written = UnicodeConvertor.fwrite(buf, lengthDoc);
|
items_written = UnicodeConvertor.fwrite(buf, static_cast<unsigned long>(lengthDoc));
|
||||||
if (lengthDoc == 0)
|
if (lengthDoc == 0)
|
||||||
items_written = 1;
|
items_written = 1;
|
||||||
}
|
}
|
||||||
@ -1026,7 +1020,7 @@ SavingStatus FileManager::saveBuffer(BufferID id, const TCHAR * filename, bool i
|
|||||||
int incompleteMultibyteChar = 0;
|
int incompleteMultibyteChar = 0;
|
||||||
const char *newData = wmc.encode(SC_CP_UTF8, encoding, buf+i, grabSize, &newDataLen, &incompleteMultibyteChar);
|
const char *newData = wmc.encode(SC_CP_UTF8, encoding, buf+i, grabSize, &newDataLen, &incompleteMultibyteChar);
|
||||||
grabSize -= incompleteMultibyteChar;
|
grabSize -= incompleteMultibyteChar;
|
||||||
items_written = UnicodeConvertor.fwrite(newData, newDataLen);
|
items_written = UnicodeConvertor.fwrite(newData, static_cast<unsigned long>(newDataLen));
|
||||||
}
|
}
|
||||||
if (lengthDoc == 0)
|
if (lengthDoc == 0)
|
||||||
items_written = 1;
|
items_written = 1;
|
||||||
@ -1071,6 +1065,10 @@ SavingStatus FileManager::saveBuffer(BufferID id, const TCHAR * filename, bool i
|
|||||||
|
|
||||||
return SavingStatus::SaveOK;
|
return SavingStatus::SaveOK;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SavingStatus::SaveOpenFailed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FileManager::nextUntitledNewNumber() const
|
size_t FileManager::nextUntitledNewNumber() const
|
||||||
@ -1478,12 +1476,8 @@ BufferID FileManager::getBufferFromDocument(Document doc)
|
|||||||
|
|
||||||
bool FileManager::createEmptyFile(const TCHAR * path)
|
bool FileManager::createEmptyFile(const TCHAR * path)
|
||||||
{
|
{
|
||||||
FILE * file = generic_fopen(path, TEXT("wbc"));
|
CFile file(path, CFile::Mode::WRITE);
|
||||||
if (!file)
|
return file.IsOpened();
|
||||||
return false;
|
|
||||||
fflush(file);
|
|
||||||
fclose(file);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,7 +278,6 @@ UniMode Utf8_16_Read::determineEncoding(const unsigned char *buf, size_t bufLen)
|
|||||||
Utf8_16_Write::Utf8_16_Write()
|
Utf8_16_Write::Utf8_16_Write()
|
||||||
{
|
{
|
||||||
m_eEncoding = uni8Bit;
|
m_eEncoding = uni8Bit;
|
||||||
m_pFile = NULL;
|
|
||||||
m_pNewBuf = NULL;
|
m_pNewBuf = NULL;
|
||||||
m_bFirstWrite = true;
|
m_bFirstWrite = true;
|
||||||
m_nBufSize = 0;
|
m_nBufSize = 0;
|
||||||
@ -289,16 +288,25 @@ Utf8_16_Write::~Utf8_16_Write()
|
|||||||
fclose();
|
fclose();
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE * Utf8_16_Write::fopen(const TCHAR *_name, const TCHAR *_type)
|
bool Utf8_16_Write::fopen(const TCHAR *name)
|
||||||
{
|
{
|
||||||
m_pFile = ::generic_fopen(_name, _type);
|
m_pFile = std::make_unique<CFile>(name, CFile::Mode::WRITE);
|
||||||
|
|
||||||
|
if (!m_pFile)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!m_pFile->IsOpened())
|
||||||
|
{
|
||||||
|
m_pFile = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_bFirstWrite = true;
|
m_bFirstWrite = true;
|
||||||
|
|
||||||
return m_pFile;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Utf8_16_Write::fwrite(const void* p, size_t _size)
|
unsigned long Utf8_16_Write::fwrite(const void* p, unsigned long _size)
|
||||||
{
|
{
|
||||||
// no file open
|
// no file open
|
||||||
if (!m_pFile)
|
if (!m_pFile)
|
||||||
@ -306,19 +314,19 @@ size_t Utf8_16_Write::fwrite(const void* p, size_t _size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ret = 0;
|
|
||||||
|
|
||||||
if (m_bFirstWrite)
|
if (m_bFirstWrite)
|
||||||
{
|
{
|
||||||
switch (m_eEncoding)
|
switch (m_eEncoding)
|
||||||
{
|
{
|
||||||
case uniUTF8: {
|
case uniUTF8: {
|
||||||
::fwrite(k_Boms[m_eEncoding], 3, 1, m_pFile);
|
if (!m_pFile->Write(k_Boms[m_eEncoding], 3))
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case uni16BE:
|
case uni16BE:
|
||||||
case uni16LE:
|
case uni16LE:
|
||||||
::fwrite(k_Boms[m_eEncoding], 2, 1, m_pFile);
|
if (!m_pFile->Write(k_Boms[m_eEncoding], 2))
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
@ -326,7 +334,9 @@ size_t Utf8_16_Write::fwrite(const void* p, size_t _size)
|
|||||||
}
|
}
|
||||||
m_bFirstWrite = false;
|
m_bFirstWrite = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long ret = 0;
|
||||||
|
|
||||||
switch (m_eEncoding)
|
switch (m_eEncoding)
|
||||||
{
|
{
|
||||||
case uni7Bit:
|
case uni7Bit:
|
||||||
@ -334,27 +344,28 @@ size_t Utf8_16_Write::fwrite(const void* p, size_t _size)
|
|||||||
case uniCookie:
|
case uniCookie:
|
||||||
case uniUTF8: {
|
case uniUTF8: {
|
||||||
// Normal write
|
// Normal write
|
||||||
ret = ::fwrite(p, _size, 1, m_pFile);
|
if (m_pFile->Write(p, _size))
|
||||||
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case uni16BE_NoBOM:
|
case uni16BE_NoBOM:
|
||||||
case uni16LE_NoBOM:
|
case uni16LE_NoBOM:
|
||||||
case uni16BE:
|
case uni16BE:
|
||||||
case uni16LE: {
|
case uni16LE: {
|
||||||
static const int bufSize = 64*1024;
|
static const unsigned int bufSize = 64*1024;
|
||||||
utf16 buf[bufSize];
|
utf16 buf[bufSize];
|
||||||
|
|
||||||
Utf8_Iter iter8;
|
Utf8_Iter iter8;
|
||||||
iter8.set(static_cast<const ubyte*>(p), _size, m_eEncoding);
|
iter8.set(static_cast<const ubyte*>(p), _size, m_eEncoding);
|
||||||
|
|
||||||
int bufIndex = 0;
|
unsigned int bufIndex = 0;
|
||||||
while (iter8) {
|
while (iter8) {
|
||||||
++iter8;
|
++iter8;
|
||||||
while ((bufIndex < bufSize) && iter8.canGet())
|
while ((bufIndex < bufSize) && iter8.canGet())
|
||||||
iter8.get(&buf [bufIndex++]);
|
iter8.get(&buf [bufIndex++]);
|
||||||
|
|
||||||
if (bufIndex == bufSize || !iter8) {
|
if (bufIndex == bufSize || !iter8) {
|
||||||
if (!::fwrite(buf, bufIndex*sizeof(utf16), 1, m_pFile)) return 0;
|
if (!m_pFile->Write(buf, bufIndex*sizeof(utf16))) return 0;
|
||||||
bufIndex = 0;
|
bufIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,6 +385,7 @@ size_t Utf8_16_Write::convert(char* p, size_t _size)
|
|||||||
if (m_pNewBuf)
|
if (m_pNewBuf)
|
||||||
{
|
{
|
||||||
delete [] m_pNewBuf;
|
delete [] m_pNewBuf;
|
||||||
|
m_pNewBuf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_eEncoding)
|
switch (m_eEncoding)
|
||||||
@ -445,11 +457,7 @@ void Utf8_16_Write::fclose()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_pFile)
|
if (m_pFile)
|
||||||
{
|
m_pFile = nullptr;
|
||||||
::fflush(m_pFile);
|
|
||||||
::fclose(m_pFile);
|
|
||||||
m_pFile = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
#pragma warning(disable: 4514) // nreferenced inline function has been removed
|
#pragma warning(disable: 4514) // nreferenced inline function has been removed
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "FileInterface.h"
|
||||||
|
|
||||||
|
|
||||||
class Utf8_16 {
|
class Utf8_16 {
|
||||||
public:
|
public:
|
||||||
typedef unsigned short utf16; // 16 bits
|
typedef unsigned short utf16; // 16 bits
|
||||||
@ -135,16 +139,16 @@ public:
|
|||||||
|
|
||||||
void setEncoding(UniMode eType);
|
void setEncoding(UniMode eType);
|
||||||
|
|
||||||
FILE * fopen(const TCHAR *_name, const TCHAR *_type);
|
bool fopen(const TCHAR *name);
|
||||||
size_t fwrite(const void* p, size_t _size);
|
unsigned long fwrite(const void* p, unsigned long _size);
|
||||||
void fclose();
|
void fclose();
|
||||||
|
|
||||||
size_t convert(char* p, size_t _size);
|
size_t convert(char* p, size_t _size);
|
||||||
char* getNewBuf() { return reinterpret_cast<char*>(m_pNewBuf); }
|
char* getNewBuf() { return reinterpret_cast<char*>(m_pNewBuf); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UniMode m_eEncoding;
|
UniMode m_eEncoding;
|
||||||
FILE* m_pFile;
|
std::unique_ptr<CFile> m_pFile;
|
||||||
ubyte* m_pNewBuf;
|
ubyte* m_pNewBuf;
|
||||||
size_t m_nBufSize;
|
size_t m_nBufSize;
|
||||||
bool m_bFirstWrite;
|
bool m_bFirstWrite;
|
||||||
|
@ -421,6 +421,7 @@ copy ..\src\contextMenu.xml ..\binarm64\contextMenu.xml
|
|||||||
<ClCompile Include="..\src\WinControls\ColourPicker\ColourPopup.cpp" />
|
<ClCompile Include="..\src\WinControls\ColourPicker\ColourPopup.cpp" />
|
||||||
<ClCompile Include="..\src\ScintillaComponent\columnEditor.cpp" />
|
<ClCompile Include="..\src\ScintillaComponent\columnEditor.cpp" />
|
||||||
<ClCompile Include="..\src\MISC\Common\Common.cpp" />
|
<ClCompile Include="..\src\MISC\Common\Common.cpp" />
|
||||||
|
<ClCompile Include="..\src\MISC\Common\FileInterface.cpp" />
|
||||||
<ClCompile Include="..\src\WinControls\ContextMenu\ContextMenu.cpp" />
|
<ClCompile Include="..\src\WinControls\ContextMenu\ContextMenu.cpp" />
|
||||||
<ClCompile Include="..\src\WinControls\OpenSaveFileDialog\CustomFileDialog.cpp" />
|
<ClCompile Include="..\src\WinControls\OpenSaveFileDialog\CustomFileDialog.cpp" />
|
||||||
<ClCompile Include="..\src\WinControls\PluginsAdmin\pluginsAdmin.cpp" />
|
<ClCompile Include="..\src\WinControls\PluginsAdmin\pluginsAdmin.cpp" />
|
||||||
@ -708,6 +709,7 @@ copy ..\src\contextMenu.xml ..\binarm64\contextMenu.xml
|
|||||||
<ClInclude Include="..\src\WinControls\ColourPicker\ColourPopup.h" />
|
<ClInclude Include="..\src\WinControls\ColourPicker\ColourPopup.h" />
|
||||||
<ClInclude Include="..\src\ScintillaComponent\columnEditor.h" />
|
<ClInclude Include="..\src\ScintillaComponent\columnEditor.h" />
|
||||||
<ClInclude Include="..\src\MISC\Common\Common.h" />
|
<ClInclude Include="..\src\MISC\Common\Common.h" />
|
||||||
|
<ClInclude Include="..\src\MISC\Common\FileInterface.h" />
|
||||||
<ClInclude Include="..\src\WinControls\ContextMenu\ContextMenu.h" />
|
<ClInclude Include="..\src\WinControls\ContextMenu\ContextMenu.h" />
|
||||||
<ClInclude Include="..\src\WinControls\OpenSaveFileDialog\CustomFileDialog.h" />
|
<ClInclude Include="..\src\WinControls\OpenSaveFileDialog\CustomFileDialog.h" />
|
||||||
<ClInclude Include="..\src\WinControls\PluginsAdmin\pluginsAdmin.h" />
|
<ClInclude Include="..\src\WinControls\PluginsAdmin\pluginsAdmin.h" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user