Patch #731613: debugger tab-completion (thanks, Willem!)

svn-id: r7293
This commit is contained in:
Max Horn 2003-05-03 21:49:19 +00:00
parent fc9100c841
commit 975d325a92
4 changed files with 117 additions and 2 deletions

View File

@ -159,7 +159,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
// comply to the C++ standard, so we can't use a dynamic sized stack array.
char *str = new char[len + 1];
// Copy the user intput to str
// Copy the user input to str
for (i = 0; i < len; i++)
str[i] = _buffer[(_promptStartPos + i) % kBufferSize];
str[len] = '\0';
@ -197,6 +197,33 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
scrollToCurrent();
draw(); // FIXME - not nice to redraw the full console just for one char!
break;
case 9: // tab
{
if (_completionCallbackProc) {
int len = _currentPos - _promptStartPos;
assert(len >= 0);
char *str = new char[len + 1];
// Copy the user input to str
for (i = 0; i < len; i++)
str[i] = _buffer[(_promptStartPos + i) % kBufferSize];
str[len] = '\0';
char *completion = 0;
if ((*_completionCallbackProc)(this, str, completion,
_callbackRefCon))
{
if (_caretVisible)
drawCaret(true);
insertIntoPrompt(completion);
scrollToCurrent();
draw();
delete[] completion;
}
delete[] str;
}
break;
}
case 127:
killChar();
draw();
@ -255,6 +282,18 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
}
}
void ConsoleDialog::insertIntoPrompt(const char* str)
{
unsigned int l = strlen(str);
for (int i = _promptEndPos-1; i >= _currentPos; i--)
_buffer[(i + l) % kBufferSize] =
_buffer[i % kBufferSize];
for (unsigned int j = 0; j < l; ++j) {
_promptEndPos++;
putcharIntern(str[j]);
}
}
void ConsoleDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kSetPositionCmd:

View File

@ -39,6 +39,7 @@ class ScrollBarWidget;
class ConsoleDialog : public Dialog {
public:
typedef bool (*InputCallbackProc)(ConsoleDialog *console, const char *input, void *refCon);
typedef bool (*CompletionCallbackProc)(ConsoleDialog* console, const char *input, char*& completion, void *refCon);
protected:
char _buffer[kBufferSize];
@ -63,6 +64,10 @@ protected:
InputCallbackProc _callbackProc;
void *_callbackRefCon;
// _completionCallbackProc is called when tab is pressed
CompletionCallbackProc _completionCallbackProc;
void *_completionCallbackRefCon;
char _history[kHistorySize][kLineBufferSize];
int _historySize;
int _historyIndex;
@ -88,10 +93,15 @@ public:
_callbackProc = proc;
_callbackRefCon = refCon;
}
void setCompletionCallback(CompletionCallbackProc proc, void *refCon) {
_completionCallbackProc = proc;
_completionCallbackRefCon = refCon;
}
protected:
void drawCaret(bool erase);
void putcharIntern(int c);
void insertIntoPrompt(const char *str);
void print(const char *str);
void nextLine();
void updateScrollBar();

View File

@ -107,8 +107,10 @@ void ScummDebugger::attach(Scumm *s, char *entry) {
void ScummDebugger::detach() {
#ifdef USE_CONSOLE
if (_s->_debuggerDialog)
if (_s->_debuggerDialog) {
_s->_debuggerDialog->setInputeCallback(0, 0);
_s->_debuggerDialog->setCompletionCallback(0, 0);
}
#endif
_s->_debugger = NULL;
@ -144,6 +146,14 @@ bool ScummDebugger::debuggerInputCallback(ConsoleDialog *console, const char *in
return debugger->RunCommand((char*)input);
}
bool ScummDebugger::debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon) {
ScummDebugger *debugger = (ScummDebugger *)refCon;
return debugger->TabComplete(input, completion);
}
#endif
///////////////////////////////////////////////////
@ -184,6 +194,8 @@ void ScummDebugger::enter() {
}
_s->_debuggerDialog->setInputeCallback(debuggerInputCallback, this);
_s->_debuggerDialog->setCompletionCallback(debuggerCompletionCallback,
this);
_s->_debuggerDialog->runModal();
#else
printf("Debugger entered, please switch to this console for input.\n");
@ -783,3 +795,53 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) {
return true;
}
// returns true if something has been completed
// completion has to be delete[]-ed then
bool ScummDebugger::TabComplete(const char *input, char*& completion) {
// very basic tab completion
// for now it just supports command completions
// adding completions of command parameters would be nice (but hard) :-)
// maybe also give a list of possible command completions?
// (but this will require changes to console)
if (strchr(input, ' '))
return false; // already finished the first word
unsigned int inputlen = strlen(input);
unsigned int matchlen = 0;
char match[30]; // the max. command name is 30 chars
for(int i=0; i < _dcmd_count; i++) {
if (!strncmp(_dcmds[i].name, input, inputlen)) {
unsigned int commandlen = strlen(_dcmds[i].name);
if (commandlen == inputlen) { // perfect match
return false;
}
if (commandlen > inputlen) { // possible match
// no previous match
if (matchlen == 0) {
strcpy(match, _dcmds[i].name + inputlen);
matchlen = commandlen - inputlen;
} else {
// take common prefix of previous match and this command
unsigned int j;
for (j = 0; j < matchlen; j++) {
if (match[j] != _dcmds[i].name[inputlen + j]) break;
}
matchlen = j;
}
}
}
}
if (matchlen == 0)
return false;
completion = new char[matchlen+1];
memcpy(completion, match, matchlen);
completion[matchlen+1] = 0;
return true;
}

View File

@ -96,7 +96,11 @@ protected:
#ifdef USE_CONSOLE
static bool debuggerInputCallback(ConsoleDialog *console, const char *input, void *refCon);
static bool debuggerCompletionCallback(ConsoleDialog *console, const char *input, char*& completion, void *refCon);
#endif
bool TabComplete(const char *input, char*& completion);
};
#endif