* 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:
@@ -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();
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
Reference in New Issue
Block a user