mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-01 05:11:09 +00:00
parent
fc9100c841
commit
975d325a92
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user