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
This commit is contained in:
Axel Dörfler 2004-02-25 17:36:12 +00:00
parent 4897914eca
commit 32d3a4554d
2 changed files with 111 additions and 3 deletions

View File

@ -9,10 +9,14 @@
#include <Window.h>
#include <ScrollBar.h>
#include <Autolock.h>
#include <Clipboard.h>
#include <Mime.h>
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;
}
}
}

View File

@ -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';