1
0
Fork 0

DBG: added command auto-completion

BRIDGE: added command auto-completion
GUI: added command auto-completion
GUI: added HistoryLineEdit in the Goto Dialog
This commit is contained in:
Mr. eXoDia 2014-05-21 00:22:49 +02:00
parent 6736028479
commit 5777b7364f
24 changed files with 357 additions and 166 deletions

View File

@ -829,6 +829,21 @@ BRIDGE_IMPEXP bool GuiGetLineWindow(const char* title, char* text)
return (bool)(duint)_gui_sendmessage(GUI_GETLINE_WINDOW, (void*)title, text);
}
BRIDGE_IMPEXP void GuiAutoCompleteAddCmd(const char* cmd)
{
_gui_sendmessage(GUI_AUTOCOMPLETE_ADDCMD, (void*)cmd, 0);
}
BRIDGE_IMPEXP void GuiAutoCompleteDelCmd(const char* cmd)
{
_gui_sendmessage(GUI_AUTOCOMPLETE_DELCMD, (void*)cmd, 0);
}
BRIDGE_IMPEXP void GuiAutoCompleteClearAll()
{
_gui_sendmessage(GUI_AUTOCOMPLETE_CLEARALL, 0, 0);
}
//Main
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{

View File

@ -549,7 +549,10 @@ enum GUIMSG
GUI_MENU_CLEAR, // param1=int hMenu, param2=unused
GUI_SELECTION_GET, // param1=int hWindow, param2=SELECTIONDATA* selection
GUI_SELECTION_SET, // param1=int hWindow, param2=const SELECTIONDATA* selection
GUI_GETLINE_WINDOW // param1=const char* title, param2=char* text
GUI_GETLINE_WINDOW, // param1=const char* title, param2=char* text
GUI_AUTOCOMPLETE_ADDCMD, // param1=const char* cmd, param2=ununsed
GUI_AUTOCOMPLETE_DELCMD, // param1=const char* cmd, param2=ununsed
GUI_AUTOCOMPLETE_CLEARALL // param1=ununsed, param2=unused
};
//GUI structures
@ -613,6 +616,9 @@ BRIDGE_IMPEXP void GuiMenuClear(int hMenu);
BRIDGE_IMPEXP bool GuiSelectionGet(int hWindow, SELECTIONDATA* selection);
BRIDGE_IMPEXP bool GuiSelectionSet(int hWindow, const SELECTIONDATA* selection);
BRIDGE_IMPEXP bool GuiGetLineWindow(const char* title, char* text);
BRIDGE_IMPEXP void GuiAutoCompleteAddCmd(const char* cmd);
BRIDGE_IMPEXP void GuiAutoCompleteDelCmd(const char* cmd);
BRIDGE_IMPEXP void GuiAutoCompleteClearAll();
#ifdef __cplusplus
}

View File

@ -99,6 +99,22 @@ bool dbgisignoredexception(unsigned int exception)
return false;
}
bool dbgcmdnew(const char* name, CBCOMMAND cbCommand, bool debugonly)
{
if(!cmdnew(dbggetcommandlist(), name, cbCommand, debugonly))
return false;
GuiAutoCompleteAddCmd(name);
return true;
}
bool dbgcmddel(const char* name)
{
if(!cmddel(dbggetcommandlist(), name))
return false;
GuiAutoCompleteDelCmd(name);
return true;
}
void DebugUpdateGui(uint disasm_addr, bool stack)
{
uint cip=GetContextData(UE_CIP);

View File

@ -29,6 +29,9 @@ void dbgsetskipexceptions(bool skip);
void dbgclearignoredexceptions();
void dbgaddignoredexception(ExceptionRange range);
bool dbgisignoredexception(unsigned int exception);
bool dbgcmdnew(const char* name, CBCOMMAND cbCommand, bool debugonly);
bool dbgcmddel(const char* name);
//callbacks
CMDRESULT cbDebugInit(int argc, char* argv[]);
CMDRESULT cbStopDebug(int argc, char* argv[]);

View File

@ -1,6 +1,6 @@
#include "plugin_loader.h"
#include "console.h"
#include "command.h"
#include "debugger.h"
#include "x64_dbg.h"
static std::vector<PLUG_DATA> pluginList;
@ -105,7 +105,7 @@ static void plugincmdunregisterall(int pluginHandle)
{
if(pluginCommandList.at(i).pluginHandle==pluginHandle)
{
cmddel(dbggetcommandlist(), pluginCommandList.at(i).command);
dbgcmddel(pluginCommandList.at(i).command);
pluginCommandList.erase(pluginCommandList.begin()+i);
}
}
@ -172,7 +172,7 @@ bool plugincmdregister(int pluginHandle, const char* command, CBPLUGINCOMMAND cb
PLUG_COMMAND plugCmd;
plugCmd.pluginHandle=pluginHandle;
strcpy(plugCmd.command, command);
if(!cmdnew(dbggetcommandlist(), command, (CBCOMMAND)cbCommand, debugonly))
if(!dbgcmdnew(command, (CBCOMMAND)cbCommand, debugonly))
return false;
pluginCommandList.push_back(plugCmd);
dprintf("[PLUGIN] command \"%s\" registered!\n", command);
@ -188,7 +188,7 @@ bool plugincmdunregister(int pluginHandle, const char* command)
{
if(pluginCommandList.at(i).pluginHandle==pluginHandle and !strcmp(pluginCommandList.at(i).command, command))
{
if(!cmddel(dbggetcommandlist(), command))
if(!dbgcmddel(command))
return false;
pluginCommandList.erase(pluginCommandList.begin()+i);
dprintf("[PLUGIN] command \"%s\" unregistered!\n", command);

View File

@ -49,108 +49,108 @@ static void registercommands()
COMMAND* cmd=command_list=cmdinit();
//debug control
cmdnew(cmd, "InitDebug\1init\1initdbg", cbDebugInit, false); //init debugger arg1:exefile,[arg2:commandline]
cmdnew(cmd, "StopDebug\1stop\1dbgstop", cbStopDebug, true); //stop debugger
cmdnew(cmd, "AttachDebugger\1attach", cbDebugAttach, false); //attach
cmdnew(cmd, "DetachDebugger\1detach", cbDebugDetach, true); //detach
cmdnew(cmd, "run\1go\1r\1g", cbDebugRun, true); //unlock WAITID_RUN
cmdnew(cmd, "erun\1egun\1er\1eg", cbDebugErun, true); //run + skip first chance exceptions
cmdnew(cmd, "pause", cbDebugPause, true); //pause debugger
cmdnew(cmd, "StepInto\1sti", cbDebugStepInto, true); //StepInto
cmdnew(cmd, "eStepInto\1esti", cbDebugeStepInto, true); //StepInto + skip first chance exceptions
cmdnew(cmd, "StepOver\1step\1sto\1st", cbDebugStepOver, true); //StepOver
cmdnew(cmd, "eStepOver\1estep\1esto\1est", cbDebugeStepOver, true); //StepOver + skip first chance exceptions
cmdnew(cmd, "SingleStep\1sstep\1sst", cbDebugSingleStep, true); //SingleStep arg1:count
cmdnew(cmd, "eSingleStep\1esstep\1esst", cbDebugeSingleStep, true); //SingleStep arg1:count + skip first chance exceptions
cmdnew(cmd, "StepOut\1rtr", cbDebugRtr, true); //rtr
cmdnew(cmd, "eStepOut\1ertr", cbDebugeRtr, true); //rtr + skip first chance exceptions
dbgcmdnew("InitDebug\1init\1initdbg", cbDebugInit, false); //init debugger arg1:exefile,[arg2:commandline]
dbgcmdnew("StopDebug\1stop\1dbgstop", cbStopDebug, true); //stop debugger
dbgcmdnew("AttachDebugger\1attach", cbDebugAttach, false); //attach
dbgcmdnew("DetachDebugger\1detach", cbDebugDetach, true); //detach
dbgcmdnew("run\1go\1r\1g", cbDebugRun, true); //unlock WAITID_RUN
dbgcmdnew("erun\1egun\1er\1eg", cbDebugErun, true); //run + skip first chance exceptions
dbgcmdnew("pause", cbDebugPause, true); //pause debugger
dbgcmdnew("StepInto\1sti", cbDebugStepInto, true); //StepInto
dbgcmdnew("eStepInto\1esti", cbDebugeStepInto, true); //StepInto + skip first chance exceptions
dbgcmdnew("StepOver\1step\1sto\1st", cbDebugStepOver, true); //StepOver
dbgcmdnew("eStepOver\1estep\1esto\1est", cbDebugeStepOver, true); //StepOver + skip first chance exceptions
dbgcmdnew("SingleStep\1sstep\1sst", cbDebugSingleStep, true); //SingleStep arg1:count
dbgcmdnew("eSingleStep\1esstep\1esst", cbDebugeSingleStep, true); //SingleStep arg1:count + skip first chance exceptions
dbgcmdnew("StepOut\1rtr", cbDebugRtr, true); //rtr
dbgcmdnew("eStepOut\1ertr", cbDebugeRtr, true); //rtr + skip first chance exceptions
//breakpoints
cmdnew(cmd, "bplist", cbDebugBplist, true); //breakpoint list
cmdnew(cmd, "SetBPXOptions\1bptype", cbDebugSetBPXOptions, false); //breakpoint type
cmdnew(cmd, "SetBPX\1bp\1bpx", cbDebugSetBPX, true); //breakpoint
cmdnew(cmd, "DeleteBPX\1bpc\1bc", cbDebugDeleteBPX, true); //breakpoint delete
cmdnew(cmd, "EnableBPX\1bpe\1be", cbDebugEnableBPX, true); //breakpoint enable
cmdnew(cmd, "DisableBPX\1bpd\1bd", cbDebugDisableBPX, true); //breakpoint disable
cmdnew(cmd, "SetHardwareBreakpoint\1bph\1bphws", cbDebugSetHardwareBreakpoint, true); //hardware breakpoint
cmdnew(cmd, "DeleteHardwareBreakpoint\1bphc\1bphwc", cbDebugDeleteHardwareBreakpoint, true); //delete hardware breakpoint
cmdnew(cmd, "SetMemoryBPX\1membp\1bpm", cbDebugSetMemoryBpx, true); //SetMemoryBPX
cmdnew(cmd, "DeleteMemoryBPX\1membpc\1bpmc", cbDebugDeleteMemoryBreakpoint, true); //delete memory breakpoint
dbgcmdnew("bplist", cbDebugBplist, true); //breakpoint list
dbgcmdnew("SetBPXOptions\1bptype", cbDebugSetBPXOptions, false); //breakpoint type
dbgcmdnew("SetBPX\1bp\1bpx", cbDebugSetBPX, true); //breakpoint
dbgcmdnew("DeleteBPX\1bpc\1bc", cbDebugDeleteBPX, true); //breakpoint delete
dbgcmdnew("EnableBPX\1bpe\1be", cbDebugEnableBPX, true); //breakpoint enable
dbgcmdnew("DisableBPX\1bpd\1bd", cbDebugDisableBPX, true); //breakpoint disable
dbgcmdnew("SetHardwareBreakpoint\1bph\1bphws", cbDebugSetHardwareBreakpoint, true); //hardware breakpoint
dbgcmdnew("DeleteHardwareBreakpoint\1bphc\1bphwc", cbDebugDeleteHardwareBreakpoint, true); //delete hardware breakpoint
dbgcmdnew("SetMemoryBPX\1membp\1bpm", cbDebugSetMemoryBpx, true); //SetMemoryBPX
dbgcmdnew("DeleteMemoryBPX\1membpc\1bpmc", cbDebugDeleteMemoryBreakpoint, true); //delete memory breakpoint
//variables
cmdnew(cmd, "varnew\1var", cbInstrVar, false); //make a variable arg1:name,[arg2:value]
cmdnew(cmd, "vardel", cbInstrVarDel, false); //delete a variable, arg1:variable name
cmdnew(cmd, "varlist", cbInstrVarList, false); //list variables[arg1:type filter]
cmdnew(cmd, "mov\1set", cbInstrMov, false); //mov a variable, arg1:dest,arg2:src
dbgcmdnew("varnew\1var", cbInstrVar, false); //make a variable arg1:name,[arg2:value]
dbgcmdnew("vardel", cbInstrVarDel, false); //delete a variable, arg1:variable name
dbgcmdnew("varlist", cbInstrVarList, false); //list variables[arg1:type filter]
dbgcmdnew("mov\1set", cbInstrMov, false); //mov a variable, arg1:dest,arg2:src
//misc
cmdnew(cmd, "strlen\1charcount\1ccount", cbStrLen, false); //get strlen, arg1:string
cmdnew(cmd, "cls\1lc\1lclr", cbCls, false); //clear the log
cmdnew(cmd, "chd", cbInstrChd, false); //Change directory
cmdnew(cmd, "disasm\1dis\1d", cbDebugDisasm, true); //doDisasm
cmdnew(cmd, "HideDebugger\1dbh\1hide", cbDebugHide, true); //HideDebugger
cmdnew(cmd, "dump", cbDebugDump, true); //dump at address
cmdnew(cmd, "sdump", cbDebugStackDump, true); //dump at stack address
dbgcmdnew("strlen\1charcount\1ccount", cbStrLen, false); //get strlen, arg1:string
dbgcmdnew("cls\1lc\1lclr", cbCls, false); //clear the log
dbgcmdnew("chd", cbInstrChd, false); //Change directory
dbgcmdnew("disasm\1dis\1d", cbDebugDisasm, true); //doDisasm
dbgcmdnew("HideDebugger\1dbh\1hide", cbDebugHide, true); //HideDebugger
dbgcmdnew("dump", cbDebugDump, true); //dump at address
dbgcmdnew("sdump", cbDebugStackDump, true); //dump at stack address
//user database
cmdnew(cmd, "cmt\1cmtset\1commentset", cbInstrCmt, true); //set/edit comment
cmdnew(cmd, "cmtc\1cmtdel\1commentdel", cbInstrCmtdel, true); //delete comment
cmdnew(cmd, "lbl\1lblset\1labelset", cbInstrLbl, true); //set/edit label
cmdnew(cmd, "lblc\1lbldel\1labeldel", cbInstrLbldel, true); //delete label
cmdnew(cmd, "bookmark\1bookmarkset", cbInstrBookmarkSet, true); //set bookmark
cmdnew(cmd, "bookmarkc\1bookmarkdel", cbInstrBookmarkDel, true); //delete bookmark
cmdnew(cmd, "savedb\1dbsave", cbSavedb, true); //save program database
cmdnew(cmd, "loaddb\1dbload", cbLoaddb, true); //load program database
cmdnew(cmd, "functionadd\1func", cbFunctionAdd, true); //function
cmdnew(cmd, "functiondel\1funcc", cbFunctionDel, true); //function
dbgcmdnew("cmt\1cmtset\1commentset", cbInstrCmt, true); //set/edit comment
dbgcmdnew("cmtc\1cmtdel\1commentdel", cbInstrCmtdel, true); //delete comment
dbgcmdnew("lbl\1lblset\1labelset", cbInstrLbl, true); //set/edit label
dbgcmdnew("lblc\1lbldel\1labeldel", cbInstrLbldel, true); //delete label
dbgcmdnew("bookmark\1bookmarkset", cbInstrBookmarkSet, true); //set bookmark
dbgcmdnew("bookmarkc\1bookmarkdel", cbInstrBookmarkDel, true); //delete bookmark
dbgcmdnew("savedb\1dbsave", cbSavedb, true); //save program database
dbgcmdnew("loaddb\1dbload", cbLoaddb, true); //load program database
dbgcmdnew("functionadd\1func", cbFunctionAdd, true); //function
dbgcmdnew("functiondel\1funcc", cbFunctionDel, true); //function
//memory operations
cmdnew(cmd, "alloc", cbDebugAlloc, true); //allocate memory
cmdnew(cmd, "free", cbDebugFree, true); //free memory
cmdnew(cmd, "Fill\1memset", cbDebugMemset, true); //memset
dbgcmdnew("alloc", cbDebugAlloc, true); //allocate memory
dbgcmdnew("free", cbDebugFree, true); //free memory
dbgcmdnew("Fill\1memset", cbDebugMemset, true); //memset
//plugins
cmdnew(cmd, "StartScylla\1scylla\1imprec", cbStartScylla, false); //start scylla
dbgcmdnew("StartScylla\1scylla\1imprec", cbStartScylla, false); //start scylla
//general purpose
cmdnew(cmd, "cmp", cbInstrCmp, false); //compare
cmdnew(cmd, "gpa", cbInstrGpa, true);
cmdnew(cmd, "add", cbInstrAdd, false);
cmdnew(cmd, "and", cbInstrAnd, false);
cmdnew(cmd, "dec", cbInstrDec, false);
cmdnew(cmd, "div", cbInstrDiv, false);
cmdnew(cmd, "inc", cbInstrInc, false);
cmdnew(cmd, "mul", cbInstrMul, false);
cmdnew(cmd, "neg", cbInstrNeg, false);
cmdnew(cmd, "not", cbInstrNot, false);
cmdnew(cmd, "or", cbInstrOr, false);
cmdnew(cmd, "rol", cbInstrRol, false);
cmdnew(cmd, "ror", cbInstrRor, false);
cmdnew(cmd, "shl", cbInstrShl, false);
cmdnew(cmd, "shr", cbInstrShr, false);
cmdnew(cmd, "sub", cbInstrSub, false);
cmdnew(cmd, "test", cbInstrTest, false);
cmdnew(cmd, "xor", cbInstrXor, false);
dbgcmdnew("cmp", cbInstrCmp, false); //compare
dbgcmdnew("gpa", cbInstrGpa, true);
dbgcmdnew("add", cbInstrAdd, false);
dbgcmdnew("and", cbInstrAnd, false);
dbgcmdnew("dec", cbInstrDec, false);
dbgcmdnew("div", cbInstrDiv, false);
dbgcmdnew("inc", cbInstrInc, false);
dbgcmdnew("mul", cbInstrMul, false);
dbgcmdnew("neg", cbInstrNeg, false);
dbgcmdnew("not", cbInstrNot, false);
dbgcmdnew("or", cbInstrOr, false);
dbgcmdnew("rol", cbInstrRol, false);
dbgcmdnew("ror", cbInstrRor, false);
dbgcmdnew("shl", cbInstrShl, false);
dbgcmdnew("shr", cbInstrShr, false);
dbgcmdnew("sub", cbInstrSub, false);
dbgcmdnew("test", cbInstrTest, false);
dbgcmdnew("xor", cbInstrXor, false);
//script
cmdnew(cmd, "scriptload", cbScriptLoad, false);
cmdnew(cmd, "msg", cbScriptMsg, false);
cmdnew(cmd, "msgyn", cbScriptMsgyn, false);
dbgcmdnew("scriptload", cbScriptLoad, false);
dbgcmdnew("msg", cbScriptMsg, false);
dbgcmdnew("msgyn", cbScriptMsgyn, false);
//data
cmdnew(cmd, "reffind\1findref\1ref", cbInstrRefFind, true);
cmdnew(cmd, "refstr\1strref", cbInstrRefStr, true);
cmdnew(cmd, "find", cbInstrFind, true); //find a pattern
dbgcmdnew("reffind\1findref\1ref", cbInstrRefFind, true);
dbgcmdnew("refstr\1strref", cbInstrRefStr, true);
dbgcmdnew("find", cbInstrFind, true); //find a pattern
//undocumented
cmdnew(cmd, "bench", cbBenchmark, true); //benchmark test (readmem etc)
cmdnew(cmd, "memwrite", cbMemWrite, true); //memwrite test
cmdnew(cmd, "asm", cbAssemble, true); //assemble instruction
cmdnew(cmd, "dprintf", cbPrintf, false); //printf
cmdnew(cmd, "refinit", cbInstrRefinit, false);
cmdnew(cmd, "refadd", cbInstrRefadd, false);
cmdnew(cmd, "setstr\1strset", cbInstrSetstr, false); //set a string variable
cmdnew(cmd, "getstr\1strget", cbInstrGetstr, false); //get a string variable
dbgcmdnew("bench", cbBenchmark, true); //benchmark test (readmem etc)
dbgcmdnew("memwrite", cbMemWrite, true); //memwrite test
dbgcmdnew("asm", cbAssemble, true); //assemble instruction
dbgcmdnew("dprintf", cbPrintf, false); //printf
dbgcmdnew("refinit", cbInstrRefinit, false);
dbgcmdnew("refadd", cbInstrRefadd, false);
dbgcmdnew("setstr\1strset", cbInstrSetstr, false); //set a string variable
dbgcmdnew("getstr\1strget", cbInstrGetstr, false); //get a string variable
}
static bool cbCommandProvider(char* cmd, int maxlen)

View File

@ -62,7 +62,9 @@ SOURCES += \
Src/Gui/ExceptionRangeDialog.cpp \
Src/BasicView/RichTextPainter.cpp \
Src/Gui/TabBar.cpp \
Src/Gui/TabWidget.cpp
Src/Gui/TabWidget.cpp \
Src/BasicView/CommandHelpView.cpp \
Src/BasicView/HistoryLineEdit.cpp
HEADERS += \
@ -105,7 +107,9 @@ HEADERS += \
Src/Gui/ExceptionRangeDialog.h \
Src/BasicView/RichTextPainter.h \
Src/Gui/TabBar.h \
Src/Gui/TabWidget.h
Src/Gui/TabWidget.h \
Src/BasicView/CommandHelpView.h \
Src/BasicView/HistoryLineEdit.h
INCLUDEPATH += \
@ -130,7 +134,8 @@ FORMS += \
Src/BasicView/SymbolView.ui \
Src/BasicView/SearchListView.ui \
Src/Gui/SettingsDialog.ui \
Src/Gui/ExceptionRangeDialog.ui
Src/Gui/ExceptionRangeDialog.ui \
Src/BasicView/CommandHelpView.ui
INCLUDEPATH += $$PWD/Src/Bridge

View File

@ -0,0 +1,51 @@
#include "HistoryLineEdit.h"
HistoryLineEdit::HistoryLineEdit(QWidget *parent) : QLineEdit(parent)
{
mCmdHistory.clear();
mCmdIndex = -1;
}
void HistoryLineEdit::addLineToHistory(QString parLine)
{
mCmdHistory.prepend(parLine);
if(mCmdHistory.size() > 32)
mCmdHistory.removeLast();
mCmdIndex = -1;
}
void HistoryLineEdit::keyPressEvent(QKeyEvent* event)
{
int wKey = event->key();
if(wKey == Qt::Key_Up || wKey == Qt::Key_Down)
{
if(wKey == Qt::Key_Up)
mCmdIndex++;
else if(wKey == Qt::Key_Down)
mCmdIndex--;
mCmdIndex = mCmdIndex < -1 ? -1 : mCmdIndex;
mCmdIndex = mCmdIndex > mCmdHistory.size() - 1 ? mCmdHistory.size() - 1 : mCmdIndex;
if(mCmdIndex == -1)
{
setText("");
}
else
{
setText(mCmdHistory.at(mCmdIndex));
}
}
QLineEdit::keyPressEvent(event);
}
void HistoryLineEdit::setFocus()
{
mCmdIndex = -1;
QLineEdit::setFocus();
}

View File

@ -0,0 +1,29 @@
#ifndef HISTORYLINEEDIT_H
#define HISTORYLINEEDIT_H
#include <QtGui>
#include <QDebug>
#include <QLineEdit>
class HistoryLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit HistoryLineEdit(QWidget *parent = 0);
void keyPressEvent(QKeyEvent* event);
void addLineToHistory(QString parLine);
void setFocus();
signals:
void keyPressed(int parKey);
public slots:
private:
QList<QString> mCmdHistory;
int mCmdIndex;
};
#endif // HISTORYLINEEDIT_H

View File

@ -30,5 +30,16 @@ void InfoBox::setInfoLine(int line, QString text)
void InfoBox::disasmSelectionChanged(int_t parVA)
{
char label[MAX_LABEL_SIZE]="";
QString info="";
if(DbgGetLabelAt(parVA, SEG_DEFAULT, label))
{
QString fullLabel="<"+QString(label)+">";
char mod[MAX_MODULE_SIZE]="";
if(DbgGetModuleAt(parVA, mod))
fullLabel="<"+QString(mod)+"."+QString(label)+">";
info=QString("%1").arg(parVA, sizeof(int_t) * 2, 16, QChar('0')).toUpper() + " " + fullLabel;
}
setInfoLine(2, info);
//setInfoLine(0, QString("%1").arg(parVA, sizeof(int_t) * 2, 16, QChar('0')).toUpper());
}

View File

@ -280,6 +280,12 @@ bool Bridge::emitSelectionGet(int hWindow, SELECTIONDATA* selection)
while(!hasBridgeResult) //wait for thread completion
Sleep(100);
mBridgeMutex.unlock();
if(selection->start > selection->end) //swap start and end
{
int_t temp=selection->end;
selection->end=selection->start;
selection->start=temp;
}
return true;
}
@ -321,6 +327,21 @@ bool Bridge::emitGetStrWindow(const QString title, QString* text)
return bridgeResult;
}
void Bridge::emitAutoCompleteAddCmd(const QString cmd)
{
emit autoCompleteAddCmd(cmd);
}
void Bridge::emitAutoCompleteDelCmd(const QString cmd)
{
emit autoCompleteDelCmd(cmd);
}
void Bridge::emitAutoCompleteClearAll()
{
emit autoCompleteClearAll();
}
/************************************************************************************
Static Functions
************************************************************************************/
@ -640,6 +661,24 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa
}
break;
case GUI_AUTOCOMPLETE_ADDCMD:
{
Bridge::getBridge()->emitAutoCompleteAddCmd(QString((const char*)param1));
}
break;
case GUI_AUTOCOMPLETE_DELCMD:
{
Bridge::getBridge()->emitAutoCompleteDelCmd(QString((const char*)param1));
}
break;
case GUI_AUTOCOMPLETE_CLEARALL:
{
Bridge::getBridge()->emitAutoCompleteClearAll();
}
break;
default:
{
}

View File

@ -70,6 +70,9 @@ public:
bool emitSelectionGet(int hWindow, SELECTIONDATA* selection);
bool emitSelectionSet(int hWindow, const SELECTIONDATA* selection);
bool emitGetStrWindow(const QString title, QString* text);
void emitAutoCompleteAddCmd(const QString cmd);
void emitAutoCompleteDelCmd(const QString cmd);
void emitAutoCompleteClearAll();
//Public variables
void* winId;
@ -122,6 +125,9 @@ signals:
void selectionStackGet(SELECTIONDATA* selection);
void selectionStackSet(const SELECTIONDATA* selection);
void getStrWindow(const QString title, QString* text);
void autoCompleteAddCmd(const QString cmd);
void autoCompleteDelCmd(const QString cmd);
void autoCompleteClearAll();
private:
QMutex mBridgeMutex;

View File

@ -7,6 +7,8 @@ CPUDisassembly::CPUDisassembly(QWidget *parent) : Disassembly(parent)
connect(Bridge::getBridge(), SIGNAL(selectionDisasmGet(SELECTIONDATA*)), this, SLOT(selectionGet(SELECTIONDATA*)));
connect(Bridge::getBridge(), SIGNAL(selectionDisasmSet(const SELECTIONDATA*)), this, SLOT(selectionSet(const SELECTIONDATA*)));
mGoto = 0;
}
void CPUDisassembly::mousePressEvent(QMouseEvent* event)
@ -631,10 +633,11 @@ void CPUDisassembly::gotoExpression()
{
if(!DbgIsDebugging())
return;
GotoDialog mGoto(this);
if(mGoto.exec()==QDialog::Accepted)
if(!mGoto)
mGoto = new GotoDialog(this);
if(mGoto->exec()==QDialog::Accepted)
{
DbgCmdExec(QString().sprintf("disasm \"%s\"", mGoto.expressionText.toUtf8().constData()).toUtf8().constData());
DbgCmdExec(QString().sprintf("disasm \"%s\"", mGoto->expressionText.toUtf8().constData()).toUtf8().constData());
}
}

View File

@ -87,6 +87,8 @@ private:
QAction* mReferenceSelectedAddress;
QAction* mSearchConstant;
QAction* mSearchStrings;
GotoDialog* mGoto;
};
#endif // CPUDISASSEMBLY_H

View File

@ -9,6 +9,8 @@ CPUDump::CPUDump(QWidget *parent) : HexDump(parent)
connect(Bridge::getBridge(), SIGNAL(selectionDumpSet(const SELECTIONDATA*)), this, SLOT(selectionSet(const SELECTIONDATA*)));
setupContextMenu();
mGoto = 0;
}
void CPUDump::setupContextMenu()
@ -168,12 +170,13 @@ void CPUDump::gotoExpressionSlot()
{
if(!DbgIsDebugging())
return;
GotoDialog mGoto(this);
mGoto.setWindowTitle("Enter expression to follow in Dump...");
if(mGoto.exec()==QDialog::Accepted)
if(!mGoto)
mGoto = new GotoDialog(this);
mGoto->setWindowTitle("Enter expression to follow in Dump...");
if(mGoto->exec()==QDialog::Accepted)
{
QString cmd;
DbgCmdExec(cmd.sprintf("dump \"%s\"", mGoto.expressionText.toUtf8().constData()).toUtf8().constData());
DbgCmdExec(cmd.sprintf("dump \"%s\"", mGoto->expressionText.toUtf8().constData()).toUtf8().constData());
}
}

View File

@ -87,6 +87,8 @@ private:
QMenu* mSpecialMenu;
QMenu* mCustomMenu;
GotoDialog* mGoto;
};
#endif // CPUDUMP_H

View File

@ -30,6 +30,8 @@ CPUStack::CPUStack(QWidget *parent) : HexDump(parent)
connect(Bridge::getBridge(), SIGNAL(selectionStackSet(const SELECTIONDATA*)), this, SLOT(selectionSet(const SELECTIONDATA*)));
setupContextMenu();
mGoto = 0;
}
void CPUStack::setupContextMenu()
@ -187,14 +189,15 @@ void CPUStack::gotoExpressionSlot()
return;
uint_t size=0;
uint_t base=DbgMemFindBaseAddr(mCsp, &size);
GotoDialog mGoto(this);
mGoto.validRangeStart=base;
mGoto.validRangeEnd=base+size;
mGoto.setWindowTitle("Enter expression to follow in Stack...");
if(mGoto.exec()==QDialog::Accepted)
if(!mGoto)
mGoto = new GotoDialog(this);
mGoto->validRangeStart=base;
mGoto->validRangeEnd=base+size;
mGoto->setWindowTitle("Enter expression to follow in Stack...");
if(mGoto->exec()==QDialog::Accepted)
{
QString cmd;
DbgCmdExec(cmd.sprintf("sdump \"%s\"", mGoto.expressionText.toUtf8().constData()).toUtf8().constData());
DbgCmdExec(cmd.sprintf("sdump \"%s\"", mGoto->expressionText.toUtf8().constData()).toUtf8().constData());
}
}

View File

@ -40,6 +40,8 @@ private:
QAction* mFollowDisasm;
QAction* mFollowDump;
QAction* mFollowStack;
GotoDialog* mGoto;
};
#endif // CPUSTACK_H

View File

@ -1,55 +1,40 @@
#include "CommandLineEdit.h"
CommandLineEdit::CommandLineEdit(QWidget *parent) : QLineEdit(parent)
CommandLineEdit::CommandLineEdit(QWidget *parent) : HistoryLineEdit(parent)
{
mCmdHistory.clear();
mCmdIndex = -1;
//Initialize QCompleter
mCompleter = new QCompleter(QStringList(), this);
mCompleter->setCaseSensitivity(Qt::CaseInsensitive);
mCompleter->setCompletionMode(QCompleter::PopupCompletion);
this->setCompleter(mCompleter);
//Setup signals & slots
connect(Bridge::getBridge(), SIGNAL(autoCompleteAddCmd(QString)), this, SLOT(autoCompleteAddCmd(QString)));
connect(Bridge::getBridge(), SIGNAL(autoCompleteDelCmd(QString)), this, SLOT(autoCompleteDelCmd(QString)));
connect(Bridge::getBridge(), SIGNAL(autoCompleteClearAll()), this, SLOT(autoCompleteClearAll()));
}
void CommandLineEdit::addCmdToHistory(QString parCmd)
void CommandLineEdit::autoCompleteAddCmd(const QString cmd)
{
mCmdHistory.prepend(parCmd);
if(mCmdHistory.size() > 32)
mCmdHistory.removeLast();
mCmdIndex = -1;
QStringListModel* model = (QStringListModel*)(mCompleter->model());
QStringList stringList = model->stringList();
stringList << cmd.split(QChar('\1'), QString::SkipEmptyParts);
stringList.removeDuplicates();
model->setStringList(stringList);
}
void CommandLineEdit::keyPressEvent(QKeyEvent* event)
void CommandLineEdit::autoCompleteDelCmd(const QString cmd)
{
int wKey = event->key();
if(wKey == Qt::Key_Up || wKey == Qt::Key_Down)
{
if(wKey == Qt::Key_Up)
mCmdIndex++;
else if(wKey == Qt::Key_Down)
mCmdIndex--;
mCmdIndex = mCmdIndex < -1 ? -1 : mCmdIndex;
mCmdIndex = mCmdIndex > mCmdHistory.size() - 1 ? mCmdHistory.size() - 1 : mCmdIndex;
if(mCmdIndex == -1)
{
setText("");
}
else
{
setText(mCmdHistory.at(mCmdIndex));
}
}
QLineEdit::keyPressEvent(event);
QStringListModel* model = (QStringListModel*)(mCompleter->model());
QStringList stringList = model->stringList();
QStringList deleteList = cmd.split(QChar('\1'), QString::SkipEmptyParts);
for(int i=0; i<deleteList.size(); i++)
stringList.removeAll(deleteList.at(i));
model->setStringList(stringList);
}
void CommandLineEdit::setFocusToCmd()
void CommandLineEdit::autoCompleteClearAll()
{
mCmdIndex = -1;
setFocus();
QStringListModel* model = (QStringListModel*)(mCompleter->model());
model->setStringList(QStringList());
}

View File

@ -1,29 +1,22 @@
#ifndef LINEEDIT_H
#define LINEEDIT_H
#ifndef COMMANDLINEEDIT_H
#define COMMANDLINEEDIT_H
#include <QtGui>
#include <QDebug>
#include <QLineEdit>
#include "HistoryLineEdit.h"
#include "Bridge.h"
class CommandLineEdit : public QLineEdit
class CommandLineEdit : public HistoryLineEdit
{
Q_OBJECT
public:
explicit CommandLineEdit(QWidget *parent = 0);
void keyPressEvent(QKeyEvent* event);
void addCmdToHistory(QString parCmd);
void setFocusToCmd();
signals:
void keyPressed(int parKey);
public slots:
public slots:
void autoCompleteAddCmd(const QString cmd);
void autoCompleteDelCmd(const QString cmd);
void autoCompleteClearAll();
private:
QList<QString> mCmdHistory;
int mCmdIndex;
QCompleter* mCompleter;
};
#endif // LINEEDIT_H
#endif // COMMANDLINEEDIT_H

View File

@ -82,3 +82,11 @@ bool GotoDialog::IsValidMemoryRange(uint_t addr)
{
return ((!validRangeStart && !validRangeEnd) || (addr >= validRangeStart && addr < validRangeEnd));
}
void GotoDialog::on_buttonOk_clicked()
{
QString expression = ui->editExpression->text();
ui->editExpression->addLineToHistory(expression);
ui->editExpression->setText("");
expressionText = expression;
}

View File

@ -23,6 +23,8 @@ public:
private slots:
void on_editExpression_textChanged(const QString &arg1);
void on_buttonOk_clicked();
private:
Ui::GotoDialog *ui;
bool IsValidMemoryRange(uint_t addr);

View File

@ -26,7 +26,7 @@
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="editExpression"/>
<widget class="HistoryLineEdit" name="editExpression"/>
</item>
<item>
<widget class="QLabel" name="labelError">
@ -75,6 +75,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>HistoryLineEdit</class>
<extends>QLineEdit</extends>
<header>HistoryLineEdit.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>editExpression</tabstop>
<tabstop>buttonOk</tabstop>

View File

@ -271,7 +271,7 @@ void MainWindow::executeCommand()
DbgCmdExec(wCmd.toUtf8().constData());
mCmdLineEdit->addCmdToHistory(wCmd);
mCmdLineEdit->addLineToHistory(wCmd);
mCmdLineEdit->setText("");
}
@ -288,7 +288,7 @@ void MainWindow::execStepInto()
void MainWindow::setFocusToCommandBar()
{
mCmdLineEdit->setFocusToCmd();
mCmdLineEdit->setFocus();
}
void MainWindow::execClose()