mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-30 00:05:05 +00:00
Highlight in red changes in the Hexdump Widget (#1880)
* Highlight changes in the Hexdump Widget
This commit is contained in:
parent
d0da81b592
commit
c1093f3971
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user