diff --git a/src/apps/diskprobe/DataView.cpp b/src/apps/diskprobe/DataView.cpp index 0a43bb2b74..ab0615183e 100644 --- a/src/apps/diskprobe/DataView.cpp +++ b/src/apps/diskprobe/DataView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -28,24 +28,58 @@ static const uint32 kHexByteWidth = 3; // these are determined by the implementation of DataView::ConvertLine() -/** This function checks if the buffer contains a valid ASCII - * string, following the convention from the DataView::ConvertLine() - * method: everything that's not replaced by a '.' there will be - * accepted. - */ - -// ToDo: a valid UTF-8 string would be nicer... - +/*! This function checks if the buffer contains a valid UTF-8 + string, following the convention from the DataView::ConvertLine() + method: everything that's not replaced by a '.' will be accepted. +*/ bool -is_valid_ascii(uint8 *data, size_t size) +is_valid_utf8(uint8 *data, size_t size) { for (size_t i = 0; i < size; i++) { // accept a terminating null byte if (i == size - 1 && data[0] == '\0') return true; - if (data[i] < ' ' || data[i] == 0x7f || data[i] & 0x80) + if ((data[i] & 0x80) == 0) { + // a single byte character + if (data[i] < ' ' || data[i] == 0x7f) + return false; + + continue; + } + + if ((data[i] & 0xc0) == 0x80) { + // not a proper multibyte start return false; + } + + // start of a multibyte character + uint8 mask = 0x80; + uint32 result = (uint32)(data[i++] & 0xff); + + while (result & mask) { + if (mask == 0x02) { + // seven byte char - invalid + return false; + } + + result &= ~mask; + mask >>= 1; + } + + while (i < size && (data[i] & 0xc0) == 0x80) { + result <<= 6; + result += data[i++] & 0x3f; + + mask <<= 1; + if (mask == 0x40) + break; + } + + if (mask != 0x40) { + // not enough bytes in multibyte char + return false; + } } return true; @@ -90,14 +124,14 @@ DataView::~DataView() } -void +void DataView::DetachedFromWindow() { fEditor.StopWatching(this); } -void +void DataView::AttachedToWindow() { fEditor.StartWatching(this); @@ -107,7 +141,7 @@ DataView::AttachedToWindow() } -void +void DataView::UpdateFromEditor(BMessage *message) { if (fData == NULL) @@ -258,7 +292,7 @@ DataView::MessageReceived(BMessage *message) } -void +void DataView::Copy() { if (!be_clipboard->Lock()) @@ -273,7 +307,7 @@ DataView::Copy() clip->AddData(B_FILE_MIME_TYPE, B_MIME_TYPE, data, length); - if (is_valid_ascii(data, length)) + if (is_valid_utf8(data, length)) clip->AddData("text/plain", B_MIME_TYPE, data, length); be_clipboard->Commit(); @@ -283,7 +317,7 @@ DataView::Copy() } -void +void DataView::Paste() { if (!be_clipboard->Lock()) @@ -347,7 +381,7 @@ DataView::ConvertLine(char *line, off_t offset, const uint8 *buffer, size_t size } -void +void DataView::Draw(BRect updateRect) { if (fData == NULL || fFileSize == 0) @@ -369,7 +403,7 @@ DataView::Draw(BRect updateRect) } -BRect +BRect DataView::DataBounds(bool inView) const { return BRect(0, 0, @@ -379,7 +413,7 @@ DataView::DataBounds(bool inView) const } -int32 +int32 DataView::PositionAt(view_focus focus, BPoint point, view_focus *_newFocus) { // clip the point into our data bounds @@ -727,7 +761,7 @@ DataView::InvalidateRange(int32 start, int32 end) int32 startLine = start / kBlockSize; int32 endLine = end / kBlockSize; - + if (endLine > startLine) { start = startLine * kBlockSize; end = (endLine + 1) * kBlockSize - 1; @@ -747,7 +781,7 @@ DataView::InvalidateRange(int32 start, int32 end) } -void +void DataView::MakeVisible(int32 position) { if (position < 0 || position > int32(fDataSize) - 1) @@ -798,7 +832,7 @@ DataView::DataAt(int32 start) } -void +void DataView::SetBase(base_type type) { if (fBase == type) @@ -809,7 +843,7 @@ DataView::SetBase(base_type type) } -void +void DataView::SetFocus(view_focus which) { if (which == fFocus) @@ -821,7 +855,7 @@ DataView::SetFocus(view_focus which) } -void +void DataView::SetActive(bool active) { if (active == fIsActive) @@ -841,7 +875,7 @@ DataView::SetActive(bool active) } -void +void DataView::WindowActivated(bool active) { BView::WindowActivated(active); @@ -849,7 +883,7 @@ DataView::WindowActivated(bool active) } -void +void DataView::MakeFocus(bool focus) { bool previous = IsFocus(); @@ -865,7 +899,7 @@ DataView::MakeFocus(bool focus) } -void +void DataView::UpdateScroller() { float width, height; @@ -940,7 +974,7 @@ DataView::InitiateDrag(view_focus focus) size_t length = fEnd + 1 - fStart; drag->AddData(B_FILE_MIME_TYPE, B_MIME_TYPE, data, length); - if (is_valid_ascii(data, length)) + if (is_valid_utf8(data, length)) drag->AddData("text/plain", B_MIME_TYPE, data, length); // get a frame that contains the whole selection - SelectionFrame() @@ -968,7 +1002,7 @@ DataView::InitiateDrag(view_focus focus) } -void +void DataView::MouseDown(BPoint where) { MakeFocus(true); @@ -1013,7 +1047,7 @@ DataView::MouseDown(BPoint where) } -void +void DataView::MouseMoved(BPoint where, uint32 transit, const BMessage *dragMessage) { if (transit == B_EXITED_VIEW && fDragMessageSize > 0) { @@ -1056,14 +1090,14 @@ DataView::MouseMoved(BPoint where, uint32 transit, const BMessage *dragMessage) } -void +void DataView::MouseUp(BPoint where) { fMouseSelectionStart = fKeySelectionStart = -1; } -void +void DataView::KeyDown(const char *bytes, int32 numBytes) { int32 modifiers; @@ -1227,7 +1261,7 @@ DataView::KeyDown(const char *bytes, int32 numBytes) case B_DELETE: SetSelection(fStart, fStart); // to make sure only the cursor is selected - + if (fFocus == kHexFocus) { const uint8 *data = DataAt(fStart); if (data == NULL) @@ -1290,7 +1324,7 @@ DataView::SetFont(const BFont *font, uint32 properties) } -float +float DataView::FontSize() const { BFont font; @@ -1300,7 +1334,7 @@ DataView::FontSize() const } -void +void DataView::SetFontSize(float point) { bool fit = (point == 0.0f); @@ -1326,7 +1360,7 @@ DataView::SetFontSize(float point) } -void +void DataView::GetPreferredSize(float *_width, float *_height) { BRect bounds = DataBounds(); diff --git a/src/apps/diskprobe/DataView.h b/src/apps/diskprobe/DataView.h index 2a7b3babd3..bc0bfe71bd 100644 --- a/src/apps/diskprobe/DataView.h +++ b/src/apps/diskprobe/DataView.h @@ -1,14 +1,14 @@ /* - * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef DATA_VIEW_H #define DATA_VIEW_H -#include -#include #include +#include +#include class DataEditor; @@ -25,83 +25,90 @@ enum view_focus { }; class DataView : public BView { - public: - DataView(BRect rect, DataEditor &editor); - virtual ~DataView(); +public: + DataView(BRect rect, DataEditor& editor); + virtual ~DataView(); - virtual void DetachedFromWindow(); - virtual void AttachedToWindow(); - virtual void MessageReceived(BMessage *message); - virtual void Draw(BRect updateRect); + virtual void DetachedFromWindow(); + virtual void AttachedToWindow(); + virtual void MessageReceived(BMessage* message); + virtual void Draw(BRect updateRect); - virtual void MouseDown(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, const BMessage *message); - virtual void MouseUp(BPoint where); + virtual void MouseDown(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* message); + virtual void MouseUp(BPoint where); - virtual void KeyDown(const char *bytes, int32 numBytes); + virtual void KeyDown(const char* bytes, int32 numBytes); - virtual void WindowActivated(bool active); - virtual void MakeFocus(bool focus); - virtual void FrameResized(float width, float height); - virtual void SetFont(const BFont *font, uint32 properties = B_FONT_ALL); - virtual void GetPreferredSize(float *_width, float *_height); + virtual void WindowActivated(bool active); + virtual void MakeFocus(bool focus); + virtual void FrameResized(float width, float height); + virtual void SetFont(const BFont* font, + uint32 properties = B_FONT_ALL); + virtual void GetPreferredSize(float* _width, float* _height); - bool FontSizeFitsBounds() const { return fFitFontSize; } - float FontSize() const; - void SetFontSize(float point); + bool FontSizeFitsBounds() const { return fFitFontSize; } + float FontSize() const; + void SetFontSize(float point); - void UpdateScroller(); + void UpdateScroller(); - void MakeVisible(int32 position); - void SetSelection(int32 start, int32 end, view_focus focus = kNoFocus); - void GetSelection(int32 &start, int32 &end); - void InvalidateRange(int32 start, int32 end); + void MakeVisible(int32 position); + void SetSelection(int32 start, int32 end, + view_focus focus = kNoFocus); + void GetSelection(int32& start, int32& end); + void InvalidateRange(int32 start, int32 end); - base_type Base() const { return fBase; } - void SetBase(base_type type); + base_type Base() const { return fBase; } + void SetBase(base_type type); - const uint8 *DataAt(int32 start); + const uint8* DataAt(int32 start); - private: - BRect DataBounds(bool inView = false) const; - BRect SelectionFrame(view_focus which, int32 start, int32 end); - int32 PositionAt(view_focus focus, BPoint point, view_focus *_newFocus = NULL); +private: + BRect DataBounds(bool inView = false) const; + BRect SelectionFrame(view_focus which, int32 start, + int32 end); + int32 PositionAt(view_focus focus, BPoint point, + view_focus* _newFocus = NULL); - void DrawSelectionFrame(view_focus which); - void DrawSelectionBlock(view_focus which, int32 start, int32 end); - void DrawSelectionBlock(view_focus which); - void DrawSelection(bool frameOnly = false); - void SetActive(bool active); - void SetFocus(view_focus which); + void DrawSelectionFrame(view_focus which); + void DrawSelectionBlock(view_focus which, int32 start, + int32 end); + void DrawSelectionBlock(view_focus which); + void DrawSelection(bool frameOnly = false); + void SetActive(bool active); + void SetFocus(view_focus which); - void UpdateFromEditor(BMessage *message = NULL); - void ConvertLine(char *line, off_t offset, const uint8 *buffer, size_t size); + void UpdateFromEditor(BMessage* message = NULL); + void ConvertLine(char* line, off_t offset, + const uint8* buffer, size_t size); - bool AcceptsDrop(const BMessage *message); - void InitiateDrag(view_focus focus); - void Copy(); - void Paste(); + bool AcceptsDrop(const BMessage* message); + void InitiateDrag(view_focus focus); + void Copy(); + void Paste(); - DataEditor &fEditor; - int32 fPositionLength; - uint8 *fData; - size_t fDataSize; - off_t fFileSize; - size_t fSizeInView; - off_t fOffset; - float fAscent; - int32 fFontHeight; - float fCharWidth; - view_focus fFocus; - base_type fBase; - bool fIsActive; - int32 fStart, fEnd; - int32 fMouseSelectionStart; - int32 fKeySelectionStart; - int32 fBitPosition; - bool fFitFontSize; - int32 fDragMessageSize; - int32 fStoredStart, fStoredEnd; + DataEditor& fEditor; + int32 fPositionLength; + uint8* fData; + size_t fDataSize; + off_t fFileSize; + size_t fSizeInView; + off_t fOffset; + float fAscent; + int32 fFontHeight; + float fCharWidth; + view_focus fFocus; + base_type fBase; + bool fIsActive; + int32 fStart, fEnd; + int32 fMouseSelectionStart; + int32 fKeySelectionStart; + int32 fBitPosition; + bool fFitFontSize; + int32 fDragMessageSize; + int32 fStoredStart, fStoredEnd; }; static const uint32 kMsgBaseType = 'base'; @@ -113,4 +120,6 @@ static const uint32 kDataViewCursorPosition = 'curs'; static const uint32 kDataViewSelection = 'dsel'; static const uint32 kDataViewPreferredSize = 'dvps'; +extern bool is_valid_utf8(uint8* data, size_t size); + #endif /* DATA_VIEW_H */