Don Ho 4dd3b257e0 Moved PowerEditor in trunk remotely
git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@460 f5eea248-9336-0410-98b8-ebc06183d4e3
2009-04-24 23:34:47 +00:00

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