mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-22 05:14:41 +02:00
[NEW_FEATURE] Add Calltip capacity.
git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository@203 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
parent
cfdbd4b5ef
commit
6b5aa92d6e
@ -706,12 +706,18 @@ bool Notepad_plus::doOpen(const char *fileName, bool isReadOnly)
|
||||
size_t lenFile = fread(data, 1, sizeof(data), fp);
|
||||
bool isNotEmpty = (lenFile != 0);
|
||||
|
||||
//try {
|
||||
while (lenFile > 0)
|
||||
{
|
||||
lenFile = UnicodeConvertor.convert(data, lenFile);
|
||||
_pEditView->execute(SCI_ADDTEXT, lenFile, reinterpret_cast<LPARAM>(UnicodeConvertor.getNewBuf()));
|
||||
lenFile = int(fread(data, 1, sizeof(data), fp));
|
||||
}
|
||||
/*}
|
||||
catch (...)
|
||||
{
|
||||
::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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
424
PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp
Normal file
424
PowerEditor/src/ScitillaComponent/FunctionCallTip.cpp
Normal file
@ -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<FunctionValues> 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<int, int> > 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<int, int>(argStart, location-argStart));
|
||||
location++; //skip newline
|
||||
}
|
||||
|
||||
_currentNrOverloads = overloadLocations.size();
|
||||
_currentOverloads = new char*[_currentNrOverloads];
|
||||
_params = new vector<int>[_currentNrOverloads];
|
||||
|
||||
int j = 0;
|
||||
for(int i = 0; i < _currentNrOverloads; i++) {
|
||||
pair<int, int> & 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;
|
||||
}
|
||||
|
62
PowerEditor/src/ScitillaComponent/FunctionCallTip.h
Normal file
62
PowerEditor/src/ScitillaComponent/FunctionCallTip.h
Normal file
@ -0,0 +1,62 @@
|
||||
//this file is part of notepad++
|
||||
//Copyright (C)2008 Harry Bruin <harrybharry@users.sourceforge.net>
|
||||
//
|
||||
//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<int> * _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
|
@ -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
|
||||
|
@ -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 :
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -263,6 +263,10 @@
|
||||
RelativePath="..\src\ScitillaComponent\FindReplaceDlg.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ScitillaComponent\FunctionCallTip.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ScitillaComponent\GoToLineDlg.cpp"
|
||||
>
|
||||
@ -512,6 +516,10 @@
|
||||
RelativePath="..\src\ScitillaComponent\FindReplaceDlg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ScitillaComponent\FunctionCallTip.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\ScitillaComponent\GoToLineDlg.h"
|
||||
>
|
||||
@ -576,10 +584,6 @@
|
||||
RelativePath="..\src\MISC\RegExt\regExtDlgRc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\WinControls\Preference\resource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\MISC\RegExt\resource.h"
|
||||
>
|
||||
@ -588,6 +592,10 @@
|
||||
RelativePath="..\src\resource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\WinControls\Preference\resource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\WinControls\StaticDialog\RunDlg\RunDlg.h"
|
||||
>
|
||||
|
Loading…
x
Reference in New Issue
Block a user