Highlight in red changes in the Hexdump Widget (#1880)

* Highlight changes in the Hexdump Widget
This commit is contained in:
GustavoLCR 2019-11-30 11:55:29 -03:00 committed by Itay Cohen
parent d0da81b592
commit c1093f3971
3 changed files with 64 additions and 14 deletions

View File

@ -124,6 +124,7 @@ HexWidget::HexWidget(QWidget *parent) :
startAddress = 0ULL;
cursor.address = 0ULL;
data.reset(new MemoryData());
oldData.reset(new MemoryData());
fetchData();
updateCursorMeta();
@ -206,6 +207,27 @@ void HexWidget::setItemGroupSize(int size)
viewport()->update();
}
/**
* @brief Checks if Item at the address changed compared to the last read data.
* @param address Address of Item to be compared.
* @return True if Item is different, False if Item is equal or last read didn't contain the address.
* @see HexWidget#readItem
*
* Checks if current Item at the address changed compared to the last read data.
* It is assumed that the current read data buffer contains the address.
*/
bool HexWidget::isItemDifferentAt(uint64_t address) {
if (address >= oldData->minIndex() && address < oldData->maxIndex()) {
uint64_t itemOffset = address - startAddress;
QVariant curItem = readItem(itemOffset);
data.swap(oldData);
QVariant oldItem = readItem(itemOffset);
data.swap(oldData);
return (oldItem != curItem);
}
return false;
}
void HexWidget::updateCounts()
{
actionHexPairs->setEnabled(rowSizeBytes > 1 && itemByteLen == 1
@ -335,6 +357,7 @@ void HexWidget::updateColors()
printableColor = Config()->getColor("ai.write");
defColor = Config()->getColor("btext");
addrColor = Config()->getColor("func_var_addr");
diffColor = Config()->getColor("graph.diff.unmatch");
updateCursorMeta();
viewport()->update();
@ -465,13 +488,13 @@ void HexWidget::wheelEvent(QWheelEvent *event)
startAddress = 0;
} else if (delta > 0 && data->maxIndex() < static_cast<uint64_t>(bytesPerScreen())) {
startAddress = 0;
} else if (delta > 0
&& (data->maxIndex() - startAddress) <= static_cast<uint64_t>(bytesPerScreen() + delta - 1)) {
startAddress = (data->maxIndex() - bytesPerScreen()) + 1;
} else {
startAddress += delta;
}
fetchData();
if ((data->maxIndex() - startAddress) <= static_cast<uint64_t>(bytesPerScreen() + delta - 1)) {
startAddress = (data->maxIndex() - bytesPerScreen()) + 1;
}
if (cursor.address >= startAddress && cursor.address <= lastVisibleAddr()) {
/* Don't enable cursor blinking if selection isn't empty */
cursorEnabled = selection.isEmpty();
@ -756,6 +779,9 @@ void HexWidget::drawItemArea(QPainter &painter)
if (selection.contains(itemAddr) && !cursorOnAscii) {
itemColor = palette().highlightedText().color();
}
if (isItemDifferentAt(itemAddr)) {
itemColor.setRgb(diffColor.rgb());
}
painter.setPen(itemColor);
painter.drawText(itemRect, Qt::AlignVCenter, itemString);
itemRect.translate(itemWidth(), 0);
@ -789,8 +815,12 @@ void HexWidget::drawAsciiArea(QPainter &painter)
charRect.moveLeft(asciiArea.left());
for (int j = 0; j < itemRowByteLen() && address <= data->maxIndex(); ++j, ++address) {
ascii = renderAscii(address - startAddress, &color);
if (selection.contains(address) && cursorOnAscii)
if (selection.contains(address) && cursorOnAscii) {
color = palette().highlightedText().color();
}
if (isItemDifferentAt(address)) {
color.setRgb(diffColor.rgb());
}
painter.setPen(color);
/* Dots look ugly. Use fillRect() instead of drawText(). */
if (ascii == '.') {
@ -985,10 +1015,6 @@ void HexWidget::setCursorAddr(BasicCursor addr, bool select)
/* Align start address */
addressValue -= (addressValue % itemRowByteLen());
if (addressValue > (data->maxIndex() - bytesPerScreen()) + 1) {
addressValue = (data->maxIndex() - bytesPerScreen()) + 1;
}
/* FIXME: handling Page Up/Down */
if (addressValue == startAddress + bytesPerScreen()) {
startAddress += itemRowByteLen();
@ -997,6 +1023,10 @@ void HexWidget::setCursorAddr(BasicCursor addr, bool select)
}
fetchData();
if (startAddress > (data->maxIndex() - bytesPerScreen()) + 1) {
startAddress = (data->maxIndex() - bytesPerScreen()) + 1;
}
}
updateCursorMeta();
@ -1192,6 +1222,7 @@ QChar HexWidget::renderAscii(int offset, QColor *color)
void HexWidget::fetchData()
{
data.swap(oldData);
data->fetch(startAddress, bytesPerScreen());
}

View File

@ -75,6 +75,7 @@ public:
virtual void fetch(uint64_t addr, int len) = 0;
virtual const void *dataPtr(uint64_t addr) = 0;
virtual uint64_t maxIndex() = 0;
virtual uint64_t minIndex() = 0;
};
class BufferData : public AbstractData
@ -121,14 +122,20 @@ public:
void fetch(uint64_t address, int length) override
{
// FIXME: reuse data if possible
uint64_t alignedAddr = address & ~(4096ULL - 1);
const uint64_t blockSize = 0x1000ULL;
uint64_t alignedAddr = address & ~(blockSize - 1);
int offset = address - alignedAddr;
int len = (offset + length + (4096 - 1)) & ~(4096 - 1);
int len = (offset + length + (blockSize - 1)) & ~(blockSize - 1);
m_firstBlockAddr = alignedAddr;
m_lastValidAddr = length ? alignedAddr + len - 1 : 0;
if (m_lastValidAddr < m_firstBlockAddr) {
m_lastValidAddr = -1;
len = m_lastValidAddr - m_firstBlockAddr + 1;
}
m_blocks.clear();
uint64_t addr = alignedAddr;
for (int i = 0; i < len / 4096; ++i, addr += 4096) {
m_blocks.append(Core()->ioRead(addr, 4096));
for (int i = 0; i < len / blockSize; ++i, addr += blockSize) {
m_blocks.append(Core()->ioRead(addr, blockSize));
}
}
@ -142,12 +149,18 @@ public:
virtual uint64_t maxIndex() override
{
return UINT64_MAX;
return m_lastValidAddr;
}
virtual uint64_t minIndex() override
{
return m_firstBlockAddr;
}
private:
QVector<QByteArray> m_blocks;
uint64_t m_firstBlockAddr;
uint64_t m_firstBlockAddr = 0;
uint64_t m_lastValidAddr = 0;
};
class HexSelection
@ -298,6 +311,7 @@ private:
void setCursorAddr(BasicCursor addr, bool select = false);
void updateCursorMeta();
void setCursorOnAscii(bool ascii);
bool isItemDifferentAt(uint64_t address);
const QColor itemColor(uint8_t byte);
QVariant readItem(int offset, QColor *color = nullptr);
QString renderItem(int offset, QColor *color = nullptr);
@ -446,6 +460,7 @@ private:
QColor backgroundColor;
QColor defColor;
QColor addrColor;
QColor diffColor;
QColor b0x00Color;
QColor b0x7fColor;
QColor b0xffColor;
@ -469,6 +484,7 @@ private:
QAction *actionCopyAddress;
QAction *actionSelectRange;
std::unique_ptr<AbstractData> oldData;
std::unique_ptr<AbstractData> data;
};

View File

@ -80,6 +80,9 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
connect(Core(), &CutterCore::refreshAll, this, [this]() { refresh(); });
connect(Core(), &CutterCore::instructionChanged, this, [this]() { refresh(); });
connect(Core(), &CutterCore::stackChanged, this, [this]() { refresh(); });
connect(Core(), &CutterCore::registersChanged, this, [this]() { refresh(); });
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::onSeekChanged);
connect(ui->hexTextView, &HexWidget::positionChanged, this, [this](RVA addr) {