From 32d3a4554d8febe3c0b7b58600bc5ff9ec795f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 25 Feb 2004 17:36:12 +0000 Subject: [PATCH] Added a method to access DataView's internal buffer. Implemented editing functionality for both focus types. Optimized InvalidateRange() if the update spans over the whole view. Now resets the cursor position/selection when the editor offset changed. UpdateFromEditor() now takes the range of the size into account. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6739 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/diskprobe/DataView.cpp | 111 +++++++++++++++++++++++++++++++- src/apps/diskprobe/DataView.h | 3 + 2 files changed, 111 insertions(+), 3 deletions(-) diff --git a/src/apps/diskprobe/DataView.cpp b/src/apps/diskprobe/DataView.cpp index 774518752d..19c9206ee6 100644 --- a/src/apps/diskprobe/DataView.cpp +++ b/src/apps/diskprobe/DataView.cpp @@ -9,10 +9,14 @@ #include #include +#include #include #include +typedef uint32 addr_t; + // this one is not yet defined in a public place + static const uint32 kBlockSize = 16; static const uint32 kHorizontalSpace = 8; static const uint32 kVerticalSpace = 4; @@ -60,6 +64,7 @@ DataView::DataView(BRect rect, DataEditor &editor) if (fEditor.Lock()) { fDataSize = fEditor.ViewSize(); + fOffset = fEditor.ViewOffset(); fEditor.Unlock(); } else fDataSize = 512; @@ -92,15 +97,33 @@ DataView::AttachedToWindow() void -DataView::UpdateFromEditor(BMessage */*message*/) +DataView::UpdateFromEditor(BMessage *message) { if (fData == NULL) return; if (fEditor.Lock()) { - fOffset = fEditor.ViewOffset(); fFileSize = fEditor.FileSize(); + // get the range of the changes + + int32 start = 0, end = fDataSize - 1; + off_t offset, size; + if (message != NULL + && message->FindInt64("offset", &offset) == B_OK + && message->FindInt64("size", &size) == B_OK) { + if (offset > fOffset + fDataSize + || offset + size < fOffset) { + // the changes are not within our scope, so we can ignore them + return; + } + + if (offset > fOffset) + start = offset - fOffset; + if (offset + size < fOffset + fDataSize) + end = offset + size - fOffset; + } + if (fOffset + fDataSize > fFileSize) fSizeInView = fFileSize - fOffset; else @@ -108,11 +131,12 @@ DataView::UpdateFromEditor(BMessage */*message*/) const uint8 *data; if (fEditor.GetViewBuffer(&data) == B_OK) + // ToDo: copy only the relevant part memcpy(fData, data, fDataSize); fEditor.Unlock(); - Invalidate(); + InvalidateRange(start, end); } } @@ -126,6 +150,10 @@ DataView::MessageReceived(BMessage *message) UpdateFromEditor(message); break; + case kMsgDataEditorOffsetChange: + SetSelection(0, 0); + break; + case kMsgBaseType: { int32 type; @@ -541,6 +569,8 @@ DataView::SetSelection(int32 start, int32 end, view_focus focus) fEnd = end; DrawSelection(); + + fBitPosition = 0; } @@ -555,6 +585,11 @@ DataView::GetSelection(int32 &start, int32 &end) void DataView::InvalidateRange(int32 start, int32 end) { + if (start <= 0 && end >= int32(fDataSize) - 1) { + Invalidate(); + return; + } + int32 startLine = start / kBlockSize; int32 endLine = end / kBlockSize; @@ -618,6 +653,16 @@ DataView::MakeVisible(int32 position) } +const uint8 * +DataView::DataAt(int32 start) +{ + if (start < 0 || start >= int32(fSizeInView) || fData == NULL) + return NULL; + + return fData + start; +} + + void DataView::SetBase(base_type type) { @@ -865,6 +910,66 @@ DataView::KeyDown(const char *bytes, int32 numBytes) SetFocus(fFocus == kHexFocus ? kAsciiFocus : kHexFocus); MakeVisible(fStart); break; + + case B_FUNCTION_KEY: + // this is ignored + break; + + case B_BACKSPACE: + if (fBitPosition == 0) + SetSelection(fStart - 1, fStart - 1); + + if (fFocus == kHexFocus) + fBitPosition = (fBitPosition + 4) % 8; + + // supposed to fall through + case B_DELETE: + { + BAutolock locker(fEditor); + + if (fFocus == kHexFocus) { + const uint8 *data = DataAt(fStart); + if (data == NULL) + break; + + uint8 c = data[0] & (fBitPosition == 0 ? 0x0f : 0xf0); + // mask out region to be cleared + + fEditor.Replace(fOffset + fStart, &c, 1); + } else + fEditor.Replace(fOffset + fStart, (const uint8 *)"", 1); + break; + } + + default: + { + BAutolock locker(fEditor); + + if (fFocus == kHexFocus) { + // only hexadecimal characters are allowed to be entered + const uint8 *data = DataAt(fStart); + uint8 c = bytes[0]; + if (c >= 'A' && c <= 'F') + c += 'A' - 'a'; + const char *hexNumbers = "0123456789abcdef"; + addr_t number; + if (data == NULL || (number = (addr_t)strchr(hexNumbers, c)) == NULL) + break; + + number -= (addr_t)hexNumbers; + fBitPosition = (fBitPosition + 4) % 8; + + c = (data[0] & (fBitPosition ? 0x0f : 0xf0)) | (number << fBitPosition); + // mask out overwritten region and bit-wise or the number to be inserted + + if (fEditor.Replace(fOffset + fStart, &c, 1) == B_OK && fBitPosition == 0) + SetSelection(fStart + 1, fStart + 1); + } else { + if (fEditor.Replace(fOffset + fStart, (const uint8 *)bytes, numBytes) == B_OK) + SetSelection(fStart + 1, fStart + 1); + } + break; + } } } diff --git a/src/apps/diskprobe/DataView.h b/src/apps/diskprobe/DataView.h index 5b1310227e..c673fcec6e 100644 --- a/src/apps/diskprobe/DataView.h +++ b/src/apps/diskprobe/DataView.h @@ -59,6 +59,8 @@ class DataView : public BView { base_type Base() const { return fBase; } void SetBase(base_type type); + const uint8 *DataAt(int32 start); + private: BRect DataBounds(bool inView = false) const; BRect SelectionFrame(view_focus which, int32 start, int32 end); @@ -88,6 +90,7 @@ class DataView : public BView { bool fIsActive; int32 fStart, fEnd; int32 fMouseSelectionStart; + int32 fBitPosition; }; static const uint32 kMsgBaseType = 'base';