1
0
Fork 0

BRIDGE: added DbgScriptGetBranchInfo

DBG: added branch info
DBG: fixed a bug with comments in scripts
DBG: fixed a bug with prepended spaces in scripts
DBG: added script command 'nop'
GUI: separate class RichTextPainter
GUI: script syntax highlighting (jumps+calls+rets+comments)
GUI: backgroundColor property in AbstractTableView
GUI: added keyPressEvent handler (enter follows jumps & arrows select next command) in ScriptView
This commit is contained in:
Mr. eXoDia 2014-04-26 20:41:03 +02:00
parent 9b36423cdc
commit 5f9f3f88f9
16 changed files with 401 additions and 136 deletions

View File

@ -534,6 +534,11 @@ BRIDGE_IMPEXP void DbgScriptSetIp(int line)
_dbg_sendmessage(DBG_SCRIPT_SETIP, (void*)(duint)line, 0);
}
BRIDGE_IMPEXP bool DbgScriptGetBranchInfo(int line, SCRIPTBRANCH* info)
{
return (bool)(duint)_dbg_sendmessage(DBG_SCRIPT_GETBRANCHINFO, (void*)(duint)line, info);
}
BRIDGE_IMPEXP void DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* user)
{
SYMBOLCBINFO cbInfo;

View File

@ -117,6 +117,7 @@ enum DBGMSG
DBG_SCRIPT_ABORT, // param1=unused, param2=unused
DBG_SCRIPT_GETLINETYPE, // param1=int line, param2=unused
DBG_SCRIPT_SETIP, // param1=int line, param2=unused
DBG_SCRIPT_GETBRANCHINFO, // param1=int line, param2=SCRIPTBRANCH* info
DBG_SYMBOL_ENUM, // param1=SYMBOLCBINFO* cbInfo, param2=unused
DBG_ASSEMBLE_AT, // param1=duint addr, param2=const char* instruction
DBG_MODBASE_FROM_NAME, // param1=const char* modname, param2=unused
@ -137,6 +138,19 @@ enum SCRIPTLINETYPE
lineempty,
};
enum SCRIPTBRANCHTYPE
{
scriptnobranch,
scriptjmp,
scriptjnejnz,
scriptjejz,
scriptjbjl,
scriptjajg,
scriptjbejle,
scriptjaejge,
scriptcall
};
enum DISASM_INSTRTYPE
{
instr_normal,
@ -414,6 +428,13 @@ struct BASIC_INSTRUCTION_INFO
bool branch; //jumps/calls
};
struct SCRIPTBRANCH
{
SCRIPTBRANCHTYPE type;
int dest;
char branchlabel[256];
};
//Debugger functions
BRIDGE_IMPEXP const char* DbgInit();
BRIDGE_IMPEXP bool DbgMemRead(duint va, unsigned char* dest, duint size);
@ -454,6 +475,7 @@ BRIDGE_IMPEXP bool DbgScriptCmdExec(const char* command);
BRIDGE_IMPEXP void DbgScriptAbort();
BRIDGE_IMPEXP SCRIPTLINETYPE DbgScriptGetLineType(int line);
BRIDGE_IMPEXP void DbgScriptSetIp(int line);
BRIDGE_IMPEXP bool DbgScriptGetBranchInfo(int line, SCRIPTBRANCH* info);
BRIDGE_IMPEXP void DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* user);
BRIDGE_IMPEXP bool DbgAssembleAt(duint addr, const char* instruction);
BRIDGE_IMPEXP duint DbgModBaseFromName(const char* name);

View File

@ -596,6 +596,12 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
}
break;
case DBG_SCRIPT_GETBRANCHINFO:
{
return (duint)scriptgetbranchinfo((int)(duint)param1, (SCRIPTBRANCH*)param2);
}
break;
case DBG_SYMBOL_ENUM:
{
SYMBOLCBINFO* cbInfo=(SYMBOLCBINFO*)param1;
@ -716,7 +722,7 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
int hEntry=(int)(uint)param1;
pluginmenucall(hEntry);
}
break;
break;
}
return 0;
}

View File

@ -49,9 +49,19 @@ static int scriptlabelfind(const char* labelname)
return 0;
}
static int scriptinternalstep(int fromIp) //internal step routine
{
int maxIp=linemap.size(); //maximum ip
if(fromIp>=maxIp) //script end
return fromIp;
while((linemap.at(fromIp).type==lineempty or linemap.at(fromIp).type==linecomment or linemap.at(fromIp).type==linelabel) and fromIp<maxIp) //skip empty lines
fromIp++;
fromIp++;
return fromIp;
}
static bool scriptcreatelinemap(const char* filename)
{
DWORD ticks=GetTickCount();
HANDLE hFile=CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(hFile==INVALID_HANDLE_VALUE)
{
@ -80,7 +90,10 @@ static bool scriptcreatelinemap(const char* filename)
if(filedata[i]=='\r' and filedata[i+1]=='\n') //windows file
{
memset(&entry, 0, sizeof(entry));
strcpy(entry.raw, temp);
int add=0;
while(temp[add]==' ')
add++;
strcpy(entry.raw, temp+add);
*temp=0;
j=0;
i++;
@ -89,7 +102,10 @@ static bool scriptcreatelinemap(const char* filename)
else if(filedata[i]=='\n') //other file
{
memset(&entry, 0, sizeof(entry));
strcpy(entry.raw, temp);
int add=0;
while(temp[add]==' ')
add++;
strcpy(entry.raw, temp+add);
*temp=0;
j=0;
linemap.push_back(entry);
@ -97,7 +113,10 @@ static bool scriptcreatelinemap(const char* filename)
else if(j>=254)
{
memset(&entry, 0, sizeof(entry));
strcpy(entry.raw, temp);
int add=0;
while(temp[add]==' ')
add++;
strcpy(entry.raw, temp+add);
*temp=0;
j=0;
linemap.push_back(entry);
@ -113,7 +132,7 @@ static bool scriptcreatelinemap(const char* filename)
}
efree(filedata, "createlinemap:filedata");
unsigned int linemapsize=linemap.size();
while(!*linemap.at(linemapsize-1).raw) //remove empty lines
while(!*linemap.at(linemapsize-1).raw) //remove empty lines from the end
{
linemapsize--;
linemap.pop_back();
@ -121,6 +140,24 @@ static bool scriptcreatelinemap(const char* filename)
for(unsigned int i=0; i<linemapsize; i++)
{
LINEMAPENTRY cur=linemap.at(i);
//temp. remove comments from the raw line
char line_comment[256]="";
char* comment=strstr(&cur.raw[0], "//");
if(comment && comment!=cur.raw) //only when the line doesnt start with a comment
{
if(*(comment-1)==' ') //space before comment
{
strcpy(line_comment, comment);
*(comment-1)='\0';
}
else //no space before comment
{
strcpy(line_comment, comment);
*comment=0;
}
}
int rawlen=strlen(cur.raw);
if(!strlen(cur.raw)) //empty
{
@ -173,25 +210,30 @@ static bool scriptcreatelinemap(const char* filename)
else
{
cur.type=linecommand;
const char* comment=strstr(cur.raw, "//"); //find comment
if(comment)
strncpy(cur.u.command, cur.raw, comment-cur.raw);
else
strcpy(cur.u.command, cur.raw);
strcpy(cur.u.command, cur.raw);
}
//append the comment to the raw line again
if(*line_comment)
sprintf(cur.raw+rawlen, " %s", line_comment);
linemap.at(i)=cur;
}
linemapsize=linemap.size();
for(unsigned int i=0; i<linemapsize; i++)
{
LINEMAPENTRY cur=linemap.at(i);
if(cur.type==linebranch and !scriptlabelfind(cur.u.branch.branchlabel)) //invalid branch label
if(linemap.at(i).type==linebranch) //invalid branch label
{
char message[256]="";
sprintf(message, "Invalid branch label \"%s\" detected on line %d!", cur.u.branch.branchlabel, i+1);
GuiScriptError(0, message);
std::vector<LINEMAPENTRY>().swap(linemap);
return false;
int labelline=scriptlabelfind(linemap.at(i).u.branch.branchlabel);
if(!labelline) //invalid branch label
{
char message[256]="";
sprintf(message, "Invalid branch label \"%s\" detected on line %d!", linemap.at(i).u.branch.branchlabel, i+1);
GuiScriptError(0, message);
std::vector<LINEMAPENTRY>().swap(linemap);
return false;
}
else //set the branch destination line
linemap.at(i).u.branch.dest=scriptinternalstep(labelline);
}
}
if(linemap.at(linemapsize-1).type==linecomment or linemap.at(linemapsize-1).type==linelabel) //label/comment on the end
@ -202,21 +244,9 @@ static bool scriptcreatelinemap(const char* filename)
strcpy(entry.u.command, "ret");
linemap.push_back(entry);
}
dprintf("%ums to parse the script\n", GetTickCount()-ticks);
return true;
}
static int scriptinternalstep(int fromIp) //internal step routine
{
int maxIp=linemap.size(); //maximum ip
if(fromIp>=maxIp) //script end
return fromIp;
while((linemap.at(fromIp).type==lineempty or linemap.at(fromIp).type==linecomment or linemap.at(fromIp).type==linelabel) and fromIp<maxIp) //skip empty lines
fromIp++;
fromIp++;
return fromIp;
}
static bool scriptinternalbpget(int line) //internal bpget routine
{
int bpcount=scriptbplist.size();
@ -304,6 +334,8 @@ static CMDRESULT scriptinternalcmdexec(const char* cmd)
return STATUS_ERROR;
else if(scriptisinternalcommand(cmd, "pause")) //pause the script
return STATUS_PAUSE;
else if(scriptisinternalcommand(cmd, "nop")) //do nothing
return STATUS_CONTINUE;
char command[deflen]="";
strcpy(command, cmd);
argformat(command);
@ -591,6 +623,16 @@ void scriptreset()
scriptsetip(0);
}
bool scriptgetbranchinfo(int line, SCRIPTBRANCH* info)
{
if(!info or !line or line>(int)linemap.size()) //invalid line
return false;
if(linemap.at(line-1).type!=linebranch) //no branch
return false;
memcpy(info, &linemap.at(line-1).u.branch, sizeof(SCRIPTBRANCH));
return true;
}
CMDRESULT cbScriptLoad(int argc, char* argv[])
{
if(argc<2)

View File

@ -3,20 +3,6 @@
#include "command.h"
//enums
enum SCRIPTBRANCHTYPE
{
scriptnobranch,
scriptjmp,
scriptjnejnz,
scriptjejz,
scriptjbjl,
scriptjajg,
scriptjbejle,
scriptjaejge,
scriptcall
};
//structures
struct SCRIPTBP
{
@ -24,12 +10,6 @@ struct SCRIPTBP
bool silent; //do not show in GUI
};
struct SCRIPTBRANCH
{
SCRIPTBRANCHTYPE type;
char branchlabel[256];
};
struct LINEMAPENTRY
{
SCRIPTLINETYPE type;
@ -55,6 +35,7 @@ void scriptabort();
SCRIPTLINETYPE scriptgetlinetype(int line);
void scriptsetip(int line);
void scriptreset();
bool scriptgetbranchinfo(int line, SCRIPTBRANCH* info);
//script commands
CMDRESULT cbScriptLoad(int argc, char* argv[]);

View File

@ -61,7 +61,8 @@ SOURCES += \
Src/Gui/SettingsDialog.cpp \
Src/Gui/ExceptionRangeDialog.cpp \
Src/Gui/tabbar.cpp \
Src/Gui/tabwidget.cpp
Src/Gui/tabwidget.cpp \
Src/BasicView/RichTextPainter.cpp
HEADERS += \
@ -103,7 +104,9 @@ HEADERS += \
Src/Gui/SettingsDialog.h \
Src/Gui/ExceptionRangeDialog.h \
Src/Gui/tabbar.h \
Src/Gui/tabwidget.h
Src/Gui/tabwidget.h \
Src/BasicView/RichTextPainter.h
INCLUDEPATH += \
Src \

View File

@ -19,6 +19,7 @@ AbstractTableView::AbstractTableView(QWidget *parent) : QAbstractScrollArea(pare
font.setStyleHint(QFont::Monospace);
this->setFont(font);
backgroundColor=QColor(255, 251, 240);
int wRowsHeight = QFontMetrics(this->font()).height();
wRowsHeight = (wRowsHeight * 105) / 100;
@ -75,7 +76,7 @@ void AbstractTableView::paintEvent(QPaintEvent* event)
}
// Paints background
wPainter.fillRect(wPainter.viewport(), QBrush(QColor(255, 251, 240)));
wPainter.fillRect(wPainter.viewport(), QBrush(backgroundColor));
// Paints header
if(mHeader.isVisible == true)

View File

@ -10,7 +10,6 @@
#include <qdebug.h>
#include <NewTypes.h>
class AbstractTableView : public QAbstractScrollArea
{
Q_OBJECT
@ -144,6 +143,9 @@ private:
bool mShouldReload;
ScrollBar64_t mScrollBarAttributes;
protected:
QColor backgroundColor;
};
#endif // ABSTRACTTABLEVIEW_H

View File

@ -37,55 +37,6 @@ Disassembly::Disassembly(QWidget *parent) : AbstractTableView(parent)
connect(Bridge::getBridge(), SIGNAL(repaintGui()), this, SLOT(reloadData()));
}
/************************************************************************************
Private Functions
************************************************************************************/
void Disassembly::paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const QList<CustomRichText_t>* richText)
{
int len=richText->size();
int charwidth=QFontMetrics(this->font()).width(QChar(' '));
for(int i=0; i<len; i++)
{
CustomRichText_t curRichText=richText->at(i);
int curRichTextLength=curRichText.text.length();
int backgroundWidth=charwidth*curRichTextLength;
if(backgroundWidth+xinc>w)
backgroundWidth=w-xinc;
if(backgroundWidth<=0) //stop drawing when going outside the specified width
break;
switch(curRichText.flags)
{
case FlagNone: //defaults
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
break;
case FlagColor: //color only
painter->save();
painter->setPen(QPen(curRichText.textColor));
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
painter->restore();
break;
case FlagBackground: //background only
painter->save();
if(backgroundWidth>0)
painter->fillRect(QRect(x+xinc, y, backgroundWidth, h), QBrush(curRichText.textBackground));
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
painter->restore();
break;
case FlagAll: //color+background
painter->save();
if(backgroundWidth>0)
painter->fillRect(QRect(x+xinc, y, backgroundWidth, h), QBrush(curRichText.textBackground));
painter->setPen(QPen(curRichText.textColor));
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
painter->restore();
break;
}
xinc+=charwidth*curRichTextLength;
}
}
/************************************************************************************
Reimplemented Functions
************************************************************************************/
@ -286,7 +237,7 @@ QString Disassembly::paintContent(QPainter* painter, int_t rowBase, int rowOffse
QList<CustomRichText_t> richText;
BeaHighlight::PrintRtfInstruction(&richText, &mInstBuffer.at(rowOffset).disasm);
Disassembly::paintRichText(painter, x + loopsize, y, getColumnWidth(col) - loopsize, getRowHeight(), 4, &richText);
RichTextPainter::paintRichText(painter, x + loopsize, y, getColumnWidth(col) - loopsize, getRowHeight(), 4, &richText, QFontMetrics(this->font()).width(QChar(' ')));
break;
}

View File

@ -8,6 +8,7 @@
#include "AbstractTableView.h"
#include "QBeaEngine.h"
#include "BeaHighlight.h"
#include "RichTextPainter.h"
class Disassembly : public AbstractTableView
{
@ -15,9 +16,6 @@ class Disassembly : public AbstractTableView
public:
explicit Disassembly(QWidget *parent = 0);
// Private Functions
void paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const QList<CustomRichText_t>* richText);
// Reimplemented Functions
QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h);

View File

@ -0,0 +1,44 @@
#include "RichTextPainter.h"
void RichTextPainter::paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const QList<CustomRichText_t>* richText, int charwidth)
{
int len=richText->size();
for(int i=0; i<len; i++)
{
CustomRichText_t curRichText=richText->at(i);
int curRichTextLength=curRichText.text.length();
int backgroundWidth=charwidth*curRichTextLength;
if(backgroundWidth+xinc>w)
backgroundWidth=w-xinc;
if(backgroundWidth<=0) //stop drawing when going outside the specified width
break;
switch(curRichText.flags)
{
case FlagNone: //defaults
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
break;
case FlagColor: //color only
painter->save();
painter->setPen(QPen(curRichText.textColor));
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
painter->restore();
break;
case FlagBackground: //background only
painter->save();
if(backgroundWidth>0)
painter->fillRect(QRect(x+xinc, y, backgroundWidth, h), QBrush(curRichText.textBackground));
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
painter->restore();
break;
case FlagAll: //color+background
painter->save();
if(backgroundWidth>0)
painter->fillRect(QRect(x+xinc, y, backgroundWidth, h), QBrush(curRichText.textBackground));
painter->setPen(QPen(curRichText.textColor));
painter->drawText(QRect(x+xinc, y, w-xinc, h), 0, curRichText.text);
painter->restore();
break;
}
xinc+=charwidth*curRichTextLength;
}
}

View File

@ -0,0 +1,31 @@
#ifndef RICHTEXTPAINTER_H
#define RICHTEXTPAINTER_H
#include <QList>
#include <QPainter>
//structures
enum CustomRichTextFlags
{
FlagNone,
FlagColor,
FlagBackground,
FlagAll
};
typedef struct _CustomRichText_t
{
QString text;
QColor textColor;
QColor textBackground;
CustomRichTextFlags flags;
} CustomRichText_t;
class RichTextPainter
{
public:
//functions
static void paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const QList<CustomRichText_t>* richText, int charwidth);
};
#endif // RICHTEXTPAINTER_H

View File

@ -67,17 +67,150 @@ QString ScriptView::paintContent(QPainter* painter, int_t rowBase, int rowOffset
case 1: //command
{
//initialize
painter->save();
if(linetype==linecomment || linetype==linelabel)
painter->setPen(QPen(QColor("#808080"))); //grey text
if(linetype!=linelabel)
returnString=QString(" ") + getCellContent(rowBase+rowOffset, col);
else //label
int charwidth=QFontMetrics(this->font()).width(QChar(' '));
int xadd=charwidth; //for testing
QList<CustomRichText_t> richText;
CustomRichText_t newRichText;
QString command=getCellContent(rowBase+rowOffset, col);
//handle comments
int comment_idx=command.indexOf("//"); //find the index of the space
QString comment="";
if(comment_idx!=-1 && command.at(0)!=QChar('/')) //there is a comment
{
returnString=getCellContent(rowBase+rowOffset, col);
painter->drawLine(QPoint(x+2, y+h-2), QPoint(x+w-4, y+h-2));
comment=command.right(command.length()-comment_idx);
if(command.at(comment_idx-1)==QChar(' '))
command.truncate(comment_idx-1);
else
command.truncate(comment_idx);
}
painter->drawText(QRect(x+1, y , w , h), Qt::AlignVCenter | Qt::AlignLeft, returnString);
//setup the richText list
switch(linetype)
{
case linecommand:
{
if(isScriptCommand(command, "ret"))
{
newRichText.flags=FlagBackground;
newRichText.textBackground=QColor(0,255,255);
newRichText.text="ret";
richText.push_back(newRichText);
QString remainder=command.right(command.length()-3);
if(remainder.length())
{
newRichText.flags=FlagNone;
newRichText.text=remainder;
richText.push_back(newRichText);
}
}
else
{
newRichText.flags=FlagNone;
newRichText.text=command;
richText.push_back(newRichText);
}
}
break;
case linebranch:
{
SCRIPTBRANCH branchinfo;
DbgScriptGetBranchInfo(line, &branchinfo);
//jumps
int i=command.indexOf(" "); //find the index of the space
switch(branchinfo.type)
{
case scriptjmp: //unconditional jumps
newRichText.flags=FlagBackground;
newRichText.textBackground=QColor(255,255,0);
break;
case scriptjnejnz: //conditional jumps
case scriptjejz:
case scriptjbjl:
case scriptjajg:
case scriptjbejle:
case scriptjaejge:
newRichText.flags=FlagAll;
newRichText.textBackground=QColor(255,255,0);
newRichText.textColor=QColor(255,0,0);
break;
case scriptcall: //calls
newRichText.flags=FlagBackground;
newRichText.textBackground=QColor(0,255,255);
break;
default:
newRichText.flags=FlagNone;
break;
}
newRichText.text=command.left(i);
richText.push_back(newRichText);
//space
newRichText.flags=FlagNone;
newRichText.text=" ";
richText.push_back(newRichText);
//label
QString label=branchinfo.branchlabel;
newRichText.flags=FlagBackground;
newRichText.textBackground=QColor(255,255,0);
newRichText.text=label;
richText.push_back(newRichText);
//remainder
QString remainder=command.right(command.length()-command.indexOf(label)-label.length());
if(remainder.length())
{
newRichText.flags=FlagNone;
newRichText.text=remainder;
richText.push_back(newRichText);
}
}
break;
case linelabel:
{
newRichText.flags=FlagColor;
newRichText.textColor=QColor("#808080");
newRichText.text=command;
richText.push_back(newRichText);
painter->drawLine(QPoint(x+xadd+2, y+h-2), QPoint(x+w-4, y+h-2));
}
break;
case linecomment:
{
newRichText.flags=FlagColor;
newRichText.textColor=QColor("#808080");
newRichText.text=command;
richText.push_back(newRichText);
}
break;
case lineempty:
{
}
break;
}
//append the comment (when present)
if(comment.length())
{
CustomRichText_t newRichText;
newRichText.flags=FlagNone;
newRichText.text=" ";
richText.push_back(newRichText); //space
newRichText.flags=FlagColor;
newRichText.textColor=QColor("#808080");
newRichText.text=comment;
richText.push_back(newRichText); //comment
}
//paint the rich text
RichTextPainter::paintRichText(painter, x+1, y, w, h, xadd, &richText, charwidth);
painter->restore();
returnString="";
}
@ -119,6 +252,41 @@ void ScriptView::mouseDoubleClickEvent(QMouseEvent* event)
newIp();
}
void ScriptView::keyPressEvent(QKeyEvent* event)
{
int key = event->key();
if(key == Qt::Key_Up || key == Qt::Key_Down)
{
int_t botRVA = getTableOffset();
int_t topRVA = botRVA + getNbrOfLineToPrint() - 1;
if(key == Qt::Key_Up)
selectPrevious();
else
selectNext();
if(getInitialSelection() < botRVA)
{
setTableOffset(getInitialSelection());
}
else if(getInitialSelection() >= topRVA)
{
setTableOffset(getInitialSelection() - getNbrOfLineToPrint() + 2);
}
repaint();
}
else if(key == Qt::Key_Return || key == Qt::Key_Enter)
{
int line=getInitialSelection()+1;
SCRIPTBRANCH branchinfo;
memset(&branchinfo, 0, sizeof(SCRIPTBRANCH));
if(DbgScriptGetBranchInfo(line, &branchinfo))
setSelection(branchinfo.dest);
}
else
{
AbstractTableView::keyPressEvent(event);
}
}
void ScriptView::setupContextMenu()
{
mLoadMenu = new QMenu("Load Script", this);
@ -178,6 +346,19 @@ void ScriptView::setupContextMenu()
connect(mScriptNewIp, SIGNAL(triggered()), this, SLOT(newIp()));
}
bool ScriptView::isScriptCommand(QString text, QString cmd)
{
int len=text.length();
int cmdlen=cmd.length();
if(cmdlen>len)
return false;
else if(cmdlen==len)
return (text.compare(cmd, Qt::CaseInsensitive)==0);
else if(text.at(cmdlen)==' ')
return (text.left(cmdlen).compare(cmd, Qt::CaseInsensitive)==0);
return false;
}
//slots
void ScriptView::add(int count, const char** lines)
{
@ -215,6 +396,21 @@ void ScriptView::setIp(int line)
reloadData(); //repaint
}
void ScriptView::setSelection(int line)
{
int offset=line-1;
if(!isValidIndex(offset, 0))
return;
int rangefrom=getTableOffset();
int rangeto=rangefrom+getViewableRowsCount()-1;
if(offset<rangefrom) //ip lays before the current view
setTableOffset(offset);
else if(offset>(rangeto-1)) //ip lays after the current view
setTableOffset(offset-getViewableRowsCount()+2);
setSingleSelection(offset);
reloadData(); //repaint
}
void ScriptView::error(int line, QString message)
{
QString title;

View File

@ -20,6 +20,7 @@ public:
QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h);
void contextMenuEvent(QContextMenuEvent* event);
void mouseDoubleClickEvent(QMouseEvent* event);
void keyPressEvent(QKeyEvent* event);
public slots:
void add(int count, const char** lines);
@ -43,6 +44,8 @@ public slots:
private:
//private functions
void setupContextMenu();
void setSelection(int line);
bool isScriptCommand(QString text, QString cmd);
//private variables
int mIpLine;

View File

@ -1,9 +1,5 @@
#include "BeaHighlight.h"
BeaHighlight::BeaHighlight()
{
}
SEGMENTREG BeaHighlight::ConvertBeaSeg(int beaSeg)
{
switch(beaSeg)

View File

@ -2,27 +2,11 @@
#define BEAHIGHLIGHT_H
#include "QBeaEngine.h"
enum CustomRichTextFlags
{
FlagNone,
FlagColor,
FlagBackground,
FlagAll
};
typedef struct _CustomRichText_t
{
QString text;
QColor textColor;
QColor textBackground;
CustomRichTextFlags flags;
} CustomRichText_t;
#include "RichTextPainter.h"
class BeaHighlight
{
public:
BeaHighlight();
static void PrintRtfInstruction(QList<CustomRichText_t>* richText, const DISASM* MyDisasm);
private:
static SEGMENTREG ConvertBeaSeg(int beaSeg);