Beispiel #1
0
bool FileManager::reloadBuffer(BufferID id)
{
	Buffer * buf = getBufferByID(id);
	Document doc = buf->getDocument();
	Utf8_16_Read UnicodeConvertor;
	buf->_canNotify = false;    // Disable notify during file load, we don't want dirty to be triggered
	int encoding = buf->getEncoding();
	formatType format;
	bool res = loadFileData(doc, buf->getFullPathName(), &UnicodeConvertor, buf->getLangType(), encoding, &format);
	buf->_canNotify = true;
	if (res)
	{
		if (encoding == -1)
		{
			if (UnicodeConvertor.getNewBuf())
			{
				int format = getEOLFormatForm(UnicodeConvertor.getNewBuf());
				buf->setFormat(format == -1?WIN_FORMAT:(formatType)format);
			}
			else
			{
				buf->setFormat(WIN_FORMAT);
			}
			buf->setUnicodeMode(UnicodeConvertor.getEncoding());
		}
		else
		{
			buf->setEncoding(encoding);
			buf->setFormat(format);
			buf->setUnicodeMode(uniCookie);
		}
	}
	return res;
}
bool FileManager::reloadBuffer(BufferID id)
{
	Buffer* buf = getBufferByID(id);
	Document doc = buf->getDocument();
	Utf8_16_Read UnicodeConvertor;
	buf->_canNotify = false;	//disable notify during file load, we dont want dirty to be triggered
	int encoding = buf->getEncoding();
	char data[blockSize + 8]; // +8 for incomplete multibyte char
	FormatType bkformat;
	LangType lang = buf->getLangType();

	bool res = loadFileData(doc, buf->getFullPathName(), data, &UnicodeConvertor, lang, encoding, &bkformat);
	buf->_canNotify = true;

	if (res)
	{
		if (encoding == -1)
		{
			if (nullptr != UnicodeConvertor.getNewBuf())
			{
				FormatType format = getEOLFormatForm(UnicodeConvertor.getNewBuf(), UnicodeConvertor.getNewSize());
				buf->setFormat(format);
			}
			else
				buf->setFormat(FormatType::osdefault);

			buf->setUnicodeMode(UnicodeConvertor.getEncoding());
		}
		else
		{
			buf->setEncoding(encoding);
			buf->setFormat(bkformat);
			buf->setUnicodeMode(uniCookie);
		}
	}
	return res;
}
// 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)
{
	bool ownDoc = false;
	if (doc == NULL)
	{
		doc = (Document)_pscratchTilla->execute(SCI_CREATEDOCUMENT);
		ownDoc = true;
	}

	TCHAR fullpath[MAX_PATH];
	::GetFullPathName(filename, MAX_PATH, fullpath, NULL);
	::GetLongPathName(fullpath, fullpath, MAX_PATH);

	bool isSnapshotMode = backupFileName != NULL && PathFileExists(backupFileName);
	if (isSnapshotMode && !PathFileExists(fullpath)) // if backup mode and fullpath doesn't exist, we guess is UNTITLED
	{
		lstrcpy(fullpath, filename); // we restore fullpath with filename, in our case is "new  #"
	}

	Utf8_16_Read UnicodeConvertor;	//declare here so we can get information after loading is done

	char data[blockSize + 8]; // +8 for incomplete multibyte char
	FormatType bkformat = FormatType::unknown;
	LangType detectedLang = L_TEXT;
	bool res = loadFileData(doc, backupFileName ? backupFileName : fullpath, data, &UnicodeConvertor, detectedLang, encoding, &bkformat);
	if (res)
	{
		Buffer* newBuf = new Buffer(this, _nextBufferID, doc, DOC_REGULAR, fullpath);
		BufferID id = (BufferID) newBuf;
		newBuf->_id = id;

		if (backupFileName != NULL)
		{
			newBuf->_backupFileName = backupFileName;
			if (!PathFileExists(fullpath))
				newBuf->_currentStatus = DOC_UNNAMED;
		}

		if (fileNameTimestamp != 0)
			newBuf->_timeStamp = fileNameTimestamp;

		_buffers.push_back(newBuf);
		++_nrBufs;
		Buffer* buf = _buffers.at(_nrBufs - 1);

		// restore the encoding (ANSI based) while opening the existing file
		NppParameters *pNppParamInst = NppParameters::getInstance();
		const NewDocDefaultSettings & ndds = (pNppParamInst->getNppGUI()).getNewDocDefaultSettings();
		buf->setUnicodeMode(ndds._unicodeMode);
		buf->setEncoding(-1);

		// if a language has been detected, and the detected value is different from the file extension,
		// we use the detected value
		if (detectedLang != L_TEXT && detectedLang != buf->getLangType())
			buf->setLangType(detectedLang);

		if (encoding == -1)
		{
			// 3 formats : WIN_FORMAT, UNIX_FORMAT and MAC_FORMAT
			if (nullptr != UnicodeConvertor.getNewBuf())
			{
				FormatType format = getEOLFormatForm(UnicodeConvertor.getNewBuf(), UnicodeConvertor.getNewSize());
				buf->setFormat(format);
			}
			else
				buf->setFormat(FormatType::osdefault);

			UniMode um = UnicodeConvertor.getEncoding();
			if (um == uni7Bit)
				um = (ndds._openAnsiAsUtf8) ? uniCookie : uni8Bit;

			buf->setUnicodeMode(um);
		}
		else // encoding != -1
		{
            // Test if encoding is set to UTF8 w/o BOM (usually for utf8 indicator of xml or html)
            buf->setEncoding((encoding == SC_CP_UTF8)?-1:encoding);
            buf->setUnicodeMode(uniCookie);
			buf->setFormat(bkformat);
		}

		//determine buffer properties
		++_nextBufferID;
		return id;
	}
	else //failed loading, release document
	{
		if (ownDoc)
			_pscratchTilla->execute(SCI_RELEASEDOCUMENT, 0, doc);	//Failure, so release document
		return BUFFER_INVALID;
	}
}
inline bool FileManager::loadFileData(Document doc, const TCHAR * filename, char* data, Utf8_16_Read * UnicodeConvertor,
	LangType & language, int & encoding, FormatType* pFormat)
{
	FILE *fp = generic_fopen(filename, TEXT("rb"));
	if (!fp)
		return false;

	//Get file size
	_fseeki64 (fp , 0 , SEEK_END);
	unsigned __int64 fileSize =_ftelli64(fp);
	rewind(fp);
	// 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)
	{
		::MessageBox(NULL, TEXT("File is too big to be opened by Notepad++"), TEXT("File open problem"), MB_OK|MB_APPLMODAL);
		/*
		_nativeLangSpeaker.messageBox("NbFileToOpenImportantWarning",
										_pPublicInterface->getHSelf(),
										TEXT("File is too big to be opened by Notepad++"),
										TEXT("File open problem"),
										MB_OK|MB_APPLMODAL);
		*/
		fclose(fp);
		return false;
	}

	//Setup scratchtilla for new filedata
	_pscratchTilla->execute(SCI_SETSTATUS, SC_STATUS_OK); // reset error status
	_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, doc);
	bool ro = _pscratchTilla->execute(SCI_GETREADONLY) != 0;
	if (ro)
	{
		_pscratchTilla->execute(SCI_SETREADONLY, false);
	}
	_pscratchTilla->execute(SCI_CLEARALL);


	if (language < L_EXTERNAL)
	{
		_pscratchTilla->execute(SCI_SETLEXER, ScintillaEditView::langNames[language].lexerID);
	}
	else
	{
		int id = language - L_EXTERNAL;
		TCHAR * name = NppParameters::getInstance()->getELCFromIndex(id)._name;
		WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
		const char *pName = wmc->wchar2char(name, CP_ACP);
		_pscratchTilla->execute(SCI_SETLEXERLANGUAGE, 0, (LPARAM)pName);
	}

	if (encoding != -1)
		_pscratchTilla->execute(SCI_SETCODEPAGE, SC_CP_UTF8);

	bool success = true;
	FormatType format = FormatType::unknown;
	__try
	{
		// First allocate enough memory for the whole file (this will reduce memory copy during loading)
		_pscratchTilla->execute(SCI_ALLOCATE, WPARAM(bufferSizeRequested));
		if (_pscratchTilla->execute(SCI_GETSTATUS) != SC_STATUS_OK)
			throw;

		size_t lenFile = 0;
		size_t lenConvert = 0;	//just in case conversion results in 0, but file not empty
		bool isFirstTime = true;
		int incompleteMultibyteChar = 0;

		do
		{
			lenFile = fread(data+incompleteMultibyteChar, 1, blockSize-incompleteMultibyteChar, fp) + incompleteMultibyteChar;
			if (lenFile == 0) break;

            if (isFirstTime)
            {
				// check if file contain any BOM
                if (Utf8_16_Read::determineEncoding((unsigned char *)data, lenFile) != uni8Bit)
                {
                    // if file contains any BOM, then encoding will be erased,
                    // and the document will be interpreted as UTF
                    encoding = -1;
				}
				else if (encoding == -1)
				{
					if (NppParameters::getInstance()->getNppGUI()._detectEncoding)
						encoding = detectCodepage(data, lenFile);
                }

				if (language == L_TEXT)
				{
					// check the language du fichier
					language = detectLanguageFromTextBegining((unsigned char *)data, lenFile);
				}

                isFirstTime = false;
            }

			if (encoding != -1)
			{
				if (encoding == SC_CP_UTF8)
				{
					// Pass through UTF-8 (this does not check validity of characters, thus inserting a multi-byte character in two halfs is working)
					_pscratchTilla->execute(SCI_APPENDTEXT, lenFile, (LPARAM)data);
				}
				else
				{
					WcharMbcsConvertor* wmc = WcharMbcsConvertor::getInstance();
					int newDataLen = 0;
					const char *newData = wmc->encode(encoding, SC_CP_UTF8, data, lenFile, &newDataLen, &incompleteMultibyteChar);
					_pscratchTilla->execute(SCI_APPENDTEXT, newDataLen, (LPARAM)newData);
				}

				if (format == FormatType::unknown)
					format = getEOLFormatForm(data, lenFile, FormatType::unknown);
			}
			else
			{
				lenConvert = UnicodeConvertor->convert(data, lenFile);
				_pscratchTilla->execute(SCI_APPENDTEXT, lenConvert, (LPARAM)(UnicodeConvertor->getNewBuf()));
			}

			if (_pscratchTilla->execute(SCI_GETSTATUS) != SC_STATUS_OK)
				throw;

			if (incompleteMultibyteChar != 0)
			{
				// copy bytes to next buffer
				memcpy(data, data+blockSize-incompleteMultibyteChar, incompleteMultibyteChar);
			}

		}
		while (lenFile > 0);
	}
	__except(EXCEPTION_EXECUTE_HANDLER) //TODO: should filter correctly for other exceptions; the old filter(GetExceptionCode(), GetExceptionInformation()) was only catching access violations
	{
		::MessageBox(NULL, TEXT("File is too big to be opened by Notepad++"), TEXT("File open problem"), MB_OK|MB_APPLMODAL);
		success = false;
	}

	fclose(fp);

	// broadcast the format
	if (pFormat != nullptr)
		*pFormat = (format != FormatType::unknown) ? format : FormatType::osdefault;

	_pscratchTilla->execute(SCI_EMPTYUNDOBUFFER);
	_pscratchTilla->execute(SCI_SETSAVEPOINT);

	if (ro)
		_pscratchTilla->execute(SCI_SETREADONLY, true);

	_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault);
	return success;
}
Beispiel #5
0
BufferID FileManager::loadFile(const TCHAR * filename, Document doc, int encoding)
{
	bool ownDoc = false;
	if (doc == NULL)
	{
		doc = (Document)_pscratchTilla->execute(SCI_CREATEDOCUMENT);
		ownDoc = true;
	}

	TCHAR fullpath[MAX_PATH];
	::GetFullPathName(filename, MAX_PATH, fullpath, NULL);
	::GetLongPathName(fullpath, fullpath, MAX_PATH);
	Utf8_16_Read UnicodeConvertor;	//declare here so we can get information after loading is done

	formatType format;
	bool res = loadFileData(doc, fullpath, &UnicodeConvertor, L_TEXT, encoding, &format);
	if (res)
	{
		Buffer * newBuf = new Buffer(this, _nextBufferID, doc, DOC_REGULAR, fullpath);
		BufferID id = (BufferID) newBuf;
		newBuf->_id = id;
		_buffers.push_back(newBuf);
		++_nrBufs;
		Buffer * buf = _buffers.at(_nrBufs - 1);

		// restore the encoding (ANSI based) while opening the existing file
		NppParameters *pNppParamInst = NppParameters::getInstance();
		const NewDocDefaultSettings & ndds = (pNppParamInst->getNppGUI()).getNewDocDefaultSettings();
		buf->setUnicodeMode(ndds._encoding);
		buf->setEncoding(-1);

		if (encoding == -1)
		{
			// 3 formats : WIN_FORMAT, UNIX_FORMAT and MAC_FORMAT
			if (UnicodeConvertor.getNewBuf())
			{
				int format = getEOLFormatForm(UnicodeConvertor.getNewBuf());
				buf->setFormat(format == -1?WIN_FORMAT:(formatType)format);

			}
			else
			{
				buf->setFormat(WIN_FORMAT);
			}

			UniMode um = UnicodeConvertor.getEncoding();
			if (um == uni7Bit)
			{
				if (ndds._openAnsiAsUtf8)
				{
					um = uniCookie;
				}
				else
				{
					um = uni8Bit;
				}
			}
			buf->setUnicodeMode(um);
		}
		else // encoding != -1
		{
			// Test if encoding is set to UTF8 without BOM (usually for UTF-8 indicator of XML or HTML)
			buf->setEncoding((encoding == SC_CP_UTF8)?-1:encoding);
			buf->setUnicodeMode(uniCookie);
			buf->setFormat(format);
		}
		//determine buffer properties
		++_nextBufferID;
		return id;
	}
	else //failed loading, release document
	{
		if (ownDoc)
			_pscratchTilla->execute(SCI_RELEASEDOCUMENT, 0, doc); //Failure, so release document
		return BUFFER_INVALID;
	}
}