[Near 5.0]

Change filehandling: buffers.
This fixes many things like clonemode etc.. Faster shutdown. Open files with date pre-1970.
Hide lines now saved during switches.
Recent files has been redone: also numbers, more stable, no duplicates.
Display asterisk in titlebar if dirty file is active.
Some minor stuff that may have come along.

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository@215 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
harrybharry 2008-06-06 12:09:54 +00:00
parent b9256773b6
commit e4cab506f8
26 changed files with 2885 additions and 2623 deletions

File diff suppressed because it is too large Load Diff

View File

@ -47,23 +47,34 @@
#include "DockingManager.h"
#include "Process.h"
#include "AutoCompletion.h"
#include "Buffer.h"
#define NOTEPAD_PP_CLASS_NAME "Notepad++"
#define MENU 0x01
#define TOOLBAR 0x02
//#define WM_LOADFILEBYPATH WM_USER
enum FileTransferMode {
TransferClone = 0x01,
TransferMove = 0x02
};
const bool MODE_TRANSFER = true;
const bool MODE_CLONE = false;
enum WindowStatus { //bitwise mask
WindowMainActive = 0x01,
WindowSubActive = 0x02,
WindowBothActive = 0x03, //little helper shortcut
WindowUserActive = 0x04,
WindowMask = 0x07
};
const unsigned char DOCK_MASK = 1;
const unsigned char TWO_VIEWS_MASK = 2;
/*
//Plugins rely on #define's
enum Views {
MAIN_VIEW = 0x00,
SUB_VIEW = 0x01
};
*/
const int blockSize = 128 * 1024 + 4;
struct TaskListInfo;
static TiXmlNode * searchDlgNode(TiXmlNode *node, const char *dlgTagName);
@ -76,12 +87,6 @@ struct iconLocator {
: listIndex(iList), iconIndex(iIcon), iconLocation(iconLoc){};
};
enum FileOpenStatus {
OPEN_FAILURE,
OPEN_SUCCESS,
OPEN_EXISTS
};
class FileDialog;
class Notepad_plus : public Window {
@ -97,7 +102,7 @@ public:
return _className;
};
void setTitleWith(const char *filePath);
void setTitle();
void getTaskListInfo(TaskListInfo *tli);
// For filtering the modeless Dialog message
@ -111,24 +116,29 @@ public:
return false;
};
// fileOperation
int doOpen(const char *fileName, bool isReadOnly = false);
bool doSimpleOpen(const char *fileName);
bool doReload(const char *fileName, bool alert = true);
inline void fileNew();
// fileOperations
//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 char *fileName, bool isReadOnly = false);
bool doReload(BufferID id, bool alert = true);
bool doSave(BufferID, const char * filename, bool isSaveCopy = false);
void doClose(BufferID, int whichOne);
inline void fileNew();
void fileOpen();
inline bool fileReload();
bool fileClose();
bool fileClose(BufferID id = BUFFER_INVALID, int curView = -1); //use curView to override view to close from
bool fileCloseAll();
bool fileCloseAllButCurrent();
bool fileSave();
bool fileSave(BufferID id = BUFFER_INVALID);
bool fileSaveAll();
bool fileSaveAs(bool isSaveCopy = false);
bool fileSaveAs(BufferID id = BUFFER_INVALID, bool isSaveCopy = false);
bool doSave(const char *filename, UniMode mode, bool isSaveCopy = false);
// end fileOperation
bool addBufferToView(BufferID id, int whichOne);
bool moveBuffer(BufferID id, int whereTo); //assumes whereFrom is otherView(whereTo)
bool switchToFile(BufferID buffer); //find buffer in active view then in other view.
// end fileOperations
bool isFileSession(const char * filename);
void filePrint(bool showDialog);
bool saveScintillaParams(bool whichOne);
@ -169,13 +179,15 @@ public:
};
bool addCurrentMacro();
bool switchToFile(const char *fileName);
inline void loadLastSession();
bool loadSession(Session & session);
winVer getWinVersion() const {return _winVersion;};
bool emergency();
void notifyBufferChanged(Buffer * buffer, int mask);
private:
void loadCommandlineParams(const char * commandLine, CmdLineParams * pCmdParams);
static const char _className[32];
char _nppPath[MAX_PATH];
Window *_pMainWindow;
@ -186,18 +198,18 @@ private:
TiXmlNode *_nativeLang, *_toolIcons;
unsigned char _mainWindowStatus;
DocTabView _mainDocTab;
DocTabView _subDocTab;
DocTabView *_pDocTab;
DocTabView *_pNonDocTab;
ScintillaEditView _subEditView;
ScintillaEditView _mainEditView;
ScintillaEditView _invisibleEditView;
ScintillaEditView _invisibleEditView; //for searches
ScintillaEditView _fileEditView; //for FileManager
ScintillaEditView *_pEditView;
ScintillaEditView *_pNonEditView;
SplitterContainer *_pMainSplitter;
SplitterContainer _subSplitter;
@ -250,7 +262,6 @@ private:
bool _linkTriggered;
bool _isDocModifing;
bool _isHotspotDblClicked;
bool _isSaving;
//For Dynamic selection highlight
CharacterRange _prevSelectedRange;
@ -338,15 +349,42 @@ private:
void specialCmd(int id, int param);
void command(int id);
//Document management
unsigned char _mainWindowStatus; //For 2 views and user dialog if docked
int _activeView;
//User dialog docking
void dockUserDlg();
void undockUserDlg();
//View visibility
void showView(int whichOne);
bool viewVisible(int whichOne);
void hideView(int whichOne);
void hideCurrentView();
bool bothActive() { return (_mainWindowStatus & WindowBothActive) == WindowBothActive; };
int currentView();
int otherView();
int otherFromView(int whichOne);
bool canHideView(int whichOne); //true if view can safely be hidden (no open docs etc)
int switchEditViewTo(int gid); //activate other view (set focus etc)
void docGotoAnotherEditView(FileTransferMode mode); //TransferMode
void loadBufferIntoView(BufferID id, int whichOne, bool dontClose = false); //Doesnt _activate_ the buffer
void removeBufferFromView(BufferID id, int whichOne); //Activates alternative of possible, or creates clean document if not clean already
bool activateBuffer(BufferID id, int whichOne); //activate buffer in that view if found
void notifyBufferActivated(BufferID bufid, int view);
//END: Document management
int doSaveOrNot(const char *fn) {
char phrase[512] = "Save file \"";
strcat(strcat(phrase, fn), "\" ?");
return ::MessageBox(_hSelf, phrase, "Save", MB_YESNOCANCEL | MB_ICONQUESTION | MB_APPLMODAL);
};
int doReloadOrNot(const char *fn) {
char phrase[512] = "The file \"";
strcat(strcat(phrase, fn), "\" is modified by another program. Reload this file?");
@ -372,16 +410,9 @@ private:
void checkSyncState();
void dropFiles(HDROP hdrop);
void checkModifiedDocument();
void reload(const char *fileName);
void docGotoAnotherEditView(bool mode);
void dockUserDlg();
void undockUserDlg();
void getMainClientRect(RECT & rc) const;
int switchEditViewTo(int gid);
void dynamicCheckMenuAndTB() const;
void enableConvertMenuItems(formatType f) const {
@ -392,36 +423,10 @@ private:
void checkUnicodeMenuItems(UniMode um) const;
int getCurrentView() const {
return (_pEditView == &_mainEditView)?MAIN_VIEW:SUB_VIEW;
};
int getNonCurrentView() const {
return (_pEditView == &_mainEditView)?SUB_VIEW:MAIN_VIEW;
};
DocTabView * getNonCurrentDocTab() {
return (_pDocTab == &_mainDocTab)?&_subDocTab:&_mainDocTab;
};
ScintillaEditView * getCurrentEditView() {
return (_pEditView == &_mainEditView)?&_mainEditView:&_subEditView;
};
ScintillaEditView * getNonCurrentEditView() {
return (_pEditView == &_mainEditView)?&_subEditView:&_mainEditView;
};
void synchronise();
string getLangDesc(LangType langType, bool shortDesc = false);
void setLangStatus(LangType langType){
_statusBar.setText(getLangDesc(langType).c_str(), STATUSBAR_DOC_TYPE);
if (_pEditView == &_mainEditView)
_autoCompleteMain.setLanguage(langType);
else
_autoCompleteSub.setLanguage(langType);
};
void setDisplayFormat(formatType f) {
@ -462,12 +467,7 @@ private:
void checkLangsMenu(int id) const ;
void setLanguage(int id, LangType langType) {
if (_pEditView->setCurrentDocType(langType))
{
_pEditView->foldAll(fold_uncollapse);
setLangStatus(langType);
checkLangsMenu(id);
}
_pEditView->getCurrentBuffer()->setLangType(langType);
};
int getFolderMarginStyle() const {
@ -646,62 +646,6 @@ private:
return line;
};
int hideLinesMarkPresent(int lineno) const {
LRESULT state = _pEditView->execute(SCI_MARKERGET, lineno);
if ((state & (1 << MARK_HIDELINESBEGIN)) != 0)
return MARK_HIDELINESBEGIN;
else if ((state & (1 << MARK_HIDELINESEND)) != 0)
return MARK_HIDELINESEND;
return 0;
};
void hideLinesMarkDelete(int lineno, int which) const {
_pEditView->execute(SCI_MARKERDELETE, lineno, which);
};
bool showLines(int lineno) const {
if (lineno == -1)
lineno = _pEditView->getCurrentLineNumber();
int hideLinesMark = hideLinesMarkPresent(lineno);
if (!hideLinesMark)
return false;
//
int start = 0;
int end = 0;
if (hideLinesMark == MARK_HIDELINESEND)
{
end = lineno;
int i = lineno - 1;
for ( ; i >= 0 ; i--)
{
if (_pEditView->execute(SCI_GETLINEVISIBLE, i))
break;
hideLinesMarkDelete(i, MARK_HIDELINESBEGIN);
hideLinesMarkDelete(i, MARK_HIDELINESEND);
}
start = i;
}
else if (hideLinesMark == MARK_HIDELINESBEGIN)
{
long nbLine = _pEditView->lastZeroBasedLineNumber();
start = lineno;
int i = lineno + 1;
for ( ; i < nbLine ; i++)
{
if (_pEditView->execute(SCI_GETLINEVISIBLE, i))
break;
hideLinesMarkDelete(i, MARK_HIDELINESBEGIN);
hideLinesMarkDelete(i, MARK_HIDELINESEND);
}
end = i;
}
_pEditView->execute(SCI_SHOWLINES, start+1, end-1);
hideLinesMarkDelete(start, MARK_HIDELINESBEGIN);
hideLinesMarkDelete(end, MARK_HIDELINESEND);
return true;
};
void findMatchingBracePos(int & braceAtCaret, int & braceOpposite);
void braceMatch();
@ -774,36 +718,27 @@ private:
command( id );
}
string getLangFromMenu(Buffer buf)
string getLangFromMenu(const Buffer * buf)
{
int id;
const char * userLangName;
char menuLangName[32];
id = (NppParameters::getInstance())->langTypeToCommandID( buf.getLangType() );
id = (NppParameters::getInstance())->langTypeToCommandID( buf->getLangType() );
if ( ( id != IDM_LANG_USER ) || !( buf.isUserDefineLangExt() ) )
if ( ( id != IDM_LANG_USER ) || !( buf->isUserDefineLangExt() ) )
{
( ::GetMenuString( _mainMenuHandle, id, menuLangName, sizeof( menuLangName ), MF_BYCOMMAND ) );
userLangName = (char *)menuLangName;
}
else
{
userLangName = buf.getUserDefineLangName();
userLangName = buf->getUserDefineLangName();
}
return userLangName;
}
void removeHideLinesBookmarks() {
for (size_t i = 0 ; i < _hideLinesMarks.size() ; i++)
{
hideLinesMarkDelete(_hideLinesMarks[i].first, MARK_HIDELINESBEGIN);
hideLinesMarkDelete(_hideLinesMarks[i].second, MARK_HIDELINESEND);
}
};
void setFileOpenSaveDlgFilters(FileDialog & fDlg);
void reloadOnSwitchBack();
void markSelectedText();
void markSelectedTextInc(bool enable);
@ -875,7 +810,7 @@ private:
return true;
};
bool dumpFiles(ScintillaEditView * viewToRecover, const char * outdir, const char * fileprefix = ""); //helper func
bool dumpFiles(const char * outdir, const char * fileprefix = ""); //helper func
void drawTabbarColoursFromStylerArray();
};

View File

@ -383,6 +383,9 @@ BEGIN
MENUITEM SEPARATOR
MENUITEM "Go to another view", IDM_VIEW_GOTO_ANOTHER_VIEW
MENUITEM "Clone to another view", IDM_VIEW_CLONE_TO_ANOTHER_VIEW
MENUITEM "Activate main view" IDM_VIEW_SWITCHTO_MAIN
MENUITEM "Activate sub view" IDM_VIEW_SWITCHTO_SUB
MENUITEM SEPARATOR
MENUITEM "Synchronize Vertical Scrolling", IDM_VIEW_SYNSCROLLV
MENUITEM "Synchronize Horizontal Scrolling", IDM_VIEW_SYNSCROLLH
MENUITEM SEPARATOR

View File

@ -107,6 +107,10 @@ WinMenuKeyDefinition winKeyDefs[] = { //array of accelerator keys for all std me
{VK_F2, IDM_SEARCH_NEXT_BOOKMARK, false, false, false, NULL},
{VK_F2, IDM_SEARCH_PREV_BOOKMARK, false, false, true, NULL},
{VK_NULL, IDM_SEARCH_CLEAR_BOOKMARKS, false, false, false, NULL},
{VK_NULL, IDM_SEARCH_CUTMARKEDLINES, false, false, false, NULL},
{VK_NULL, IDM_SEARCH_COPYMARKEDLINES, false, false, false, NULL},
{VK_NULL, IDM_SEARCH_PASTEMARKEDLINES, false, false, false, NULL},
{VK_NULL, IDM_SEARCH_DELETEMARKEDLINES, false, false, false, NULL},
{VK_F11, IDM_VIEW_FULLSCREENTOGGLE, false, false, false, NULL},
{VK_NULL, IDM_VIEW_ALWAYSONTOP, false, false, false, NULL},
@ -145,6 +149,8 @@ WinMenuKeyDefinition winKeyDefs[] = { //array of accelerator keys for all std me
{VK_NULL, IDM_VIEW_CLONE_TO_ANOTHER_VIEW, false, false, false, NULL},
{VK_NULL, IDM_VIEW_SYNSCROLLV, false, false, false, NULL},
{VK_NULL, IDM_VIEW_SYNSCROLLH, false, false, false, NULL},
{VK_F7, IDM_VIEW_SWITCHTO_MAIN, false, false, false, NULL},
{VK_F8, IDM_VIEW_SWITCHTO_SUB, false, false, false, NULL},
{VK_NULL, IDM_FORMAT_TODOS, false, false, false, NULL},
{VK_NULL, IDM_FORMAT_TOUNIX, false, false, false, NULL},

View File

@ -296,10 +296,10 @@ bool AutoCompletion::setLanguage(LangType language) {
const char * AutoCompletion::getApiFileName() {
if (_curLang == L_USER)
{
Buffer & currentBuf = _pEditView->getCurrentBuffer();
if (currentBuf.isUserDefineLangExt())
Buffer * currentBuf = _pEditView->getCurrentBuffer();
if (currentBuf->isUserDefineLangExt())
{
return currentBuf.getUserDefineLangName();
return currentBuf->getUserDefineLangName();
}
}

View File

@ -1,7 +1,95 @@
#include "Buffer.h"
#include <shlwapi.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "Scintilla.h"
#include "Parameters.h"
#include "Notepad_plus.h"
#include "ScintillaEditView.h"
FileManager * FileManager::_pSelf = new FileManager();
const int blockSize = 128 * 1024 + 4;
const char UNTITLED_STR[] = "new ";
// Ordre important!! Ne le changes pas!
//SC_EOL_CRLF (0), SC_EOL_CR (1), or SC_EOL_LF (2).
const int CR = 0x0D;
const int LF = 0x0A;
static bool isInList(const char *token, const char *list) {
if ((!token) || (!list))
return false;
char word[64];
int i = 0;
int j = 0;
for (; i <= int(strlen(list)) ; i++)
{
if ((list[i] == ' ')||(list[i] == '\0'))
{
if (j != 0)
{
word[j] = '\0';
j = 0;
if (!stricmp(token, word))
return true;
}
}
else
{
word[j] = list[i];
j++;
}
}
return false;
};
void Buffer::determinateFormat(char *data) {
_format = WIN_FORMAT;
size_t len = strlen(data);
for (size_t i = 0 ; i < len ; i++)
{
if (data[i] == CR)
{
if (data[i+1] == LF)
{
_format = WIN_FORMAT;
break;
}
else
{
_format = MAC_FORMAT;
break;
}
}
if (data[i] == LF)
{
_format = UNIX_FORMAT;
break;
}
}
doNotify(BufferChangeFormat);
return;
};
long Buffer::_recentTagCtr = 0;
void Buffer::updateTimeStamp() {
struct _stat buf;
time_t timeStamp = (_stat(_fullPathName, &buf)==0)?buf.st_mtime:0;
if (timeStamp != _timeStamp) {
_timeStamp = timeStamp;
doNotify(BufferChangeTimestamp);
}
};
// Set full path file name in buffer object,
// and determinate its language by its extension.
// If the ext is not in the list, the defaultLang passed as argument will be set.
@ -9,11 +97,13 @@ void Buffer::setFileName(const char *fn, LangType defaultLang)
{
NppParameters *pNppParamInst = NppParameters::getInstance();
strcpy(_fullPathName, fn);
if (PathFileExists(_fullPathName))
{
_fileName = PathFindFileName(_fullPathName);
// for _lang
_lang = defaultLang;
char *ext = PathFindExtension(_fullPathName);
if (*ext == '.') ext += 1;
if (*ext == '.') { //extension found
ext += 1;
// Define User Lang firstly
const char *langName = NULL;
@ -24,29 +114,96 @@ void Buffer::setFileName(const char *fn, LangType defaultLang)
}
else // if it's not user lang, then check if it's supported lang
{
_userLangExt[0] = '\0';
_lang = getLangFromExt(ext);
if (_lang == L_TXT)
{
char *fileName = PathFindFileName(_fullPathName);
}
}
if ((!_stricmp(fileName, "makefile")) || (!_stricmp(fileName, "GNUmakefile")))
if (_lang == defaultLang || _lang == L_TXT) //language can probably be refined
{
if ((!_stricmp(_fileName, "makefile")) || (!_stricmp(_fileName, "GNUmakefile")))
_lang = L_MAKEFILE;
else if (!_stricmp(fileName, "CmakeLists.txt"))
else if (!_stricmp(_fileName, "CmakeLists.txt"))
_lang = L_CMAKE;
}
_userLangExt[0] = '\0';
updateTimeStamp();
doNotify(BufferChangeFilename | BufferChangeLanguage | BufferChangeTimestamp);
}
// for _timeStamp
updatTimeStamp();
}
else // new doc
bool Buffer::checkFileState() { //returns true if the status has been changed (it can change into DOC_REGULAR too). false otherwise
struct _stat buf;
if (_currentStatus == DOC_UNNAMED) //unsaved document cannot change by environment
return false;
if (_currentStatus != DOC_DELETED && !PathFileExists(_fullPathName)) //document has been deleted
{
_lang = defaultLang;
_currentStatus = DOC_DELETED;
_isFileReadOnly = false;
_timeStamp = 0;
doNotify(BufferChangeStatus | BufferChangeReadonly | BufferChangeTimestamp);
return true;
} else if (_currentStatus == DOC_DELETED && PathFileExists(_fullPathName)) { //document has returned from its grave
if (!_stat(_fullPathName, &buf))
{
_isFileReadOnly = (bool)(!(buf.st_mode & _S_IWRITE));
_currentStatus = DOC_MODIFIED;
_timeStamp = buf.st_mtime;
doNotify(BufferChangeStatus | BufferChangeReadonly | BufferChangeTimestamp);
return true;
}
}
if (!_stat(_fullPathName, &buf))
{
_isFileReadOnly = (bool)(!(buf.st_mode & _S_IWRITE));
if (_timeStamp != buf.st_mtime) {
_currentStatus = DOC_MODIFIED;
_timeStamp = buf.st_mtime;
doNotify(BufferChangeStatus | BufferChangeReadonly | BufferChangeTimestamp);
return true;
}
doNotify(BufferChangeReadonly | BufferChangeTimestamp);
return false;
}
return false;
}
void Buffer::setPosition(const Position & pos, ScintillaEditView * identifier) {
int index = indexOfReference(identifier);
if (index == -1)
return;
_positions[index] = pos;
}
Position & Buffer::getPosition(ScintillaEditView * identifier) {
int index = indexOfReference(identifier);
return _positions.at(index);
}
void Buffer::setHeaderLineState(const std::vector<HeaderLineState> & folds, ScintillaEditView * identifier) {
int index = indexOfReference(identifier);
if (index == -1)
return;
//deep copy
std::vector<HeaderLineState> & local = _foldStates[index];
local.clear();
size_t size = folds.size();
for(size_t i = 0; i < size; i++) {
local.push_back(folds[i]);
}
}
std::vector<HeaderLineState> & Buffer::getHeaderLineState(ScintillaEditView * identifier) {
int index = indexOfReference(identifier);
return _foldStates.at(index);
}
LangType Buffer::getLangFromExt(const char *ext)
{
NppParameters *pNppParam = NppParameters::getInstance();
@ -79,3 +236,303 @@ LangType Buffer::getLangFromExt(const char *ext)
}
return L_TXT;
}
Lang * Buffer::getCurrentLang() const {
NppParameters *pNppParam = NppParameters::getInstance();
int i = 0;
Lang *l = pNppParam->getLangFromIndex(i++);
while (l)
{
if (l->_langID == _lang)
return l;
l = pNppParam->getLangFromIndex(i++);
}
return NULL;
};
int Buffer::indexOfReference(ScintillaEditView * identifier) const {
int size = (int)_referees.size();
for(int i = 0; i < size; i++) {
if (_referees[i] == identifier)
return i;
}
return -1; //not found
}
int Buffer::addReference(ScintillaEditView * identifier) {
if (indexOfReference(identifier) != -1)
return _references;
_referees.push_back(identifier);
_positions.push_back(Position());
_foldStates.push_back(std::vector<HeaderLineState>());
_references++;
return _references;
}
int Buffer::removeReference(ScintillaEditView * identifier) {
int indexToPop = indexOfReference(identifier);
if (indexToPop == -1)
return _references;
_referees.erase(_referees.begin() + indexToPop);
_positions.erase(_positions.begin() + indexToPop);
_foldStates.erase(_foldStates.begin() + indexToPop);
_references--;
return _references;
}
void Buffer::setHideLineChanged(bool isHide, int location) {
for(int i = 0; i < _references; i++) {
_referees.at(i)->notifyMarkers(this, isHide, location, (i == _references-1));
}
}
//filemanager
FileManager::FileManager() :
_nextNewNumber(1), _nextBufferID(0), _pNotepadPlus(NULL), _nrBufs(0), _pscratchTilla(NULL)
{
}
void FileManager::init(Notepad_plus * pNotepadPlus, ScintillaEditView * pscratchTilla)
{
_pNotepadPlus = pNotepadPlus;
_pscratchTilla = pscratchTilla;
_pscratchTilla->execute(SCI_SETUNDOCOLLECTION, false); //dont store any undo information
_scratchDocDefault = (Document)_pscratchTilla->execute(SCI_GETDOCPOINTER);
_pscratchTilla->execute(SCI_ADDREFDOCUMENT, 0, _scratchDocDefault);
}
FileManager::~FileManager() {
//Release automatic with Scintilla destructor
//_pscratchTilla->execute(SCI_RELEASEDOCUMENT, 0, _scratchDocDefault);
}
void FileManager::checkFilesystemChanges() {
for(size_t i = 0; i < _nrBufs; i++) {
if (_buffers[i]->checkFileState()){} //something has changed. Triggers update automatically
//_pNotepadPlus->notifyBufferChanged(_buffers[i]._id, _buffers[i]);
}
}
int FileManager::getBufferIndexByID(BufferID id) {
for(size_t i = 0; i < _nrBufs; i++) {
if (_buffers[i]->_id == id)
return (int)i;
}
return -1;
}
Buffer * FileManager::getBufferByIndex(int index) {
return _buffers.at(index);
}
Buffer * FileManager::getBufferByID(BufferID id) {
return (Buffer*)id;
//return _buffers.at(getBufferIndexByID(id));
}
void FileManager::beNotifiedOfBufferChange(Buffer * theBuf, int mask) {
_pNotepadPlus->notifyBufferChanged(theBuf, mask);
};
void FileManager::addBufferReference(BufferID buffer, ScintillaEditView * identifier) {
Buffer * buf = getBufferByID(buffer);
buf->addReference(identifier);
}
void FileManager::closeBuffer(BufferID id, ScintillaEditView * identifier) {
int index = getBufferIndexByID(id);
Buffer * buf = getBufferByIndex(index);
int oldRefs = buf->_references;
int refs = buf->removeReference(identifier);
//if (oldRefs != refs)
// _pscratchTilla->execute(SCI_RELEASEDOCUMENT, 0, buf->_doc); //we can release the document for the reference of container (it has changed so it was a valid operation)
if (!refs) { //buffer can be deallocated
_pscratchTilla->execute(SCI_RELEASEDOCUMENT, 0, buf->_doc); //release for FileManager, Document is now gone
_buffers.erase(_buffers.begin() + index);
delete buf;
_nrBufs--;
}
}
BufferID FileManager::loadFile(const char * filename, Document doc) {
if (doc == NULL) {
doc = (Document)_pscratchTilla->execute(SCI_CREATEDOCUMENT);
}
Utf8_16_Read UnicodeConvertor; //declare here so we can get information after loading is done
if (loadFileData(doc, filename, &UnicodeConvertor)) {
Buffer * newBuf = new Buffer(this, _nextBufferID, doc, DOC_REGULAR, filename);
BufferID id = (BufferID) newBuf;
newBuf->_id = id;
_buffers.push_back(newBuf);
_nrBufs++;
Buffer * buf = _buffers.at(_nrBufs - 1);
// 3 formats : WIN_FORMAT, UNIX_FORMAT and MAC_FORMAT
if (UnicodeConvertor.getNewBuf()) {
buf->determinateFormat(UnicodeConvertor.getNewBuf());
} else {
buf->determinateFormat("");
}
buf->setUnicodeMode(UnicodeConvertor.getEncoding());
//determine buffer properties
BufferID retval = _nextBufferID++;
return id;
} else { //failed loading, release document
_pscratchTilla->execute(SCI_RELEASEDOCUMENT, 0, doc); //Failure, so release document
return BUFFER_INVALID;
}
}
bool FileManager::reloadBuffer(BufferID id) {
Buffer * buf = getBufferByID(id);
Document doc = buf->getDocument();
Utf8_16_Read UnicodeConvertor;
return loadFileData(doc, buf->getFilePath(), &UnicodeConvertor);
}
bool FileManager::saveBuffer(BufferID id, const char * filename, bool isCopy) {
Buffer * buffer = getBufferByID(id);
bool isHidden = false;
bool isSys = false;
DWORD attrib;
if (PathFileExists(filename))
{
attrib = ::GetFileAttributes(filename);
if (attrib != INVALID_FILE_ATTRIBUTES)
{
isHidden = (attrib & FILE_ATTRIBUTE_HIDDEN) != 0;
if (isHidden)
::SetFileAttributes(filename, attrib & ~FILE_ATTRIBUTE_HIDDEN);
isSys = (attrib & FILE_ATTRIBUTE_SYSTEM) != 0;
if (isSys)
::SetFileAttributes(filename, attrib & ~FILE_ATTRIBUTE_SYSTEM);
}
}
UniMode mode = buffer->getUnicodeMode();
if (mode == uniCookie)
mode = uni8Bit; //set the mode to ANSI to prevent converter from adding BOM and performing conversions, Scintilla's data can be copied directly
Utf8_16_Write UnicodeConvertor;
UnicodeConvertor.setEncoding(mode);
FILE *fp = UnicodeConvertor.fopen(filename, "wb");
if (fp)
{
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, buffer->_doc); //generate new document
char data[blockSize + 1];
int lengthDoc = _pscratchTilla->getCurrentDocLen();
for (int i = 0; i < lengthDoc; i += blockSize)
{
int grabSize = lengthDoc - i;
if (grabSize > blockSize)
grabSize = blockSize;
_pscratchTilla->getText(data, i, i + grabSize);
UnicodeConvertor.fwrite(data, grabSize);
}
UnicodeConvertor.fclose();
if (isHidden)
::SetFileAttributes(filename, attrib | FILE_ATTRIBUTE_HIDDEN);
if (isSys)
::SetFileAttributes(filename, attrib | FILE_ATTRIBUTE_SYSTEM);
if (isCopy) {
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault);
return true; //all done
}
buffer->setFileName(filename);
buffer->setDirty(false);
buffer->setStatus(DOC_REGULAR);
_pscratchTilla->execute(SCI_SETSAVEPOINT);
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault);
return true;
}
return false;
}
BufferID FileManager::newEmptyDocument() {
char newTitle[10];
strcpy(newTitle, UNTITLED_STR);
itoa(_nextNewNumber, newTitle+4, 10);
_nextNewNumber++;
Document doc = (Document)_pscratchTilla->execute(SCI_CREATEDOCUMENT); //this already sets a reference for filemanager
Buffer * newBuf = new Buffer(this, _nextBufferID, doc, DOC_UNNAMED, newTitle);
BufferID id = (BufferID)newBuf;
newBuf->_id = id;
_buffers.push_back(newBuf);
_nrBufs++;
BufferID retval = _nextBufferID++;
return id;
}
BufferID FileManager::bufferFromDocument(Document doc, bool dontIncrease) {
char newTitle[10];
strcpy(newTitle, UNTITLED_STR);
itoa(_nextNewNumber, newTitle+4, 10);
_pscratchTilla->execute(SCI_ADDREFDOCUMENT, 0, doc); //set reference for FileManager
Buffer * newBuf = new Buffer(this, _nextBufferID, doc, DOC_UNNAMED, newTitle);
BufferID id = (BufferID)newBuf;
newBuf->_id = id;
_buffers.push_back(newBuf);
_nrBufs++;
BufferID retval = _nextBufferID;
if (!dontIncrease)
_nextBufferID++;
return id;
}
bool FileManager::loadFileData(Document doc, const char * filename, Utf8_16_Read * UnicodeConvertor) {
const int blockSize = 128 * 1024; //128 kB
char data[blockSize];
FILE *fp = fopen(filename, "rb");
if (!fp)
return false;
//Setup scratchtilla for new filedata
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, doc);
_pscratchTilla->execute(SCI_CLEARALL);
size_t lenFile = 0;
size_t lenConvert = 0; //just in case conversion results in 0, but file not empty
do {
lenFile = fread(data, 1, blockSize, fp);
lenConvert = UnicodeConvertor->convert(data, lenFile);
_pscratchTilla->execute(SCI_ADDTEXT, lenConvert, (LPARAM)(UnicodeConvertor->getNewBuf()));
} while (lenFile > 0);
fclose(fp);
_pscratchTilla->execute(SCI_EMPTYUNDOBUFFER);
_pscratchTilla->execute(SCI_SETSAVEPOINT);
_pscratchTilla->execute(SCI_SETDOCPOINTER, 0, _scratchDocDefault);
return true;
}
BufferID FileManager::getBufferFromName(const char * name) {
for(size_t i = 0; i < _buffers.size(); i++) {
if (!strcmp(name, _buffers.at(i)->getFilePath()))
return _buffers.at(i)->getID();
}
return BUFFER_INVALID;
}
bool FileManager::createEmptyFile(const char * path) {
FILE * file = fopen(path, "wb");
if (!file)
return false;
fclose(file);
return true;
}

View File

@ -18,124 +18,128 @@
#ifndef BUFFER_H
#define BUFFER_H
#include <shlwapi.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "Scintilla.h"
#include "Parameters.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
const char UNTITLED_STR[] = "new ";
typedef sptr_t Document;
// Ordre important!! Ne le changes pas!
//SC_EOL_CRLF (0), SC_EOL_CR (1), or SC_EOL_LF (2).
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
};
const int CR = 0x0D;
const int LF = 0x0A;
enum docFileStaus{NEW_DOC, FILE_DELETED, NO_PROBLEM, MODIFIED_FROM_OUTSIDE};
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
BufferChangeMask = 0x1FF //Mask: covers all changes
};
struct HeaderLineState {
HeaderLineState() : _headerLineNumber(0), _isCollapsed(false){};
HeaderLineState(int lineNumber, bool isFoldUp) : _headerLineNumber(lineNumber), _isCollapsed(isFoldUp){};
HeaderLineState() : _headerLineNumber(0), _isExpanded(true){};
HeaderLineState(int lineNumber, bool isExpanded) : _headerLineNumber(lineNumber), _isExpanded(isExpanded){};
int _headerLineNumber;
bool _isCollapsed;
bool _isExpanded;
};
/*
struct Position
{
int _firstVisibleLine;
int _startPos;
int _endPos;
int _xOffset;
};
*/
//#define USER_LANG_CURRENT ""
const int userLangNameMax = 16;
static bool isInList(const char *token, const char *list) {
if ((!token) || (!list))
return false;
char word[64];
int i = 0;
int j = 0;
for (; i <= int(strlen(list)) ; i++)
{
if ((list[i] == ' ')||(list[i] == '\0'))
{
if (j != 0)
{
word[j] = '\0';
j = 0;
//File manager class maintains all buffers
class FileManager {
public:
void init(Notepad_plus * pNotepadPlus, ScintillaEditView * pscratchTilla);
if (!stricmp(token, word))
return true;
}
}
else
{
word[j] = list[i];
j++;
}
}
return false;
//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); //generates exception if id is invalid
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 char * 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();
BufferID bufferFromDocument(Document doc, bool dontIncrease = false); //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
BufferID getBufferFromName(const char * name);
bool reloadBuffer(BufferID id);
bool saveBuffer(BufferID id, const char * filename, bool isCopy = false);
bool createEmptyFile(const char * path);
static FileManager * getInstance() {return _pSelf;};
void destroyInstance() { delete _pSelf; };
void increaseDocNr() { _nextNewNumber++; };
private:
FileManager();
~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 char * filename, Utf8_16_Read * UnicodeConvertor);
};
#define MainFileManager FileManager::getInstance()
class Buffer
{
friend class ScintillaEditView;
friend class Notepad_plus;
friend class FileManager;
public :
Buffer(Document doc, const char *fileName)
: _isDirty(false), _doc(doc), _isReadOnly(false), _isSetReadOnly(false), _recentTag(-1)
//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 char *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), _needLexer(true)
{
NppParameters *pNppParamInst = NppParameters::getInstance();
const NewDocDefaultSettings & ndds = (pNppParamInst->getNppGUI()).getNewDocDefaultSettings();
_format = ndds._format;
_unicodeMode = ndds._encoding;
_pos._firstVisibleLine = 0;
_pos._startPos = 0;
_pos._endPos = 0;
_pos._xOffset = 0;
_pos._scrollWidth = 1;
setFileName(fileName, ndds._lang);
//_userLangExt[0] = '\0';
updateTimeStamp();
checkFileState();
_currentStatus = type;
_isDirty = false;
_userLangExt[0] = 0;
if (type == DOC_UNNAMED)
_needLexer = false; //empty document, no styling
_canNotify = true;
};
Buffer(const Buffer & buf) : _isDirty(buf._isDirty), _doc(buf._doc), _lang(buf._lang),
_timeStamp(buf._timeStamp), _isReadOnly(buf._isReadOnly), _isSetReadOnly(buf._isSetReadOnly), _pos(buf._pos),
_format(buf._format),_unicodeMode(buf._unicodeMode), _foldState(buf._foldState), _recentTag(buf._recentTag),
_dontBotherMeAnymore(false), _reloadOnSwitchBack(false)
{
strcpy(_fullPathName, buf._fullPathName);
strcpy(_userLangExt, buf._userLangExt);
};
Buffer & operator=(const Buffer & buf)
{
if (this != &buf)
{
this->_isDirty = buf._isDirty;
this->_doc = buf._doc;
this->_lang = buf._lang;
this->_timeStamp = buf._timeStamp;
this->_isReadOnly = buf._isReadOnly;
this->_isSetReadOnly = buf._isSetReadOnly;
this->_pos = buf._pos;
this->_format = buf._format;
this->_unicodeMode = buf._unicodeMode;
this->_foldState = buf._foldState;
this->_recentTag = buf._recentTag;
strcpy(this->_fullPathName, buf._fullPathName);
strcpy(this->_userLangExt, buf._userLangExt);
}
return *this;
}
LangType getLangFromExt(const char *ext);
// this method 1. copies the file name
@ -143,150 +147,127 @@ public :
// 3. gets the last modified time
void setFileName(const char *fn, LangType defaultLang = L_TXT);
const char * getFileName() const {return _fullPathName;};
const char * getFilePath() const {
return _fullPathName;
};
void updatTimeStamp() {
struct _stat buf;
_timeStamp = (_stat(_fullPathName, &buf)==0)?buf.st_mtime:0;
const char * getFileName() const { return _fileName; };
BufferID getID() const {
return _id;
};
void increaseRecentTag() {
_recentTag = ++_recentTagCtr;
}
doNotify(BufferChangeRecentTag);
};
long getRecentTag() const {
return _recentTag;
}
docFileStaus checkFileState() {
if (isUntitled(_fullPathName))
{
_isReadOnly = false;
return NEW_DOC;
}
if (!PathFileExists(_fullPathName))
{
_isReadOnly = false;
return FILE_DELETED;
}
struct _stat buf;
if (!_stat(_fullPathName, &buf))
{
_isReadOnly = (bool)(!(buf.st_mode & _S_IWRITE));
if (_timeStamp != buf.st_mtime)
return MODIFIED_FROM_OUTSIDE;
}
return NO_PROBLEM;
};
// to use this method with open and save
void checkIfReadOnlyFile() {
struct _stat buf;
if (!_stat(_fullPathName, &buf))
{
_isReadOnly = (bool)(!(buf.st_mode & _S_IWRITE));
}
};
bool checkFileState();
bool isDirty() const {
return _isDirty;
};
bool isReadOnly() const {
return (_isReadOnly || _isSetReadOnly);
return (_isUserReadOnly || _isFileReadOnly);
};
bool isSystemReadOnly() const {
return _isReadOnly;
bool isUntitled() const {
return (_currentStatus == DOC_UNNAMED);
};
bool isUserReadOnly() const {
return _isSetReadOnly;
bool getFileReadOnly() const {
return _isFileReadOnly;
};
bool setReadOnly(bool ro) {
bool oldVal = _isSetReadOnly;
_isSetReadOnly = ro;
return oldVal;
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 char * userLangName = "") {
if (lang == _lang && lang != L_USER)
return;
_lang = lang;
if (_lang == L_USER) {
strcpy(_userLangExt, userLangName);
}
_needLexer = true; //change of lang means lexern eeds updating
doNotify(BufferChangeLanguage);
};
UniMode getUnicodeMode() const {
return _unicodeMode;
};
void setUnicodeMode(UniMode mode) {
/*if ((_unicodeMode != mode) &&
!((_unicodeMode == uni8Bit) && (mode == uniCookie)) && \
!((_unicodeMode == uniCookie) && (mode == uni8Bit))) {
//this check excludes switch between Utf8-w/o bom and ANSI. However, that makes a change too
}*/
_unicodeMode = mode;
//_isDirty = true; //set to dirty if change unicode mode
doNotify(BufferChangeUnicode | BufferChangeDirty);
};
DocFileStatus getStatus() const {
return _currentStatus;
};
time_t getTimeStamp() const {
return _timeStamp;
};
void synchroniseWith(const Buffer & buf) {
_isDirty = buf.isDirty();
_timeStamp = buf.getTimeStamp();
Document getDocument() const {
return _doc;
};
// that is : the prefix of the string is "new "
static bool isUntitled(const char *str2Test) {
return (strncmp(str2Test, UNTITLED_STR, sizeof(UNTITLED_STR)-1) == 0);
}
void setFormat(formatType format) {
_format = format;
void setDirty(bool dirty) {
_isDirty = dirty;
doNotify(BufferChangeDirty);
};
void determinateFormat(char *data) {
size_t len = strlen(data);
for (size_t i = 0 ; i < len ; i++)
{
if (data[i] == CR)
{
if (data[i+1] == LF)
{
_format = WIN_FORMAT;
return;
}
else
{
_format = MAC_FORMAT;
return;
}
}
if (data[i] == LF)
{
_format = UNIX_FORMAT;
return;
}
}
_format = WIN_FORMAT;
};
/*
void detectBin(char *data) {
size_t len = strlen(data);
const size_t lenMax = 2048;
void setPosition(const Position & pos, ScintillaEditView * identifier);
Position & getPosition(ScintillaEditView * identifier);
size_t size2Detect = (len > lenMax)?lenMax:len;
for (size_t i = 0 ; i < size2Detect ; i++)
{
if (isNotPrintableChar(data[i]))
{
_isBinary = true;
break;
}
}
};
*/
formatType getFormat() const {
return _format;
};
void setHeaderLineState(const std::vector<HeaderLineState> & folds, ScintillaEditView * identifier);
std::vector<HeaderLineState> & getHeaderLineState(ScintillaEditView * identifier);
void determinateFormat(char *data);
bool isUserDefineLangExt() const {
return (_userLangExt[0] != '\0');
};
const char * getUserDefineLangName() const {return _userLangExt;};
void setUnicodeMode(UniMode mode) {
if ((_unicodeMode != mode) && !((_unicodeMode == uni8Bit) && (mode == uniCookie)) && \
!((_unicodeMode == uniCookie) && (mode == uni8Bit)))
_isDirty = true;
_unicodeMode = mode;
const char * getUserDefineLangName() const {
return _userLangExt;
};
UniMode getUnicodeMode() const {return _unicodeMode;};
const char * getCommentLineSymbol() const {
Lang *l = getCurrentLang();
@ -295,12 +276,14 @@ public :
return l->_pCommentLineSymbol;
};
const char * getCommentStart() const {
Lang *l = getCurrentLang();
if (!l)
return NULL;
return l->_pCommentStart;
};
const char * getCommentEnd() const {
Lang *l = getCurrentLang();
if (!l)
@ -308,53 +291,61 @@ public :
return l->_pCommentEnd;
};
const Position & getPosition() const {
return _pos;
bool getNeedsLexing() const {
return _needLexer;
};
LangType getLangType() const {
return _lang;
void setNeedsLexing(bool lex) {
_needLexer = lex;
};
void setPosition(const Position& pos) {
_pos = pos;
};
//bool isBin() const {return _isBinary;};
//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);
private :
bool _isDirty;
Document _doc;
FileManager * _pManager;
bool _canNotify;
int _references; //if no references file inaccessible, can be closed
BufferID _id;
//document properties
Document _doc; //invariable
LangType _lang;
char _userLangExt[userLangNameMax]; // it's useful if only (_lang == L_USER)
time_t _timeStamp; // 0 if it's a new doc
bool _isReadOnly;
bool _isSetReadOnly;
Position _pos;
char _fullPathName[MAX_PATH];
bool _isDirty;
formatType _format;
UniMode _unicodeMode;
std::vector<HeaderLineState> _foldState;
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
std::vector< ScintillaEditView * > _referees;
std::vector< Position > _positions;
std::vector< std::vector<HeaderLineState> > _foldStates;
//Environment properties
DocFileStatus _currentStatus;
time_t _timeStamp; // 0 if it's a new doc
bool _isFileReadOnly;
char _fullPathName[MAX_PATH];
char * _fileName; //points to filename part in _fullPathName
long _recentTag;
static long _recentTagCtr;
//bool _isBinary;
bool _dontBotherMeAnymore;
bool _reloadOnSwitchBack;
Lang * getCurrentLang() const {
NppParameters *pNppParam = NppParameters::getInstance();
int i = 0;
Lang *l = pNppParam->getLangFromIndex(i++);
while (l)
{
if (l->_langID == _lang)
return l;
void updateTimeStamp();
Lang * getCurrentLang() const;
l = pNppParam->getLangFromIndex(i++);
int indexOfReference(ScintillaEditView * identifier) const;
void setStatus(DocFileStatus status) {
_currentStatus = status;
doNotify(BufferChangeStatus);
}
return NULL;
};
void doNotify(int mask) { if (_canNotify) _pManager->beNotifiedOfBufferChange(this, mask); };
};
#endif //BUFFER_H

View File

@ -24,155 +24,123 @@
#include <commctrl.h>
#include <shlwapi.h>
unsigned short DocTabView::_nbNewTitle = 0;
bool DocTabView::_hideTabBarStatus = false;
// return the index if fn is found in DocTabView
// otherwise -1
int DocTabView::find(const char *fn) const
{
return _pView->findDocIndexByName(fn);
}
char * DocTabView::newDocInit()
{
// create the new entry for this doc
char * newTitle = _pView->attatchDefaultDoc(_nbNewTitle++);
// create a new (the first) sub tab then hightlight it
TabBar::insertAtEnd(newTitle);
return newTitle;
}
const char * DocTabView::newDoc(const char *fn)
{
char *completName;
if ((!fn) || (!strcmp(fn, "")))
completName = _pView->createNewDoc(_nbNewTitle++);
else
completName = _pView->createNewDoc(fn);
// for the title of sub tab
fn = PathFindFileName(completName);
char fnConformToTab[MAX_PATH];
for (int i = 0, j = 0 ; ; i++)
{
fnConformToTab[j++] = fn[i];
if (fn[i] == '&')
fnConformToTab[j++] = '&';
if (fn[i] == '\0')
break;
}
TabBar::insertAtEnd(fnConformToTab);
TabBar::activateAt(_nbItem - 1);
if (_isMultiLine)
{
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
return (const char *)completName;
}
const char * DocTabView::newDoc(Buffer & buf)
{
const char *completName = buf.getFileName();
int i = _pView->addBuffer(buf);
_pView->activateDocAt(i);
// for the title of sub tab
TabBar::insertAtEnd(PathFindFileName(completName));
TabBar::activateAt(_nbItem - 1);
if (_isMultiLine)
{
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
return completName;
}
//! \brief this method activates the doc and the corresponding sub tab
//! \brief return the index of previeus current doc
char * DocTabView::activate(int index)
{
TabBar::activateAt(index);
return _pView->activateDocAt(index);
}
// this method updates the doc when user clicks a sub tab
// return Null if the user clicks on an active sub tab,
// otherwize the name of new activated doc
char * DocTabView::clickedUpdate()
{
int indexClicked = int(::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0));
if (indexClicked == _pView->getCurrentDocIndex()) return NULL;
return _pView->activateDocAt(indexClicked);
}
const char * DocTabView::closeCurrentDoc()
{
if (_nbItem == 1)
{
newDoc();
closeDocAt(0);
}
else
{
int i2activate;
int i2close = _pView->closeCurrentDoc(i2activate);
TabBar::deletItemAt(i2close);
if (i2activate > 1)
TabBar::activateAt(i2activate-1);
TabBar::activateAt(i2activate);
}
if (_isMultiLine)
{
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
return _pView->getCurrentTitle();
}
const char * DocTabView::closeAllDocs()
{
_pView->removeAllUnusedDocs();
TabBar::deletAllItem();
_nbNewTitle = 0;
newDocInit();
return _pView->getCurrentTitle();
}
void DocTabView::closeDocAt(int index2Close)
{
_pView->closeDocAt(index2Close);
TabBar::deletItemAt(index2Close);
}
void DocTabView::updateCurrentTabItem(const char *title)
{
int currentIndex = TabCtrl_GetCurSel(_hSelf);
updateTabItem(currentIndex, title);
}
void DocTabView::updateTabItem(int index, const char *title)
{
char str[MAX_PATH];
void DocTabView::addBuffer(BufferID buffer) {
if (buffer == BUFFER_INVALID) //valid only
return;
if (this->getIndexByBuffer(buffer) != -1) //no duplicates
return;
Buffer * buf = MainFileManager->getBufferByID(buffer);
TCITEM tie;
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.pszText = str;
tie.cchTextMax = (sizeof(str)-1);
tie.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
TabCtrl_GetItem(_hSelf, index, &tie);
if ((title)&&(strcmp(title, "")))
tie.pszText = (char *)title;
int index = -1;
if (_hasImgLst)
index = 0;
tie.iImage = index;
tie.pszText = (LPSTR)buf->getFileName();
tie.lParam = (LPARAM)buffer;
::SendMessage(_hSelf, TCM_INSERTITEM, _nbItem++, reinterpret_cast<LPARAM>(&tie));
bufferUpdated(buf, BufferChangeMask);
bool isDirty = (_pView->getBufferAt(index)).isDirty();//isCurrentBufReadOnly();
bool isReadOnly = (_pView->getBufferAt(index)).isReadOnly();//getCurrentDocStat();
tie.iImage = isReadOnly?REDONLY_IMG_INDEX:(isDirty?UNSAVED_IMG_INDEX:SAVED_IMG_INDEX);
TabCtrl_SetItem(_hSelf, index, &tie);
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
void DocTabView::closeBuffer(BufferID buffer) {
int indexToClose = getIndexByBuffer(buffer);
deletItemAt(indexToClose);
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
bool DocTabView::activateBuffer(BufferID buffer) {
int indexToActivate = getIndexByBuffer(buffer);
if (indexToActivate == -1)
return false; //cannot activate
activateAt(indexToActivate);
return true;
}
BufferID DocTabView::activeBuffer() {
int index = getCurrentTabIndex();
return (BufferID)getBufferByIndex(index);
}
BufferID DocTabView::findBufferByName(const char * fullfilename) { //-1 if not found, something else otherwise
TCITEM tie;
tie.lParam = -1;
tie.mask = TCIF_PARAM;
for(size_t i = 0; i < _nbItem; i++) {
::SendMessage(_hSelf, TCM_GETITEM, i, reinterpret_cast<LPARAM>(&tie));
BufferID id = (BufferID)tie.lParam;
Buffer * buf = MainFileManager->getBufferByID(id);
if (!strcmp(fullfilename, buf->getFilePath())) {
return id;
}
}
return BUFFER_INVALID;
}
int DocTabView::getIndexByBuffer(BufferID id) {
TCITEM tie;
tie.lParam = -1;
tie.mask = TCIF_PARAM;
for(int i = 0; i < (int)_nbItem; i++) {
::SendMessage(_hSelf, TCM_GETITEM, i, reinterpret_cast<LPARAM>(&tie));
if ((BufferID)tie.lParam == id)
return i;
}
return -1;
}
BufferID DocTabView::getBufferByIndex(int index) {
TCITEM tie;
tie.lParam = -1;
tie.mask = TCIF_PARAM;
::SendMessage(_hSelf, TCM_GETITEM, index, reinterpret_cast<LPARAM>(&tie));
return (BufferID)tie.lParam;
}
void DocTabView::bufferUpdated(Buffer * buffer, int mask) {
int index = getIndexByBuffer(buffer->getID());
if (index == -1)
return;
TCITEM tie;
tie.lParam = -1;
tie.mask = 0;
if (mask & BufferChangeReadonly || mask & BufferChangeDirty) {
tie.mask |= TCIF_IMAGE;
tie.iImage = buffer->isDirty()?UNSAVED_IMG_INDEX:SAVED_IMG_INDEX;
if (buffer->isReadOnly()) {
tie.iImage = REDONLY_IMG_INDEX;
}
}
if (mask & BufferChangeFilename) {
tie.mask |= TCIF_TEXT;
tie.pszText = (LPSTR)buffer->getFileName();
}
::SendMessage(_hSelf, TCM_SETITEM, index, reinterpret_cast<LPARAM>(&tie));
::SendMessage(_hParent, WM_SIZE, 0, 0);
}
void DocTabView::setBuffer(int index, BufferID id) {
if (index < 0 || index >= (int)_nbItem)
return;
TCITEM tie;
tie.lParam = (LPARAM)id;
tie.mask = TCIF_PARAM;
::SendMessage(_hSelf, TCM_SETITEM, index, reinterpret_cast<LPARAM>(&tie));
bufferUpdated(MainFileManager->getBufferByID(id), BufferChangeMask); //update tab, everything has changed
::SendMessage(_hParent, WM_SIZE, 0, 0);
}

View File

@ -29,47 +29,43 @@ const int REDONLY_IMG_INDEX = 2;
class DocTabView : public TabBarPlus
{
public :
DocTabView():TabBarPlus(), _pView(NULL), _hideTabBarStatus(false){};
DocTabView():TabBarPlus(), _pView(NULL) {};
virtual ~DocTabView(){};
virtual void destroy() {
TabBarPlus::destroy();
};
char * init(HINSTANCE hInst, HWND parent, ScintillaEditView *pView, IconList *pIconList = NULL)
void init(HINSTANCE hInst, HWND parent, ScintillaEditView * pView, IconList *pIconList = NULL)
{
TabBarPlus::init(hInst, parent);
_pView = pView;
if (pIconList)
TabBar::setImageList(pIconList->getHandle());
return newDocInit();
return;
};
char * newDocInit();
int find(const char *) const;
char * activate(int index);
void addBuffer(BufferID buffer);
void closeBuffer(BufferID buffer);
void bufferUpdated(Buffer * buffer, int mask);
const char * newDoc(const char *fn = NULL);
const char * newDoc(Buffer & buf);
bool activateBuffer(BufferID buffer);
char * clickedUpdate();
BufferID activeBuffer();
BufferID findBufferByName(const char * fullfilename); //-1 if not found, something else otherwise
const char * closeCurrentDoc();
const char * closeAllDocs();
void closeDocAt(int index);
int getIndexByBuffer(BufferID id);
BufferID getBufferByIndex(int index);
//void setCurrentTabItem(const char *title, bool isDirty);
void updateCurrentTabItem(const char *title = NULL);
void updateTabItem(int index, const char *title = NULL);
void setBuffer(int index, BufferID id);
bool setHideTabBarStatus(bool hideOrNot){
static bool setHideTabBarStatus(bool hideOrNot) {
bool temp = _hideTabBarStatus;
_hideTabBarStatus = hideOrNot;
return temp;
};
bool getHideTabBarStatus() const {
static bool getHideTabBarStatus() {
return _hideTabBarStatus;
};
@ -88,14 +84,9 @@ public :
}
};
const ScintillaEditView * getView() const {
return _pView;
};
private :
static unsigned short _nbNewTitle;
ScintillaEditView *_pView;
bool _hideTabBarStatus;
static bool _hideTabBarStatus;
};
#endif //DOCTABVIEW_H

View File

@ -306,7 +306,7 @@ void FindReplaceDlg::create(int dialogID, bool isRTL)
void FindReplaceDlg::updateCombos()
{
bool isUnicode = (*_ppEditView)->getCurrentBuffer().getUnicodeMode() != uni8Bit;
bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH);
addText2Combo(getTextFromCombo(hReplaceCombo, isUnicode).c_str(), hReplaceCombo, isUnicode);
@ -521,7 +521,7 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP
{
if ((_currentStatus == FIND_DLG) || (_currentStatus == REPLACE_DLG))
{
bool isUnicode = (*_ppEditView)->getCurrentBuffer().getUnicodeMode() != uni8Bit;
bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT);
string str2Search = getTextFromCombo(hFindCombo, isUnicode);
updateCombo(IDFINDWHAT);
@ -538,7 +538,7 @@ BOOL CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lP
{
if (_currentStatus == REPLACE_DLG)
{
bool isUnicode = (*_ppEditView)->getCurrentBuffer().getUnicodeMode() != uni8Bit;
bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT);
HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH);
string str2Search = getTextFromCombo(hFindCombo, isUnicode);
@ -915,7 +915,7 @@ bool FindReplaceDlg::processReplace(const char *txt2find, const char *txt2replac
FindOption *pOptions = options?options:&_options;
if ((*_ppEditView)->getCurrentBuffer().isReadOnly()) return false;
if ((*_ppEditView)->getCurrentBuffer()->isReadOnly()) return false;
int stringSizeFind = strlen(txt2find);
int stringSizeReplace = strlen(txt2replace);
@ -950,12 +950,14 @@ bool FindReplaceDlg::processReplace(const char *txt2find, const char *txt2replac
int replacedLen = (*_ppEditView)->execute(SCI_REPLACETARGETRE, stringSizeReplace, (LPARAM)pTextReplace);
if (!foundTextLen)
//if (!foundTextLen)
(*_ppEditView)->execute(SCI_SETSEL, start, start + replacedLen);
}
else
{
(*_ppEditView)->execute(SCI_REPLACETARGET, stringSizeReplace, (LPARAM)pTextReplace);
int start = int((*_ppEditView)->execute(SCI_GETTARGETSTART));
int replacedLen = (*_ppEditView)->execute(SCI_REPLACETARGET, stringSizeReplace, (LPARAM)pTextReplace);
(*_ppEditView)->execute(SCI_SETSEL, start, start + replacedLen);
}
}
@ -993,14 +995,14 @@ int FindReplaceDlg::processAll(ProcessOperation op, const char *txt2find, const
if (!isCreated() && !txt2find)
return nbReplaced;
if ((op == ProcessReplaceAll) && (*_ppEditView)->getCurrentBuffer().isReadOnly())
if ((op == ProcessReplaceAll) && (*_ppEditView)->getCurrentBuffer()->isReadOnly())
return nbReplaced;
if (!fileName)
fileName = "";
FindOption *pOptions = opt?opt:&_options;
bool isUnicode = (*_ppEditView)->getCurrentBuffer().getUnicodeMode() != uni8Bit;
bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
int stringSizeFind = 0;
int stringSizeReplace = 0;
@ -1263,7 +1265,7 @@ void FindReplaceDlg::findAllIn(InWhat op)
//HANDLE hEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, "findInFilesEvent");
if (!_pFinder)
{
_pFinder = new Finder;
_pFinder = new Finder();
_pFinder->init(_hInst, _hSelf, _ppEditView);
tTbData data = {0};
@ -1281,6 +1283,7 @@ void FindReplaceDlg::findAllIn(InWhat op)
::SendMessage(_hParent, NPPM_DMMREGASDCKDLG, 0, (LPARAM)&data);
_pFinder->_scintView.init(_hInst, _pFinder->getHSelf());
_pFinder->setFinderReadOnly(true);
_pFinder->_scintView.execute(SCI_SETCODEPAGE, SC_CP_UTF8);
_pFinder->_scintView.execute(SCI_USEPOPUP, FALSE);
@ -1521,7 +1524,7 @@ BOOL CALLBACK FindIncrementDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
{
case WM_COMMAND :
{
bool isUnicode = (*(_pFRDlg->_ppEditView))->getCurrentBuffer().getUnicodeMode() != uni8Bit;
bool isUnicode = (*(_pFRDlg->_ppEditView))->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
switch (LOWORD(wParam))
{
case IDCANCEL :

View File

@ -105,7 +105,9 @@ public:
str += fileName;
str += "]\n";
setFinderReadOnly(false);
_scintView.execute(SCI_APPENDTEXT, str.length(), (LPARAM)str.c_str());
setFinderReadOnly(true);
_lineCounter++;
};
@ -117,7 +119,9 @@ public:
str += itoa(lineNb, lnb, 10);
str += " : ";
str += fi._foundLine;
setFinderReadOnly(false);
_scintView.execute(SCI_APPENDTEXT, str.length(), (LPARAM)str.c_str());
setFinderReadOnly(true);
_lineCounter++;
};
@ -126,7 +130,9 @@ public:
void removeAll() {
_markedLine = -1;
_foundInfos.clear();
setFinderReadOnly(false);
_scintView.execute(SCI_CLEARALL);
setFinderReadOnly(true);
_lineCounter = 0;
};
@ -167,6 +173,10 @@ private:
int _markedLine;
InWhat _mode;
size_t _lineCounter;
void setFinderReadOnly(bool isReadOnly) {
_scintView.execute(SCI_SETREADONLY, isReadOnly);
};
};
//FindReplaceDialog: standard find/replace window
@ -248,10 +258,6 @@ public :
addText2Combo(txt2find, ::GetDlgItem(_hSelf, IDFINDWHAT), isUTF8);
}
void setFinderReadOnly(bool isReadOnly = true) {
_pFinder->_scintView.execute(SCI_SETREADONLY, isReadOnly);
};
bool isFinderEmpty() const {
return _pFinder->isEmpty();
};
@ -291,7 +297,7 @@ public :
};
string getText2search() const {
bool isUnicode = (*_ppEditView)->getCurrentBuffer().getUnicodeMode() != uni8Bit;
bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
return getTextFromCombo(::GetDlgItem(_hSelf, IDFINDWHAT), isUnicode);
};
@ -363,7 +369,7 @@ private :
void updateCombos();
void updateCombo(int comboID) {
bool isUnicode = (*_ppEditView)->getCurrentBuffer().getUnicodeMode() != uni8Bit;
bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit;
HWND hCombo = ::GetDlgItem(_hSelf, comboID);
addText2Combo(getTextFromCombo(hCombo, isUnicode).c_str(), hCombo, isUnicode);
};

View File

@ -178,7 +178,7 @@ size_t Printer::doPrint(bool justDoIt)
DOCINFO docInfo;
docInfo.cbSize = sizeof(DOCINFO);
docInfo.lpszDocName = _pSEView->getCurrentTitle();
docInfo.lpszDocName = _pSEView->getCurrentBuffer()->getFilePath();
docInfo.lpszOutput = NULL;
if (::StartDoc(_pdlg.hDC, &docInfo) < 0)

View File

@ -20,6 +20,7 @@
#include <ShellAPI.h>
#include "ScintillaEditView.h"
#include "Parameters.h"
#include "constant.h"
// initialize the static variable
@ -193,6 +194,9 @@ void ScintillaEditView::init(HINSTANCE hInst, HWND hPere)
_callWindowProc = CallWindowProcA;
_scintillaDefaultProc = reinterpret_cast<WNDPROC>(::SetWindowLongA(_hSelf, GWL_WNDPROC, reinterpret_cast<LONG>(scintillaStatic_Proc)));
}
//Get the startup document and make a buffer for it so it can be accessed like a file
//attachDefaultDoc(); //Let Notepad_plus do it
}
LRESULT ScintillaEditView::scintillaNew_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
@ -696,7 +700,6 @@ void ScintillaEditView::defineDocType(LangType typeDoc)
}
execute(SCI_STYLECLEARALL);
execute(SCI_CLEARDOCUMENTSTYLE);
int iFind = stylers.getStylerIndexByID(SCE_UNIVERSAL_FOUND_STYLE);
if (iFind != -1)
@ -735,7 +738,7 @@ void ScintillaEditView::defineDocType(LangType typeDoc)
// Sinon y'aura un soucis de performance!
if (isCJK())
{
if (getCurrentBuffer()._unicodeMode == uni8Bit)
if (getCurrentBuffer()->getUnicodeMode() == uni8Bit)
execute(SCI_SETCODEPAGE, _codepage);
}
@ -773,12 +776,13 @@ void ScintillaEditView::defineDocType(LangType typeDoc)
case L_INI :
setIniLexer(); break;
case L_USER :
if (_buffers[_currentIndex]._userLangExt[0])
setUserLexer(_buffers[_currentIndex]._userLangExt);
case L_USER : {
const char * langExt = _currentBuffer->getUserDefineLangName();
if (langExt[0])
setUserLexer(langExt);
else
setUserLexer();
break;
break; }
case L_NFO :
{
@ -937,44 +941,22 @@ void ScintillaEditView::defineDocType(LangType typeDoc)
int bitsNeeded = execute(SCI_GETSTYLEBITSNEEDED);
execute(SCI_SETSTYLEBITS, bitsNeeded);
execute(SCI_COLOURISE, 0, -1);
}
char * ScintillaEditView::attatchDefaultDoc(int nb)
BufferID ScintillaEditView::attachDefaultDoc()
{
char title[10];
char nb_str[4];
strcat(strcpy(title, UNTITLED_STR), _itoa(nb, nb_str, 10));
// get the doc pointer attached (by default) on the view Scintilla
Document doc = execute(SCI_GETDOCPOINTER, 0, 0);
BufferID id = MainFileManager->bufferFromDocument(doc, false);//true); //keep counter on 1
Buffer * buf = MainFileManager->getBufferByID(id);
// create the entry for our list
_buffers.push_back(Buffer(doc, title));
MainFileManager->addBufferReference(id, this); //add a reference. Notepad only shows the buffer in tabbar
// set current index to 0
_currentIndex = 0;
_currentBufferID = id;
_currentBuffer = buf;
bufferUpdated(buf, BufferChangeMask); //make sure everything is in sync with the buffer, since no reference exists
if (getCurrentBuffer()._unicodeMode != uni8Bit)
execute(SCI_SETCODEPAGE, SC_CP_UTF8);
return _buffers[_currentIndex]._fullPathName;
}
int ScintillaEditView::findDocIndexByName(const char *fn) const
{
int index = -1;
for (int i = 0 ; i < int(_buffers.size()) ; i++)
{
if (!stricmp(_buffers[i]._fullPathName, fn))
{
index = i;
break;
}
}
return index;
return id;
}
void ScintillaEditView::saveCurrentPos()
@ -984,61 +966,66 @@ void ScintillaEditView::saveCurrentPos()
int docLine = execute(SCI_DOCLINEFROMVISIBLE, displayedLine); //linenumber of the line displayed in the top
//int offset = displayedLine - execute(SCI_VISIBLEFROMDOCLINE, docLine); //use this to calc offset of wrap. If no wrap this should be zero
Buffer & buf = _buffers[_currentIndex];
Buffer * buf = MainFileManager->getBufferByID(_currentBufferID);
Position pos;
// the correct visible line number
buf._pos._firstVisibleLine = docLine;//docLine - nbInvisibleLine;
pos._firstVisibleLine = docLine;
pos._startPos = static_cast<int>(execute(SCI_GETSELECTIONSTART));
pos._endPos = static_cast<int>(execute(SCI_GETSELECTIONEND));
pos._xOffset = static_cast<int>(execute(SCI_GETXOFFSET));
pos._selMode = execute(SCI_GETSELECTIONMODE);
pos._scrollWidth = execute(SCI_GETSCROLLWIDTH);
buf._pos._startPos = static_cast<int>(execute(SCI_GETSELECTIONSTART));
buf._pos._endPos = static_cast<int>(execute(SCI_GETSELECTIONEND));
buf._pos._xOffset = static_cast<int>(execute(SCI_GETXOFFSET));
buf._pos._selMode = execute(SCI_GETSELECTIONMODE);
buf._pos._scrollWidth = execute(SCI_GETSCROLLWIDTH);
buf->setPosition(pos, this);
}
void ScintillaEditView::restoreCurrentPos()
{
_wrapRestoreNeeded = isWrap();
Buffer * buf = MainFileManager->getBufferByID(_currentBufferID);
Position & pos = buf->getPosition(this);
execute(SCI_GOTOPOS, 0); //make sure first line visible by setting caret there, will scroll to top of document
Buffer & buf = _buffers[_currentIndex];
if (buf._pos._selMode == SC_SEL_RECTANGLE)
{
execute(SCI_SETSELECTIONMODE, buf._pos._selMode);
execute(SCI_SETSELECTIONMODE, pos._selMode);
execute(SCI_SETSELECTIONSTART, pos._startPos);
execute(SCI_SETSELECTIONEND, pos._endPos);
if (!isWrap()) { //only offset if not wrapping, otherwise the offset isnt needed at all
execute(SCI_SETSCROLLWIDTH, pos._scrollWidth);
execute(SCI_SETXOFFSET, pos._xOffset);
}
execute(SCI_SETSELECTIONSTART, buf._pos._startPos);
execute(SCI_SETSELECTIONEND, buf._pos._endPos);
//int scrollWidth = execute(SCI_GETSCROLLWIDTH);
//execute(SCI_SETSCROLLWIDTH, scrollWidth);
execute(SCI_SETSCROLLWIDTH, buf._pos._scrollWidth);
execute(SCI_SETXOFFSET, buf._pos._xOffset);
// these 3 lines should be at the end so it works in wrap mode
int lineToShow = execute(SCI_VISIBLEFROMDOCLINE, buf._pos._firstVisibleLine);
int lineToShow = execute(SCI_VISIBLEFROMDOCLINE, pos._firstVisibleLine);
scroll(0, lineToShow);
}
//! \brief this method activates the doc and the corresponding sub tab
//! \brief return the index of previeus current doc
char * ScintillaEditView::activateDocAt(int index)
{
::SendMessage(_hParent, NPPM_INTERNAL_DOCSWITCHOFF, 0, (LPARAM)_hSelf);
void ScintillaEditView::restyleBuffer() {
execute(SCI_CLEARDOCUMENTSTYLE);
execute(SCI_COLOURISE, 0, -1);
_currentBuffer->setNeedsLexing(false);
}
// To minimize the scroll width on each doc switch
//execute(SCI_SETSCROLLWIDTH, 1);
void ScintillaEditView::styleChange() {
defineDocType(_currentBuffer->getLangType());
}
void ScintillaEditView::activateBuffer(BufferID buffer)
{
if (buffer == BUFFER_INVALID)
return;
if (buffer == _currentBuffer)
return;
Buffer * newBuf = MainFileManager->getBufferByID(buffer);
// before activating another document, we get the current position
// from the Scintilla view then save it to the current document
saveCurrentPos();
//Position & prevDocPos = _buffers[_currentIndex]._pos;
// get foldStateIOnfo of current doc
// get foldStateInfo of current doc
std::vector<HeaderLineState> lineStateVector;
int maxLine = execute(SCI_GETLINECOUNT);
for (int line = 0; line < maxLine; line++)
@ -1052,76 +1039,85 @@ char * ScintillaEditView::activateDocAt(int index)
}
// put the state into the future ex buffer
_buffers[_currentIndex]._foldState = lineStateVector;
// increase current doc ref count to 2
execute(SCI_ADDREFDOCUMENT, 0, _buffers[_currentIndex]._doc);
_currentBuffer->setHeaderLineState(lineStateVector, this);
_currentBufferID = buffer; //the magical switch happens here
_currentBuffer = newBuf;
// change the doc, this operation will decrease
// the ref count of old current doc to 1
// then increase the new current doc to 2
execute(SCI_SETDOCPOINTER, 0, _buffers[index]._doc);
// Important : to avoid the leak of memory
// Now keep the ref counter of new current doc as 1
int refCtr = execute(SCI_RELEASEDOCUMENT, 0, _buffers[index]._doc);
// NOW WE TAKE NEW DOC AND WE THROW OUT THE OLD ONE
_currentIndex = index;
_buffers[_currentIndex].increaseRecentTag();
// the ref count of old current doc and increase the one of the new doc. FileManager should manage the rest
// Note that the actual reference in the Buffer itself is NOT decreased, Notepad_plus does that if neccessary
execute(SCI_SETDOCPOINTER, 0, _currentBuffer->getDocument());
// Due to execute(SCI_CLEARDOCUMENTSTYLE); in defineDocType() function
// defineDocType() function should be called here, but not be after the fold info loop
defineDocType(_buffers[_currentIndex]._lang);
defineDocType(_currentBuffer->getLangType());
if (_currentBuffer->getNeedsLexing()) {
restyleBuffer();
}
// restore the collapsed info
int nbLineState = _buffers[_currentIndex]._foldState.size();
std::vector<HeaderLineState> & lineStateVectorNew = newBuf->getHeaderLineState(this);
int nbLineState = lineStateVectorNew.size();
for (int i = 0 ; i < nbLineState ; i++)
{
HeaderLineState &hls = _buffers[_currentIndex]._foldState[i];
HeaderLineState & hls = lineStateVectorNew.at(i);
bool expanded = (execute(SCI_GETFOLDEXPANDED, hls._headerLineNumber) != 0);
// set line to state folded
if (hls._isCollapsed && !expanded)
execute(SCI_TOGGLEFOLD, hls._headerLineNumber);
if (!hls._isCollapsed && expanded)
if (hls._isExpanded != expanded)
execute(SCI_TOGGLEFOLD, hls._headerLineNumber);
}
restoreCurrentPos();
execute(SCI_SETEOLMODE, _buffers[_currentIndex]._format);
::SendMessage(_hParent, NPPM_INTERNAL_DOCSWITCHIN, 0, (LPARAM)_hSelf);
bufferUpdated(_currentBuffer, (BufferChangeMask & ~BufferChangeLanguage)); //everything should be updated, but the language (which undoes some operations done here like folding)
return _buffers[_currentIndex]._fullPathName;
//setup line number margin
int numLines = execute(SCI_GETLINECOUNT);
char numLineStr[32];
itoa(numLines, numLineStr, 10);
int nbDigit = strlen(numLineStr);
if (increaseMaxNbDigit(nbDigit))
setLineNumberWidth(hasMarginShowed(ScintillaEditView::_SC_MARGE_LINENUMBER));
runMarkers(true, 0, true, false);
return; //all done
}
// this method creates a new doc ,and adds it into
// the end of the doc list and a last sub tab, then activate it
// it returns the name of this created doc (that's the current doc also)
char * ScintillaEditView::createNewDoc(const char *fn)
{
Document newDoc = execute(SCI_CREATEDOCUMENT);
_buffers.push_back(Buffer(newDoc, fn));
_buffers[_buffers.size()-1].checkIfReadOnlyFile();
return activateDocAt(int(_buffers.size())-1);
void ScintillaEditView::bufferUpdated(Buffer * buffer, int mask) {
//actually only care about language and lexing etc
if (buffer == _currentBuffer) {
if (mask & BufferChangeLanguage) {
defineDocType(buffer->getLangType());
foldAll(fold_uncollapse);
if (buffer->getNeedsLexing()) {
restyleBuffer();
}
char * ScintillaEditView::createNewDoc(int nbNew)
{
char title[10];
char nb[4];
strcat(strcpy(title, UNTITLED_STR), _itoa(nbNew, nb, 10));
char * newTitle = createNewDoc(title);
if (getCurrentBuffer()._unicodeMode != uni8Bit)
}
if (mask & BufferChangeFormat) {
execute(SCI_SETEOLMODE, _currentBuffer->getFormat());
}
if (mask & BufferChangeReadonly) {
execute(SCI_SETREADONLY, _currentBuffer->isReadOnly());
}
if (mask & BufferChangeUnicode) {
if (_currentBuffer->getUnicodeMode() == uni8Bit) { //either 0 or CJK codepage
if (isCJK()) {
execute(SCI_SETCODEPAGE, _codepage); //you may also want to set charsets here, not yet implemented
} else {
execute(SCI_SETCODEPAGE, 0);
}
} else { //CP UTF8 for all unicode
execute(SCI_SETCODEPAGE, SC_CP_UTF8);
return newTitle;
}
}
}
}
void ScintillaEditView::collapse(int level2Collapse, bool mode)
{
execute(SCI_COLOURISE, 0, -1);
execute(SCI_COLOURISE, 0, -1); //TODO: is this needed?
int maxLine = execute(SCI_GETLINECOUNT);
for (int line = 0; line < maxLine; line++)
@ -1135,7 +1131,8 @@ void ScintillaEditView::collapse(int level2Collapse, bool mode)
execute(SCI_TOGGLEFOLD, line);
}
}
//recalcHorizontalScrollbar(); //Update scrollbar after folding
runMarkers(true, 0, true, false);
}
void ScintillaEditView::foldCurrentPos(bool mode)
@ -1157,7 +1154,6 @@ void ScintillaEditView::foldCurrentPos(bool mode)
if ((execute(SCI_GETFOLDEXPANDED, headerLine) != 0) != mode)
execute(SCI_TOGGLEFOLD, headerLine);
//recalcHorizontalScrollbar(); //Update scrollbar after folding
}
void ScintillaEditView::foldAll(bool mode)
@ -1172,92 +1168,6 @@ void ScintillaEditView::foldAll(bool mode)
if ((execute(SCI_GETFOLDEXPANDED, line) != 0) != mode)
execute(SCI_TOGGLEFOLD, line);
}
//recalcHorizontalScrollbar(); //Update scrollbar after folding
}
// return the index to close then (argument) the index to activate
int ScintillaEditView::closeCurrentDoc(int & i2Activate)
{
int oldCurrent = _currentIndex;
//Position & prevDocPos = _buffers[_currentIndex]._pos;
// if the file 2 delete is the last one
if (_currentIndex == int(_buffers.size()) - 1)
{
// if current index is 0, ie. the current is the only one
if (!_currentIndex)
{
_currentIndex = 0;
}
// the current is NOT the only one and it is the last one,
// we set it to the index which precedes it
else
_currentIndex -= 1;
}
// else the next current index will be the same,
// we do nothing
// get the iterator and calculate its position with the old current index value
buf_vec_t::iterator posIt = _buffers.begin() + oldCurrent;
// erase the position given document from our list
_buffers.erase(posIt);
// set another document, so the ref count of old active document owned
// by Scintilla view will be decreased to 0 by SCI_SETDOCPOINTER message
// then increase the new current doc to 2
execute(SCI_SETDOCPOINTER, 0, _buffers[_currentIndex]._doc);
// Important : to avoid the leak of memory
// Now keep the ref counter of new current doc as 1
execute(SCI_RELEASEDOCUMENT, 0, _buffers[_currentIndex]._doc);
defineDocType(_buffers[_currentIndex]._lang);
restoreCurrentPos();
// restore the collapsed info
int nbLineState = _buffers[_currentIndex]._foldState.size();
for (int i = 0 ; i < nbLineState ; i++)
{
HeaderLineState &hls = _buffers[_currentIndex]._foldState[i];
bool expanded = (execute(SCI_GETFOLDEXPANDED, hls._headerLineNumber) != 0);
// set line to state folded
if (hls._isCollapsed && !expanded)
execute(SCI_TOGGLEFOLD, hls._headerLineNumber);
if (!hls._isCollapsed && expanded)
execute(SCI_TOGGLEFOLD, hls._headerLineNumber);
}
i2Activate = _currentIndex;
return oldCurrent;
}
void ScintillaEditView::closeDocAt(int i2Close)
{
execute(SCI_RELEASEDOCUMENT, 0, _buffers[i2Close]._doc);
// get the iterator and calculate its position with the old current index value
buf_vec_t::iterator posIt = _buffers.begin() + i2Close;
// erase the position given document from our list
_buffers.erase(posIt);
_currentIndex -= (i2Close < _currentIndex)?1:0;
}
void ScintillaEditView::removeAllUnusedDocs()
{
// unreference all docs from list of Scintilla
// by sending SCI_RELEASEDOCUMENT message
for (int i = 0 ; i < int(_buffers.size()) ; i++)
if (i != _currentIndex)
execute(SCI_RELEASEDOCUMENT, 0, _buffers[i]._doc);
// remove all docs except the current doc from list
_buffers.clear();
}
void ScintillaEditView::getText(char *dest, int start, int end) const
@ -1300,9 +1210,9 @@ void ScintillaEditView::marginClick(int position, int modifiers)
{
// Toggle this line
execute(SCI_TOGGLEFOLD, lineClick, 0);
runMarkers(true, lineClick, true, false);
}
}
//recalcHorizontalScrollbar(); //Update scrollbar after folding
}
void ScintillaEditView::expand(int &line, bool doExpand, bool force, int visLevels, int level)
@ -1356,7 +1266,8 @@ void ScintillaEditView::expand(int &line, bool doExpand, bool force, int visLeve
line++;
}
}
//recalcHorizontalScrollbar(); //Update scrollbar after folding
runMarkers(true, 0, true, false);
}
void ScintillaEditView::performGlobalStyles()
@ -1486,7 +1397,7 @@ const char * ScintillaEditView::getCompleteKeywordList(std::string & kwl, LangTy
void ScintillaEditView::convertSelectedTextTo(bool Case)
{
unsigned int codepage = _codepage;
UniMode um = getCurrentBuffer().getUnicodeMode();
UniMode um = getCurrentBuffer()->getUnicodeMode();
if (um != uni8Bit)
codepage = CP_UTF8;
@ -1571,30 +1482,6 @@ bool ScintillaEditView::expandWordSelection()
return false;
}
void ScintillaEditView::arrangeBuffers(UINT nItems, UINT *items) {
// Do nothing if item size mismatches
if (nItems != getNbDoc())
return;
int ncurpos = getCurrentDocIndex();
int newpos = 0;
UINT i;
buf_vec_t tmp;
for (i=0; i<nItems; ++i)
{
tmp.push_back(_buffers[items[i]]);
}
for (i=0; i<nItems; ++i)
{
if (tmp[i]._fullPathName[0] == 0)
return; // abort if we find an invalid buffer.
if (items[i] == ncurpos)
newpos = i;
}
tmp.swap(_buffers);
setCurrentIndex(newpos);
}
char * int2str(char *str, int strLen, int number, int base, int nbChiffre, bool isZeroLeading)
{
if (nbChiffre >= strLen) return NULL;
@ -1793,9 +1680,9 @@ void ScintillaEditView::columnReplace(const ColumnModeInfo & cmi, const char ch)
void ScintillaEditView::foldChanged(int line, int levelNow, int levelPrev)
{
if (levelNow & SC_FOLDLEVELHEADERFLAG)
if (levelNow & SC_FOLDLEVELHEADERFLAG) //line can be folded
{
if (!(levelPrev & SC_FOLDLEVELHEADERFLAG))
if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) //but previously couldnt
{
// Adding a fold point.
execute(SCI_SETFOLDEXPANDED, line, 1);
@ -1821,3 +1708,175 @@ void ScintillaEditView::foldChanged(int line, int levelNow, int levelPrev)
execute(SCI_SHOWLINES, line, line);
}
}
void ScintillaEditView::hideLines() {
//Folding can screw up hide lines badly if it unfolds a hidden section.
//Adding runMarkers(hide, foldstart) directly (folding on single document) can help
//Special func on buffer. If markers are added, create notification with location of start, and hide bool set to true
int startLine = execute(SCI_LINEFROMPOSITION, execute(SCI_GETSELECTIONSTART));
int endLine = execute(SCI_LINEFROMPOSITION, execute(SCI_GETSELECTIONEND));
//perform range check: cannot hide very first and very last lines
//Offset them one off the edges, and then check if they are within the reasonable
int nrLines = execute(SCI_GETLINECOUNT);
if (nrLines < 3)
return; //cannot possibly hide anything
if (!startLine)
startLine++;
if (endLine == (nrLines-1))
endLine--;
if (startLine > endLine)
return; //tried to hide line at edge
//Hide the lines. We add marks on the outside of the hidden section and hide the lines
//execute(SCI_HIDELINES, startLine, endLine);
//Add markers
execute(SCI_MARKERADD, startLine-1, MARK_HIDELINESBEGIN);
execute(SCI_MARKERADD, endLine+1, MARK_HIDELINESEND);
//remove any markers in between
int scope = 0;
for(int i = startLine; i <= endLine; i++) {
int state = execute(SCI_MARKERGET, i);
bool closePresent = ((state & (1 << MARK_HIDELINESEND)) != 0); //check close first, then open, since close closes scope
bool openPresent = ((state & (1 << MARK_HIDELINESBEGIN)) != 0);
if (closePresent) {
execute(SCI_MARKERDELETE, i, MARK_HIDELINESEND);
if (scope > 0) scope--;
}
if (openPresent) {
execute(SCI_MARKERDELETE, i, MARK_HIDELINESBEGIN);
scope++;
}
}
if (scope != 0) { //something went wrong
//Someone managed to make overlapping hidelines sections.
//We cant do anything since this isnt supposed to happen
}
_currentBuffer->setHideLineChanged(true, startLine-1);
}
bool ScintillaEditView::markerMarginClick(int lineNumber) {
int state = execute(SCI_MARKERGET, lineNumber);
bool openPresent = ((state & (1 << MARK_HIDELINESBEGIN)) != 0);
bool closePresent = ((state & (1 << MARK_HIDELINESEND)) != 0);
if (!openPresent && !closePresent)
return false;
//Special func on buffer. First call show with location of opening marker. Then remove the marker manually
if (openPresent) {
_currentBuffer->setHideLineChanged(false, lineNumber);
}
if (closePresent) {
openPresent = false;
for(lineNumber--; lineNumber >= 0 && !openPresent; lineNumber--) {
state = execute(SCI_MARKERGET, lineNumber);
openPresent = ((state & (1 << MARK_HIDELINESBEGIN)) != 0);
}
if (openPresent) {
_currentBuffer->setHideLineChanged(false, lineNumber);
}
}
return true;
}
void ScintillaEditView::notifyMarkers(Buffer * buf, bool isHide, int location, bool del) {
if (buf != _currentBuffer) //if not visible buffer dont do a thing
return;
runMarkers(isHide, location, false, del);
}
//Run through full document. When switching in or opening folding
//hide is false only when user click on margin
void ScintillaEditView::runMarkers(bool doHide, int searchStart, bool endOfDoc, bool doDelete) {
//Removes markers if opening
/*
AllLines = (start,ENDOFDOCUMENT)
Hide:
Run through all lines.
Find open hiding marker:
set hiding start
Find closing:
if (hiding):
Hide lines between now and start
if (endOfDoc = false)
return
else
search for other hidden sections
Show:
Run through all lines
Find open hiding marker
set last start
Find closing:
Show from last start. Stop.
Find closed folding header:
Show from last start to folding header
Skip to LASTCHILD
Set last start to lastchild
*/
int maxLines = execute(SCI_GETLINECOUNT);
if (doHide) {
int startHiding = searchStart;
bool isInSection = false;
for(int i = searchStart; i < maxLines; i++) {
int state = execute(SCI_MARKERGET, i);
if ( ((state & (1 << MARK_HIDELINESEND)) != 0) ) {
if (isInSection) {
execute(SCI_HIDELINES, startHiding, i-1);
if (!endOfDoc) {
return; //done, only single section requested
} //otherwise keep going
}
isInSection = false;
}
if ( ((state & (1 << MARK_HIDELINESBEGIN)) != 0) ) {
isInSection = true;
startHiding = i+1;
}
}
} else {
int startShowing = searchStart;
bool isInSection = false;
for(int i = searchStart; i < maxLines; i++) {
int state = execute(SCI_MARKERGET, i);
if ( ((state & (1 << MARK_HIDELINESEND)) != 0) ) {
if (doDelete)
execute(SCI_MARKERDELETE, i, MARK_HIDELINESEND);
if (isInSection) {
if (startShowing >= i) { //because of fold skipping, we passed the close tag. In that case we cant do anything
if (!endOfDoc) {
return;
} else {
continue;
}
}
execute(SCI_SHOWLINES, startShowing, i-1);
if (!endOfDoc) {
return; //done, only single section requested
} //otherwise keep going
}
isInSection = false;
}
if ( ((state & (1 << MARK_HIDELINESBEGIN)) != 0) ) {
isInSection = true;
startShowing = i+1;
if (doDelete)
execute(SCI_MARKERDELETE, i, MARK_HIDELINESBEGIN);
}
int levelLine = execute(SCI_GETFOLDLEVEL, i, 0);
if (levelLine & SC_FOLDLEVELHEADERFLAG) { //fold section. Dont show lines if fold is closed
if (isInSection && execute(SCI_GETFOLDEXPANDED, i) == 0) {
execute(SCI_SHOWLINES, startShowing, i);
startShowing = execute(SCI_GETLASTCHILD, i, (levelLine & SC_FOLDLEVELNUMBERMASK));
}
}
}
}
}

View File

@ -139,7 +139,7 @@ class ScintillaEditView : public Window
public:
ScintillaEditView()
: Window(), _pScintillaFunc(NULL),_pScintillaPtr(NULL),
_currentIndex(0), _folderStyle(FOLDER_STYLE_BOX), _maxNbDigit(_MARGE_LINENUMBER_NB_CHIFFRE), _wrapRestoreNeeded(false)
_folderStyle(FOLDER_STYLE_BOX), _maxNbDigit(_MARGE_LINENUMBER_NB_CHIFFRE), _wrapRestoreNeeded(false)
{
++_refCount;
};
@ -155,7 +155,6 @@ public:
};
virtual void destroy()
{
removeAllUnusedDocs();
::DestroyWindow(_hSelf);
_hSelf = NULL;
};
@ -166,103 +165,22 @@ public:
return _pScintillaFunc(_pScintillaPtr, static_cast<int>(Msg), static_cast<int>(wParam), static_cast<int>(lParam));
};
void defineDocType(LangType typeDoc);
void activateBuffer(BufferID buffer);
bool setCurrentDocType(LangType typeDoc) {
if ((_buffers[_currentIndex]._lang == typeDoc) && (typeDoc != L_USER))
return false;
if (typeDoc == L_USER)
_buffers[_currentIndex]._userLangExt[0] = '\0';
_buffers[_currentIndex]._lang = typeDoc;
defineDocType(typeDoc);
return true;
};
void setCurrentDocUserType(const char *userLangName) {
/*void setCurrentDocUserType(const char *userLangName) {
strcpy(_buffers[_currentIndex]._userLangExt, userLangName);
_buffers[_currentIndex]._lang = L_USER;
defineDocType(L_USER);
};
};*/
char * attatchDefaultDoc(int nb);
int findDocIndexByName(const char *fn) const;
char * activateDocAt(int index);
char * createNewDoc(const char *fn);
char * createNewDoc(int nbNew);
int getCurrentDocIndex() const {return _currentIndex;};
const char * getCurrentTitle() const {return _buffers[_currentIndex]._fullPathName;};
int setCurrentTitle(const char *fn) {
_buffers[_currentIndex].setFileName(fn);
defineDocType(_buffers[_currentIndex]._lang);
return _currentIndex;
};
int closeCurrentDoc(int & i2Activate);
void closeDocAt(int i2Close);
void removeAllUnusedDocs();
BufferID attachDefaultDoc();
void getText(char *dest, int start, int end) const;
void setCurrentDocState(bool isDirty) {
_buffers[_currentIndex]._isDirty = isDirty;
};
bool isCurrentDocDirty() const {
return _buffers[_currentIndex]._isDirty;
};
void setCurrentDocReadOnly(bool isReadOnly) {
_buffers[_currentIndex]._isReadOnly = isReadOnly;
execute(SCI_SETREADONLY, isReadOnly);
};
bool setCurrentDocReadOnlyByUser(bool ro) {
execute(SCI_SETREADONLY, ro);
return _buffers[_currentIndex].setReadOnly(ro);
};
void updateCurrentDocSysReadOnlyStat() {
_buffers[_currentIndex].checkIfReadOnlyFile();
};
bool isCurrentBufReadOnly() const {
return _buffers[_currentIndex].isReadOnly();
};
bool isCurrentBufSysReadOnly() const {
return _buffers[_currentIndex].isSystemReadOnly();
};
bool isCurrentBufUserReadOnly() const {
return _buffers[_currentIndex].isUserReadOnly();
};
bool isAllDocsClean() const {
for (int i = 0 ; i < static_cast<int>(_buffers.size()) ; i++)
if (_buffers[i]._isDirty)
return false;
return true;
};
size_t getNbDoc() const {
return _buffers.size();
};
void saveCurrentPos();
void restoreCurrentPos();
Buffer & getBufferAt(size_t index) {
if (index >= _buffers.size())
throw int(index);
return _buffers[index];
};
void updateCurrentBufTimeStamp() {
_buffers[_currentIndex].updatTimeStamp();
};
void saveCurrentFold();
void restoreCurrentFold();
int getCurrentDocLen() const {
return int(execute(SCI_GETLENGTH));
@ -284,10 +202,6 @@ public:
getText(str, startPos, caretPos);
};
LangType getCurrentDocType() const {
return _buffers[_currentIndex]._lang;
};
void doUserDefineDlg(bool willBeShown = true, bool isRTL = false) {
_userDefineDlg.doDialog(willBeShown, isRTL);
};
@ -299,24 +213,11 @@ public:
execute(SCI_SETCARETWIDTH, width);
};
// if we use this method, it must be via the
// gotoAnotherView or cloneToAnotherEditView
// So the ref counter of document should increase
int addBuffer(Buffer & buffer) {
_buffers.push_back(buffer);
execute(SCI_ADDREFDOCUMENT, 0, buffer._doc);
return (int(_buffers.size()) - 1);
};
Buffer & getCurrentBuffer() {
return getBufferAt(_currentIndex);
};
void beSwitched() {
_userDefineDlg.setScintilla(this);
};
//Marge memeber and method
//Marge member and method
static const int _SC_MARGE_LINENUMBER;
static const int _SC_MARGE_SYBOLE;
static const int _SC_MARGE_FOLDER;
@ -391,16 +292,6 @@ public:
execute(SCI_SETWRAPVISUALFLAGS, willBeShown?SC_WRAPVISUALFLAG_END:SC_WRAPVISUALFLAG_NONE);
};
void sortBuffer(int destIndex, int scrIndex) {
// Do nothing if there's no change of the position
if (scrIndex == destIndex)
return;
Buffer buf2Insert = _buffers.at(scrIndex);
_buffers.erase(_buffers.begin() + scrIndex);
_buffers.insert(_buffers.begin() + destIndex, buf2Insert);
};
int getSelectedTextCount() {
CharacterRange range = getSelection();
return (range.cpMax - range.cpMin);
@ -487,8 +378,6 @@ public:
execute(SCI_SETMARGINWIDTHN, 0, pixelWidth);
};
void setCurrentIndex(int index2Set) {_currentIndex = index2Set;};
void setCurrentLineHiLiting(bool isHiliting, COLORREF bgColor) const {
execute(SCI_SETCARETLINEVISIBLE, isHiliting);
if (!isHiliting)
@ -503,26 +392,6 @@ public:
void performGlobalStyles();
void expand(int &line, bool doExpand, bool force = false, int visLevels = 0, int level = -1);
void removeUserLang(const char *name) {
for (int i = 0 ; i < int(_buffers.size()) ; i++)
{
if ((_buffers[i]._lang == L_USER) && (!strcmp(name, _buffers[i]._userLangExt)))
{
_buffers[i]._userLangExt[0] = '\0';
}
}
};
void renameUserLang(const char *oldName, const char *newName) {
for (int i = 0 ; i < int(_buffers.size()) ; i++)
{
if ((_buffers[i]._lang == L_USER) && (!strcmp(oldName, _buffers[i]._userLangExt)))
{
strcpy(_buffers[i]._userLangExt, newName);
}
}
};
void currentLineUp() const {
int currentLine = getCurrentLineNumber();
@ -537,8 +406,6 @@ public:
};
void currentLineDown() const {
int currentLine = getCurrentLineNumber();
if (currentLine != (execute(SCI_GETLINECOUNT) - 1))
{
@ -571,7 +438,7 @@ public:
void collapse(int level2Collapse, bool mode);
void foldAll(bool mode);
void foldCurrentPos(bool mode);
int getCodpage() const {return _codepage;};
int getCodepage() const {return _codepage;};
//int getMaxNbDigit const () {return _maxNbDigit;};
@ -584,26 +451,6 @@ public:
return false;
};
int getNextPriorityIndex(int & weight, int heavest) {
weight = 0;
if (_buffers.size() <= 0)
return -1;
if (_buffers[0]._recentTag < heavest)
weight = _buffers[0]._recentTag;
int maxIndex = 0;
for (size_t i = 1 ; i < _buffers.size() ; i++)
{
if ((_buffers[i]._recentTag < heavest) && (weight < _buffers[i]._recentTag))
{
weight = _buffers[i]._recentTag;
maxIndex = i;
}
}
return maxIndex;
};
NppParameters * getParameter() {
return _pParameter;
};
@ -614,7 +461,6 @@ public:
void columnReplace(const ColumnModeInfo & cmi, const char ch);
void columnReplace(ColumnModeInfo & cmi, int initial, int incr, unsigned char format);
void recalcHorizontalScrollbar();
void foldChanged(int line, int levelNow, int levelPrev);
void clearIndicator(int indicatorNumber) {
int docStart = 0;
@ -624,6 +470,17 @@ public:
};
static LanguageName ScintillaEditView::langNames[L_EXTERNAL+1];
void bufferUpdated(Buffer * buffer, int mask);
BufferID getCurrentBufferID() { return _currentBufferID; };
Buffer * getCurrentBuffer() { return _currentBuffer; };
void styleChange();
void hideLines();
bool markerMarginClick(int lineNumber); //true if it did something
void notifyMarkers(Buffer * buf, bool isHide, int location, bool del);
void runMarkers(bool doHide, int searchStart, bool endOfDoc, bool doDelete);
protected:
static HINSTANCE _hLib;
static int _refCount;
@ -657,16 +514,12 @@ protected:
SCINTILLA_FUNC _pScintillaFunc;
SCINTILLA_PTR _pScintillaPtr;
// the current active buffer index of _buffers
int _currentIndex;
static WNDPROC _scintillaDefaultProc;
CallWindowProcFunc _callWindowProc;
// the list of docs
buf_vec_t _buffers;
// For the file nfo
//int _MSLineDrawFont;
//Store the current buffer so it can be retrieved later
BufferID _currentBufferID;
Buffer * _currentBuffer;
folderStyle _folderStyle;
@ -680,6 +533,8 @@ protected:
bool _wrapRestoreNeeded;
//Lexers and Styling
void defineDocType(LangType typeDoc); //setup stylers for active document
void restyleBuffer();
const char * getCompleteKeywordList(std::string & kwl, LangType langType, int keywordIndex);
void setKeywords(LangType langType, const char *keywords, int index);
void setLexer(int lexerID, LangType langType, int whichList);
@ -887,7 +742,6 @@ protected:
};
bool expandWordSelection();
void arrangeBuffers(UINT nItems, UINT *items);
};
#endif //SCINTILLA_EDIT_VIEW_H

View File

@ -83,8 +83,8 @@ bool SharedParametersDialog::setPropertyByCheck(HWND hwnd, WPARAM id, bool & boo
{
bool2set = (BST_CHECKED == ::SendMessage(::GetDlgItem(hwnd, id), BM_GETCHECK, 0, 0));
if (_pScintilla->getCurrentDocType() == L_USER)
_pScintilla->defineDocType(L_USER);
if (_pScintilla->getCurrentBuffer()->getLangType() == L_USER)
_pScintilla->styleChange();
return TRUE;
}
@ -171,8 +171,8 @@ BOOL CALLBACK SharedParametersDialog::run_dlgProc(UINT Message, WPARAM wParam, L
{
setKeywords2List(LOWORD(wParam));
if (_pScintilla->getCurrentDocType() == L_USER)
_pScintilla->defineDocType(L_USER);
if (_pScintilla->getCurrentBuffer()->getLangType() == L_USER)
_pScintilla->styleChange();
return TRUE;
}
@ -206,8 +206,8 @@ BOOL CALLBACK SharedParametersDialog::run_dlgProc(UINT Message, WPARAM wParam, L
{
style._fontName = (char *)::SendDlgItemMessage(_hSelf, LOWORD(wParam), CB_GETITEMDATA, i, 0);
}
if (_pScintilla->getCurrentDocType() == L_USER)
_pScintilla->defineDocType(L_USER);
if (_pScintilla->getCurrentBuffer()->getLangType() == L_USER)
_pScintilla->styleChange();
return TRUE;
}
}
@ -250,8 +250,8 @@ BOOL CALLBACK SharedParametersDialog::run_dlgProc(UINT Message, WPARAM wParam, L
//::MessageBox(NULL, "Bingo!!!", "", MB_OK);
}
}
if (_pScintilla->getCurrentDocType() == L_USER)
_pScintilla->defineDocType(L_USER);
if (_pScintilla->getCurrentBuffer()->getLangType() == L_USER)
_pScintilla->styleChange();
return TRUE;
}
return FALSE;
@ -819,8 +819,8 @@ void SymbolsStyleDialog::symbolAction(bool action)
}
_pUserLang->_keywordLists[3][--j] = '\0';
if (_pScintilla->getCurrentDocType() == L_USER)
_pScintilla->defineDocType(L_USER);
if (_pScintilla->getCurrentBuffer()->getLangType() == L_USER)
_pScintilla->styleChange();
}
void SymbolsStyleDialog::listboxsRemoveAll()
@ -995,8 +995,8 @@ BOOL CALLBACK SymbolsStyleDialog::run_dlgProc(UINT Message, WPARAM wParam, LPARA
if ((wParam == IDC_ADD_BUTTON) || (wParam == IDC_REMOVE_BUTTON))
{
symbolAction((wParam == IDC_ADD_BUTTON)?ADD:REMOVE);
if (_pScintilla->getCurrentDocType() == L_USER)
_pScintilla->defineDocType(L_USER);
if (_pScintilla->getCurrentBuffer()->getLangType() == L_USER)
_pScintilla->styleChange();
return TRUE;
}
// car LBN_SELCHANGE == CBN_SELCHANGE == 1
@ -1048,8 +1048,8 @@ BOOL CALLBACK SymbolsStyleDialog::run_dlgProc(UINT Message, WPARAM wParam, LPARA
char *delims = _pUserLang->_keywordLists[KWL_DELIM_INDEX];
delims[symbIndex] = charStr[0]?charStr[0]:'0';
if (_pScintilla->getCurrentDocType() == L_USER)
_pScintilla->defineDocType(L_USER);
if (_pScintilla->getCurrentBuffer()->getLangType() == L_USER)
_pScintilla->styleChange();
return TRUE;
}
else

View File

@ -18,6 +18,7 @@
// - Removing UCS-Bug in Utf8_Iter
// - Add convert function in Utf8_16_Write
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <stdio.h>
#include <assert.h>

View File

@ -276,13 +276,14 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
}
::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam);
int currentTabOn = ::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0);
if (wParam == 2)
return TRUE;
if (_doDragNDrop)
{
_nSrcTab = _nTabDragged = ::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0);
_nSrcTab = _nTabDragged = currentTabOn;
POINT point;
point.x = LOWORD(lParam);
@ -295,15 +296,21 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
}
}
NMHDR nmhdr;
nmhdr.hwndFrom = _hSelf;
nmhdr.code = NM_CLICK;
nmhdr.idFrom = reinterpret_cast<unsigned int>(this);
TBHDR nmhdr;
nmhdr.hdr.hwndFrom = _hSelf;
nmhdr.hdr.code = NM_CLICK;
nmhdr.hdr.idFrom = reinterpret_cast<unsigned int>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
return TRUE;
}
case WM_RBUTTONDOWN : //rightclick selects tab aswell
{
::CallWindowProc(_tabBarDefaultProc, hwnd, WM_LBUTTONDOWN, wParam, lParam);
return TRUE;
}
case WM_MOUSEMOVE :
{
@ -353,6 +360,9 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
case WM_LBUTTONUP :
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
int currentTabOn = getTabIndexAt(xPos, yPos);
if (_isDragging)
{
if(::GetCapture() == _hSelf)
@ -362,10 +372,11 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
// nmhdr.idFrom = this
// destIndex = this->_nSrcTab
// scrIndex = this->_nTabDragged
NMHDR nmhdr;
nmhdr.hwndFrom = _hSelf;
nmhdr.code = _isDraggingInside?TCN_TABDROPPED:TCN_TABDROPPEDOUTSIDE;
nmhdr.idFrom = reinterpret_cast<unsigned int>(this);
TBHDR nmhdr;
nmhdr.hdr.hwndFrom = _hSelf;
nmhdr.hdr.code = _isDraggingInside?TCN_TABDROPPED:TCN_TABDROPPEDOUTSIDE;
nmhdr.hdr.idFrom = reinterpret_cast<unsigned int>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
return TRUE;
@ -373,19 +384,14 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
if (_drawTabCloseButton)
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
int currentTabOn = getTabIndexAt(xPos, yPos);
if ((_whichCloseClickDown == currentTabOn) && _closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect))
{
NMHDR nmhdr;
nmhdr.hwndFrom = _hSelf;
nmhdr.code = TCN_TABDELETE;
nmhdr.idFrom = reinterpret_cast<unsigned int>(this);
TBHDR nmhdr;
nmhdr.hdr.hwndFrom = _hSelf;
nmhdr.hdr.code = TCN_TABDELETE;
nmhdr.hdr.idFrom = reinterpret_cast<unsigned int>(this);
nmhdr.tabOrigin = currentTabOn;
::CallWindowProc(_tabBarDefaultProc, hwnd, WM_LBUTTONDOWN, wParam, lParam);
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
_whichCloseClickDown = -1;
@ -422,12 +428,14 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
case WM_MBUTTONUP:
{
::CallWindowProc(_tabBarDefaultProc, hwnd, WM_LBUTTONDOWN, wParam, lParam);
NMHDR nmhdr;
nmhdr.hwndFrom = _hSelf;
nmhdr.code = TCN_TABDELETE;
nmhdr.idFrom = reinterpret_cast<unsigned int>(this);
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
int currentTabOn = getTabIndexAt(xPos, yPos);
TBHDR nmhdr;
nmhdr.hdr.hwndFrom = _hSelf;
nmhdr.hdr.code = TCN_TABDELETE;
nmhdr.hdr.idFrom = reinterpret_cast<unsigned int>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
return TRUE;
@ -435,13 +443,16 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
case WM_LBUTTONDBLCLK :
{
::CallWindowProc(_tabBarDefaultProc, hwnd, WM_LBUTTONDOWN, wParam, lParam);
if (_isDbClk2Close)
{
NMHDR nmhdr;
nmhdr.hwndFrom = _hSelf;
nmhdr.code = TCN_TABDELETE;
nmhdr.idFrom = reinterpret_cast<unsigned int>(this);
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
int currentTabOn = getTabIndexAt(xPos, yPos);
TBHDR nmhdr;
nmhdr.hdr.hwndFrom = _hSelf;
nmhdr.hdr.code = TCN_TABDELETE;
nmhdr.hdr.idFrom = reinterpret_cast<unsigned int>(this);
nmhdr.tabOrigin = currentTabOn;
::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmhdr));
}
@ -726,7 +737,7 @@ void TabBarPlus::exchangeItemData(POINT point)
//2. shift their data, and insert the source
TCITEM itemData_nDraggedTab, itemData_shift;
itemData_nDraggedTab.mask = itemData_shift.mask = TCIF_IMAGE | TCIF_TEXT;
itemData_nDraggedTab.mask = itemData_shift.mask = TCIF_IMAGE | TCIF_TEXT | TCIF_PARAM;
char str1[256];
char str2[256];

View File

@ -43,6 +43,11 @@ const int nbCtrlMax = 10;
#define TABBAR_ACTIVETEXT "Active tab text"
#define TABBAR_INACTIVETEXT "Inactive tabs"
struct TBHDR {
NMHDR hdr;
int tabOrigin;
};
class TabBar : public Window
{
public:
@ -74,7 +79,14 @@ public:
int insertAtEnd(const char *subTabName);
void activateAt(int index) const {
::SendMessage(_hSelf, TCM_SETCURSEL, index, 0);
if (getCurrentTabIndex() != index) {
::SendMessage(_hSelf, TCM_SETCURSEL, index, 0);}
TBHDR nmhdr;
nmhdr.hdr.hwndFrom = _hSelf;
nmhdr.hdr.code = TCN_SELCHANGE;
nmhdr.hdr.idFrom = reinterpret_cast<unsigned int>(this);
nmhdr.tabOrigin = index;
};
void getCurrentTitle(char *title, int titleLen);

View File

@ -1,7 +1,7 @@
#include <windows.h>
#include "WindowsDlg.h"
#include "WindowsDlgRc.h"
#include "ScintillaEditView.h"
#include "DocTabView.h"
#include <algorithm>
#include <functional>
#include <vector>
@ -90,11 +90,11 @@ struct NumericStringEquivalence
struct BufferEquivalent
{
NumericStringEquivalence _strequiv;
ScintillaEditView *_pView;
DocTabView *_pTab;
int _iColumn;
bool _reverse;
BufferEquivalent(ScintillaEditView *pView, int iColumn, bool reverse)
: _pView(pView), _iColumn(iColumn), _reverse(reverse)
BufferEquivalent(DocTabView *pTab, int iColumn, bool reverse)
: _pTab(pTab), _iColumn(iColumn), _reverse(reverse)
{}
bool operator()(int i1, int i2) const
@ -106,32 +106,26 @@ struct BufferEquivalent
bool compare(int i1, int i2) const
{
const Buffer& b1 = _pView->getBufferAt(i1);
const Buffer& b2 = _pView->getBufferAt(i2);
BufferID bid1 = _pTab->getBufferByIndex(i1);
BufferID bid2 = _pTab->getBufferByIndex(i2);
Buffer * b1 = MainFileManager->getBufferByID(bid1);
Buffer * b2 = MainFileManager->getBufferByID(bid2);
if (_iColumn == 0)
{
const char *s1 = PathFindFileName(b1.getFileName());
const char *s2 = PathFindFileName(b2.getFileName());
const char *s1 = b1->getFileName();
const char *s2 = b2->getFileName();
return _strequiv(s1, s2);
}
else if (_iColumn == 1)
{
char buf1[MAX_PATH];
char buf2[MAX_PATH];
const char *f1 = b1.getFileName();
const char *f2 = b2.getFileName();
const char *s1 = PathFindFileName(b1.getFileName());
const char *s2 = PathFindFileName(b2.getFileName());
int l1 = min((s1 - f1), (_countof(buf1)-1));
int l2 = min((s2 - f2), (_countof(buf2)-1));
strncpy(buf1, f1, l1); buf1[l1] = 0;
strncpy(buf2, f2, l2); buf2[l2] = 0;
return _strequiv(buf1, buf2);
const char *s1 = b1->getFilePath();
const char *s2 = b2->getFilePath();
return _strequiv(s1, s2); //we can compare the full path to sort on directory, since after sorting directories sorting files is the second thing to do (if directories are the same that is)
}
else if (_iColumn == 2)
{
int t1 = (int)b1.getLangType();
int t2 = (int)b2.getLangType();
int t1 = (int)b1->getLangType();
int t2 = (int)b2->getLangType();
return (t1 < t2); // yeah should be the name
}
return false;
@ -173,17 +167,17 @@ WindowsDlg::WindowsDlg() : MyBaseClass(WindowsDlgMap), _isSorted(false)
_szMinListCtrl = SIZEZERO;
}
void WindowsDlg::init(HINSTANCE hInst, HWND parent, ScintillaEditView *pView)
void WindowsDlg::init(HINSTANCE hInst, HWND parent, DocTabView *pTab)
{
MyBaseClass::init(hInst, parent);
_pView = pView;
_pTab = pTab;
}
void WindowsDlg::init(HINSTANCE hInst, HWND parent)
{
assert(!"Call other initialize method");
MyBaseClass::init(hInst, parent);
_pView = NULL;
_pTab = NULL;
}
BOOL CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
@ -244,20 +238,22 @@ BOOL CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam
if(pLvdi->item.mask & LVIF_TEXT)
{
pLvdi->item.pszText[0] = 0;
size_t index = pLvdi->item.iItem;
if (index >= _pView->getNbDoc() || index >= _idxMap.size())
int index = pLvdi->item.iItem;
if (index >= _pTab->nbItem() || index >= (int)_idxMap.size())
return FALSE;
index = _idxMap[index];
const Buffer& buffer = _pView->getBufferAt(index);
//const Buffer& buffer = _pView->getBufferAt(index);
BufferID bufID = _pTab->getBufferByIndex(index);
Buffer * buf = MainFileManager->getBufferByID(bufID);
if (pLvdi->item.iSubItem == 0) // file name
{
int len = pLvdi->item.cchTextMax;
const char *fullName = buffer.getFileName();
strncpy(pLvdi->item.pszText, PathFindFileName(fullName), len-1);
const char *fileName = buf->getFileName();
strncpy(pLvdi->item.pszText, fileName, len-1);
pLvdi->item.pszText[len-1] = 0;
len = strlen(pLvdi->item.pszText);
if (buffer.isDirty())
if (buf->isDirty())
{
if (len < pLvdi->item.cchTextMax)
{
@ -265,7 +261,7 @@ BOOL CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam
pLvdi->item.pszText[len] = 0;
}
}
else if (buffer.isReadOnly())
else if (buf->isReadOnly())
{
len += strlen(readonlyString);
if (len <= pLvdi->item.cchTextMax)
@ -274,9 +270,13 @@ BOOL CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam
}
else if (pLvdi->item.iSubItem == 1) // directory
{
const char *fullName = buffer.getFileName();
const char *fileName = PathFindFileName(fullName);
int len = fileName-fullName+1;
const char *fullName = buf->getFilePath();
const char *fileName = buf->getFileName();
int len = strlen(fullName)-strlen(fileName);
if (!len) {
len = 1;
fullName = "";
}
if (pLvdi->item.cchTextMax < len)
len = pLvdi->item.cchTextMax;
strncpy(pLvdi->item.pszText, fullName, len-1);
@ -286,7 +286,7 @@ BOOL CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam
{
int len = pLvdi->item.cchTextMax;
NppParameters *pNppParameters = NppParameters::getInstance();
Lang *lang = pNppParameters->getLangFromID(buffer.getLangType());
Lang *lang = pNppParameters->getLangFromID(buf->getLangType());
if (NULL != lang)
{
strncpy(pLvdi->item.pszText, lang->getLangName(), len-1);
@ -316,7 +316,7 @@ BOOL CALLBACK WindowsDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam
vector<int> sortMap;
sortMap.resize(n);
for (i=0; i<n; ++i) sortMap[_idxMap[i]] = ListView_GetItemState(_hList, i, LVIS_SELECTED);
stable_sort(_idxMap.begin(), _idxMap.end(), BufferEquivalent(_pView, iColumn, reverse));
stable_sort(_idxMap.begin(), _idxMap.end(), BufferEquivalent(_pTab, iColumn, reverse));
for (i=0; i<n; ++i) ListView_SetItemState(_hList, i, sortMap[_idxMap[i]] ? LVIS_SELECTED : 0, LVIS_SELECTED);
::InvalidateRect(_hList, &_rc, FALSE);
@ -509,7 +509,7 @@ void WindowsDlg::doRefresh(bool invalidate /*= false*/)
{
if (_hList != NULL)
{
size_t count = (_pView != NULL) ? _pView->getNbDoc() : 0;
size_t count = (_pTab != NULL) ? _pTab->nbItem() : 0;
size_t oldSize = _idxMap.size();
if (!invalidate && count == oldSize)
return;
@ -551,7 +551,7 @@ void WindowsDlg::fitColumnsToSize()
void WindowsDlg::resetSelection()
{
int curSel = _pView->getCurrentDocIndex();
int curSel = _pTab->getCurrentTabIndex();
int pos = 0;
for (vector<int>::iterator itr = _idxMap.begin(), end = _idxMap.end(); itr != end; ++itr, ++pos)
{
@ -654,7 +654,7 @@ void WindowsDlg::doClose()
}
delete[] nmdlg.Items;
if (_pView->getNbDoc() != _idxMap.size())
if (_pTab->nbItem() != _idxMap.size())
doRefresh(true);
else
{
@ -738,25 +738,26 @@ void WindowsMenu::init(HINSTANCE hInst, HMENU hMainMenu, const char *translation
InsertMenuItem(hMainMenu, pos, TRUE, &mii);
}
void WindowsMenu::initPopupMenu(HMENU hMenu, ScintillaEditView *pView)
void WindowsMenu::initPopupMenu(HMENU hMenu, DocTabView *pTab)
{
if (hMenu == _hMenu)
{
int curDoc = pView->getCurrentDocIndex();
int curDoc = pTab->getCurrentTabIndex();
int nMaxDoc = IDM_WINDOW_MRU_LIMIT - IDM_WINDOW_MRU_FIRST + 1;
int nDoc = pView->getNbDoc();
int nDoc = pTab->nbItem();
nDoc = min(nDoc, nMaxDoc);
int id, pos;
for (id=IDM_WINDOW_MRU_FIRST, pos=0; id<IDM_WINDOW_MRU_FIRST + nDoc; ++id, ++pos)
{
char buffer[MAX_PATH];
const Buffer& scbuf = pView->getBufferAt(pos);
BufferID bufID = pTab->getBufferByIndex(pos);
Buffer * buf = MainFileManager->getBufferByID(bufID);
MENUITEMINFO mii;
memset(&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING|MIIM_STATE|MIIM_ID;
mii.dwTypeData = buildFileName(buffer, 60, pos, scbuf.getFileName());
mii.dwTypeData = buildFileName(buffer, 60, pos, buf->getFileName());
mii.fState &= ~(MF_GRAYED|MF_DISABLED|MF_CHECKED);
if (pos == curDoc)
mii.fState |= MF_CHECKED;

View File

@ -24,7 +24,7 @@
#include <vector>
#include <string>
class ScintillaEditView;
class DocTabView;
typedef enum {
WDT_ACTIVATE = 1,
@ -62,7 +62,7 @@ class WindowsDlg : public SizeableDlg
public :
WindowsDlg();
int doDialog(TiXmlNode *dlgNode);
virtual void init(HINSTANCE hInst, HWND parent, ScintillaEditView *pView);
virtual void init(HINSTANCE hInst, HWND parent, DocTabView *pTab);
void doRefresh(bool invalidate = false);
bool changeDlgLang();
@ -86,7 +86,7 @@ protected :
static RECT _lastKnownLocation;
SIZE _szMinButton;
SIZE _szMinListCtrl;
ScintillaEditView *_pView;
DocTabView *_pTab;
std::vector<int> _idxMap;
int _lastSort;
bool _isSorted;
@ -103,7 +103,7 @@ public:
~WindowsMenu();
void init(HINSTANCE hInst, HMENU hMainMenu, const char *translation);
//void initMenu(HMENU hMenu, ScintillaEditView *pView);
void initPopupMenu(HMENU hMenu, ScintillaEditView *pView);
void initPopupMenu(HMENU hMenu, DocTabView *pTab);
//void uninitPopupMenu(HMENU hMenu, ScintillaEditView *pView);
private:
char *buildFileName(char *buffer, int len, int pos, const char *filename);

View File

@ -0,0 +1,199 @@
//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.
#include "lastRecentFileList.h"
#include "menuCmdID.h"
void LastRecentFileList::initMenu(HMENU hMenu, int idBase, int posBase) {
_hMenu = hMenu;
_idBase = idBase;
_posBase = posBase;
for (int i = 0 ; i < sizeof(_idFreeArray) ; i++)
_idFreeArray[i] = true;
};
void LastRecentFileList::updateMenu() {
if (!_hasSeparators && _size > 0) { //add separators
const char * nativeLangOpenAllFiles = (NppParameters::getInstance())->getNativeLangMenuString(IDM_OPEN_ALL_RECENT_FILE);
const char * nativeLangCleanFilesList = (NppParameters::getInstance())->getNativeLangMenuString(IDM_CLEAN_RECENT_FILE_LIST);
const char * openAllFileStr = nativeLangOpenAllFiles?nativeLangOpenAllFiles:"Open All Recent Files";
const char * cleanFileListStr = nativeLangCleanFilesList?nativeLangCleanFilesList:"Clean Recent Files List";
::InsertMenu(_hMenu, _posBase + 0, MF_BYPOSITION, UINT(-1), 0);
::InsertMenu(_hMenu, _posBase + 1, MF_BYPOSITION, IDM_OPEN_ALL_RECENT_FILE, openAllFileStr);
::InsertMenu(_hMenu, _posBase + 2, MF_BYPOSITION, IDM_CLEAN_RECENT_FILE_LIST, cleanFileListStr);
::InsertMenu(_hMenu, _posBase + 3, MF_BYPOSITION, UINT(-1), 0);
_hasSeparators = true;
} else if (_hasSeparators && _size == 0) { //remove separators
::RemoveMenu(_hMenu, _posBase + 3, MF_BYPOSITION);
::RemoveMenu(_hMenu, IDM_CLEAN_RECENT_FILE_LIST, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_OPEN_ALL_RECENT_FILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, _posBase + 0, MF_BYPOSITION);
_hasSeparators = false;
}
//Remove all menu items
for(int i = 0; i < _size; i++) {
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND);
}
//Then readd them, so everything stays in sync
char indexBuffer[4];
for(int j = 0; j < _size; j++) {
std::string menuString = "";
if (j < 9) { //first 9 have accelerator (0 unused)
menuString += "&";
}
itoa(j+1, indexBuffer, 10);//one based numbering
menuString += indexBuffer;
menuString += " ";
menuString += _lrfl.at(j)._name;
::InsertMenu(_hMenu, _posBase + j, MF_BYPOSITION, _lrfl.at(j)._id, menuString.c_str());
i++;
}
}
void LastRecentFileList::add(const char *fn) {
if (_userMax == 0 || _locked)
return;
RecentItem itemToAdd(fn);
int index = find(fn);
if (index != -1) { //already in list, bump upwards
remove(index);
}
if (_size == _userMax) {
itemToAdd._id = _lrfl.back()._id;
_lrfl.pop_back(); //remove oldest
} else {
itemToAdd._id = popFirstAvailableID();
_size++;
}
_lrfl.push_front(itemToAdd);
updateMenu();
};
void LastRecentFileList::remove(const char *fn) {
int index = find(fn);
if (index != -1)
remove(index);
};
void LastRecentFileList::remove(int index) {
if (_size == 0 || _locked)
return;
if (index > -1 && index < (int)_lrfl.size()) {
::RemoveMenu(_hMenu, _lrfl.at(index)._id, MF_BYCOMMAND);
setAvailable(_lrfl.at(index)._id);
_lrfl.erase(_lrfl.begin() + index);
_size--;
updateMenu();
}
};
void LastRecentFileList::clear() {
if (_size == 0)
return;
for(int i = (_size-1); i >= 0; i--) {
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND);
setAvailable(_lrfl.at(i)._id);
_lrfl.erase(_lrfl.begin() + i);
}
_size = 0;
updateMenu();
}
std::string & LastRecentFileList::getItem(int id) {
int i = 0;
for(; i < _size; i++) {
if (_lrfl.at(i)._id == id)
break;
}
if (i == _size)
i = 0;
return _lrfl.at(i)._name; //if not found, return first
};
std::string & LastRecentFileList::getIndex(int index) {
return _lrfl.at(index)._name; //if not found, return first
};
void LastRecentFileList::setUserMaxNbLRF(int size) {
if (size < _userMax) { //start popping items
int toPop = _userMax-size;
while(toPop > 0) {
::RemoveMenu(_hMenu, _lrfl.back()._id, MF_BYCOMMAND);
setAvailable(_lrfl.back()._id);
_lrfl.pop_back();
toPop--;
}
_size = size;
updateMenu();
}
_userMax = size;
};
void LastRecentFileList::saveLRFL() {
NppParameters *pNppParams = NppParameters::getInstance();
if (pNppParams->writeNbHistoryFile(_userMax))
{
for(int i = _size - 1; i >= 0; i--) //reverse order: so loading goes in correct order
{
pNppParams->writeHistory(_lrfl.at(i)._name.c_str());
}
}
};
int LastRecentFileList::find(const char *fn) {
int i = 0;
for(int i = 0; i < _size; i++) {
if (_lrfl.at(i)._name == fn) {
return i;
}
}
return -1;
};
int LastRecentFileList::popFirstAvailableID() {
for (int i = 0 ; i < NB_MAX_LRF_FILE ; i++)
{
if (_idFreeArray[i])
{
_idFreeArray[i] = false;
return i + _idBase;
}
}
return 0;
};
void LastRecentFileList::setAvailable(int id) {
int index = id - _idBase;
_idFreeArray[index] = true;
};

View File

@ -1,128 +1,61 @@
#ifndef LASTRECENTFILELIST_H
#define LASTRECENTFILELIST_H
#include <list>
#include <deque>
#include <string>
#include "windows.h"
#include "Parameters.h"
typedef std::list<std::string> stringList;
struct RecentItem {
int _id;
std::string _name;
RecentItem(const char * name) : _name(name) {};
};
typedef std::deque<RecentItem> recentList;
class LastRecentFileList
{
public :
LastRecentFileList() : _hasSeparators(false){
LastRecentFileList() : _hasSeparators(false), _size(0), _locked(false) {
_userMax = (NppParameters::getInstance())->getNbMaxFile();
};
void initMenu(HMENU hMenu, int idBase, int posBase) {
_hMenu = hMenu;
_idBase = idBase;
_posBase = posBase;
void initMenu(HMENU hMenu, int idBase, int posBase);
for (int i = 0 ; i < sizeof(_idFreeArray) ; i++)
_idFreeArray[i] = true;
void updateMenu();
void add(const char *fn);
void remove(const char *fn);
void remove(int index);
void clear();
int getSize() {
return _size;
};
void add(const char *fn) {
if (_userMax == 0)
return;
int size = _lrfl.size();
if (size >= _userMax)
{
_lrfl.erase(_lrfl.begin());
int id = ::GetMenuItemID(_hMenu, 0 + _posBase);
::RemoveMenu(_hMenu, id, MF_BYCOMMAND);
setAvailable(id);
size--;
}
_lrfl.push_back(fn);
::InsertMenu(_hMenu, _posBase + size, MF_BYPOSITION, popFirstAvailableID() + _idBase, fn);
if (!_hasSeparators)
{
const char * nativeLangOpenAllFiles = (NppParameters::getInstance())->getNativeLangMenuString(IDM_OPEN_ALL_RECENT_FILE);
const char * nativeLangCleanFilesList = (NppParameters::getInstance())->getNativeLangMenuString(IDM_CLEAN_RECENT_FILE_LIST);
const char * openAllFileStr = nativeLangOpenAllFiles?nativeLangOpenAllFiles:"Open All Recent Files";
const char * cleanFileListStr = nativeLangCleanFilesList?nativeLangCleanFilesList:"Clean Recent Files List";
::InsertMenu(_hMenu, _posBase + size + 1, MF_BYPOSITION, UINT(-1), 0);
::InsertMenu(_hMenu, _posBase + size + 2, MF_BYPOSITION, IDM_OPEN_ALL_RECENT_FILE, openAllFileStr);
::InsertMenu(_hMenu, _posBase + size + 3, MF_BYPOSITION, IDM_CLEAN_RECENT_FILE_LIST, cleanFileListStr);
::InsertMenu(_hMenu, _posBase + size + 4, MF_BYPOSITION, UINT(-1), 0);
_hasSeparators = true;
}
};
void remove(const char *fn) {
if (find2Remove(fn))
{
int id = 0;
char filename[MAX_PATH];
for (size_t i = 0 ; i < _lrfl.size() + 1 ; i++)
{
::GetMenuString(_hMenu, i + _posBase, filename, sizeof(filename), MF_BYPOSITION);
if (!strcmp(fn, filename))
{
id = ::GetMenuItemID(_hMenu, i + _posBase);
break;
}
}
::RemoveMenu(_hMenu, id, MF_BYCOMMAND);
setAvailable(id);
int size;
if (!(size = _lrfl.size()))
{
::RemoveMenu(_hMenu, _posBase + 3, MF_BYPOSITION);
::RemoveMenu(_hMenu, _posBase + 0, MF_BYPOSITION);
::RemoveMenu(_hMenu, IDM_OPEN_ALL_RECENT_FILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_CLEAN_RECENT_FILE_LIST, MF_BYCOMMAND);
_hasSeparators = false;
}
}
};
/*
int getNbLRF() const {
return _lrfl.size();
};
*/
int getMaxNbLRF() const {
return NB_MAX_LRF_FILE;
};
void setUserMaxNbLRF(int size) {
_userMax = size;
};
int getUserMaxNbLRF() const {
return _userMax;
};
void saveLRFL() const {
NppParameters *pNppParams = NppParameters::getInstance();
if (pNppParams->writeNbHistoryFile(_userMax))
{
// if user defined nb recent files smaller than the size of list,
// we just keep the newest ones
int decal = _lrfl.size() - _userMax;
decal = (decal >= 0)?decal:0;
stringList::const_iterator it = _lrfl.begin();
for (int i = 0 ; i < decal ; i++, it++);
std::string & getItem(int id); //use menu id
std::string & getIndex(int index); //use menu id
for (int i = 0 ; it != _lrfl.end() && (i < _userMax) ; it++, i++)
{
pNppParams->writeHistory(((const std::string)*it).c_str());
}
}
void setUserMaxNbLRF(int size);
void saveLRFL();
void setLock(bool lock) {
_locked = lock;
};
private:
stringList _lrfl;
recentList _lrfl;
int _userMax;
int _size;
// For the menu
HMENU _hMenu;
@ -130,42 +63,12 @@ private:
int _idBase;
bool _idFreeArray[NB_MAX_LRF_FILE];
bool _hasSeparators;
bool _locked;
bool find(const char *fn) const {
for (stringList::const_iterator it = _lrfl.begin() ; it != _lrfl.end() ; it++)
if (*it == fn)
return true;
return false;
};
int find(const char *fn);
bool find2Remove(const char *fn) {
for (stringList::iterator it = _lrfl.begin() ; it != _lrfl.end() ; it++)
{
if (*it == fn)
{
_lrfl.erase(it);
return true;
}
}
return false;
};
int popFirstAvailableID() {
for (int i = 0 ; i < NB_MAX_LRF_FILE ; i++)
{
if (_idFreeArray[i])
{
_idFreeArray[i] = false;
return i;
}
}
return 0;
};
void setAvailable(int id) {
int index = id - _idBase;
_idFreeArray[index] = true;
};
int popFirstAvailableID();
void setAvailable(int id);
};
#endif //LASTRECENTFILELIST_H

View File

@ -179,6 +179,9 @@
#define IDM_VIEW_GOTO_ANOTHER_VIEW 10001
#define IDM_VIEW_CLONE_TO_ANOTHER_VIEW 10002
#define IDM_VIEW_SWITCHTO_MAIN (IDM_VIEW + 70)
#define IDM_VIEW_SWITCHTO_SUB (IDM_VIEW + 71)
#define IDM_FORMAT (IDM + 5000)
#define IDM_FORMAT_TODOS (IDM_FORMAT + 1)

View File

@ -279,8 +279,8 @@
#define NPPM_INTERNAL_SCINTILLAKEYMODIFIED (NOTEPADPLUS_USER_INTERNAL + 7)
#define NPPM_INTERNAL_SCINTILLAFINFERCOLLAPSE (NOTEPADPLUS_USER_INTERNAL + 8)
#define NPPM_INTERNAL_SCINTILLAFINFERUNCOLLAPSE (NOTEPADPLUS_USER_INTERNAL + 9)
#define NPPM_INTERNAL_DOCSWITCHOFF (NOTEPADPLUS_USER_INTERNAL + 10)
#define NPPM_INTERNAL_DOCSWITCHIN (NOTEPADPLUS_USER_INTERNAL + 11)
//#define NPPM_INTERNAL_DOCSWITCHOFF (NOTEPADPLUS_USER_INTERNAL + 10)
//#define NPPM_INTERNAL_DOCSWITCHIN (NOTEPADPLUS_USER_INTERNAL + 11)
#define NPPM_INTERNAL_ISTABBARREDUCED (NOTEPADPLUS_USER_INTERNAL + 12)
#define NPPM_INTERNAL_ISFOCUSEDTAB (NOTEPADPLUS_USER_INTERNAL + 13)
#define NPPM_INTERNAL_GETMENU (NOTEPADPLUS_USER_INTERNAL + 14)

View File

@ -138,6 +138,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdSh
size_t nrFilesToOpen = params.size();
const char * currentFile;
char fullFileName[MAX_PATH];
//TODO: try merging the flenames and see if it exists, user may have typed a single spaced filename without quotes
for(size_t i = 0; i < nrFilesToOpen; i++) {
currentFile = params.at(i);
//check if relative or full path. Relative paths dont have a colon for driveletter
@ -160,6 +161,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdSh
// First of all, destroy static object NppParameters
pNppParameters->destroyInstance();
MainFileManager->destroyInstance();
int sw;
@ -261,24 +264,25 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdSh
::MessageBox(NULL, strcat(str, code), "Notepad++ Exception", MB_OK);
}
doException(notepad_plus_plus);
} catch(std::exception ex) {
::MessageBox(NULL, ex.what(), "C++ Exception", MB_OK);
doException(notepad_plus_plus);
} catch (const Win32Exception & ex) {
char message[1024]; //TODO: sane number
sprintf(message, "An exception occured. Notepad++ cannot recover and must be shut down.\r\nThe exception details are as follows:\r\n"
"Code:\t0x%08X\r\nType:\t%s\r\nException address: 0x%08X"
"\r\n\r\nNotepad++ will attempt to save any unsaved data. However, dataloss is very likely.",
"Code:\t0x%08X\r\nType:\t%s\r\nException address: 0x%08X",
ex.code(), ex.what(), ex.where());
::MessageBox(NULL, message, "Win32Exception", MB_OK | MB_ICONERROR);
doException(notepad_plus_plus);
} catch(std::exception ex) {
::MessageBox(NULL, ex.what(), "C++ Exception", MB_OK);
doException(notepad_plus_plus);
} catch(...) { //this shouldnt ever have to happen
doException(notepad_plus_plus);
}
return (UINT)msg.wParam;
}
void doException(Notepad_plus & notepad_plus_plus) {
_set_se_translator(NULL); //disable exception handler after excpetion, we dont want corrupt data structurs to crash the exception handler
::MessageBox(NULL, "Notepad++ will attempt to save any unsaved data. However, dataloss is very likely.", "Recovery initiating", MB_OK | MB_ICONINFORMATION);
bool res = notepad_plus_plus.emergency();
if (res) {

View File

@ -89,15 +89,17 @@ IF NOT EXIST ..\bin\userDefineLang.xml COPY ..\src\userDefineLang.xml ..\bin\use
WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/EHa"
Optimization="2"
GlobalOptimizations="TRUE"
InlineFunctionExpansion="1"
FavorSizeOrSpeed="2"
OmitFramePointers="TRUE"
OptimizeForWindowsApplication="TRUE"
AdditionalIncludeDirectories="..\src\WinControls\AboutDlg;..\..\scintilla\include;..\include;..\src\WinControls;..\src\WinControls\ImageListSet;..\src\WinControls\OpenSaveFileDialog;..\src\WinControls\SplitterContainer;..\src\WinControls\StaticDialog;..\src\WinControls\TabBar;..\src\WinControls\ToolBar;..\src\MISC\Process;..\src\ScitillaComponent;..\src\MISC;..\src\MISC\SysMsg;..\src\WinControls\StatusBar;..\src;..\src\WinControls\StaticDialog\RunDlg;..\src\tinyxml;..\src\WinControls\ColourPicker;..\src\Win32Explr;..\src\MISC\RegExt;..\src\WinControls\TrayIcon;..\src\WinControls\shortcut;..\src\WinControls\Grid;..\src\WinControls\ContextMenu;..\src\MISC\PluginsManager;..\src\WinControls\Preference;..\src\WinControls\WindowsDlg;..\src\WinControls\TaskList;..\src\WinControls\DockingWnd;..\src\WinControls\ToolTip"
AdditionalIncludeDirectories="..\src\WinControls\AboutDlg;..\..\scintilla\include;..\include;..\src\WinControls;..\src\WinControls\ImageListSet;..\src\WinControls\OpenSaveFileDialog;..\src\WinControls\SplitterContainer;..\src\WinControls\StaticDialog;..\src\WinControls\TabBar;..\src\WinControls\ToolBar;..\src\MISC\Process;..\src\ScitillaComponent;..\src\MISC;..\src\MISC\SysMsg;..\src\WinControls\StatusBar;..\src;..\src\WinControls\StaticDialog\RunDlg;..\src\tinyxml;..\src\WinControls\ColourPicker;..\src\Win32Explr;..\src\MISC\RegExt;..\src\WinControls\TrayIcon;..\src\WinControls\shortcut;..\src\WinControls\Grid;..\src\WinControls\ContextMenu;..\src\MISC\PluginsManager;..\src\WinControls\Preference;..\src\WinControls\WindowsDlg;..\src\WinControls\TaskList;..\src\WinControls\DockingWnd;..\src\WinControls\ToolTip;..\src\MISC\Exception"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
StringPooling="TRUE"
ExceptionHandling="FALSE"
RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
@ -109,7 +111,7 @@ IF NOT EXIST ..\bin\userDefineLang.xml COPY ..\src\userDefineLang.xml ..\bin\use
<Tool
Name="VCLinkerTool"
AdditionalOptions="/OPT:WIN98"
AdditionalDependencies="comctl32.lib shlwapi.lib shell32.lib odbc32.lib odbccp32.lib Oleacc.lib"
AdditionalDependencies="comctl32.lib shlwapi.lib shell32.lib Oleacc.lib"
ShowProgress="2"
OutputFile="$(OutDir)/notepad++.exe"
Version="1.0"
@ -160,6 +162,9 @@ IF NOT EXIST ..\bin\userDefineLang.xml COPY ..\src\userDefineLang.xml ..\bin\use
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
<File
RelativePath="..\src\lastRecentFileList.cpp">
</File>
<File
RelativePath="..\src\Notepad_plus.cpp">
</File>