Fix case sensitivity bug in Calltips
Single existing file on commandline will not be interpreted but opened directly git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository@253 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
parent
4c138a5518
commit
ec66a22890
|
@ -249,13 +249,16 @@ bool AutoCompletion::setLanguage(LangType language) {
|
|||
_funcCalltip._stop = ')';
|
||||
_funcCalltip._param = ',';
|
||||
_funcCalltip._terminal = ';';
|
||||
_funcCalltip._ignoreCase = true;
|
||||
|
||||
TiXmlElement * pElem = pAutoNode->FirstChildElement("Environment");
|
||||
if (pElem) {
|
||||
const char * val = 0;
|
||||
val = pElem->Attribute("ignoreCase");
|
||||
if (val && !strcmp(val, "no"))
|
||||
if (val && !strcmp(val, "no")) {
|
||||
_ignoreCase = false;
|
||||
_funcCalltip._ignoreCase = false;
|
||||
}
|
||||
val = pElem->Attribute("startFunc");
|
||||
if (val && val[0])
|
||||
_funcCalltip._start = val[0];
|
||||
|
|
|
@ -33,15 +33,38 @@ struct FunctionValues {
|
|||
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++;
|
||||
inline bool lower(char c) {
|
||||
return (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
inline bool match(char c1, char c2) {
|
||||
if (c1 == c2) return true;
|
||||
if (lower(c1))
|
||||
return ((c1-32) == c2);
|
||||
if (lower(c2))
|
||||
return ((c2-32) == c1);
|
||||
return false;
|
||||
}
|
||||
|
||||
//test string case insensitive ala Scintilla
|
||||
//0 if equal, <0 of before, >0 if after (name1 that is)
|
||||
int testNameNoCase(const char * name1, const char * name2, int len = -1) {
|
||||
if (len == -1) {
|
||||
len = 1024; //magic value, but it probably fails way before it reaches this
|
||||
}
|
||||
return true;
|
||||
};
|
||||
int i = 0;
|
||||
while(match(name1[i], name2[i])) {
|
||||
if (name1[i] == 0 || i == len) {
|
||||
return 0; //equal
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
int subs1 = lower(name1[i])?32:0;
|
||||
int subs2 = lower(name2[i])?32:0;
|
||||
|
||||
return ( (name1[i]-subs1) - (name2[i]-subs2) );
|
||||
}
|
||||
|
||||
void FunctionCallTip::setLanguageXML(TiXmlElement * pXmlKeyword) {
|
||||
if (isVisible())
|
||||
|
@ -172,7 +195,7 @@ bool FunctionCallTip::getCursorFunction() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool res = false;
|
||||
|
||||
if (curValue.lastFunctionIdentifier == -1) { //not in direct function. Start popping the stack untill we empty it, or a func IS found
|
||||
|
@ -186,19 +209,24 @@ bool FunctionCallTip::getCursorFunction() {
|
|||
funcToken.token[funcToken.length] = 0;
|
||||
_currentParam = curValue.param;
|
||||
|
||||
if (!_funcName || !stringEqualN(_funcName, funcToken.token, strlen(_funcName))) { //check if we need to reload data
|
||||
res = loadFunction(funcToken.token);
|
||||
bool same = false;
|
||||
if (_funcName) {
|
||||
if(_ignoreCase)
|
||||
same = testNameNoCase(_funcName, funcToken.token, strlen(_funcName)) == 0;
|
||||
else
|
||||
same = strncmp(_funcName, funcToken.token, strlen(_funcName)) == 0;
|
||||
}
|
||||
if (!same) { //check if we need to reload data
|
||||
if (_funcName) {
|
||||
delete [] _funcName;
|
||||
}
|
||||
_funcName = new char[funcToken.length+1];
|
||||
strcpy(_funcName, funcToken.token);
|
||||
res = loadFunction();
|
||||
} else {
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
reset();
|
||||
if (_funcName) {
|
||||
delete [] _funcName;
|
||||
_funcName = 0;
|
||||
}
|
||||
}
|
||||
delete [] lineData;
|
||||
return res;
|
||||
}
|
||||
|
@ -206,8 +234,8 @@ bool FunctionCallTip::getCursorFunction() {
|
|||
/*
|
||||
Find function in XML structure and parse it
|
||||
*/
|
||||
|
||||
bool FunctionCallTip::loadFunction(const char * nameToFind) {
|
||||
bool FunctionCallTip::loadFunction() {
|
||||
reset(); //set everything back to 0
|
||||
//The functions should be ordered, but linear search because we cant access like array
|
||||
_curFunction = NULL;
|
||||
//Iterate through all keywords and find the correct function keyword
|
||||
|
@ -217,7 +245,11 @@ bool FunctionCallTip::loadFunction(const char * nameToFind) {
|
|||
name = funcNode->Attribute("name");
|
||||
if (!name) //malformed node
|
||||
continue;
|
||||
int compVal = strcmp(name, nameToFind);
|
||||
int compVal = 0;
|
||||
if (_ignoreCase)
|
||||
compVal = testNameNoCase(name, _funcName); //strcmpi doesnt work in this case
|
||||
else
|
||||
compVal = strcmp(name, _funcName);
|
||||
if (!compVal) { //found it?
|
||||
const char * val = funcNode->Attribute("func");
|
||||
if (val)
|
||||
|
@ -240,12 +272,6 @@ bool FunctionCallTip::loadFunction(const char * nameToFind) {
|
|||
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");
|
||||
|
@ -255,6 +281,13 @@ bool FunctionCallTip::loadFunction(const char * nameToFind) {
|
|||
if (!retVal)
|
||||
continue; //malformed node
|
||||
_retVals.push_back(retVal);
|
||||
|
||||
const char * description = overloadNode->Attribute("descr");
|
||||
if (description)
|
||||
_descriptions.push_back(description);
|
||||
else
|
||||
_descriptions.push_back(""); //"no description available"
|
||||
|
||||
paramNode = overloadNode->FirstChildElement("Param");
|
||||
for (; paramNode ; paramNode = paramNode->NextSiblingElement("Param") ) {
|
||||
const char * param = paramNode->Attribute("name");
|
||||
|
@ -296,8 +329,15 @@ void FunctionCallTip::showCalltip() {
|
|||
}
|
||||
}
|
||||
const char * curRetValText = _retVals.at(_currentOverload);
|
||||
const char * curDescriptionText = _descriptions.at(_currentOverload);
|
||||
bool hasDescr = true;
|
||||
if (!curDescriptionText[0])
|
||||
hasDescr = false;
|
||||
|
||||
int bytesNeeded = strlen(curRetValText) + strlen(_funcName) + 5;//'retval funcName (params)\0'
|
||||
if (hasDescr)
|
||||
bytesNeeded += strlen(curDescriptionText);
|
||||
|
||||
size_t nrParams = params.size();
|
||||
for(size_t i = 0; i < nrParams; i++) {
|
||||
bytesNeeded += strlen(params.at(i)) + 2; //'param, '
|
||||
|
@ -332,6 +372,10 @@ void FunctionCallTip::showCalltip() {
|
|||
}
|
||||
|
||||
strcat(textBuffer, ")");
|
||||
if (hasDescr) {
|
||||
strcat(textBuffer, "\n");
|
||||
strcat(textBuffer, curDescriptionText);
|
||||
}
|
||||
|
||||
if (isVisible())
|
||||
_pEditView->execute(SCI_CALLTIPCANCEL);
|
||||
|
@ -351,13 +395,16 @@ void FunctionCallTip::reset() {
|
|||
_currentParam = 0;
|
||||
_curPos = 0;
|
||||
_startPos = 0;
|
||||
_overloads.clear();
|
||||
_currentNrOverloads = 0;
|
||||
_retVals.clear();
|
||||
_descriptions.clear();
|
||||
}
|
||||
|
||||
void FunctionCallTip::cleanup() {
|
||||
reset();
|
||||
_overloads.clear();
|
||||
_currentNrOverloads = 0;
|
||||
_retVals.clear();
|
||||
if (_funcName)
|
||||
delete [] _funcName;
|
||||
_funcName = 0;
|
||||
_pEditView = NULL;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
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(';')
|
||||
_start('('), _stop(')'), _param(','), _terminal(';'), _ignoreCase(true)
|
||||
{};
|
||||
~FunctionCallTip() {/* cleanup(); */};
|
||||
void setLanguageXML(TiXmlElement * pXmlKeyword); //set calltip keyword node
|
||||
|
@ -47,9 +47,10 @@ private:
|
|||
|
||||
TiXmlElement * _curFunction; //current function element
|
||||
//cache some XML values n stuff
|
||||
const char * _funcName; //name of function
|
||||
char * _funcName; //name of function
|
||||
stringVec _retVals; //vector of overload return values/types
|
||||
vector<stringVec> _overloads; //vector of overload params (=vector)
|
||||
stringVec _descriptions; //vecotr of function descriptions
|
||||
int _currentNrOverloads; //current amount of overloads
|
||||
int _currentOverload; //current chosen overload
|
||||
int _currentParam; //current highlighted param
|
||||
|
@ -58,9 +59,10 @@ private:
|
|||
char _stop;
|
||||
char _param;
|
||||
char _terminal;
|
||||
bool _ignoreCase;
|
||||
|
||||
bool getCursorFunction(); //retrieve data about function at cursor. Returns true if a function was found. Calls loaddata if needed
|
||||
bool loadFunction(const char * nameToFind); //returns true if the function can be found
|
||||
bool loadFunction(); //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
|
||||
|
|
|
@ -19,11 +19,27 @@
|
|||
#include "SysMsg.h"
|
||||
#include "Process.h"
|
||||
|
||||
#include <exception> //default C++ esception
|
||||
#include <exception> //default C++ exception
|
||||
#include "Win32Exception.h" //Win32 exception
|
||||
|
||||
typedef std::vector<const char*> ParamVector;
|
||||
|
||||
bool checkSingleFile(const char * commandLine) {
|
||||
char fullpath[MAX_PATH];
|
||||
::GetFullPathName(commandLine, MAX_PATH, fullpath, NULL);
|
||||
if (::PathFileExists(fullpath)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void parseCommandLine(char * commandLine, ParamVector & paramVector) {
|
||||
bool isFile = checkSingleFile(commandLine); //if the commandline specifies only a file, open it as such
|
||||
if (isFile) {
|
||||
paramVector.push_back(commandLine);
|
||||
return;
|
||||
}
|
||||
bool isInFile = false;
|
||||
bool isInWhiteSpace = true;
|
||||
paramVector.clear();
|
||||
|
@ -153,7 +169,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, int nCmdSh
|
|||
} else {
|
||||
quotFileName += currentFile;
|
||||
}
|
||||
quotFileName += "\"";
|
||||
quotFileName += "\" ";
|
||||
}
|
||||
if ((!isMultiInst) && (!TheFirstOne))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue