mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-09-26 11:28:51 +02:00
git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@460 f5eea248-9336-0410-98b8-ebc06183d4e3
387 lines
12 KiB
C++
387 lines
12 KiB
C++
//this file is part of notepad++
|
|
//Copyright (C)2003 Don HO < donho@altern.org >
|
|
//
|
|
//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 2 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, write to the Free Software
|
|
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
#ifndef BUFFER_H
|
|
#define BUFFER_H
|
|
|
|
#include "Utf8_16.h"
|
|
|
|
class Buffer;
|
|
typedef Buffer * BufferID; //each buffer has unique ID by which it can be retrieved
|
|
#define BUFFER_INVALID (BufferID)0
|
|
|
|
typedef sptr_t Document;
|
|
|
|
enum DocFileStatus{
|
|
DOC_REGULAR = 0x01, //should not be combined with anything
|
|
DOC_UNNAMED = 0x02, //not saved (new ##)
|
|
DOC_DELETED = 0x04, //doesnt exist in environment anymore, but not DOC_UNNAMED
|
|
DOC_MODIFIED = 0x08 //File in environment has changed
|
|
};
|
|
|
|
enum BufferStatusInfo {
|
|
BufferChangeLanguage = 0x001, //Language was altered
|
|
BufferChangeDirty = 0x002, //Buffer has changed dirty state
|
|
BufferChangeFormat = 0x004, //EOL type was changed
|
|
BufferChangeUnicode = 0x008, //Unicode type was changed
|
|
BufferChangeReadonly = 0x010, //Readonly state was changed, can be both file and user
|
|
BufferChangeStatus = 0x020, //Filesystem Status has changed
|
|
BufferChangeTimestamp = 0x040, //Timestamp was changed
|
|
BufferChangeFilename = 0x080, //Filename was changed
|
|
BufferChangeRecentTag = 0x100, //Recent tag has changed
|
|
BufferChangeLexing = 0x200, //Document needs lexing
|
|
BufferChangeMask = 0x3FF //Mask: covers all changes
|
|
};
|
|
|
|
struct HeaderLineState {
|
|
HeaderLineState() : _headerLineNumber(0), _isExpanded(true){};
|
|
HeaderLineState(int lineNumber, bool isExpanded) : _headerLineNumber(lineNumber), _isExpanded(isExpanded){};
|
|
int _headerLineNumber;
|
|
bool _isExpanded;
|
|
};
|
|
|
|
const int userLangNameMax = 16;
|
|
const TCHAR UNTITLED_STR[] = TEXT("new ");
|
|
|
|
//File manager class maintains all buffers
|
|
class Buffer;
|
|
class FileManager {
|
|
public:
|
|
void init(Notepad_plus * pNotepadPlus, ScintillaEditView * pscratchTilla);
|
|
|
|
//void activateBuffer(int index);
|
|
void checkFilesystemChanges();
|
|
|
|
int getNrBuffers() { return _nrBufs; };
|
|
int getBufferIndexByID(BufferID id);
|
|
Buffer * getBufferByIndex(int index); //generates exception if index is invalid
|
|
Buffer * getBufferByID(BufferID id) {return (Buffer*)id;}
|
|
|
|
void beNotifiedOfBufferChange(Buffer * theBuf, int mask);
|
|
|
|
void closeBuffer(BufferID, ScintillaEditView * identifer); //called by Notepad++
|
|
|
|
void addBufferReference(BufferID id, ScintillaEditView * identifer); //called by Scintilla etc indirectly
|
|
|
|
BufferID loadFile(const TCHAR * filename, Document doc = NULL); //ID == BUFFER_INVALID on failure. If Doc == NULL, a new file is created, otherwise data is loaded in given document
|
|
BufferID newEmptyDocument();
|
|
//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
|
|
//If dontRef = false, then no extra reference is added for the doc. Its the responsibility of the caller to do so
|
|
BufferID bufferFromDocument(Document doc, bool dontIncrease = false, bool dontRef = false);
|
|
|
|
BufferID getBufferFromName(const TCHAR * name);
|
|
BufferID getBufferFromDocument(Document doc);
|
|
|
|
bool reloadBuffer(BufferID id);
|
|
bool reloadBufferDeferred(BufferID id);
|
|
bool saveBuffer(BufferID id, const TCHAR * filename, bool isCopy = false);
|
|
bool deleteFile(BufferID id);
|
|
bool moveFile(BufferID id, const TCHAR * newFilename);
|
|
|
|
bool createEmptyFile(const TCHAR * path);
|
|
|
|
static FileManager * getInstance() {return _pSelf;};
|
|
void destroyInstance() { delete _pSelf; };
|
|
|
|
void increaseDocNr() {_nextNewNumber++;};
|
|
|
|
int getFileNameFromBuffer(BufferID id, TCHAR * fn2copy);
|
|
|
|
int docLength(Buffer * buffer) const;
|
|
|
|
private:
|
|
FileManager() : _nextNewNumber(1), _nextBufferID(0), _pNotepadPlus(NULL), _nrBufs(0), _pscratchTilla(NULL){};
|
|
~FileManager(){};
|
|
static FileManager *_pSelf;
|
|
|
|
Notepad_plus * _pNotepadPlus;
|
|
ScintillaEditView * _pscratchTilla;
|
|
Document _scratchDocDefault;
|
|
|
|
int _nextNewNumber;
|
|
|
|
std::vector<Buffer *> _buffers;
|
|
BufferID _nextBufferID;
|
|
size_t _nrBufs;
|
|
|
|
bool loadFileData(Document doc, const TCHAR * filename, Utf8_16_Read * UnicodeConvertor, LangType language);
|
|
};
|
|
|
|
#define MainFileManager FileManager::getInstance()
|
|
|
|
class Buffer
|
|
{
|
|
friend class FileManager;
|
|
public :
|
|
//Loading a document:
|
|
//constructor with ID.
|
|
//Set a reference (pointer to a container mostly, like DocTabView or ScintillaEditView)
|
|
//Set the position manually if needed
|
|
//Load the document into Scintilla/add to TabBar
|
|
//The entire lifetime if the buffer, the Document has reference count of _atleast_ one
|
|
//Destructor makes sure its purged
|
|
Buffer(FileManager * pManager, BufferID id, Document doc, DocFileStatus type, const TCHAR *fileName) //type must be either DOC_REGULAR or DOC_UNNAMED
|
|
: _pManager(pManager), _id(id), _isDirty(false), _doc(doc), _isFileReadOnly(false), _isUserReadOnly(false), _recentTag(-1), _references(0),
|
|
_canNotify(false), _timeStamp(0), _needReloading(false)
|
|
{
|
|
NppParameters *pNppParamInst = NppParameters::getInstance();
|
|
const NewDocDefaultSettings & ndds = (pNppParamInst->getNppGUI()).getNewDocDefaultSettings();
|
|
_format = ndds._format;
|
|
_unicodeMode = ndds._encoding;
|
|
|
|
_userLangExt[0] = 0;
|
|
_fullPathName[0] = 0;
|
|
_fileName = NULL;
|
|
setFileName(fileName, ndds._lang);
|
|
updateTimeStamp();
|
|
checkFileState();
|
|
_currentStatus = type;
|
|
_isDirty = false;
|
|
|
|
_needLexer = false; //new buffers do not need lexing, Scintilla takes care of that
|
|
_canNotify = true;
|
|
};
|
|
|
|
LangType getLangFromExt(const TCHAR *ext);
|
|
|
|
// this method 1. copies the file name
|
|
// 2. determinates the language from the ext of file name
|
|
// 3. gets the last modified time
|
|
void setFileName(const TCHAR *fn, LangType defaultLang = L_TXT);
|
|
|
|
const TCHAR * getFullPathName() const {
|
|
return _fullPathName;
|
|
};
|
|
|
|
const TCHAR * getFileName() const { return _fileName; };
|
|
|
|
BufferID getID() const {
|
|
return _id;
|
|
};
|
|
|
|
void increaseRecentTag() {
|
|
_recentTag = ++_recentTagCtr;
|
|
doNotify(BufferChangeRecentTag);
|
|
};
|
|
|
|
long getRecentTag() const {
|
|
return _recentTag;
|
|
};
|
|
|
|
bool checkFileState();
|
|
|
|
bool isDirty() const {
|
|
return _isDirty;
|
|
};
|
|
|
|
bool isReadOnly() const {
|
|
return (_isUserReadOnly || _isFileReadOnly);
|
|
};
|
|
|
|
bool isUntitled() const {
|
|
return (_currentStatus == DOC_UNNAMED);
|
|
};
|
|
|
|
bool getFileReadOnly() const {
|
|
return _isFileReadOnly;
|
|
};
|
|
|
|
void setFileReadOnly(bool ro) {
|
|
_isFileReadOnly = ro;
|
|
doNotify(BufferChangeReadonly);
|
|
};
|
|
|
|
bool getUserReadOnly() const {
|
|
return _isUserReadOnly;
|
|
};
|
|
|
|
void setUserReadOnly(bool ro) {
|
|
_isUserReadOnly = ro;
|
|
doNotify(BufferChangeReadonly);
|
|
};
|
|
|
|
formatType getFormat() const {
|
|
return _format;
|
|
};
|
|
|
|
void setFormat(formatType format) {
|
|
_format = format;
|
|
doNotify(BufferChangeFormat);
|
|
};
|
|
|
|
LangType getLangType() const {
|
|
return _lang;
|
|
};
|
|
|
|
void setLangType(LangType lang, const TCHAR * userLangName = TEXT("")) {
|
|
if (lang == _lang && lang != L_USER)
|
|
return;
|
|
_lang = lang;
|
|
if (_lang == L_USER) {
|
|
lstrcpy(_userLangExt, userLangName);
|
|
}
|
|
_needLexer = true; //change of lang means lexern eeds updating
|
|
doNotify(BufferChangeLanguage|BufferChangeLexing);
|
|
};
|
|
|
|
UniMode getUnicodeMode() const {
|
|
return _unicodeMode;
|
|
};
|
|
|
|
void setUnicodeMode(UniMode mode) {
|
|
_unicodeMode = mode;
|
|
//_isDirty = true; //set to dirty if change unicode mode
|
|
doNotify(BufferChangeUnicode | BufferChangeDirty);
|
|
};
|
|
DocFileStatus getStatus() const {
|
|
return _currentStatus;
|
|
};
|
|
|
|
Document getDocument() {
|
|
return _doc;
|
|
};
|
|
|
|
void setDirty(bool dirty) {
|
|
_isDirty = dirty;
|
|
doNotify(BufferChangeDirty);
|
|
};
|
|
|
|
void setPosition(const Position & pos, ScintillaEditView * identifier);
|
|
Position & getPosition(ScintillaEditView * identifier);
|
|
|
|
void setHeaderLineState(const std::vector<HeaderLineState> & folds, ScintillaEditView * identifier);
|
|
std::vector<HeaderLineState> & getHeaderLineState(ScintillaEditView * identifier);
|
|
|
|
void determinateFormat(const char *data);
|
|
|
|
bool isUserDefineLangExt() const {
|
|
return (_userLangExt[0] != '\0');
|
|
};
|
|
|
|
const TCHAR * getUserDefineLangName() const {
|
|
return _userLangExt;
|
|
};
|
|
|
|
const TCHAR * getCommentLineSymbol() const {
|
|
Lang *l = getCurrentLang();
|
|
if (!l)
|
|
return NULL;
|
|
return l->_pCommentLineSymbol;
|
|
|
|
};
|
|
|
|
const TCHAR * getCommentStart() const {
|
|
Lang *l = getCurrentLang();
|
|
if (!l)
|
|
return NULL;
|
|
return l->_pCommentStart;
|
|
};
|
|
|
|
const TCHAR * getCommentEnd() const {
|
|
Lang *l = getCurrentLang();
|
|
if (!l)
|
|
return NULL;
|
|
return l->_pCommentEnd;
|
|
};
|
|
|
|
bool getNeedsLexing() const {
|
|
return _needLexer;
|
|
};
|
|
|
|
void setNeedsLexing(bool lex) {
|
|
_needLexer = lex;
|
|
doNotify(BufferChangeLexing);
|
|
};
|
|
|
|
//these two return reference count after operation
|
|
int addReference(ScintillaEditView * identifier); //if ID not registered, creates a new Position for that ID and new foldstate
|
|
int removeReference(ScintillaEditView * identifier); //reduces reference. If zero, Document is purged
|
|
|
|
void setHideLineChanged(bool isHide, int location);
|
|
|
|
void setDeferredReload();
|
|
|
|
bool getNeedReload() {
|
|
return _needReloading;
|
|
}
|
|
|
|
void setNeedReload(bool reload) {
|
|
_needReloading = reload;
|
|
}
|
|
|
|
/*
|
|
pair<size_t, bool> getLineUndoState(size_t currentLine) const;
|
|
void setLineUndoState(size_t currentLine, size_t undoLevel, bool isSaved = false);
|
|
*/
|
|
|
|
int docLength() const {
|
|
return _pManager->docLength(_id);
|
|
};
|
|
|
|
private :
|
|
FileManager * _pManager;
|
|
bool _canNotify;
|
|
int _references; //if no references file inaccessible, can be closed
|
|
BufferID _id;
|
|
|
|
//document properties
|
|
Document _doc; //invariable
|
|
LangType _lang;
|
|
TCHAR _userLangExt[userLangNameMax]; // it's useful if only (_lang == L_USER)
|
|
bool _isDirty;
|
|
formatType _format;
|
|
UniMode _unicodeMode;
|
|
bool _isUserReadOnly;
|
|
bool _needLexer; //initially true
|
|
//these properties have to be duplicated because of multiple references
|
|
//All the vectors must have the same size at all times
|
|
vector< ScintillaEditView * > _referees;
|
|
vector< Position > _positions;
|
|
vector< vector<HeaderLineState> > _foldStates;
|
|
|
|
//vector< pair<size_t, pair<size_t, bool> > > _linesUndoState;
|
|
|
|
//Environment properties
|
|
DocFileStatus _currentStatus;
|
|
time_t _timeStamp; // 0 if it's a new doc
|
|
bool _isFileReadOnly;
|
|
TCHAR _fullPathName[MAX_PATH];
|
|
TCHAR * _fileName; //points to filename part in _fullPathName
|
|
bool _needReloading; //True if Buffer needs to be reloaded on activation
|
|
|
|
long _recentTag;
|
|
static long _recentTagCtr;
|
|
|
|
void updateTimeStamp();
|
|
Lang * getCurrentLang() const;
|
|
|
|
int indexOfReference(ScintillaEditView * identifier) const;
|
|
|
|
void setStatus(DocFileStatus status) {
|
|
_currentStatus = status;
|
|
doNotify(BufferChangeStatus);
|
|
}
|
|
|
|
void doNotify(int mask) {
|
|
if (_canNotify)
|
|
_pManager->beNotifiedOfBufferChange(this, mask);
|
|
};
|
|
};
|
|
|
|
#endif //BUFFER_H
|