diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index 6ed686c48..c2e5b7bb6 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -705,13 +705,19 @@ bool Notepad_plus::doOpen(const char *fileName, bool isReadOnly) char data[blockSize]; size_t lenFile = fread(data, 1, sizeof(data), fp); bool isNotEmpty = (lenFile != 0); - - while (lenFile > 0) + + //try { + while (lenFile > 0) + { + lenFile = UnicodeConvertor.convert(data, lenFile); + _pEditView->execute(SCI_ADDTEXT, lenFile, reinterpret_cast(UnicodeConvertor.getNewBuf())); + lenFile = int(fread(data, 1, sizeof(data), fp)); + } + /*} + catch (...) { - lenFile = UnicodeConvertor.convert(data, lenFile); - _pEditView->execute(SCI_ADDTEXT, lenFile, reinterpret_cast(UnicodeConvertor.getNewBuf())); - lenFile = int(fread(data, 1, sizeof(data), fp)); - } + ::MessageBox(_hSelf, "File is too large to open.", "Open File Error", MB_OK); + }*/ fclose(fp); // 3 formats : WIN_FORMAT, UNIX_FORMAT and MAC_FORMAT @@ -2166,6 +2172,10 @@ BOOL Notepad_plus::notify(SCNotification *notification) else if (nppGUI._autocStatus == nppGUI.autoc_func) showAutoComp(); } + + if (nppGUI._funcParams || _funcCalltip.isVisible()) { + _funcCalltip.updateCalltip(notification->ch); + } break; } @@ -2189,6 +2199,8 @@ BOOL Notepad_plus::notify(SCNotification *notification) braceMatch(); markSelectedText(); updateStatusBar(); + if (_funcCalltip.isVisible()) + _funcCalltip.updateCalltip(0); break; case TTN_GETDISPINFO: @@ -2271,6 +2283,17 @@ BOOL Notepad_plus::notify(SCNotification *notification) break; } + case SCN_CALLTIPCLICK: + { + int dir = notification->position; + if (dir == 1) { + _funcCalltip.showPrevOverload(); + } else if (dir == 2) { + _funcCalltip.showNextOverload(); + } + break; + } + case RBN_HEIGHTCHANGE: { SendMessage(_hSelf, WM_SIZE, 0, 0); @@ -3814,6 +3837,10 @@ void Notepad_plus::command(int id) autoCompFromCurrentFile(); break; + case IDM_EDIT_FUNCCALLTIP : + showFunctionComp(); + break; + case IDM_LANGSTYLE_CONFIG_DLG : { bool isFirstTime = !_configStyleDlg.isCreated(); @@ -5143,6 +5170,16 @@ void Notepad_plus::showAutoComp() } } +void Notepad_plus::showFunctionComp() { + //string langName; + //LangType langType = _pEditView->getCurrentDocType(); + //getApiFileName(langType, langName); + //_funcCalltip.initCalltip(_pEditView, langName.c_str()); + _funcCalltip.updateCalltip(0, true); +} + + + void Notepad_plus::changeMenuLang(string & pluginsTrans, string & windowTrans) { if (!_nativeLang) return; @@ -7052,7 +7089,7 @@ LRESULT Notepad_plus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa case NPPM_DECODESCI: { - /* convert to ASCII */ + // convert to ASCII Utf8_16_Write UnicodeConvertor; UINT length = 0; char* buffer = NULL; @@ -7066,27 +7103,27 @@ LRESULT Notepad_plus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa return -1; - /* get text of current scintilla */ + // get text of current scintilla length = pSci->execute(SCI_GETTEXTLENGTH, 0, 0) + 1; buffer = new char[length]; pSci->execute(SCI_GETTEXT, length, (LPARAM)buffer); - /* convert here */ + // convert here UniMode unicodeMode = pSci->getCurrentBuffer().getUnicodeMode(); UnicodeConvertor.setEncoding(unicodeMode); length = UnicodeConvertor.convert(buffer, length-1); - /* set text in target */ + // set text in target pSci->execute(SCI_CLEARALL); pSci->execute(SCI_ADDTEXT, length, (LPARAM)UnicodeConvertor.getNewBuf()); pSci->execute(SCI_EMPTYUNDOBUFFER); pSci->execute(SCI_SETCODEPAGE); - /* set cursor position */ + // set cursor position pSci->execute(SCI_GOTOPOS); - /* clean buffer */ + // clean buffer delete [] buffer; return unicodeMode; @@ -8325,3 +8362,4 @@ void Notepad_plus::markSelectedText() _findReplaceDlg.markAll2(text2Find); } + diff --git a/PowerEditor/src/Notepad_plus.h b/PowerEditor/src/Notepad_plus.h index 896fa3f50..60feea53c 100644 --- a/PowerEditor/src/Notepad_plus.h +++ b/PowerEditor/src/Notepad_plus.h @@ -46,6 +46,7 @@ #include "RunMacroDlg.h" #include "DockingManager.h" #include "Process.h" +#include "FunctionCallTip.h" #define NOTEPAD_PP_CLASS_NAME "Notepad++" @@ -77,6 +78,9 @@ 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: @@ -173,6 +177,8 @@ private: Window *_pMainWindow; DockingManager _dockingManager; + FunctionCallTip _funcCalltip; + TiXmlNode *_nativeLang, *_toolIcons; unsigned char _mainWindowStatus; @@ -407,6 +413,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()); }; void setDisplayFormat(formatType f) { @@ -590,9 +600,11 @@ private: void activateDoc(int pos); void updateStatusBar(); + 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); bool replaceAllFiles(); diff --git a/PowerEditor/src/Notepad_plus.rc b/PowerEditor/src/Notepad_plus.rc index d70ceb2ad..e2a293134 100644 --- a/PowerEditor/src/Notepad_plus.rc +++ b/PowerEditor/src/Notepad_plus.rc @@ -300,6 +300,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Function completion", IDM_EDIT_AUTOCOMPLETE MENUITEM "Word completion", IDM_EDIT_AUTOCOMPLETE_CURRENTFILE + MENUITEM "Function parameters", IDM_EDIT_FUNCCALLTIP MENUITEM SEPARATOR MENUITEM "Set Read Only", IDM_EDIT_SETREADONLY MENUITEM "Clear Read Only Flag", IDM_EDIT_CLEARREADONLY @@ -550,3 +551,4 @@ END END + diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index 30aea5db9..88b896c6f 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -86,7 +86,8 @@ WinMenuKeyDefinition winKeyDefs[] = { //array of accelerator keys for all std me {VK_K, IDM_EDIT_BLOCK_UNCOMMENT, true, false, true, NULL}, {VK_Q, IDM_EDIT_STREAM_COMMENT, true, false, true, NULL}, {VK_SPACE, IDM_EDIT_AUTOCOMPLETE, true, false, false, NULL}, - {VK_SPACE, IDM_EDIT_AUTOCOMPLETE_CURRENTFILE, true, false, true, NULL}, + {VK_SPACE, IDM_EDIT_AUTOCOMPLETE_CURRENTFILE, false, false, true, NULL}, + {VK_SPACE, IDM_EDIT_FUNCCALLTIP, true, false, true, NULL}, {VK_R, IDM_EDIT_RTL, true, true, false, NULL}, {VK_L, IDM_EDIT_LTR, true, true, false, NULL}, @@ -2806,6 +2807,12 @@ void NppParameters::feedGUIParameters(TiXmlNode *node) if (element->Attribute("triggerFromNbChar", &i)) _nppGUI._autocFromLen = i; + + const char * funcParams = element->Attribute("funcParams"); + if (funcParams && !strcmp(funcParams, "yes")) + { + _nppGUI._funcParams = true; + } } else if (!strcmp(nm, "sessionExt")) { @@ -3402,6 +3409,8 @@ bool NppParameters::writeGUIParams() autocExist = true; element->SetAttribute("autoCAction", _nppGUI._autocStatus); element->SetAttribute("triggerFromNbChar", _nppGUI._autocFromLen); + const char * pStr = _nppGUI._funcParams?"yes":"no"; + element->SetAttribute("funcParams", pStr); } else if (!strcmp(nm, "sessionExt")) { @@ -3549,6 +3558,9 @@ bool NppParameters::writeGUIParams() GUIConfigElement->SetAttribute("name", "auto-completion"); GUIConfigElement->SetAttribute("autoCAction", _nppGUI._autocStatus); GUIConfigElement->SetAttribute("triggerFromNbChar", _nppGUI._autocFromLen); + const char * pStr = _nppGUI._funcParams?"yes":"no"; + GUIConfigElement->SetAttribute("funcParams", pStr); + autocExist = true; } if (!saveOpenFileInSameDirExist) diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 0d6f2666d..d8995e7b8 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -531,7 +531,7 @@ struct NppGUI _tabReplacedBySpace(false), _fileAutoDetection(cdEnabled), _checkHistoryFiles(true) ,_enableSmartHilite(true),\ _isMaximized(false), _isMinimizedToTray(false), _rememberLastSession(true), _backup(bak_none), _useDir(false),\ _doTaskList(true), _maitainIndent(true), _saveOpenKeepInSameDir(false), _styleMRU(true), _styleURL(0), - _autocStatus(autoc_none), _autocFromLen(1), _definedSessionExt(""), _neverUpdate(false), _doesExistUpdater(false){ + _autocStatus(autoc_none), _autocFromLen(1), _funcParams(false), _definedSessionExt(""), _neverUpdate(false), _doesExistUpdater(false){ _appPos.left = 0; _appPos.top = 0; _appPos.right = 700; @@ -592,6 +592,7 @@ struct NppGUI enum AutocStatus{autoc_none, autoc_func, autoc_word}; AutocStatus _autocStatus; size_t _autocFromLen; + bool _funcParams; string _definedSessionExt; bool _neverUpdate; diff --git a/PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp b/PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp new file mode 100644 index 000000000..143906489 --- /dev/null +++ b/PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp @@ -0,0 +1,424 @@ +//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 "FunctionCallTip.h" + + +struct Token { + char * token; + int length; + bool isIdentifier; + Token(char * tok, int len, bool isID) : token(tok), length(len), isIdentifier(isID) {}; +}; + +struct FunctionValues { + int lastIdentifier; + int lastFunctionIdentifier; + int param; + int scopeLevel; + FunctionValues() : lastIdentifier(-1), lastFunctionIdentifier(-1), param(0), scopeLevel(-1) {}; +}; + +bool stringEqualN(const char * first, const char * second, int n) { + int i = 0; + while(i < n) { //no checks for 0 as n has to take that into account (if one string is shorter, no overflow as 0 doesnt equal anything + if (first[i] != second[i]) + return false; + i++; + } + 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::updateCalltip(int ch, bool needShown) { + if (!_initialized) + return; + + if (!needShown && ch != _start && !isVisible()) //must be already visible + return; + + _curPos = _pEditView->execute(SCI_GETCURRENTPOS); + + //recalculate everything + if (!getCursorFunction()) { //cannot display calltip (anymore) + close(); + return; + } + 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; } + } + */ +} + +void FunctionCallTip::showNextOverload() { + if (!_initialized) + return; + if (!isVisible()) + return; + _currentOverload = (_currentOverload+1) % _currentNrOverloads; + showCalltip(); +} + +void FunctionCallTip::showPrevOverload() { + if (!_initialized) + return; + if (!isVisible()) + return; + _currentOverload = _currentOverload > 0?(_currentOverload-1) : _currentNrOverloads-1; + showCalltip(); +} + +void FunctionCallTip::close() { + if (!_initialized) + return; + if (!isVisible()) { + return; + } + + _pEditView->execute(SCI_CALLTIPCANCEL); + _currentOverload = 0; +} + +bool FunctionCallTip::getCursorFunction() { + int line = _pEditView->execute(SCI_LINEFROMPOSITION, _curPos); + int startpos = _pEditView->execute(SCI_POSITIONFROMLINE, line); + int endpos = _pEditView->execute(SCI_GETLINEENDPOSITION, line); + int len = endpos - startpos + 3; //also take CRLF in account, even if not there + 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]; + _pEditView->execute(SCI_GETLINE, line, (LPARAM)lineData); + + //line aquired, find the functionname + //first split line into tokens to parse + //token is identifier or some expression, whitespace is ignored + std::vector< Token > tokenVector; + int tokenLen = 0; + char ch; + for (int i = 0; i < offset; i++) { //we dont care about stuff after the offset + //tokenVector.push_back(pair(lineData+i, len)); + ch = lineData[i]; + if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' || ch == '_') { //part of identifier + tokenLen = 0; + char * begin = lineData+i; + while ( (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' || ch == '_') && i < offset) { + tokenLen++; + i++; + ch = lineData[i]; + } + tokenVector.push_back(Token(begin, tokenLen, true)); + i--; //correct overshooting of while loop + } else { + if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') { //whitespace + //do nothing + } else { + tokenLen = 1; + tokenVector.push_back(Token(lineData+i, tokenLen, false)); + } + } + } + + size_t vsize = tokenVector.size(); + //mind nested funcs, like |blblb a (x, b(), c);| + //therefore, use stack + std::vector valueVec; + + FunctionValues curValue, newValue; + int scopeLevel = 0; + for (size_t i = 0; i < vsize; i++) { + Token & curToken = tokenVector.at(i); + if (curToken.isIdentifier) { + curValue.lastIdentifier = i; + } else { + if (curToken.token[0] == _start) { + scopeLevel++; + newValue = curValue; + valueVec.push_back(newValue); //store the current settings, so when this new function doesnt happen to be the 'real' one, we can restore everything + + curValue.scopeLevel = scopeLevel; + if (i > 0 && curValue.lastIdentifier == i-1) { //identifier must be right before (, else we have some expression like "( x + y() )" + curValue.lastFunctionIdentifier = curValue.lastIdentifier; + curValue.param = 0; + } else { //some expression + curValue.lastFunctionIdentifier = -1; + } + } else if (curToken.token[0] == _param && curValue.lastFunctionIdentifier > -1) { + curValue.param++; + } else if (curToken.token[0] == _stop) { + if (scopeLevel) //scope cannot go below -1 + scopeLevel--; + if (valueVec.size() > 0) { //only pop level if scope was of actual function + curValue = valueVec.back(); + valueVec.pop_back(); + } else { + //invalidate curValue + curValue = FunctionValues(); + } + } else if (curToken.token[0] == _terminal) { + //invalidate everything + valueVec.clear(); + curValue = FunctionValues(); + } + } + } + + bool res = false; + + if (curValue.lastFunctionIdentifier == -1) { //not in direct function. Start popping the stack untill we empty it, or a func IS found + while(curValue.lastFunctionIdentifier == -1 && valueVec.size() > 0) { + curValue = valueVec.back(); + valueVec.pop_back(); + } + } + if (curValue.lastFunctionIdentifier > -1) { + Token funcToken = tokenVector.at(curValue.lastFunctionIdentifier); + funcToken.token[funcToken.length] = 0; + _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(); + } else { + res = true; + } + } + if (!res) { + reset(); + if (_funcName) { + delete [] _funcName; + _funcName = 0; + } + } + delete [] lineData; + return res; +} + +/* +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 +*/ + +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); + + //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); + } + j++; + } + } + + + delete [] fileData; + return true; +} + +void FunctionCallTip::showCalltip() { + if (_currentNrOverloads == 0) { + //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, ' + } + } + + if (_currentNrOverloads > 1) { + bytesNeeded += 24; // /\00001 of 00003\/ + } + char * textBuffer = new char[bytesNeeded]; + textBuffer[0] = 0; + + if (_currentNrOverloads > 1) { + sprintf(textBuffer, "\001%u of %u\002", _currentOverload+1, _currentNrOverloads); + } + + strcat(textBuffer, curOverloadText); + strcat(textBuffer, " "); + strcat(textBuffer, _funcName); + strcat(textBuffer, " ("); + + int highlightstart = 0; + int highlightend = 0; + for(size_t i = 0; i < nrParams; i++) { + if (i == _currentParam) { + highlightstart = strlen(textBuffer); + highlightend = highlightstart + strlen(curOverloadText+_params[_currentOverload][i]); + } + strcat(textBuffer, curOverloadText+_params[_currentOverload][i]); + if (i < nrParams-1) + strcat(textBuffer, ", "); + } + + strcat(textBuffer, ")"); + + if (isVisible()) + _pEditView->execute(SCI_CALLTIPCANCEL); + else + _startPos = _curPos; + _pEditView->execute(SCI_CALLTIPSHOW, _startPos, (LPARAM)textBuffer); + + if (highlightstart != highlightend) { + _pEditView->execute(SCI_CALLTIPSETHLT, highlightstart, highlightend); + } + + delete [] textBuffer; +} + +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(); + _pEditView = NULL; + _currentOverload = 0; + _currentParam = 0; + _initialized = false; +} + diff --git a/PowerEditor/src/ScitillaComponent/FunctionCallTip.h b/PowerEditor/src/ScitillaComponent/FunctionCallTip.h new file mode 100644 index 000000000..a0ffab4d9 --- /dev/null +++ b/PowerEditor/src/ScitillaComponent/FunctionCallTip.h @@ -0,0 +1,62 @@ +//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 FUNCTIONCALLTIP_H +#define FUNCTIONCALLTIP_H + +#include "ScintillaEditView.h" + + +class FunctionCallTip { +public: + FunctionCallTip() : _pEditView(NULL), _langName(NULL), _currentOverloads(NULL), _funcName(NULL), _params(NULL), _initialized(false), + _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 close(); //Close calltip if visible + +private: + char * _langName; //current language + ScintillaEditView * _pEditView; //Scintilla to display calltip in + bool _initialized; + + 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 + int _currentNrOverloads; //current amount of overloads + int _currentOverload; //current chosen overload + int _currentParam; //current highlighted param + + char _start; + char _stop; + char _param; + 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 + 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/WinControls/Preference/preference.rc b/PowerEditor/src/WinControls/Preference/preference.rc index b82fbd4c2..e1305840b 100644 --- a/PowerEditor/src/WinControls/Preference/preference.rc +++ b/PowerEditor/src/WinControls/Preference/preference.rc @@ -217,7 +217,7 @@ BEGIN RTEXT "Directory :",IDD_BACKUPDIR_STATIC,66,67,40,8 EDITTEXT IDC_BACKUPDIR_EDIT,113,65,179,14,ES_AUTOHSCROLL PUSHBUTTON "...",IDD_BACKUPDIR_BROWSE_BUTTON,299,65,16,14 - GROUPBOX "Auto-completion",IDD_AUTOC_GRPSTATIC,46,103,289,59,BS_CENTER + GROUPBOX "Auto-completion",IDD_AUTOC_GRPSTATIC,46,103,289,73,BS_CENTER CONTROL "Enable Auto-completion on each input",IDD_AUTOC_ENABLECHECK, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,51,114,150,10 CONTROL "Function completion",IDD_AUTOC_FUNCRADIO,"Button",BS_AUTORADIOBUTTON | WS_GROUP,78,128,145,10 @@ -226,4 +226,6 @@ BEGIN CTEXT "1",IDD_AUTOC_STATIC_N,259,114,8,8 LTEXT "th characters",IDD_AUTOC_STATIC_CHAR,273,114,57,8 LTEXT "Valid value : 1 - 9",IDD_AUTOC_STATIC_NOTE,238,124,93,8 + CONTROL "Show function parameters on input",IDD_FUNC_CHECK, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,51,156,160,10 END diff --git a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp index 8f1c1ce51..723cf00e9 100644 --- a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp +++ b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp @@ -1365,6 +1365,7 @@ BOOL CALLBACK BackupDlg::run_dlgProc(UINT Message, WPARAM wParam, LPARAM lParam) ::SendDlgItemMessage(_hSelf, IDD_AUTOC_ENABLECHECK, BM_SETCHECK, isEnableAutoC?BST_CHECKED:BST_UNCHECKED, 0); ::SendDlgItemMessage(_hSelf, IDD_AUTOC_FUNCRADIO, BM_SETCHECK, nppGUI._autocStatus == nppGUI.autoc_func?BST_CHECKED:BST_UNCHECKED, 0); ::SendDlgItemMessage(_hSelf, IDD_AUTOC_WORDRADIO, BM_SETCHECK, nppGUI._autocStatus == nppGUI.autoc_word?BST_CHECKED:BST_UNCHECKED, 0); + ::SendDlgItemMessage(_hSelf, IDD_FUNC_CHECK, BM_SETCHECK, nppGUI._funcParams?BST_CHECKED:BST_UNCHECKED, 0); if (!isEnableAutoC) { ::EnableWindow(::GetDlgItem(_hSelf, IDD_AUTOC_FUNCRADIO), FALSE); @@ -1463,6 +1464,11 @@ BOOL CALLBACK BackupDlg::run_dlgProc(UINT Message, WPARAM wParam, LPARAM lParam) nppGUI._autocStatus = nppGUI.autoc_word; return TRUE; } + case IDD_FUNC_CHECK : + { + nppGUI._funcParams = (BST_CHECKED == ::SendDlgItemMessage(_hSelf, IDD_FUNC_CHECK, BM_GETCHECK, 0, 0)); + return TRUE; + } case IDM_SETTING_AUTOCNBCHAR : { diff --git a/PowerEditor/src/WinControls/Preference/preference_rc.h b/PowerEditor/src/WinControls/Preference/preference_rc.h index 7ca182883..f48cae217 100644 --- a/PowerEditor/src/WinControls/Preference/preference_rc.h +++ b/PowerEditor/src/WinControls/Preference/preference_rc.h @@ -178,3 +178,4 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #define IDD_AUTOC_STATIC_N (IDD_PREFERENCE_BACKUP_BOX + 12) #define IDD_AUTOC_STATIC_CHAR (IDD_PREFERENCE_BACKUP_BOX + 13) #define IDD_AUTOC_STATIC_NOTE (IDD_PREFERENCE_BACKUP_BOX + 14) + #define IDD_FUNC_CHECK (IDD_PREFERENCE_BACKUP_BOX + 15) diff --git a/PowerEditor/src/menuCmdID.h b/PowerEditor/src/menuCmdID.h index d6cf1aadf..0c21e817d 100644 --- a/PowerEditor/src/menuCmdID.h +++ b/PowerEditor/src/menuCmdID.h @@ -79,6 +79,7 @@ #define IDM_EDIT_AUTOCOMPLETE (50000+0) #define IDM_EDIT_AUTOCOMPLETE_CURRENTFILE (50000+1) + #define IDM_EDIT_FUNCCALLTIP (50000+2) //Belong to MENU FILE #define IDM_OPEN_ALL_RECENT_FILE (IDM_EDIT + 40) diff --git a/PowerEditor/visual.net/notepadPlus.vcproj b/PowerEditor/visual.net/notepadPlus.vcproj index ee001250c..9b0ed7760 100644 --- a/PowerEditor/visual.net/notepadPlus.vcproj +++ b/PowerEditor/visual.net/notepadPlus.vcproj @@ -263,6 +263,10 @@ RelativePath="..\src\ScitillaComponent\FindReplaceDlg.cpp" > + + @@ -512,6 +516,10 @@ RelativePath="..\src\ScitillaComponent\FindReplaceDlg.h" > + + @@ -576,10 +584,6 @@ RelativePath="..\src\MISC\RegExt\regExtDlgRc.h" > - - @@ -588,6 +592,10 @@ RelativePath="..\src\resource.h" > + +