* Resolved a TODO and implemented an is_valid_utf8() function that replaces the

former is_valid_ascii(). This function is now also exported in the header.
* Some cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28975 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-01-21 08:30:24 +00:00
parent 2409f4caa6
commit 8bc239bc55
2 changed files with 146 additions and 103 deletions
+71 -37
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2006, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2004-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * 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() // these are determined by the implementation of DataView::ConvertLine()
/** This function checks if the buffer contains a valid ASCII /*! This function checks if the buffer contains a valid UTF-8
* string, following the convention from the DataView::ConvertLine() string, following the convention from the DataView::ConvertLine()
* method: everything that's not replaced by a '.' there will be method: everything that's not replaced by a '.' will be accepted.
* accepted. */
*/
// ToDo: a valid UTF-8 string would be nicer...
bool 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++) { for (size_t i = 0; i < size; i++) {
// accept a terminating null byte // accept a terminating null byte
if (i == size - 1 && data[0] == '\0') if (i == size - 1 && data[0] == '\0')
return true; 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; 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; return true;
@@ -90,14 +124,14 @@ DataView::~DataView()
} }
void void
DataView::DetachedFromWindow() DataView::DetachedFromWindow()
{ {
fEditor.StopWatching(this); fEditor.StopWatching(this);
} }
void void
DataView::AttachedToWindow() DataView::AttachedToWindow()
{ {
fEditor.StartWatching(this); fEditor.StartWatching(this);
@@ -107,7 +141,7 @@ DataView::AttachedToWindow()
} }
void void
DataView::UpdateFromEditor(BMessage *message) DataView::UpdateFromEditor(BMessage *message)
{ {
if (fData == NULL) if (fData == NULL)
@@ -258,7 +292,7 @@ DataView::MessageReceived(BMessage *message)
} }
void void
DataView::Copy() DataView::Copy()
{ {
if (!be_clipboard->Lock()) if (!be_clipboard->Lock())
@@ -273,7 +307,7 @@ DataView::Copy()
clip->AddData(B_FILE_MIME_TYPE, B_MIME_TYPE, data, length); 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); clip->AddData("text/plain", B_MIME_TYPE, data, length);
be_clipboard->Commit(); be_clipboard->Commit();
@@ -283,7 +317,7 @@ DataView::Copy()
} }
void void
DataView::Paste() DataView::Paste()
{ {
if (!be_clipboard->Lock()) 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) DataView::Draw(BRect updateRect)
{ {
if (fData == NULL || fFileSize == 0) if (fData == NULL || fFileSize == 0)
@@ -369,7 +403,7 @@ DataView::Draw(BRect updateRect)
} }
BRect BRect
DataView::DataBounds(bool inView) const DataView::DataBounds(bool inView) const
{ {
return BRect(0, 0, 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) DataView::PositionAt(view_focus focus, BPoint point, view_focus *_newFocus)
{ {
// clip the point into our data bounds // clip the point into our data bounds
@@ -727,7 +761,7 @@ DataView::InvalidateRange(int32 start, int32 end)
int32 startLine = start / kBlockSize; int32 startLine = start / kBlockSize;
int32 endLine = end / kBlockSize; int32 endLine = end / kBlockSize;
if (endLine > startLine) { if (endLine > startLine) {
start = startLine * kBlockSize; start = startLine * kBlockSize;
end = (endLine + 1) * kBlockSize - 1; end = (endLine + 1) * kBlockSize - 1;
@@ -747,7 +781,7 @@ DataView::InvalidateRange(int32 start, int32 end)
} }
void void
DataView::MakeVisible(int32 position) DataView::MakeVisible(int32 position)
{ {
if (position < 0 || position > int32(fDataSize) - 1) if (position < 0 || position > int32(fDataSize) - 1)
@@ -798,7 +832,7 @@ DataView::DataAt(int32 start)
} }
void void
DataView::SetBase(base_type type) DataView::SetBase(base_type type)
{ {
if (fBase == type) if (fBase == type)
@@ -809,7 +843,7 @@ DataView::SetBase(base_type type)
} }
void void
DataView::SetFocus(view_focus which) DataView::SetFocus(view_focus which)
{ {
if (which == fFocus) if (which == fFocus)
@@ -821,7 +855,7 @@ DataView::SetFocus(view_focus which)
} }
void void
DataView::SetActive(bool active) DataView::SetActive(bool active)
{ {
if (active == fIsActive) if (active == fIsActive)
@@ -841,7 +875,7 @@ DataView::SetActive(bool active)
} }
void void
DataView::WindowActivated(bool active) DataView::WindowActivated(bool active)
{ {
BView::WindowActivated(active); BView::WindowActivated(active);
@@ -849,7 +883,7 @@ DataView::WindowActivated(bool active)
} }
void void
DataView::MakeFocus(bool focus) DataView::MakeFocus(bool focus)
{ {
bool previous = IsFocus(); bool previous = IsFocus();
@@ -865,7 +899,7 @@ DataView::MakeFocus(bool focus)
} }
void void
DataView::UpdateScroller() DataView::UpdateScroller()
{ {
float width, height; float width, height;
@@ -940,7 +974,7 @@ DataView::InitiateDrag(view_focus focus)
size_t length = fEnd + 1 - fStart; size_t length = fEnd + 1 - fStart;
drag->AddData(B_FILE_MIME_TYPE, B_MIME_TYPE, data, length); 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); drag->AddData("text/plain", B_MIME_TYPE, data, length);
// get a frame that contains the whole selection - SelectionFrame() // get a frame that contains the whole selection - SelectionFrame()
@@ -968,7 +1002,7 @@ DataView::InitiateDrag(view_focus focus)
} }
void void
DataView::MouseDown(BPoint where) DataView::MouseDown(BPoint where)
{ {
MakeFocus(true); MakeFocus(true);
@@ -1013,7 +1047,7 @@ DataView::MouseDown(BPoint where)
} }
void void
DataView::MouseMoved(BPoint where, uint32 transit, const BMessage *dragMessage) DataView::MouseMoved(BPoint where, uint32 transit, const BMessage *dragMessage)
{ {
if (transit == B_EXITED_VIEW && fDragMessageSize > 0) { 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) DataView::MouseUp(BPoint where)
{ {
fMouseSelectionStart = fKeySelectionStart = -1; fMouseSelectionStart = fKeySelectionStart = -1;
} }
void void
DataView::KeyDown(const char *bytes, int32 numBytes) DataView::KeyDown(const char *bytes, int32 numBytes)
{ {
int32 modifiers; int32 modifiers;
@@ -1227,7 +1261,7 @@ DataView::KeyDown(const char *bytes, int32 numBytes)
case B_DELETE: case B_DELETE:
SetSelection(fStart, fStart); SetSelection(fStart, fStart);
// to make sure only the cursor is selected // to make sure only the cursor is selected
if (fFocus == kHexFocus) { if (fFocus == kHexFocus) {
const uint8 *data = DataAt(fStart); const uint8 *data = DataAt(fStart);
if (data == NULL) if (data == NULL)
@@ -1290,7 +1324,7 @@ DataView::SetFont(const BFont *font, uint32 properties)
} }
float float
DataView::FontSize() const DataView::FontSize() const
{ {
BFont font; BFont font;
@@ -1300,7 +1334,7 @@ DataView::FontSize() const
} }
void void
DataView::SetFontSize(float point) DataView::SetFontSize(float point)
{ {
bool fit = (point == 0.0f); bool fit = (point == 0.0f);
@@ -1326,7 +1360,7 @@ DataView::SetFontSize(float point)
} }
void void
DataView::GetPreferredSize(float *_width, float *_height) DataView::GetPreferredSize(float *_width, float *_height)
{ {
BRect bounds = DataBounds(); BRect bounds = DataBounds();
+75 -66
View File
@@ -1,14 +1,14 @@
/* /*
* Copyright 2004, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2004-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef DATA_VIEW_H #ifndef DATA_VIEW_H
#define DATA_VIEW_H #define DATA_VIEW_H
#include <View.h>
#include <String.h>
#include <Path.h> #include <Path.h>
#include <String.h>
#include <View.h>
class DataEditor; class DataEditor;
@@ -25,83 +25,90 @@ enum view_focus {
}; };
class DataView : public BView { class DataView : public BView {
public: public:
DataView(BRect rect, DataEditor &editor); DataView(BRect rect, DataEditor& editor);
virtual ~DataView(); virtual ~DataView();
virtual void DetachedFromWindow(); virtual void DetachedFromWindow();
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage *message); virtual void MessageReceived(BMessage* message);
virtual void Draw(BRect updateRect); virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where); virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit, const BMessage *message); virtual void MouseMoved(BPoint where, uint32 transit,
virtual void MouseUp(BPoint where); 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 WindowActivated(bool active);
virtual void MakeFocus(bool focus); virtual void MakeFocus(bool focus);
virtual void FrameResized(float width, float height); virtual void FrameResized(float width, float height);
virtual void SetFont(const BFont *font, uint32 properties = B_FONT_ALL); virtual void SetFont(const BFont* font,
virtual void GetPreferredSize(float *_width, float *_height); uint32 properties = B_FONT_ALL);
virtual void GetPreferredSize(float* _width, float* _height);
bool FontSizeFitsBounds() const { return fFitFontSize; } bool FontSizeFitsBounds() const { return fFitFontSize; }
float FontSize() const; float FontSize() const;
void SetFontSize(float point); void SetFontSize(float point);
void UpdateScroller(); void UpdateScroller();
void MakeVisible(int32 position); void MakeVisible(int32 position);
void SetSelection(int32 start, int32 end, view_focus focus = kNoFocus); void SetSelection(int32 start, int32 end,
void GetSelection(int32 &start, int32 &end); view_focus focus = kNoFocus);
void InvalidateRange(int32 start, int32 end); void GetSelection(int32& start, int32& end);
void InvalidateRange(int32 start, int32 end);
base_type Base() const { return fBase; } base_type Base() const { return fBase; }
void SetBase(base_type type); void SetBase(base_type type);
const uint8 *DataAt(int32 start); const uint8* DataAt(int32 start);
private: private:
BRect DataBounds(bool inView = false) const; BRect DataBounds(bool inView = false) const;
BRect SelectionFrame(view_focus which, int32 start, int32 end); BRect SelectionFrame(view_focus which, int32 start,
int32 PositionAt(view_focus focus, BPoint point, view_focus *_newFocus = NULL); int32 end);
int32 PositionAt(view_focus focus, BPoint point,
view_focus* _newFocus = NULL);
void DrawSelectionFrame(view_focus which); void DrawSelectionFrame(view_focus which);
void DrawSelectionBlock(view_focus which, int32 start, int32 end); void DrawSelectionBlock(view_focus which, int32 start,
void DrawSelectionBlock(view_focus which); int32 end);
void DrawSelection(bool frameOnly = false); void DrawSelectionBlock(view_focus which);
void SetActive(bool active); void DrawSelection(bool frameOnly = false);
void SetFocus(view_focus which); void SetActive(bool active);
void SetFocus(view_focus which);
void UpdateFromEditor(BMessage *message = NULL); void UpdateFromEditor(BMessage* message = NULL);
void ConvertLine(char *line, off_t offset, const uint8 *buffer, size_t size); void ConvertLine(char* line, off_t offset,
const uint8* buffer, size_t size);
bool AcceptsDrop(const BMessage *message); bool AcceptsDrop(const BMessage* message);
void InitiateDrag(view_focus focus); void InitiateDrag(view_focus focus);
void Copy(); void Copy();
void Paste(); void Paste();
DataEditor &fEditor; DataEditor& fEditor;
int32 fPositionLength; int32 fPositionLength;
uint8 *fData; uint8* fData;
size_t fDataSize; size_t fDataSize;
off_t fFileSize; off_t fFileSize;
size_t fSizeInView; size_t fSizeInView;
off_t fOffset; off_t fOffset;
float fAscent; float fAscent;
int32 fFontHeight; int32 fFontHeight;
float fCharWidth; float fCharWidth;
view_focus fFocus; view_focus fFocus;
base_type fBase; base_type fBase;
bool fIsActive; bool fIsActive;
int32 fStart, fEnd; int32 fStart, fEnd;
int32 fMouseSelectionStart; int32 fMouseSelectionStart;
int32 fKeySelectionStart; int32 fKeySelectionStart;
int32 fBitPosition; int32 fBitPosition;
bool fFitFontSize; bool fFitFontSize;
int32 fDragMessageSize; int32 fDragMessageSize;
int32 fStoredStart, fStoredEnd; int32 fStoredStart, fStoredEnd;
}; };
static const uint32 kMsgBaseType = 'base'; static const uint32 kMsgBaseType = 'base';
@@ -113,4 +120,6 @@ static const uint32 kDataViewCursorPosition = 'curs';
static const uint32 kDataViewSelection = 'dsel'; static const uint32 kDataViewSelection = 'dsel';
static const uint32 kDataViewPreferredSize = 'dvps'; static const uint32 kDataViewPreferredSize = 'dvps';
extern bool is_valid_utf8(uint8* data, size_t size);
#endif /* DATA_VIEW_H */ #endif /* DATA_VIEW_H */