Use QTextDocument instead of html to build text display

Continued work on rendering disassembly level text.
This commit is contained in:
nemerle 2016-05-05 16:06:06 +02:00
parent 6ade935e37
commit 4cc3b41e64
6 changed files with 413 additions and 246 deletions

View File

@ -98,11 +98,7 @@ static void toStructuredText(STKFRAME &stk,IStructuredTextTarget *out, int level
out->prtt(QString(" gap len = %1h").arg(maxlevel - curlevel,0,16));
}
}
static void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
out->prtt("LLINST");
out->addEOL();
}
extern void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level);
static void toStructuredText(ICODE &stk,IStructuredTextTarget *out, int level) {
if(level==0) {

View File

@ -18,6 +18,7 @@
#include <iomanip>
#include <stdio.h>
#include <string.h>
#include "src/ui/StructuredTextTarget.h"
// Note: for the time being, there is no interactive disassembler
// for unix
@ -768,5 +769,137 @@ void LLInst::flops(QTextStream &out)
}
}
}
/****************************************************************************
* formatRM
***************************************************************************/
static void formatRM(IStructuredTextTarget *out,const LLOperand &pm)
{
if (pm.segOver)
{
out->prtt(Machine_X86::regName(pm.segOver)+':');
}
if (pm.regi == rUNDEF)
{
out->prtt(QString("[")+strHex((uint32_t)pm.off)+"]");
}
else if (pm.isReg())
{
out->prtt(Machine_X86::regName(pm.regi));
}
else if (pm.off)
{
if (pm.off < 0)
{
out->prtt("["+Machine_X86::regName(pm.regi)+"-"+strHex((uint32_t)(- pm.off))+"]");
}
else
{
out->prtt("["+Machine_X86::regName(pm.regi)+"+"+strHex((uint32_t)(pm.off))+"]");
}
}
else
out->prtt("["+Machine_X86::regName(pm.regi)+"]");
}
static void strDst(IStructuredTextTarget *out,uint32_t flg, const LLOperand &pm)
{
/* Immediates to memory require size descriptor */
//os << setw(WID_PTR);
if ((flg & I) and not pm.isReg()) {
out->addTaggedString(XT_Keyword,szPtr[flg&B]);
}
formatRM(out,pm);
}
static void strSrc(IStructuredTextTarget *out,LLInst *insn,bool skip_comma=false)
{
if(false==skip_comma)
out->prtt(", ");
if (insn->testFlags(I))
out->addTaggedString(XT_Number,strHex(insn->src().getImm2()));
else if (insn->testFlags(IM_SRC)) /* level 2 */
out->addTaggedString(XT_Symbol,"dx:ax");
else
formatRM(out,insn->src());
}
void toStructuredText(LLInst *insn,IStructuredTextTarget *out, int level) {
const LLInst &inst(*insn);
QString opcode = Machine_X86::opcodeName(insn->getOpcode());
out->addSpace(4);
out->addTaggedString(XT_Number,strHex(insn->label));
out->addSpace(4);
out->addTaggedString(XT_Keyword,Machine_X86::opcodeName(insn->getOpcode()),insn);
out->addSpace(2);
switch(insn->getOpcode()) {
case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
strDst(out,insn->getFlag(), insn->m_dst);
strSrc(out,insn);
break;
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
case iROR:
strDst(out,insn->getFlag() | I, insn->m_dst);
if(insn->testFlags(I))
strSrc(out,insn);
else {
out->prtt(", ");
out->addTaggedString(XT_Symbol,"cl");
}
break;
case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
strDst(out,insn->getFlag() | I, insn->m_dst);
break;
case iPUSH:
if (inst.testFlags(I))
{
out->addTaggedString(XT_Number,strHex(inst.src().getImm2()));
}
else
{
strDst(out,insn->getFlag() | I, insn->m_dst);
}
break;
case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
if (inst.testFlags(I))
{
strDst(out,insn->getFlag(), insn->m_dst);
out->prtt(", ");
formatRM(out, inst.src());
strSrc(out,insn);
}
else
strDst(out,insn->getFlag() | I, insn->m_dst);
break;
case iLDS: case iLES: case iBOUND:
strDst(out,inst.getFlag(), inst.m_dst);
out->prtt(", ");
out->addTaggedString(XT_Keyword,"dword ptr");
strSrc(out,insn,true);
break;
case iJB: case iJBE: case iJAE: case iJA:
case iJL: case iJLE: case iJGE: case iJG:
case iJE: case iJNE: case iJS: case iJNS:
case iJO: case iJNO: case iJP: case iJNP:
case iJCXZ:case iLOOP: case iLOOPE:case iLOOPNE:
case iJMP: case iJMPF:
/* Check if there is a symbol here */
{
// ICODE *lab=pc.GetIcode(inst.src().getImm2());
// selectTable(Label);
// if ((inst.src().getImm2() < (uint32_t)numIcode) and /* Ensure in range */
// readVal(operands_s, lab->ll()->label, nullptr))
// {
// break; /* Symbolic label. Done */
// }
}
break;
}
out->addEOL();
}

View File

@ -9,6 +9,14 @@ FunctionViewWidget::FunctionViewWidget(QWidget *parent) :
ui(new Ui::FunctionViewWidget)
{
ui->setupUi(this);
m_current_rendering = new QTextDocument(ui->textEdit);
m_doc_cursor = new QTextCursor(m_current_rendering);
ui->textEdit->setTextBackgroundColor(Qt::black);
m_current_format = m_doc_cursor->blockFormat();
m_current_format.setNonBreakableLines(true); // each block is single line
m_current_format.setBackground(Qt::black);
m_chars_format.setBackground(Qt::black);
m_chars_format.setForeground(Qt::white);
//ui->label->setTextFormat(Qt::RichText);
}
@ -19,21 +27,33 @@ FunctionViewWidget::~FunctionViewWidget()
void FunctionViewWidget::prtt(const char *s)
{
m_doc_cursor->insertText(s);
collected_text+=s;
//collected_text+="<br>";
}
void FunctionViewWidget::prtt(const QString &s)
{
m_doc_cursor->insertText(s);
collected_text+=s;
//collected_text+="<br>";
}
void FunctionViewWidget::addEOL()
{
m_doc_cursor->insertBlock(m_current_format);
m_doc_cursor->setBlockFormat(m_current_format);
}
void FunctionViewWidget::TAGbegin(TAG_TYPE tag_type, void *p)
{
QColor col= RenderTag_2_Color(tag_type);
switch(tag_type)
{
case XT_Function:
collected_text+="<body style='color: #FFFFFF; background-color: #000000'>";
m_current_rendering->clear();
m_chars_format.setForeground(Qt::white);
m_doc_cursor->setBlockFormat(m_current_format);
m_doc_cursor->setCharFormat(m_chars_format);
break;
case XT_FuncName:
case XT_Symbol:
@ -42,7 +62,8 @@ void FunctionViewWidget::TAGbegin(TAG_TYPE tag_type, void *p)
case XT_Number:
case XT_AsmOffset:
case XT_AsmLabel:
collected_text+="<font color='"+col.name()+"'>";
m_chars_format.setForeground(col);
m_doc_cursor->setCharFormat(m_chars_format);
break;
default:
qDebug()<<"Tag type:"<<tag_type;
@ -56,13 +77,11 @@ void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
{
collected_text+="</body>";
// TODO: What about attributes with spaces?
collected_text.replace(" ", "&nbsp;&nbsp;");
QFile res("result.html");
res.open(QFile::WriteOnly);
res.write(collected_text.toUtf8());
res.write(m_current_rendering->toHtml().toUtf8());
res.close();
collected_text.replace(QChar('\n'),"<br>");
ui->textEdit->setHtml(collected_text);
ui->textEdit->setDocument(m_current_rendering);
collected_text.clear();
break;
}
@ -73,7 +92,9 @@ void FunctionViewWidget::TAGend(TAG_TYPE tag_type)
case XT_Number:
case XT_AsmOffset:
case XT_AsmLabel:
collected_text+="</font>";
m_chars_format.setForeground(Qt::white);
m_doc_cursor->setCharFormat(m_chars_format);
m_doc_cursor->setBlockFormat(m_current_format);
break;
default:
qDebug()<<"Tag end:"<<tag_type;

View File

@ -1,9 +1,12 @@
#ifndef FUNCTIONVIEWWIDGET_H
#define FUNCTIONVIEWWIDGET_H
#include <QWidget>
#include "StructuredTextTarget.h"
#include "RenderTags.h"
#include <QWidget>
#include <QTextDocument>
#include <QTextBlockFormat>
//#include "XmlPrt.h"
namespace Ui {
class FunctionViewWidget;
@ -11,12 +14,16 @@ class FunctionViewWidget;
class FunctionViewWidget : public QWidget,public IStructuredTextTarget
{
Q_OBJECT
QTextDocument *m_current_rendering;
QTextCursor* m_doc_cursor;
QTextBlockFormat m_current_format;
QTextCharFormat m_chars_format;
public:
explicit FunctionViewWidget(QWidget *parent = 0);
~FunctionViewWidget();
void prtt(const char * s);
void prtt(const QString &s);
void addEOL() override;
void TAGbegin(enum TAG_TYPE tag_type, void * p);
void TAGend(enum TAG_TYPE tag_type);
private:

View File

@ -16,9 +16,22 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="textEdit">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Corbel'; font-size:10pt; font-weight:400; font-style:normal;&quot; bgcolor=&quot;#000000&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>

View File

@ -7,10 +7,7 @@ public:
virtual void TAGend(TAG_TYPE t)=0;
virtual void prtt(const QString &v)=0;
virtual void addEOL() // some targets might want to disable newlines
{
prtt("\n");
}
virtual void addEOL() = 0; // some targets might want to disable newlines
void addSpace(int n=1) {
while(n--)
prtt(" ");