From e6cfeedc0de75d6e477f3353226ba294dd097690 Mon Sep 17 00:00:00 2001 From: harrybharry Date: Thu, 22 May 2008 23:42:00 +0000 Subject: [PATCH] Finish Calltip. Make AutoComplete class. AutoComplete uses XML data. Add exception handling (dumping filedata). Sync Project file with added files. git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository@205 f5eea248-9336-0410-98b8-ebc06183d4e3 --- .../src/MISC/Exception/Win32Exception.cpp | 44 ++ .../src/MISC/Exception/Win32Exception.h | 42 ++ PowerEditor/src/Notepad_plus.cpp | 458 ++++-------------- PowerEditor/src/Notepad_plus.h | 20 +- PowerEditor/src/Parameters.cpp | 64 +-- PowerEditor/src/Parameters.h | 3 + .../src/ScitillaComponent/AutoCompletion.cpp | 311 ++++++++++++ .../src/ScitillaComponent/AutoCompletion.h | 57 +++ .../src/ScitillaComponent/FunctionCallTip.cpp | 263 ++++------ .../src/ScitillaComponent/FunctionCallTip.h | 35 +- .../ScitillaComponent/ScintillaEditView.cpp | 150 +++--- .../src/ScitillaComponent/ScintillaEditView.h | 132 ++--- PowerEditor/src/winmain.cpp | 51 +- .../visual.net/notepadPlus.vc.7.0.vcproj | 24 +- 14 files changed, 925 insertions(+), 729 deletions(-) create mode 100644 PowerEditor/src/MISC/Exception/Win32Exception.cpp create mode 100644 PowerEditor/src/MISC/Exception/Win32Exception.h create mode 100644 PowerEditor/src/ScitillaComponent/AutoCompletion.cpp create mode 100644 PowerEditor/src/ScitillaComponent/AutoCompletion.h diff --git a/PowerEditor/src/MISC/Exception/Win32Exception.cpp b/PowerEditor/src/MISC/Exception/Win32Exception.cpp new file mode 100644 index 000000000..0e0cd2ab8 --- /dev/null +++ b/PowerEditor/src/MISC/Exception/Win32Exception.cpp @@ -0,0 +1,44 @@ +//This code was retrieved from +//http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/3/ +//(Visual C++ exception handling) +//By Bennett +//Formatting Slightly modified for N++ + +#include "Win32Exception.h" +#include "eh.h" //eehh... =] + +Win32Exception::Win32Exception(const EXCEPTION_RECORD * info) { + _location = info->ExceptionAddress; + _code = info->ExceptionCode; + switch (info->ExceptionCode) { + case EXCEPTION_ACCESS_VIOLATION: + _event = "Access violation"; + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_INT_DIVIDE_BY_ZERO: + _event = "Division by zero"; + break; + default: + _event = "Unlisted exception"; + } +} + +void Win32Exception::installHandler() { + _set_se_translator(Win32Exception::translate); +} + +void Win32Exception::translate(unsigned code, EXCEPTION_POINTERS * info) { + // Windows guarantees that *(info->ExceptionRecord) is valid + switch (code) { + case EXCEPTION_ACCESS_VIOLATION: + throw Win32AccessViolation(info->ExceptionRecord); + break; + default: + throw Win32Exception(info->ExceptionRecord); + } +} + +Win32AccessViolation::Win32AccessViolation(const EXCEPTION_RECORD * info) : Win32Exception(info) { + _isWrite = info->ExceptionInformation[0] == 1; + _badAddress = reinterpret_cast(info->ExceptionInformation[1]); +} diff --git a/PowerEditor/src/MISC/Exception/Win32Exception.h b/PowerEditor/src/MISC/Exception/Win32Exception.h new file mode 100644 index 000000000..cbba1273d --- /dev/null +++ b/PowerEditor/src/MISC/Exception/Win32Exception.h @@ -0,0 +1,42 @@ +//This code was retrieved from +//http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/3/ +//(Visual C++ exception handling) +//By Bennett +//Formatting Slightly modified for N++ + +#include "windows.h" +#include + +typedef const void* ExceptionAddress; // OK on Win32 platform + +class Win32Exception : public std::exception +{ +public: + static void installHandler(); + virtual const char* what() const { return _event; }; + ExceptionAddress where() const { return _location; }; + unsigned code() const { return _code; }; + +protected: + Win32Exception(const EXCEPTION_RECORD * info); //Constructor only accessible by exception handler + static void translate(unsigned code, EXCEPTION_POINTERS * info); + +private: + const char * _event; + ExceptionAddress _location; + unsigned int _code; +}; + +class Win32AccessViolation: public Win32Exception +{ +public: + bool isWrite() const { return _isWrite; }; + ExceptionAddress badAddress() const { return _badAddress; }; +private: + Win32AccessViolation(const EXCEPTION_RECORD * info); + + bool _isWrite; + ExceptionAddress _badAddress; + + friend void Win32Exception::translate(unsigned code, EXCEPTION_POINTERS* info); +}; diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index fd7fb6d40..29100c117 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -61,8 +61,10 @@ struct SortTaskListPred Notepad_plus::Notepad_plus(): Window(), _mainWindowStatus(0), _pDocTab(NULL), _pEditView(NULL), _pMainSplitter(NULL), _isfullScreen(false), _recordingMacro(false), _pTrayIco(NULL), _isUDDocked(false), _isRTL(false), - _linkTriggered(true), _isDocModifing(false), _isHotspotDblClicked(false), _isSaving(false), _sysMenuEntering(false) + _linkTriggered(true), _isDocModifing(false), _isHotspotDblClicked(false), _isSaving(false), _sysMenuEntering(false), + _autoCompleteMain(&_mainEditView), _autoCompleteSub(&_subEditView) { + ZeroMemory(&_prevSelectedRange, sizeof(_prevSelectedRange)); _winVersion = (NppParameters::getInstance())->getWinVersion(); @@ -1611,65 +1613,7 @@ string Notepad_plus::getLangDesc(LangType langType, bool shortDesc) return string(elc._desc); } - static const int maxChar = 64; - static char langDescArray[][maxChar] = { - "Normal text", "Normal text file", - "PHP", "PHP Hypertext Preprocessor file", - "C", "C source file", - "C++", "C++ source file", - "C#", "C# source file", - "Objective-C", "Objective-C source file", - "Java", "Java source file", - "RC", "Windows Resource file", - "HTML", "Hyper Text Markup Language file", - "XML", "eXtensible Markup Language file", - "Makefile", "Makefile", - "Pascal", "Pascal source file", - "Batch", "Batch file", - "ini", "MS ini file", - "NFO", "MSDOS Style/ASCII Art", - "udf", "User Define File", - "ASP", "Active Server Pages script file", - "SQL", "Structured Query Language file", - "VB", "Visual Basic file", - "JavaScript", "JavaScript file", - "CSS", "Cascade Style Sheets File", - "Perl", "Perl source file", - "Python", "Python file", - "Lua", "Lua source File", - "TeX", "TeX file", - "Fortran", "Fortran source file", - "Shell", "Unix script file", - "Flash Action", "Flash Action script file", - "NSIS", "Nullsoft Scriptable Install System script file", - "TCL", "Tool Command Language file", - "Lisp", "List Processing language file", - "Scheme", "Scheme file", - "Assembly", "Assembly language source file", - "Diff", "Diff file", - "Properties file", "Properties file", - "Postscript", "Postscript file", - "Ruby", "Ruby file", - "Smalltalk", "Smalltalk file", - "VHDL", "VHSIC Hardware Description Language file", - "KiXtart", "KiXtart file", - "AutoIt", "AutoIt", - "CAML", "Categorical Abstract Machine Language", - "Ada", "Ada file", - "Verilog", "Verilog file", - "MATLAB", "MATrix LABoratory", - "Haskell", "Haskell", - "Inno", "Inno Setup script", - "Internal Search", "Internal Search", - "CMAKEFILE", "CMAKEFILE", - "YAML", "YAML Ain't Markup Language" - }; - - int index = (int(langType)) * 2 + (shortDesc?0:1); - if (index >= sizeof(langDescArray)/maxChar) - index = 0; - - string str2Show = langDescArray[index]; + string str2Show = ScintillaEditView::langNames[langType].longName; if (langType == L_USER) { @@ -1683,125 +1627,6 @@ string Notepad_plus::getLangDesc(LangType langType, bool shortDesc) return str2Show; } -void Notepad_plus::getApiFileName(LangType langType, string &fn) -{ - - switch (langType) - { - case L_C: fn = "c"; break; - - case L_CPP: fn = "cpp"; break; - - case L_OBJC: fn = "objC"; break; - - case L_JAVA: fn = "java"; break; - - case L_CS : fn = "cs"; break; - - case L_XML: fn = "xml"; break; - - case L_JS: fn = "javascript"; break; - - case L_PHP: fn = "php"; break; - - case L_VB: - case L_ASP: fn = "vb"; break; - - case L_CSS: fn = "css"; break; - - case L_LUA: fn = "lua"; break; - - case L_PERL: fn = "perl"; break; - - case L_PASCAL: fn = "pascal"; break; - - case L_PYTHON: fn = "python"; break; - - case L_TEX : fn = "tex"; break; - - case L_FORTRAN : fn = "fortran"; break; - - case L_BASH : fn = "bash"; break; - - case L_FLASH : fn = "flash"; break; - - case L_NSIS : fn = "nsis"; break; - - case L_TCL : fn = "tcl"; break; - - case L_LISP : fn = "lisp"; break; - - case L_SCHEME : fn = "scheme"; break; - - case L_ASM : - fn = "asm"; break; - - case L_DIFF : - fn = "diff"; break; -/* - case L_PROPS : - fn = "Properties file"; break; -*/ - case L_PS : - fn = "postscript"; break; - - case L_RUBY : - fn = "ruby"; break; - - case L_SMALLTALK : - fn = "smalltalk"; break; - - case L_VHDL : - fn = "vhdl"; break; - - case L_KIX : - fn = "kix"; break; - - case L_AU3 : - fn = "autoit"; break; - - case L_CAML : - fn = "caml"; break; - - case L_ADA : - fn = "ada"; break; - - case L_VERILOG : - fn = "verilog"; break; - - case L_MATLAB : - fn = "matlab"; break; - - case L_HASKELL : - fn = "haskell"; break; - - case L_INNO : - fn = "inno"; break; - - case L_CMAKE : - fn = "cmake"; break; - - case L_YAML : - fn = "yaml"; break; - - case L_USER : - { - Buffer & currentBuf = _pEditView->getCurrentBuffer(); - if (currentBuf.isUserDefineLangExt()) - { - fn = currentBuf.getUserDefineLangName(); - } - break; - } - default: - if (langType >= L_EXTERNAL && langType < NppParameters::getInstance()->L_END) - fn = NppParameters::getInstance()->getELCFromIndex(langType - L_EXTERNAL)._name; - else - fn = "text"; - } -} - - BOOL Notepad_plus::notify(SCNotification *notification) { //Important, keep track of which element generated the message @@ -2160,22 +1985,11 @@ BOOL Notepad_plus::notify(SCNotification *notification) case SCN_CHARADDED: { charAdded(static_cast(notification->ch)); - static const NppGUI & nppGUI = NppParameters::getInstance()->getNppGUI(); - char s[64]; - notifyView->getWordToCurrentPos(s, sizeof(s)); + AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub; + + autoC->update(notification->ch); - if (strlen(s) >= nppGUI._autocFromLen) - { - if (nppGUI._autocStatus == nppGUI.autoc_word) - autoCompFromCurrentFile(false); - else if (nppGUI._autocStatus == nppGUI.autoc_func) - showAutoComp(); - } - - if (nppGUI._funcParams || _funcCalltip.isVisible()) { - _funcCalltip.updateCalltip(notification->ch); - } break; } @@ -2196,12 +2010,14 @@ BOOL Notepad_plus::notify(SCNotification *notification) break; case SCN_UPDATEUI: + { braceMatch(); markSelectedText(); updateStatusBar(); - if (_funcCalltip.isVisible()) - _funcCalltip.updateCalltip(0); + AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub; + autoC->update(0); break; + } case TTN_GETDISPINFO: { @@ -2303,12 +2119,8 @@ BOOL Notepad_plus::notify(SCNotification *notification) case SCN_CALLTIPCLICK: { - int dir = notification->position; - if (dir == 1) { - _funcCalltip.showPrevOverload(); - } else if (dir == 2) { - _funcCalltip.showNextOverload(); - } + AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub; + autoC->callTipClick(notification->position); break; } @@ -5036,167 +4848,24 @@ void Notepad_plus::checkUnicodeMenuItems(UniMode um) const ::CheckMenuRadioItem(_mainMenuHandle, IDM_FORMAT_ANSI, IDM_FORMAT_AS_UTF_8, id, MF_BYCOMMAND); } -static bool isInList(string word, const vector & wordArray) -{ - for (size_t i = 0 ; i < wordArray.size() ; i++) - if (wordArray[i] == word) - return true; - return false; -}; - -void Notepad_plus::autoCompFromCurrentFile(bool autoInsert) -{ - int curPos = int(_pEditView->execute(SCI_GETCURRENTPOS)); - int startPos = int(_pEditView->execute(SCI_WORDSTARTPOSITION, curPos, true)); - - if (curPos == startPos) - return; - - const size_t bufSize = 256; - size_t len = (curPos > startPos)?(curPos - startPos):(startPos - curPos); - if (len >= bufSize) - return; - - char beginChars[bufSize]; - - _pEditView->getText(beginChars, startPos, curPos); - - string expr("\\<"); - expr += beginChars; - expr += "[^ \\t.,;:\"()=<>'+!\\[\\]]*"; - - //::MessageBox(NULL, expr.c_str(), "", MB_OK); - - int docLength = int(_pEditView->execute(SCI_GETLENGTH)); - - int flags = SCFIND_WORDSTART | SCFIND_MATCHCASE | SCFIND_REGEXP | SCFIND_POSIX; - - _pEditView->execute(SCI_SETTARGETSTART, 0); - _pEditView->execute(SCI_SETTARGETEND, docLength); - _pEditView->execute(SCI_SETSEARCHFLAGS, flags); - - vector wordArray; - - int posFind = int(_pEditView->execute(SCI_SEARCHINTARGET, expr.length(), (LPARAM)expr.c_str())); - - while (posFind != -1) - { - int wordStart = int(_pEditView->execute(SCI_GETTARGETSTART)); - int wordEnd = int(_pEditView->execute(SCI_GETTARGETEND)); - - size_t foundTextLen = wordEnd - wordStart; - - if (foundTextLen < bufSize) - { - char w[bufSize]; - _pEditView->getText(w, wordStart, wordEnd); - - if (strcmp(w, beginChars)) - if (!isInList(w, wordArray)) - wordArray.push_back(w); - } - _pEditView->execute(SCI_SETTARGETSTART, wordEnd/*posFind + foundTextLen*/); - _pEditView->execute(SCI_SETTARGETEND, docLength); - posFind = int(_pEditView->execute(SCI_SEARCHINTARGET, expr.length(), (LPARAM)expr.c_str())); - } - if (wordArray.size() == 0) return; - - if (wordArray.size() == 1 && autoInsert) - { - _pEditView->execute(SCI_SETTARGETSTART, startPos); - _pEditView->execute(SCI_SETTARGETEND, curPos); - _pEditView->execute(SCI_REPLACETARGETRE, wordArray[0].length(), (LPARAM)wordArray[0].c_str()); - - _pEditView->execute(SCI_GOTOPOS, startPos + wordArray[0].length()); - return; - } - - sort(wordArray.begin(), wordArray.end()); - - string words(""); - - for (size_t i = 0 ; i < wordArray.size() ; i++) - { - words += wordArray[i]; - if (i != wordArray.size()-1) - words += " "; - } - - _pEditView->execute(SCI_AUTOCSETSEPARATOR, WPARAM(' ')); - _pEditView->execute(SCI_AUTOCSETIGNORECASE, 3); - _pEditView->execute(SCI_AUTOCSHOW, curPos - startPos, WPARAM(words.c_str())); - +void Notepad_plus::showAutoComp() { + bool isFromPrimary = _pEditView == &_mainEditView; + AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub; + autoC->showAutoComplete(); } -void Notepad_plus::showAutoComp() -{ - int curPos = int(_pEditView->execute(SCI_GETCURRENTPOS)); - int line = _pEditView->getCurrentLineNumber(); - int debutLinePos = int(_pEditView->execute(SCI_POSITIONFROMLINE, line )); - int debutMotPos = curPos; - - - char c = char(_pEditView->execute(SCI_GETCHARAT, debutMotPos-1)); - while ((debutMotPos>0)&&(debutMotPos>=debutLinePos)&&((isalnum(c))||(c=='_'))) - { - debutMotPos--; - c = char(_pEditView->execute(SCI_GETCHARAT, debutMotPos-1)); - } - LangType langType = _pEditView->getCurrentDocType(); - if ((langType == L_RC) || (langType == L_HTML) || (langType == L_SQL)) - { - int typeIndex = LANG_INDEX_INSTR; - - const char *pKeywords = (NppParameters::getInstance())->getWordList(langType, typeIndex); - if (pKeywords) - { - _pEditView->execute(SCI_AUTOCSETSEPARATOR, WPARAM(' ')); - _pEditView->execute(SCI_AUTOCSETIGNORECASE, 3); - _pEditView->execute(SCI_AUTOCSHOW, curPos-debutMotPos, WPARAM(pKeywords)); - } - } - else - { - char nppPath[MAX_PATH]; - strcpy(nppPath, _nppPath); - PathRemoveFileSpec(nppPath); - string fullFileName = nppPath; - string fileName; - getApiFileName(langType, fileName); - fileName += ".api"; - fullFileName += "\\plugins\\APIs\\"; - fullFileName += fileName; - - FILE* f = fopen( fullFileName.c_str(), "r" ); - - if (f) - { - fseek( f, 0, SEEK_END ); - size_t sz = ftell( f ); - fseek( f, 0, SEEK_SET ); - char* pData = new char[sz+1]; - size_t nbChar = fread(pData, 1, sz, f); - pData[nbChar] = '\0'; - fclose( f ); - - _pEditView->execute(SCI_AUTOCSETSEPARATOR, WPARAM('\n')); - _pEditView->execute(SCI_AUTOCSETIGNORECASE, 3); - _pEditView->execute(SCI_AUTOCSHOW, curPos-debutMotPos, WPARAM(pData)); - delete[] pData; - } - } +void Notepad_plus::autoCompFromCurrentFile(bool autoInsert) { + bool isFromPrimary = _pEditView == &_mainEditView; + AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub; + autoC->showWordComplete(autoInsert); } void Notepad_plus::showFunctionComp() { - //string langName; - //LangType langType = _pEditView->getCurrentDocType(); - //getApiFileName(langType, langName); - //_funcCalltip.initCalltip(_pEditView, langName.c_str()); - _funcCalltip.updateCalltip(0, true); + bool isFromPrimary = _pEditView == &_mainEditView; + AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub; + autoC->showFunctionComplete(); } - - void Notepad_plus::changeMenuLang(string & pluginsTrans, string & windowTrans) { if (!_nativeLang) return; @@ -8379,4 +8048,83 @@ void Notepad_plus::markSelectedText() _findReplaceDlg.markAll2(text2Find); } +//ONLY CALL IN CASE OF EMERGENCY: EXCEPTION +//This function is destructive +bool Notepad_plus::emergency() { + const char * outdir = "C:\\N++RECOV"; + bool status = false; + do { + if (::CreateDirectory(outdir, NULL) == FALSE && ::GetLastError() != ERROR_ALREADY_EXISTS) { + break; + } + ScintillaEditView * viewToRecover = &_mainEditView; + status |= dumpFiles(viewToRecover, outdir, "Main"); + viewToRecover = &_subEditView; + status |= dumpFiles(viewToRecover, outdir, "Sub"); + + + } while (false); + + return status; +} + +bool Notepad_plus::dumpFiles(ScintillaEditView * viewToRecover, const char * outdir, const char * fileprefix) { + //start dumping unsaved files to recovery directory + bool somethingsaved = false; + bool somedirty = false; + size_t nrdocs = viewToRecover->getNbDoc(); + bool skipfirst = viewToRecover->getCurrentDocIndex() == 0; //if cur doc is first, dont do setdocpointer or itll be deleted + char savePath[MAX_PATH] = {0}; + + int bufferSize = 2048; + char dataBuffer[2048+1] = {0}; //not too bug of a buffer, we dont know how much we've got here + + FILE * dumpFile; + TextRange textRange; + textRange.lpstrText = dataBuffer; + //rescue primary + for(size_t i = 0; i < nrdocs; i++) { + Buffer & docbuf = viewToRecover->getBufferAt(i); + if (!docbuf.isDirty()) //skip saved documents + continue; + else + somedirty = true; + if (i != 0 || !skipfirst) + viewToRecover->execute(SCI_SETDOCPOINTER, 0, docbuf._doc); + + const char * unitext = ""; + if (docbuf.getUnicodeMode() != uni8Bit) + unitext = "_uni"; + + sprintf(savePath, "%s\\%s%03d%s.dump", outdir, fileprefix, i, unitext); + dumpFile = fopen(savePath, "wb"); + if (!dumpFile) { //cannot create file, this is bad + ::MessageBox(NULL, savePath, "Cannot dump file", MB_OK | MB_ICONWARNING); + continue; + } + + //now it gets tricky, we have to have some allocated memory, we can only hope we have some + int size = viewToRecover->execute(SCI_GETLENGTH); + int saved = 0; + while(0 < size) { + if (size < bufferSize) { + bufferSize = size; //last piece of data smaller than buffer + } + + textRange.chrg.cpMin = saved; + textRange.chrg.cpMax = saved + bufferSize; + viewToRecover->execute(SCI_GETTEXTRANGE, 0, (LPARAM)&textRange); + size_t res = fwrite(dataBuffer, bufferSize, 1, dumpFile); + if (!res) //FAILURE! + break; + saved += bufferSize; + size -= bufferSize; + } + + somethingsaved |= size==0; + fclose(dumpFile); + } + + return somethingsaved || !somedirty; +} diff --git a/PowerEditor/src/Notepad_plus.h b/PowerEditor/src/Notepad_plus.h index 60feea53c..6d49c791b 100644 --- a/PowerEditor/src/Notepad_plus.h +++ b/PowerEditor/src/Notepad_plus.h @@ -46,7 +46,7 @@ #include "RunMacroDlg.h" #include "DockingManager.h" #include "Process.h" -#include "FunctionCallTip.h" +#include "AutoCompletion.h" #define NOTEPAD_PP_CLASS_NAME "Notepad++" @@ -78,9 +78,6 @@ struct iconLocator { class FileDialog; -//Class assumes Scintilla makes sure calltip never gets displayed twice - - class Notepad_plus : public Window { enum comment_mode {cm_comment, cm_uncomment, cm_toggle}; public: @@ -171,13 +168,15 @@ public: bool loadSession(Session & session); winVer getWinVersion() const {return _winVersion;}; + bool emergency(); private: static const char _className[32]; char _nppPath[MAX_PATH]; Window *_pMainWindow; DockingManager _dockingManager; - FunctionCallTip _funcCalltip; + AutoCompletion _autoCompleteMain; + AutoCompletion _autoCompleteSub; //each Scintilla has its own autoComplete TiXmlNode *_nativeLang, *_toolIcons; @@ -413,10 +412,10 @@ private: void setLangStatus(LangType langType){ _statusBar.setText(getLangDesc(langType).c_str(), STATUSBAR_DOC_TYPE); - - string langName; - getApiFileName(langType, langName); - _funcCalltip.initCalltip(_pEditView, langName.c_str()); + if (_pEditView == &_mainEditView) + _autoCompleteMain.setLanguage(langType); + else + _autoCompleteSub.setLanguage(langType); }; void setDisplayFormat(formatType f) { @@ -603,7 +602,6 @@ private: void showAutoComp(); void autoCompFromCurrentFile(bool autoInsert = true); - void getApiFileName(LangType langType, std::string &fn); void showFunctionComp(); void changeStyleCtrlsLang(HWND hDlg, int *idArray, const char **translatedText); @@ -753,6 +751,8 @@ private: } return true; }; + + bool dumpFiles(ScintillaEditView * viewToRecover, const char * outdir, const char * fileprefix = ""); //helper func }; #endif //NOTEPAD_PLUS_H diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index 88b896c6f..070e444cf 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -2013,59 +2013,21 @@ TiXmlNode * NppParameters::getChildElementByAttribut(TiXmlNode *pere, const char // 2 restes : L_H, L_USER LangType NppParameters::getLangIDFromStr(const char *langName) { - if (!strcmp("c", langName)) return L_C; - if (!strcmp("cpp", langName)) return L_CPP; - if (!strcmp("java", langName)) return L_JAVA; - if (!strcmp("cs", langName)) return L_CS; - if (!strcmp("objc", langName)) return L_OBJC; - if (!strcmp("rc", langName)) return L_RC; - if (!strcmp("html", langName)) return L_HTML; - if (!strcmp("javascript", langName)) return L_JS; - if (!strcmp("php", langName)) return L_PHP; - if (!strcmp("vb", langName)) return L_VB; - if (!strcmp("sql", langName)) return L_SQL; - if (!strcmp("xml", langName)) return L_XML; - if (!strcmp("asp", langName)) return L_ASP; - if (!strcmp("perl", langName)) return L_PERL; - if (!strcmp("pascal", langName)) return L_PASCAL; - if (!strcmp("python", langName)) return L_PYTHON; - if (!strcmp("css", langName)) return L_CSS; - if (!strcmp("lua", langName)) return L_LUA; - if (!strcmp("batch", langName)) return L_BATCH; - if (!strcmp("ini", langName)) return L_INI; - if (!strcmp("nfo", langName)) return L_NFO; - if (!strcmp("makefile", langName)) return L_MAKEFILE; - if (!strcmp("tex", langName)) return L_TEX; - if (!strcmp("fortran", langName)) return L_FORTRAN; - if (!strcmp("bash", langName)) return L_BASH; - if (!strcmp("actionscript", langName)) return L_FLASH; - if (!strcmp("nsis", langName)) return L_NSIS; - if (!strcmp("tcl", langName)) return L_TCL; + int lang = (int)L_TXT; + for(; lang < L_EXTERNAL; lang++) { + const char * name = ScintillaEditView::langNames[lang].lexerName; + if (!strcmp(name, langName)) { //found lang? + return (LangType)lang; + } + } - if (!strcmp("lisp", langName)) return L_LISP; - if (!strcmp("scheme", langName)) return L_SCHEME; - if (!strcmp("asm", langName)) return L_ASM; - if (!strcmp("diff", langName)) return L_DIFF; - if (!strcmp("props", langName)) return L_PROPS; - if (!strcmp("postscript", langName)) return L_PS; - if (!strcmp("ruby", langName)) return L_RUBY; - if (!strcmp("smalltalk", langName)) return L_SMALLTALK; - if (!strcmp("vhdl", langName)) return L_VHDL; + //Cannot find language, check if its an external one - if (!strcmp("caml", langName)) return L_CAML; - if (!strcmp("verilog", langName)) return L_VERILOG; - if (!strcmp("kix", langName)) return L_KIX; - if (!strcmp("autoit", langName)) return L_AU3; - if (!strcmp("ada", langName)) return L_ADA; - if (!strcmp("matlab", langName)) return L_MATLAB; - if (!strcmp("haskell", langName)) return L_HASKELL; - if (!strcmp("inno", langName)) return L_INNO; - if (!strcmp("searchResult", langName)) return L_SEARCHRESULT; - if (!strcmp("cmake", langName)) return L_CMAKE; - if (!strcmp("yaml", langName)) return L_YAML; - - int id = _pSelf->getExternalLangIndexFromName(langName); - if (id != -1) return (LangType)(id + L_EXTERNAL); + LangType l = (LangType)lang; + if (l == L_EXTERNAL) { //try find external lexer + int id = _pSelf->getExternalLangIndexFromName(langName); + if (id != -1) return (LangType)(id + L_EXTERNAL); + } return L_TXT; } diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index d8995e7b8..3b37d396e 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -357,8 +357,11 @@ public: void addStyler(int styleID, TiXmlNode *styleNode); void addStyler(int styleID, char *styleName) { + ZeroMemory(&_styleArray[_nbStyler], sizeof(Style));; _styleArray[_nbStyler]._styleID = styleID; _styleArray[_nbStyler]._styleDesc = styleName; + _styleArray[_nbStyler]._fgColor = black; + _styleArray[_nbStyler]._bgColor = white; _nbStyler++; }; diff --git a/PowerEditor/src/ScitillaComponent/AutoCompletion.cpp b/PowerEditor/src/ScitillaComponent/AutoCompletion.cpp new file mode 100644 index 000000000..cf0f5619e --- /dev/null +++ b/PowerEditor/src/ScitillaComponent/AutoCompletion.cpp @@ -0,0 +1,311 @@ +//this file is part of Notepad++ +//Copyright (C)2008 Harry Bruin +// +//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 "AutoCompletion.h" +#include "Notepad_plus_msgs.h" + +static bool isInList(string word, const vector & wordArray) +{ + for (size_t i = 0 ; i < wordArray.size() ; i++) + if (wordArray[i] == word) + return true; + return false; +}; + +AutoCompletion::AutoCompletion(ScintillaEditView * pEditView) : _active(false), _pEditView(pEditView), _funcCalltip(pEditView), + _curLang(L_TXT), _XmlFile(NULL), _activeCompletion(CompletionNone), + _pXmlKeyword(NULL), _ignoreCase(true), _keyWords("") +{ + //Do not load any language yet +} + +bool AutoCompletion::showAutoComplete() { + if (!_active) + return false; + + int curPos = int(_pEditView->execute(SCI_GETCURRENTPOS)); + int line = _pEditView->getCurrentLineNumber(); + int startLinePos = int(_pEditView->execute(SCI_POSITIONFROMLINE, line )); + int startWordPos = startLinePos; + + int len = curPos-startLinePos; + char * lineBuffer = new char[len+1]; + _pEditView->getText(lineBuffer, startLinePos, curPos); + //_pEditView->execute(SCI_GETTEXT, (WPARAM)len, (LPARAM)lineBuffer); + + int offset = len-1; + int nrChars = 0; + char c; + while (offset>=0) + { + c = lineBuffer[offset]; + if (isalnum(c) || c == '_') { + nrChars++; + } else { + break; + } + offset--; + + } + startWordPos = curPos-nrChars; + + _pEditView->execute(SCI_AUTOCSETSEPARATOR, WPARAM('\n')); + _pEditView->execute(SCI_AUTOCSETIGNORECASE, _ignoreCase); + _pEditView->execute(SCI_AUTOCSHOW, curPos-startWordPos, WPARAM(_keyWords.c_str())); + + _activeCompletion = CompletionAuto; + return true; +} + +bool AutoCompletion::showWordComplete(bool autoInsert) { + if (!_active) + return false; + + int curPos = int(_pEditView->execute(SCI_GETCURRENTPOS)); + int startPos = int(_pEditView->execute(SCI_WORDSTARTPOSITION, curPos, true)); + + if (curPos == startPos) + return false; + + const size_t bufSize = 256; + size_t len = (curPos > startPos)?(curPos - startPos):(startPos - curPos); + if (len >= bufSize) + return false; + + char beginChars[bufSize]; + + _pEditView->getText(beginChars, startPos, curPos); + + string expr("\\<"); + expr += beginChars; + expr += "[^ \\t.,;:\"()=<>'+!\\[\\]]*"; + + int docLength = int(_pEditView->execute(SCI_GETLENGTH)); + + int flags = SCFIND_WORDSTART | SCFIND_MATCHCASE | SCFIND_REGEXP | SCFIND_POSIX; + + _pEditView->execute(SCI_SETTARGETSTART, 0); + _pEditView->execute(SCI_SETTARGETEND, docLength); + _pEditView->execute(SCI_SETSEARCHFLAGS, flags); + + vector wordArray; + + int posFind = int(_pEditView->execute(SCI_SEARCHINTARGET, expr.length(), (LPARAM)expr.c_str())); + + while (posFind != -1) + { + int wordStart = int(_pEditView->execute(SCI_GETTARGETSTART)); + int wordEnd = int(_pEditView->execute(SCI_GETTARGETEND)); + + size_t foundTextLen = wordEnd - wordStart; + + if (foundTextLen < bufSize) + { + char w[bufSize]; + _pEditView->getText(w, wordStart, wordEnd); + + if (strcmp(w, beginChars)) + if (!isInList(w, wordArray)) + wordArray.push_back(w); + } + _pEditView->execute(SCI_SETTARGETSTART, wordEnd/*posFind + foundTextLen*/); + _pEditView->execute(SCI_SETTARGETEND, docLength); + posFind = int(_pEditView->execute(SCI_SEARCHINTARGET, expr.length(), (LPARAM)expr.c_str())); + } + if (wordArray.size() == 0) return false; + + if (wordArray.size() == 1 && autoInsert) + { + _pEditView->execute(SCI_SETTARGETSTART, startPos); + _pEditView->execute(SCI_SETTARGETEND, curPos); + _pEditView->execute(SCI_REPLACETARGETRE, wordArray[0].length(), (LPARAM)wordArray[0].c_str()); + + _pEditView->execute(SCI_GOTOPOS, startPos + wordArray[0].length()); + return true; + } + + string words(""); + + for (size_t i = 0 ; i < wordArray.size() ; i++) + { + words += wordArray[i]; + if (i != wordArray.size()-1) + words += " "; + } + + _pEditView->execute(SCI_AUTOCSETSEPARATOR, WPARAM(' ')); + _pEditView->execute(SCI_AUTOCSETIGNORECASE, _ignoreCase); + _pEditView->execute(SCI_AUTOCSHOW, curPos - startPos, WPARAM(words.c_str())); + + _activeCompletion = CompletionWord; + return true; +} + +bool AutoCompletion::showFunctionComplete() { + if (!_active) + return false; + + if (_funcCalltip.updateCalltip(0, true)) { + _activeCompletion = CompletionFunc; + return true; + } + return false; +} + +void AutoCompletion::update(int character) { + if (!_active) + return; + + const NppGUI & nppGUI = NppParameters::getInstance()->getNppGUI(); + + if (nppGUI._funcParams || _funcCalltip.isVisible()) { + if (_funcCalltip.updateCalltip(character)) { //calltip visible because triggered by autocomplete, set mode + _activeCompletion = CompletionFunc; + return; //only return in case of success, else autocomplete + } + } + + if (!character) + return; + + //If autocomplete already active, let Scintilla handle it + if (_pEditView->execute(SCI_AUTOCACTIVE) != 0) + return; + + char s[64]; + _pEditView->getWordToCurrentPos(s, sizeof(s)); + + if (strlen(s) >= nppGUI._autocFromLen) + { + if (nppGUI._autocStatus == nppGUI.autoc_word) + showWordComplete(false); + else if (nppGUI._autocStatus == nppGUI.autoc_func) + showAutoComplete(); + } +} + +void AutoCompletion::callTipClick(int direction) { + if (!_active) + return; + + if (direction == 1) { + _funcCalltip.showPrevOverload(); + } else if (direction == 2) { + _funcCalltip.showNextOverload(); + } +} + +bool AutoCompletion::setLanguage(LangType language) { + if (_curLang == language) + return true; + _curLang = language; + + char path[MAX_PATH]; + ::GetModuleFileName(NULL, path, MAX_PATH); + PathRemoveFileSpec(path); + strcat(path, "\\plugins\\APIs\\"); + strcat(path, getApiFileName()); + strcat(path, ".xml"); + + _XmlFile = TiXmlDocument(path); + _active = _XmlFile.LoadFile(); + + TiXmlNode * pAutoNode = NULL; + if (_active) { + _active = false; //safety + TiXmlNode * pNode = _XmlFile.FirstChild("NotepadPlus"); + if (!pNode) + return false; + pAutoNode = pNode = pNode->FirstChildElement("AutoComplete"); + if (!pNode) + return false; + pNode = pNode->FirstChildElement("KeyWord"); + if (!pNode) + return false; + _pXmlKeyword = reinterpret_cast(pNode); + if (!_pXmlKeyword) + return false; + _active = true; + } + + if(_active) { //try setting up environment + //setup defaults + _ignoreCase = true; + _funcCalltip._start = '('; + _funcCalltip._stop = ')'; + _funcCalltip._param = ','; + _funcCalltip._terminal = ';'; + + TiXmlElement * pElem = pAutoNode->FirstChildElement("Environment"); + if (pElem) { + const char * val = 0; + val = pElem->Attribute("ignoreCase"); + if (val && !strcmp(val, "no")) + _ignoreCase = false; + val = pElem->Attribute("startFunc"); + if (val && val[0]) + _funcCalltip._start = val[0]; + val = pElem->Attribute("stopFunc"); + if (val && val[0]) + _funcCalltip._stop = val[0]; + val = pElem->Attribute("paramSeparator"); + if (val && val[0]) + _funcCalltip._param = val[0]; + val = pElem->Attribute("terminal"); + if (val && val[0]) + _funcCalltip._terminal = val[0]; + } + } + + if (_active) { + _funcCalltip.setLanguageXML(_pXmlKeyword); + } else { + _funcCalltip.setLanguageXML(NULL); + } + + _keyWords = ""; + if (_active) { //Cache the keywords + //Iterate through all keywords + TiXmlElement *funcNode = _pXmlKeyword; + const char * name = NULL; + for (; funcNode; funcNode = funcNode->NextSiblingElement("KeyWord") ) { + name = funcNode->Attribute("name"); + if (!name) //malformed node + continue; + _keyWords.append(name); + _keyWords.append("\n"); + } + } + return _active; +} + +const char * AutoCompletion::getApiFileName() { + if (_curLang == L_USER) + { + Buffer & currentBuf = _pEditView->getCurrentBuffer(); + if (currentBuf.isUserDefineLangExt()) + { + return currentBuf.getUserDefineLangName(); + } + } + + if (_curLang >= L_EXTERNAL && _curLang < NppParameters::getInstance()->L_END) + return NppParameters::getInstance()->getELCFromIndex(_curLang - L_EXTERNAL)._name; + + return ScintillaEditView::langNames[_curLang].lexerName; + +} diff --git a/PowerEditor/src/ScitillaComponent/AutoCompletion.h b/PowerEditor/src/ScitillaComponent/AutoCompletion.h new file mode 100644 index 000000000..84732e1d8 --- /dev/null +++ b/PowerEditor/src/ScitillaComponent/AutoCompletion.h @@ -0,0 +1,57 @@ +//this file is part of Notepad++ +//Copyright (C)2008 Harry Bruin +// +//This program is free software; you can redistribute it and/or +//modify it under the terms of the GNU General Public License +//as published by the Free Software Foundation; either +//version 2 of the License, or (at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program; if not, write to the Free Software +//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +#ifndef AUTOCOMPLETION_H +#define AUTOCOMPLETION_H + +#include "ScintillaEditView.h" +#include "FunctionCallTip.h" +#include "tinyxml.h" + +class AutoCompletion { +public: + enum ActiveCompletion {CompletionNone = 0, CompletionAuto, CompletionWord, CompletionFunc}; + AutoCompletion(ScintillaEditView * pEditView); + bool setLanguage(LangType language); + + //AutoComplete from the list + bool showAutoComplete(); + //WordCompletion from the current file + bool showWordComplete(bool autoInsert); //autoInsert true if completion should fill in the word on a single match + //Parameter display from the list + bool showFunctionComplete(); + + void update(int character); + void callTipClick(int direction); + +private: + bool _active; + ScintillaEditView * _pEditView; + LangType _curLang; + TiXmlDocument _XmlFile; + TiXmlElement * _pXmlKeyword; + ActiveCompletion _activeCompletion; + + bool _ignoreCase; + + std::string _keyWords; + + FunctionCallTip _funcCalltip; + const char * getApiFileName(); +}; + +#endif //AUTOCOMPLETION_H diff --git a/PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp b/PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp index 143906489..0525e6056 100644 --- a/PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp +++ b/PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp @@ -1,3 +1,7 @@ +//this file is part of Notepad++ +//Copyright (C)2008 Harry Bruin +// +//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. @@ -39,59 +43,28 @@ bool stringEqualN(const char * first, const char * second, int n) { return true; }; - -void FunctionCallTip::initCalltip(ScintillaEditView * editView, const char * language) { - _pEditView = editView; - if (_langName) - delete [] _langName; - _langName = new char[strlen(language)+1]; - strcpy(_langName, language); - _initialized = true; +void FunctionCallTip::setLanguageXML(TiXmlElement * pXmlKeyword) { + if (isVisible()) + close(); + _pXmlKeyword = pXmlKeyword; } -void FunctionCallTip::updateCalltip(int ch, bool needShown) { - if (!_initialized) - return; - +bool FunctionCallTip::updateCalltip(int ch, bool needShown) { if (!needShown && ch != _start && !isVisible()) //must be already visible - return; + return false; _curPos = _pEditView->execute(SCI_GETCURRENTPOS); //recalculate everything if (!getCursorFunction()) { //cannot display calltip (anymore) close(); - return; + return false; } showCalltip(); - return; - - /* - switch (ch) { - case '(': - case 0: { //recalculate everything - if (!getCursorFunction()) { //cannot display calltip (anymore) - close(); - return; - } - showCalltip(); - return; } - case ')': { //close calltip - close(); - return; } - case ',': { //show next param - _currentParam++; - showCalltip(); - return; } - default: { //any other character: nothing to do - break; } - } - */ + return true; } void FunctionCallTip::showNextOverload() { - if (!_initialized) - return; if (!isVisible()) return; _currentOverload = (_currentOverload+1) % _currentNrOverloads; @@ -99,8 +72,6 @@ void FunctionCallTip::showNextOverload() { } void FunctionCallTip::showPrevOverload() { - if (!_initialized) - return; if (!isVisible()) return; _currentOverload = _currentOverload > 0?(_currentOverload-1) : _currentNrOverloads-1; @@ -108,8 +79,6 @@ void FunctionCallTip::showPrevOverload() { } void FunctionCallTip::close() { - if (!_initialized) - return; if (!isVisible()) { return; } @@ -126,10 +95,6 @@ bool FunctionCallTip::getCursorFunction() { int offset = _curPos - startpos; //offset is cursor location, only stuff before cursor has influence if (offset < 2) { reset(); - if (_funcName) { - delete [] _funcName; - _funcName = 0; - } return false; //cannot be a func, need name and separator } char * lineData = new char[len]; @@ -222,11 +187,7 @@ bool FunctionCallTip::getCursorFunction() { _currentParam = curValue.param; if (!_funcName || !stringEqualN(_funcName, funcToken.token, strlen(_funcName))) { //check if we need to reload data - if (_funcName) - delete [] _funcName; - _funcName = new char[strlen(funcToken.token) + 1]; //add the return type aswell - strcpy(_funcName, funcToken.token); - res = loadData(); + res = loadFunction(funcToken.token); } else { res = true; } @@ -243,91 +204,75 @@ bool FunctionCallTip::getCursorFunction() { } /* -CTF (CalltipFormat) file structure (ignore spaces). -There MUST be a return type, however, may be empty string (or empty line even) -_no_ CR. ESC = 027 = 0x1B -( -NULL FunctionName LF -return value (ESC possibleparam)* LF -)* -NULL +Find function in XML structure and parse it */ -bool FunctionCallTip::loadData() { - char filePath[MAX_PATH]; - ::GetModuleFileName(NULL, filePath, MAX_PATH); - PathRemoveFileSpec(filePath); - strcat(filePath, "\\plugins\\APIs\\"); - strcat(filePath, _langName); - strcat(filePath, ".ctf"); - - FILE * ctfFile = fopen(filePath, "rb"); //CalltipFormat File - if (!ctfFile) - return false; - - //Copy all data, close with \n to be sure - fseek(ctfFile, 0, SEEK_END ); - size_t fileSize = ftell(ctfFile); - fseek(ctfFile, 0, SEEK_SET ); - char * fileData = new char[fileSize+1]; - size_t nbChar = fread(fileData, 1, fileSize, ctfFile); - fileData[nbChar] = 0; - fclose(ctfFile); - +bool FunctionCallTip::loadFunction(const char * nameToFind) { //The functions should be ordered, but linear search because we cant access like array - size_t i = 0, location = 0; - bool found = false; - int funcLen = strlen(_funcName); - fileSize -= funcLen; //if not enough is left, no need to keep searching - while(i < fileSize) { - if (fileData[i] == 0) { //reached new function - //case sensitive search - if (stringEqualN(_funcName, fileData+i+1, funcLen)) { //found it - found = true; - location = i + 2 + funcLen; //skip zero + LF + name of func (all known at this point) - break; - } - } - i++; - } - if (!found) { - delete [] fileData; - return false; - } - - int argStart = location; - std::vector< pair > overloadLocations; //start, length - while(fileData[location] != 0) { //keep reading each line of overloads untill next function is found - argStart = location; - while(fileData[location] != '\n') { - location++; - } - overloadLocations.push_back(pair(argStart, location-argStart)); - location++; //skip newline - } - - _currentNrOverloads = overloadLocations.size(); - _currentOverloads = new char*[_currentNrOverloads]; - _params = new vector[_currentNrOverloads]; - - int j = 0; - for(int i = 0; i < _currentNrOverloads; i++) { - pair & cur = overloadLocations.at(i); - _currentOverloads[i] = new char[cur.second+1]; - memcpy(_currentOverloads[i], fileData+cur.first, cur.second); - _currentOverloads[i][cur.second] = 0; - j = 0; - while(_currentOverloads[i][j] != 0) { - if (_currentOverloads[i][j] == 0x1B) { - _currentOverloads[i][j] = 0; - _params[i].push_back(j+1); + _curFunction = NULL; + //Iterate through all keywords and find the correct function keyword + TiXmlElement *funcNode = _pXmlKeyword; + const char * name = NULL; + for (; funcNode; funcNode = funcNode->NextSiblingElement("KeyWord") ) { + name = funcNode->Attribute("name"); + if (!name) //malformed node + continue; + int compVal = strcmp(name, nameToFind); + if (!compVal) { //found it? + const char * val = funcNode->Attribute("func"); + if (val) + { + if (!strcmp(val, "yes")) { + //what we've been looking for + _curFunction = funcNode; + break; + } else { + //name matches, but not a function, abort the entire procedure + return false; } - j++; } + } else if (compVal > 0) { //too far, abort + return false; + } } + //Nothing found + if (!_curFunction) + return false; + + _funcName = name; + if (!_funcName) //this should not happen + return false; + + _retVals.clear(); + _overloads.clear(); + stringVec paramVec; + + TiXmlElement *overloadNode = _curFunction->FirstChildElement("Overload"); + TiXmlElement *paramNode = NULL; + for (; overloadNode ; overloadNode = overloadNode->NextSiblingElement("Overload") ) { + const char * retVal = overloadNode->Attribute("retVal"); + if (!retVal) + continue; //malformed node + _retVals.push_back(retVal); + paramNode = overloadNode->FirstChildElement("Param"); + for (; paramNode ; paramNode = paramNode->NextSiblingElement("Param") ) { + const char * param = paramNode->Attribute("name"); + if (!param) + continue; //malformed node + paramVec.push_back(param); + } + _overloads.push_back(paramVec); + paramVec.clear(); + + _currentNrOverloads++; + } + + _currentNrOverloads = (int)_overloads.size(); + + if (_currentNrOverloads == 0) //malformed node + return false; - delete [] fileData; return true; } @@ -336,26 +281,40 @@ void FunctionCallTip::showCalltip() { //ASSERT return; } - char * curOverloadText = _currentOverloads[_currentOverload]; - int bytesNeeded = strlen(curOverloadText) + strlen(_funcName) + 5;//'retval funcName (params)\0' - size_t nrParams = _params[_currentOverload].size(); - if (nrParams) { - for(size_t i = 0; i < nrParams; i++) { - bytesNeeded += strlen(curOverloadText+_params[_currentOverload][i]) + 2; //'param, ' + + //Check if the current overload still holds. If the current param exceeds amounti n overload, see if another one fits better (enough params) + stringVec & params = _overloads.at(_currentOverload); + size_t psize = params.size()+1, osize; + if ((size_t)_currentParam >= psize) { + osize = _overloads.size(); + for(size_t i = 0; i < osize; i++) { + psize = _overloads.at(i).size()+1; + if ((size_t)_currentParam < psize) { + _currentOverload = i; + break; + } } } + const char * curRetValText = _retVals.at(_currentOverload); + + int bytesNeeded = strlen(curRetValText) + strlen(_funcName) + 5;//'retval funcName (params)\0' + size_t nrParams = params.size(); + for(size_t i = 0; i < nrParams; i++) { + bytesNeeded += strlen(params.at(i)) + 2; //'param, ' + } if (_currentNrOverloads > 1) { bytesNeeded += 24; // /\00001 of 00003\/ } char * textBuffer = new char[bytesNeeded]; + //char langDepChar[4] = " "; //Language dependant characters, like '(', ')', ',' and ';' textBuffer[0] = 0; if (_currentNrOverloads > 1) { sprintf(textBuffer, "\001%u of %u\002", _currentOverload+1, _currentNrOverloads); } - strcat(textBuffer, curOverloadText); + strcat(textBuffer, curRetValText); strcat(textBuffer, " "); strcat(textBuffer, _funcName); strcat(textBuffer, " ("); @@ -365,9 +324,9 @@ void FunctionCallTip::showCalltip() { for(size_t i = 0; i < nrParams; i++) { if (i == _currentParam) { highlightstart = strlen(textBuffer); - highlightend = highlightstart + strlen(curOverloadText+_params[_currentOverload][i]); + highlightend = highlightstart + strlen(params.at(i)); } - strcat(textBuffer, curOverloadText+_params[_currentOverload][i]); + strcat(textBuffer, params.at(i)); if (i < nrParams-1) strcat(textBuffer, ", "); } @@ -389,36 +348,16 @@ void FunctionCallTip::showCalltip() { void FunctionCallTip::reset() { _currentOverload = 0; - //_currentNrOverloads = 0; _currentParam = 0; _curPos = 0; _startPos = 0; } void FunctionCallTip::cleanup() { - if (_currentOverloads) { - for(int i = 0; i < _currentNrOverloads; i++) - delete [] _currentOverloads[i]; - _currentNrOverloads = 0; - delete [] _currentOverloads; - _currentOverloads = 0; - } - if(_funcName) { - delete [] _funcName; - _funcName = 0; - } - if (_params) { - delete [] _params; - _params = 0; - } - if (_langName) { - delete [] _langName; - _langName = 0; - } reset(); + _overloads.clear(); + _currentNrOverloads = 0; + _retVals.clear(); + _funcName = 0; _pEditView = NULL; - _currentOverload = 0; - _currentParam = 0; - _initialized = false; } - diff --git a/PowerEditor/src/ScitillaComponent/FunctionCallTip.h b/PowerEditor/src/ScitillaComponent/FunctionCallTip.h index a0ffab4d9..7c8158e7d 100644 --- a/PowerEditor/src/ScitillaComponent/FunctionCallTip.h +++ b/PowerEditor/src/ScitillaComponent/FunctionCallTip.h @@ -1,4 +1,4 @@ -//this file is part of notepad++ +//this file is part of Notepad++ //Copyright (C)2008 Harry Bruin // //This program is free software; you can redistribute it and/or @@ -20,30 +20,36 @@ #include "ScintillaEditView.h" +typedef std::vector stringVec; class FunctionCallTip { + friend class AutoCompletion; public: - FunctionCallTip() : _pEditView(NULL), _langName(NULL), _currentOverloads(NULL), _funcName(NULL), _params(NULL), _initialized(false), - _start('('), _stop(')'), _param(','), _terminal(';') {}; + FunctionCallTip(ScintillaEditView * pEditView) : _pEditView(pEditView), _pXmlKeyword(NULL), _curPos(0), _startPos(0), + _curFunction(NULL), _currentNrOverloads(0), _currentOverload(0), + _currentParam(0), _funcName(NULL), + _start('('), _stop(')'), _param(','), _terminal(';') + {}; ~FunctionCallTip() {/* cleanup(); */}; - void initCalltip(ScintillaEditView * editView, const char * language); //show the calltip - void updateCalltip(int ch, bool needShown = false); //Ch is character typed, or 0 if another event occured. NeedShown is true if calltip should be attempted to displayed - void showNextOverload(); - void showPrevOverload(); - bool isVisible() { return _pEditView?_pEditView->execute(SCI_CALLTIPACTIVE) == TRUE:false; }; + void setLanguageXML(TiXmlElement * pXmlKeyword); //set calltip keyword node + bool updateCalltip(int ch, bool needShown = false); //Ch is character typed, or 0 if another event occured. NeedShown is true if calltip should be attempted to displayed. Return true if calltip was made visible + void showNextOverload(); //show next overlaoded parameters + void showPrevOverload(); //show prev overlaoded parameters + bool isVisible() { return _pEditView?_pEditView->execute(SCI_CALLTIPACTIVE) == TRUE:false; }; //true if calltip visible void close(); //Close calltip if visible private: - char * _langName; //current language ScintillaEditView * _pEditView; //Scintilla to display calltip in - bool _initialized; + TiXmlElement * _pXmlKeyword; //current keyword node (first one) int _curPos; //cursor position int _startPos; //display start position - char * _funcName; //current name of function - char ** _currentOverloads; //pointer to list of strings each containing possible overload - vector * _params; //array of vectors with offsets found for params + TiXmlElement * _curFunction; //current function element + //cache some XML values n stuff + const char * _funcName; //name of function + stringVec _retVals; //vector of overload return values/types + vector _overloads; //vector of overload params (=vector) int _currentNrOverloads; //current amount of overloads int _currentOverload; //current chosen overload int _currentParam; //current highlighted param @@ -54,9 +60,10 @@ private: char _terminal; bool getCursorFunction(); //retrieve data about function at cursor. Returns true if a function was found. Calls loaddata if needed - bool loadData(); //returns true if the function can be found + bool loadFunction(const char * nameToFind); //returns true if the function can be found void showCalltip(); //display calltip based on current variables void reset(); //reset all vars in case function is invalidated void cleanup(); //delete any leftovers }; + #endif// FUNCTIONCALLTIP_H diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp index 6f8f53d70..afd6b4419 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp @@ -54,6 +54,61 @@ const int ScintillaEditView::_markersArray[][NB_FOLDER_STATE] = { {SC_MARK_BOXMINUS, SC_MARK_BOXPLUS, SC_MARK_VLINE, SC_MARK_LCORNER, SC_MARK_BOXPLUSCONNECTED, SC_MARK_BOXMINUSCONNECTED, SC_MARK_TCORNER} }; +//Array with all the names of all languages +LanguageName ScintillaEditView::langNames[L_EXTERNAL+1] = { +{"normal", "Normal text", "Normal text file", L_TXT}, +{"php", "PHP", "PHP Hypertext Preprocessor file", L_PHP}, +{"c", "C", "C source file", L_C}, +{"cpp", "C++", "C++ source file", L_CPP}, +{"cs", "C#", "C# source file", L_CS}, +{"objc", "Objective-C", "Objective-C source file", L_OBJC}, +{"java", "Java", "Java source file", L_JAVA}, +{"rc", "RC", "Windows Resource file", L_RC}, +{"html", "HTML", "Hyper Text Markup Language file", L_HTML}, +{"xml", "XML", "eXtensible Markup Language file", L_XML}, +{"makefile", "Makefile", "Makefile", L_MAKEFILE}, +{"pascal", "Pascal", "Pascal source file", L_PASCAL}, +{"batch", "Batch", "Batch file", L_BATCH}, +{"ini", "ini", "MS ini file", L_INI}, +{"nfo", "NFO", "MSDOS Style/ASCII Art", L_NFO}, +{"udf", "udf", "User Define File", L_USER}, +{"asp", "ASP", "Active Server Pages script file", L_ASP}, +{"sql", "SQL", "Structured Query Language file", L_SQL}, +{"vb", "VB", "Visual Basic file", L_VB}, +{"javascript", "JavaScript", "JavaScript file", L_JS}, +{"css", "CSS", "Cascade Style Sheets File", L_CSS}, +{"perl", "Perl", "Perl source file", L_PERL}, +{"python", "Python", "Python file", L_PYTHON}, +{"lua", "Lua", "Lua source File", L_LUA}, +{"tex", "TeX", "TeX file", L_TEX}, +{"fortran", "Fortran", "Fortran source file", L_FORTRAN}, +{"bash", "Shell", "Unix script file", L_BASH}, +{"actionscript","Flash Action", "Flash Action script file", L_FLASH}, //WARNING, was "flash" +{"nsis", "NSIS", "Nullsoft Scriptable Install System script file", L_NSIS}, +{"tcl", "TCL", "Tool Command Language file", L_TCL}, +{"lisp", "Lisp", "List Processing language file", L_LISP}, +{"scheme", "Scheme", "Scheme file", L_SCHEME}, +{"asm", "Assembly", "Assembly language source file", L_ASM}, +{"diff", "Diff", "Diff file", L_DIFF}, +{"props", "Properties file", "Properties file", L_PROPS}, +{"postscript", "Postscript", "Postscript file", L_PS}, +{"ruby", "Ruby", "Ruby file", L_RUBY}, +{"smalltalk", "Smalltalk", "Smalltalk file", L_SMALLTALK}, +{"vhdl", "VHDL", "VHSIC Hardware Description Language file", L_VHDL}, +{"kix", "KiXtart", "KiXtart file", L_KIX}, +{"autoit", "AutoIt", "AutoIt", L_AU3}, +{"caml", "CAML", "Categorical Abstract Machine Language", L_CAML}, +{"ada", "Ada", "Ada file", L_ADA}, +{"verilog", "Verilog", "Verilog file", L_VERILOG}, +{"matlab", "MATLAB", "MATrix LABoratory", L_MATLAB}, +{"haskell", "Haskell", "Haskell", L_HASKELL}, +{"inno", "Inno", "Inno Setup script", L_INNO}, +{"searchResult","Internal Search", "Internal Search", L_SEARCHRESULT}, +{"cmake", "CMAKEFILE", "CMAKEFILE", L_CMAKE}, +{"yaml", "YAML", "YAML Ain't Markup Language", L_YAML}, +{"ext", "External", "External", L_EXTERNAL} +}; + //const int MASK_RED = 0xFF0000; //const int MASK_GREEN = 0x00FF00; //const int MASK_BLUE = 0x0000FF; @@ -297,7 +352,7 @@ void ScintillaEditView::setXmlLexer(LangType type) for (int i = 0 ; i < 4 ; i++) execute(SCI_SETKEYWORDS, i, reinterpret_cast("")); - makeStyle("xml"); + makeStyle(type); } else if ((type == L_HTML) || (type == L_PHP) || (type == L_ASP)) { @@ -307,7 +362,7 @@ void ScintillaEditView::setXmlLexer(LangType type) const char *htmlKeyWords =_pParameter->getWordList(L_HTML, LANG_INDEX_INSTR); execute(SCI_SETKEYWORDS, 0, reinterpret_cast(htmlKeyWords?htmlKeyWords:"")); - makeStyle("html"); + makeStyle(type); setEmbeddedJSLexer(); setPhpEmbeddedLexer(); @@ -318,7 +373,7 @@ void ScintillaEditView::setXmlLexer(LangType type) void ScintillaEditView::setEmbeddedJSLexer() { const char *pKwArray[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - makeStyle("javascript", pKwArray); + makeStyle(L_JS, pKwArray); std::string keywordList(""); if (pKwArray[LANG_INDEX_INSTR]) @@ -334,7 +389,7 @@ void ScintillaEditView::setEmbeddedJSLexer() void ScintillaEditView::setPhpEmbeddedLexer() { const char *pKwArray[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - makeStyle("php", pKwArray); + makeStyle(L_PHP, pKwArray); std::string keywordList(""); if (pKwArray[LANG_INDEX_INSTR]) @@ -349,7 +404,7 @@ void ScintillaEditView::setPhpEmbeddedLexer() void ScintillaEditView::setEmbeddedAspLexer() { const char *pKwArray[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - makeStyle("asp", pKwArray); + makeStyle(L_ASP, pKwArray); std::string keywordList(""); if (pKwArray[LANG_INDEX_INSTR]) @@ -360,36 +415,11 @@ void ScintillaEditView::setEmbeddedAspLexer() execute(SCI_STYLESETEOLFILLED, SCE_HBA_DEFAULT, true); } -void ScintillaEditView::setUserLexer() -{ - execute(SCI_SETLEXER, SCLEX_USER); - UserLangContainer & userLangContainer = *(_userDefineDlg._pCurrentUserLang); - execute(SCI_SETPROPERTY, (WPARAM)"userDefine.ignoreCase", (LPARAM)(userLangContainer._isCaseIgnored?"1":"0")); - execute(SCI_SETPROPERTY, (WPARAM)"userDefine.commentLineSymbol", (LPARAM)(userLangContainer._isCommentLineSymbol?"1":"0")); - execute(SCI_SETPROPERTY, (WPARAM)"userDefine.commentSymbol", (LPARAM)(userLangContainer._isCommentSymbol?"1":"0")); - - const char strArray[4][20] = {"userDefine.g1Prefix", "userDefine.g2Prefix", "userDefine.g3Prefix", "userDefine.g4Prefix"}; - for (int i = 0 ; i < 4 ; i++) - execute(SCI_SETPROPERTY, (WPARAM)strArray[i], (LPARAM)(userLangContainer._isPrefix[i]?"1":"0")); - - for (int i = 0 ; i < userLangContainer.getNbKeywordList() ; i++) - { - execute(SCI_SETKEYWORDS, i, reinterpret_cast(userLangContainer._keywordLists[i])); - } - - for (int i = 0 ; i < userLangContainer._styleArray.getNbStyler() ; i++) - { - Style & style = userLangContainer._styleArray.getStyler(i); - setStyle(style); - } -} - void ScintillaEditView::setUserLexer(const char *userLangName) { - execute(SCI_SETLEXER, SCLEX_USER); - UserLangContainer & userLangContainer = NppParameters::getInstance()->getULCFromName(userLangName); + UserLangContainer & userLangContainer = userLangName?NppParameters::getInstance()->getULCFromName(userLangName):*(_userDefineDlg._pCurrentUserLang); execute(SCI_SETPROPERTY, (WPARAM)"userDefine.ignoreCase", (LPARAM)(userLangContainer._isCaseIgnored?"1":"0")); execute(SCI_SETPROPERTY, (WPARAM)"userDefine.commentLineSymbol", (LPARAM)(userLangContainer._isCommentLineSymbol?"1":"0")); execute(SCI_SETPROPERTY, (WPARAM)"userDefine.commentSymbol", (LPARAM)(userLangContainer._isCommentSymbol?"1":"0")); @@ -443,7 +473,8 @@ void ScintillaEditView::setCppLexer(LangType langType) const char *cppTypes; const char *doxygenKeyWords = _pParameter->getWordList(L_CPP, LANG_INDEX_TYPE2); - char *lexerName; + const char *lexerName = ScintillaEditView::langNames[langType].lexerName; + /*char *lexerName; switch (langType) { case L_C: @@ -469,7 +500,7 @@ void ScintillaEditView::setCppLexer(LangType langType) default: return; - } + }*/ execute(SCI_SETLEXER, SCLEX_CPP); if (isCJK()) @@ -487,7 +518,7 @@ void ScintillaEditView::setCppLexer(LangType langType) if (langType == L_JS) { - LexerStyler *pStyler = (_pParameter->getLStylerArray()).getLexerStylerByName("javascript"); + LexerStyler *pStyler = (_pParameter->getLStylerArray()).getLexerStylerByName(lexerName); if (pStyler) { for (int i = 0 ; i < pStyler->getNbStyler() ; i++) @@ -519,7 +550,7 @@ void ScintillaEditView::setCppLexer(LangType langType) } const char *pKwArray[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - makeStyle(lexerName, pKwArray); + makeStyle(langType, pKwArray); std::string instr1(""); if (pKwArray[LANG_INDEX_INSTR]) @@ -544,11 +575,11 @@ void ScintillaEditView::setObjCLexer(LangType langType) const char *pKwArray[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - const char *lexerName = "objc"; - if (langType == L_FLASH) - lexerName = "actionscript"; + //const char *lexerName = "objc"; + //if (langType == L_FLASH) + // lexerName = "actionscript"; - makeStyle(lexerName, pKwArray); + makeStyle(langType, pKwArray); std::string objcInstr1Kwl(""); if (pKwArray[LANG_INDEX_INSTR]) @@ -584,13 +615,13 @@ void ScintillaEditView::setKeywords(LangType langType, const char *keywords, int execute(SCI_SETKEYWORDS, index, (LPARAM)getCompleteKeywordList(wordList, langType, index)); } -void ScintillaEditView::setLexer(int lexerID, LangType langType, const char *lexerName, int whichList) +void ScintillaEditView::setLexer(int lexerID, LangType langType, int whichList) { execute(SCI_SETLEXER, lexerID); const char *pKwArray[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - makeStyle(lexerName, pKwArray); + makeStyle(langType, pKwArray); if (whichList & LIST_0) { @@ -628,6 +659,25 @@ void ScintillaEditView::setLexer(int lexerID, LangType langType, const char *lex } } +void ScintillaEditView::makeStyle(LangType language, const char **keywordArray) +{ + const char * lexerName = ScintillaEditView::langNames[language].lexerName; + LexerStyler *pStyler = (_pParameter->getLStylerArray()).getLexerStylerByName(lexerName); + if (pStyler) + { + for (int i = 0 ; i < pStyler->getNbStyler() ; i++) + { + Style & style = pStyler->getStyler(i); + setStyle(style); + if (keywordArray) + { + if ((style._keywordClass != -1) && (style._keywords)) + keywordArray[style._keywordClass] = style._keywords->c_str(); + } + } + } +} + void ScintillaEditView::defineDocType(LangType typeDoc) { //setStyle(STYLE_DEFAULT, black, white, "Verdana", 0, 9); @@ -1305,24 +1355,6 @@ void ScintillaEditView::expand(int &line, bool doExpand, bool force, int visLeve //recalcHorizontalScrollbar(); //Update scrollbar after folding } -void ScintillaEditView::makeStyle(const char *lexerName, const char **keywordArray) -{ - LexerStyler *pStyler = (_pParameter->getLStylerArray()).getLexerStylerByName(lexerName); - if (pStyler) - { - for (int i = 0 ; i < pStyler->getNbStyler() ; i++) - { - Style & style = pStyler->getStyler(i); - setStyle(style); - if (keywordArray) - { - if ((style._keywordClass != -1) && (style._keywords)) - keywordArray[style._keywordClass] = style._keywords->c_str(); - } - } - } -} - void ScintillaEditView::performGlobalStyles() { StyleArray & stylers = _pParameter->getMiscStylerArray(); diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h index 264a9092d..b86393c95 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h @@ -125,6 +125,13 @@ char * int2str(char *str, int strLen, int number, int base, int nbChiffre, bool typedef LRESULT (WINAPI *CallWindowProcFunc) (WNDPROC,HWND,UINT,WPARAM,LPARAM); +struct LanguageName { + const char * lexerName; + const char * shortName; + const char * longName; + LangType LangID; +}; + class ScintillaEditView : public Window { friend class Notepad_plus; @@ -493,8 +500,6 @@ public: return (execute(SCI_GETCARETLINEVISIBLE) != 0); }; - inline void makeStyle(const char *lexerName, const char **keywordArray = NULL); - void performGlobalStyles(); void expand(int &line, bool doExpand, bool force = false, int visLevels = 0, int level = -1); @@ -618,6 +623,7 @@ public: execute(SCI_INDICATORCLEARRANGE, docStart, docEnd-docStart); }; + static LanguageName ScintillaEditView::langNames[L_EXTERNAL+1]; protected: static HINSTANCE _hLib; static int _refCount; @@ -673,168 +679,168 @@ protected: bool _wrapRestoreNeeded; +//Lexers and Styling + 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); + inline void makeStyle(LangType langType, const char **keywordArray = NULL); void setStyle(Style styleToSet); //NOT by reference (style edited) void setSpecialStyle(Style & styleToSet); //by reference void setSpecialIndicator(Style & styleToSet); - void setCppLexer(LangType type); + //Complex lexers (same lexer, different language) void setXmlLexer(LangType type); - void setUserLexer(); - void setUserLexer(const char *userLangName); + void setCppLexer(LangType type); + void setObjCLexer(LangType type); + void setUserLexer(const char *userLangName = NULL); void setExternalLexer(LangType typeDoc); void setEmbeddedJSLexer(); void setPhpEmbeddedLexer(); void setEmbeddedAspLexer(); + //Simple lexers void setCssLexer() { - setLexer(SCLEX_CSS, L_CSS, "css", LIST_0 | LIST_1); + setLexer(SCLEX_CSS, L_CSS, LIST_0 | LIST_1); }; void setLuaLexer() { - setLexer(SCLEX_LUA, L_LUA, "lua", LIST_0 | LIST_1 | LIST_2 | LIST_3); + setLexer(SCLEX_LUA, L_LUA, LIST_0 | LIST_1 | LIST_2 | LIST_3); }; void setMakefileLexer() { execute(SCI_SETLEXER, SCLEX_MAKEFILE); - makeStyle("makefile"); + makeStyle(L_MAKEFILE); }; void setIniLexer() { execute(SCI_SETLEXER, SCLEX_PROPERTIES); execute(SCI_STYLESETEOLFILLED, SCE_PROPS_SECTION, true); - makeStyle("ini"); + makeStyle(L_INI); }; - void setObjCLexer(LangType type); void setSqlLexer() { - setLexer(SCLEX_SQL, L_SQL, "sql", LIST_0); + setLexer(SCLEX_SQL, L_SQL, LIST_0); }; void setBashLexer() { - setLexer(SCLEX_BASH, L_BASH, "bash", LIST_0); + setLexer(SCLEX_BASH, L_BASH, LIST_0); }; void setVBLexer() { - setLexer(SCLEX_VB, L_VB, "vb", LIST_0); + setLexer(SCLEX_VB, L_VB, LIST_0); }; void setPascalLexer() { - setLexer(SCLEX_PASCAL, L_PASCAL, "pascal", LIST_0); + setLexer(SCLEX_PASCAL, L_PASCAL, LIST_0); }; void setPerlLexer() { - setLexer(SCLEX_PERL, L_PERL, "perl", LIST_0); + setLexer(SCLEX_PERL, L_PERL, LIST_0); }; void setPythonLexer() { - setLexer(SCLEX_PYTHON, L_PYTHON, "python", LIST_0); + setLexer(SCLEX_PYTHON, L_PYTHON, LIST_0); }; void setBatchLexer() { - setLexer(SCLEX_BATCH, L_BATCH, "batch", LIST_0); + setLexer(SCLEX_BATCH, L_BATCH, LIST_0); }; void setTeXLexer() { for (int i = 0 ; i < 4 ; i++) execute(SCI_SETKEYWORDS, i, reinterpret_cast("")); - setLexer(SCLEX_TEX, L_TEX, "tex", 0); + setLexer(SCLEX_TEX, L_TEX, 0); }; void setNsisLexer() { - setLexer(SCLEX_NSIS, L_NSIS, "nsis", LIST_0 | LIST_1 | LIST_2 | LIST_3); + setLexer(SCLEX_NSIS, L_NSIS, LIST_0 | LIST_1 | LIST_2 | LIST_3); }; void setFortranLexer() { - setLexer(SCLEX_F77, L_FORTRAN, "fortran", LIST_0 | LIST_1 | LIST_2); + setLexer(SCLEX_F77, L_FORTRAN, LIST_0 | LIST_1 | LIST_2); }; void setLispLexer(){ - setLexer(SCLEX_LISP, L_LISP, "lisp", LIST_0); + setLexer(SCLEX_LISP, L_LISP, LIST_0); }; - + void setSchemeLexer(){ - setLexer(SCLEX_LISP, L_SCHEME, "lisp", LIST_0); + setLexer(SCLEX_LISP, L_SCHEME, LIST_0); }; void setAsmLexer(){ - setLexer(SCLEX_ASM, L_ASM, "asm", LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5); + setLexer(SCLEX_ASM, L_ASM, LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5); }; - + void setDiffLexer(){ - setLexer(SCLEX_DIFF, L_DIFF, "diff", LIST_NONE); + setLexer(SCLEX_DIFF, L_DIFF, LIST_NONE); }; - + void setPropsLexer(){ - setLexer(SCLEX_PROPERTIES, L_PROPS, "props", LIST_NONE); + setLexer(SCLEX_PROPERTIES, L_PROPS, LIST_NONE); }; - + void setPostscriptLexer(){ - setLexer(SCLEX_PS, L_PS, "postscript", LIST_0 | LIST_1 | LIST_2 | LIST_3); + setLexer(SCLEX_PS, L_PS, LIST_0 | LIST_1 | LIST_2 | LIST_3); }; - + void setRubyLexer(){ - setLexer(SCLEX_RUBY, L_RUBY, "ruby", LIST_0); + setLexer(SCLEX_RUBY, L_RUBY, LIST_0); execute(SCI_STYLESETEOLFILLED, SCE_RB_POD, true); }; - + void setSmalltalkLexer(){ - setLexer(SCLEX_SMALLTALK, L_SMALLTALK, "smalltalk", LIST_0); + setLexer(SCLEX_SMALLTALK, L_SMALLTALK, LIST_0); }; - + void setVhdlLexer(){ - setLexer(SCLEX_VHDL, L_VHDL, "vhdl", LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5 | LIST_6); + setLexer(SCLEX_VHDL, L_VHDL, LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5 | LIST_6); }; - + void setKixLexer(){ - setLexer(SCLEX_KIX, L_KIX, "kix", LIST_0 | LIST_1 | LIST_2); + setLexer(SCLEX_KIX, L_KIX, LIST_0 | LIST_1 | LIST_2); }; - + void setAutoItLexer(){ - setLexer(SCLEX_AU3, L_AU3, "autoit", LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5 | LIST_6); + setLexer(SCLEX_AU3, L_AU3, LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5 | LIST_6); }; void setCamlLexer(){ - setLexer(SCLEX_CAML, L_CAML, "caml", LIST_0 | LIST_1 | LIST_2); + setLexer(SCLEX_CAML, L_CAML, LIST_0 | LIST_1 | LIST_2); }; void setAdaLexer(){ - setLexer(SCLEX_ADA, L_ADA, "ada", LIST_0); + setLexer(SCLEX_ADA, L_ADA, LIST_0); }; - + void setVerilogLexer(){ - setLexer(SCLEX_VERILOG, L_VERILOG, "verilog", LIST_0 | LIST_1); + setLexer(SCLEX_VERILOG, L_VERILOG, LIST_0 | LIST_1); }; void setMatlabLexer(){ - setLexer(SCLEX_MATLAB, L_MATLAB, "matlab", LIST_0); + setLexer(SCLEX_MATLAB, L_MATLAB, LIST_0); }; void setHaskellLexer(){ - setLexer(SCLEX_HASKELL, L_HASKELL, "haskell", LIST_0); + setLexer(SCLEX_HASKELL, L_HASKELL, LIST_0); }; void setInnoLexer() { - setLexer(SCLEX_INNOSETUP, L_INNO, "inno", LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5); + setLexer(SCLEX_INNOSETUP, L_INNO, LIST_0 | LIST_1 | LIST_2 | LIST_3 | LIST_4 | LIST_5); }; - + void setCmakeLexer() { - setLexer(SCLEX_CMAKE, L_CMAKE, "cmake", LIST_0 | LIST_1 | LIST_2); + setLexer(SCLEX_CMAKE, L_CMAKE, LIST_0 | LIST_1 | LIST_2); }; void setYamlLexer() { - setLexer(SCLEX_YAML, L_YAML, "yaml", LIST_0); + setLexer(SCLEX_YAML, L_YAML, LIST_0); }; void setSearchResultLexer() { execute(SCI_STYLESETEOLFILLED, SCE_SEARCHRESULT_HEARDER, true); - setLexer(SCLEX_SEARCHRESULT, L_SEARCHRESULT, "searchResult", LIST_1 | LIST_2 | LIST_3); + setLexer(SCLEX_SEARCHRESULT, L_SEARCHRESULT, LIST_1 | LIST_2 | LIST_3); }; - void defineMarker(int marker, int markerType, COLORREF fore, COLORREF back) { - execute(SCI_MARKERDEFINE, marker, markerType); - execute(SCI_MARKERSETFORE, marker, fore); - execute(SCI_MARKERSETBACK, marker, back); - }; - bool isNeededFolderMarge(LangType typeDoc) const { switch (typeDoc) { @@ -855,6 +861,14 @@ protected: return true; } }; +//END: Lexers and Styling + + void defineMarker(int marker, int markerType, COLORREF fore, COLORREF back) { + execute(SCI_MARKERDEFINE, marker, markerType); + execute(SCI_MARKERSETFORE, marker, fore); + execute(SCI_MARKERSETBACK, marker, back); + }; + bool isCJK() const { return ((_codepage == CP_CHINESE_TRADITIONAL) || (_codepage == CP_CHINESE_SIMPLIFIED) || (_codepage == CP_JAPANESE) || (_codepage == CP_KOREAN) || (_codepage == CP_GREEK)); @@ -871,10 +885,6 @@ protected: default : return 0; } }; - - 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, const char *lexerName, int whichList); bool expandWordSelection(); void arrangeBuffers(UINT nItems, UINT *items); diff --git a/PowerEditor/src/winmain.cpp b/PowerEditor/src/winmain.cpp index 7e09e6ca8..d203bc1ea 100644 --- a/PowerEditor/src/winmain.cpp +++ b/PowerEditor/src/winmain.cpp @@ -19,9 +19,8 @@ #include "SysMsg.h" #include "Process.h" -#include - -//const char localConfFile[] = "doLocalConf.xml"; +#include //default C++ esception +#include "Win32Exception.h" //Win32 exception typedef std::vector ParamVector; void parseCommandLine(char * commandLine, ParamVector & paramVector) { @@ -101,6 +100,8 @@ const char FLAG_READONLY[] = "-ro"; const char FLAG_NOSESSION[] = "-nosession"; const char FLAG_NOTABBAR[] = "-notabbar"; +void doException(Notepad_plus & notepad_plus_plus); + int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdShow) { bool TheFirstOne = true; @@ -225,6 +226,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdSh MSG msg; msg.wParam = 0; + Win32Exception::installHandler(); try { notepad_plus_plus.init(hInstance, NULL, quotFileName.c_str(), &cmdLineParams); @@ -240,31 +242,48 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdSh { if (::TranslateAccelerator(notepad_plus_plus.getHSelf(), notepad_plus_plus.getAccTable(), &msg) == 0) { - try { - ::TranslateMessage(&msg); - if (unicodeSupported) - ::DispatchMessageW(&msg); - else - ::DispatchMessage(&msg); - } catch(std::exception ex) { - ::MessageBox(NULL, ex.what(), "Exception", MB_OK); - } catch(...) { - systemMessage("System Error"); - } + ::TranslateMessage(&msg); + if (unicodeSupported) + ::DispatchMessageW(&msg); + else + ::DispatchMessage(&msg); } } } } } catch(int i) { if (i == 106901) - ::MessageBox(NULL, "Scintilla.init is failed!", "106901", MB_OK); + ::MessageBox(NULL, "Scintilla.init is failed!", "Notepad++ Exception: 106901", MB_OK); else { char str[50] = "God Damned Exception : "; char code[10]; itoa(i, code, 10); - ::MessageBox(NULL, strcat(str, code), "int exception", MB_OK); + ::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.", + ex.code(), ex.what(), ex.where()); + ::MessageBox(NULL, message, "Win32Exception", MB_OK | MB_ICONERROR); + 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) { + ::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) { + ::MessageBox(NULL, "Notepad++ was able to successfully recover some unsaved documents, or nothing to be saved could be found.\r\nYou can find the results at C:\\N++RECOV", "Recovery success", MB_OK | MB_ICONINFORMATION); + } else { + ::MessageBox(NULL, "Unfortunatly, Notepad++ was not able to save your work. We are sorry for any lost data.", "Recovery failure", MB_OK | MB_ICONERROR); + } +} diff --git a/PowerEditor/visual.net/notepadPlus.vc.7.0.vcproj b/PowerEditor/visual.net/notepadPlus.vc.7.0.vcproj index cb6cb4861..30fd6f2e7 100644 --- a/PowerEditor/visual.net/notepadPlus.vc.7.0.vcproj +++ b/PowerEditor/visual.net/notepadPlus.vc.7.0.vcproj @@ -19,10 +19,12 @@ CharacterSet="2"> + + + + @@ -204,6 +212,9 @@ IF NOT EXIST ..\bin\userDefineLang.xml COPY ..\src\userDefineLang.xml ..\bin\use + + @@ -397,10 +408,16 @@ IF NOT EXIST ..\bin\userDefineLang.xml COPY ..\src\userDefineLang.xml ..\bin\use + + + + @@ -416,6 +433,9 @@ IF NOT EXIST ..\bin\userDefineLang.xml COPY ..\src\userDefineLang.xml ..\bin\use + + @@ -871,4 +891,6 @@ IF NOT EXIST ..\bin\userDefineLang.xml COPY ..\src\userDefineLang.xml ..\bin\use + +