Implemented find functionality. The find panel is still missing though, it
just searches for "test". The find itself is implemented in DataEditor::Find() which sets the editor in read-only mode and searches for the specified data. It will update a progress monitor, it will find data no matter if it's on a view size break, and it is interruptible at any time. The DataEditor change methods now respect the read-only mode, and return B_NOT_ALLOWED in this case. Renamed the UpdateLooper class to EditorLooper class, since it now also runs the find action. The ProbeView class now maintains the "Find Again" menu item; it's target message always contains the item that last searched for. The HeaderView will now show a "Stop" button while the search operation is in progress; it also acts as the Find() progress monitor. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6789 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -383,6 +383,8 @@ DataEditor::SetTo(entry_ref &ref, const char *attribute)
|
|||||||
status_t
|
status_t
|
||||||
DataEditor::SetTo(BEntry &entry, const char *attribute)
|
DataEditor::SetTo(BEntry &entry, const char *attribute)
|
||||||
{
|
{
|
||||||
|
fSize = 0;
|
||||||
|
|
||||||
struct stat stat;
|
struct stat stat;
|
||||||
stat.st_mode = 0;
|
stat.st_mode = 0;
|
||||||
|
|
||||||
@@ -510,6 +512,9 @@ DataEditor::AddChange(DataChange *change)
|
|||||||
status_t
|
status_t
|
||||||
DataEditor::Replace(off_t offset, const uint8 *data, size_t length)
|
DataEditor::Replace(off_t offset, const uint8 *data, size_t length)
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly())
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
BAutolock locker(this);
|
BAutolock locker(this);
|
||||||
|
|
||||||
if (offset >= fSize)
|
if (offset >= fSize)
|
||||||
@@ -533,6 +538,9 @@ DataEditor::Replace(off_t offset, const uint8 *data, size_t length)
|
|||||||
status_t
|
status_t
|
||||||
DataEditor::Remove(off_t offset, off_t length)
|
DataEditor::Remove(off_t offset, off_t length)
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly())
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
BAutolock locker(this);
|
BAutolock locker(this);
|
||||||
|
|
||||||
// not yet implemented
|
// not yet implemented
|
||||||
@@ -545,6 +553,9 @@ DataEditor::Remove(off_t offset, off_t length)
|
|||||||
status_t
|
status_t
|
||||||
DataEditor::Insert(off_t offset, const uint8 *text, size_t length)
|
DataEditor::Insert(off_t offset, const uint8 *text, size_t length)
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly())
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
BAutolock locker(this);
|
BAutolock locker(this);
|
||||||
|
|
||||||
// not yet implemented
|
// not yet implemented
|
||||||
@@ -926,6 +937,21 @@ DataEditor::UpdateIfNeeded(bool *_updated = NULL)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DataEditor::ForceUpdate()
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
if (fView == NULL)
|
||||||
|
status = SetViewOffset(fViewOffset);
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
status = Update();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DataEditor::GetViewBuffer(const uint8 **_buffer)
|
DataEditor::GetViewBuffer(const uint8 **_buffer)
|
||||||
{
|
{
|
||||||
@@ -941,6 +967,130 @@ DataEditor::GetViewBuffer(const uint8 **_buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
off_t
|
||||||
|
DataEditor::Find(off_t startPosition, const uint8 *data, size_t dataSize,
|
||||||
|
bool cyclic, BMessenger progressMonitor, volatile bool *stop)
|
||||||
|
{
|
||||||
|
if (data == NULL || dataSize == 0)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (startPosition < 0)
|
||||||
|
startPosition = 0;
|
||||||
|
|
||||||
|
BAutolock locker(this);
|
||||||
|
|
||||||
|
bool savedIsReadOnly = fIsReadOnly;
|
||||||
|
fIsReadOnly = true;
|
||||||
|
off_t savedOffset = fViewOffset;
|
||||||
|
off_t position = (startPosition / fRealViewSize) * fRealViewSize;
|
||||||
|
size_t firstByte = startPosition % fRealViewSize;
|
||||||
|
size_t matchLastOffset = 0;
|
||||||
|
off_t foundAt = B_ENTRY_NOT_FOUND;
|
||||||
|
bool noStop = false;
|
||||||
|
if (stop == NULL)
|
||||||
|
stop = &noStop;
|
||||||
|
|
||||||
|
// start progress monitor
|
||||||
|
{
|
||||||
|
BMessage progress(kMsgDataEditorFindProgress);
|
||||||
|
progress.AddBool("running", true);
|
||||||
|
progressMonitor.SendMessage(&progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
bigtime_t lastReport = 0;
|
||||||
|
|
||||||
|
off_t blocks = fSize;
|
||||||
|
if (!cyclic)
|
||||||
|
blocks -= position;
|
||||||
|
blocks = (blocks + fRealViewSize - 1) / fRealViewSize;
|
||||||
|
|
||||||
|
for (; blocks-- > 0 && !*stop; position += fRealViewSize) {
|
||||||
|
if (position > fSize)
|
||||||
|
position = 0;
|
||||||
|
|
||||||
|
SetViewOffset(position, false);
|
||||||
|
if (fNeedsUpdate)
|
||||||
|
Update();
|
||||||
|
|
||||||
|
bigtime_t current = system_time();
|
||||||
|
if (lastReport + 500000LL < current) {
|
||||||
|
// report the progress two times a second
|
||||||
|
BMessage progress(kMsgDataEditorFindProgress);
|
||||||
|
progress.AddInt64("position", position);
|
||||||
|
progressMonitor.SendMessage(&progress);
|
||||||
|
|
||||||
|
lastReport = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for data in current block
|
||||||
|
|
||||||
|
if (matchLastOffset != 0) {
|
||||||
|
// we had a partial match in the previous block, let's
|
||||||
|
// check if it is a whole match
|
||||||
|
if (!memcmp(fView, data + matchLastOffset, dataSize - matchLastOffset)) {
|
||||||
|
matchLastOffset = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foundAt = B_ENTRY_NOT_FOUND;
|
||||||
|
matchLastOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = firstByte; i < fRealViewSize; i++) {
|
||||||
|
if (position + i + dataSize > fSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (fView[i] == data[0]) {
|
||||||
|
// one byte matches, compare the rest
|
||||||
|
size_t size = dataSize - 1;
|
||||||
|
size_t offset = i + 1;
|
||||||
|
|
||||||
|
if (offset + size > fRealViewSize)
|
||||||
|
size = fRealViewSize - offset;
|
||||||
|
|
||||||
|
if (size == 0 || !memcmp(fView + offset, data + 1, size)) {
|
||||||
|
foundAt = position + i;
|
||||||
|
|
||||||
|
if (size != dataSize - 1) {
|
||||||
|
// only a partial match, we have to check the start
|
||||||
|
// of the next block
|
||||||
|
matchLastOffset = size + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundAt >= 0 && matchLastOffset == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
firstByte = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fIsReadOnly = savedIsReadOnly;
|
||||||
|
|
||||||
|
if (foundAt >= 0 && matchLastOffset != 0)
|
||||||
|
foundAt = B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
// stop progress monitor
|
||||||
|
{
|
||||||
|
BMessage progress(kMsgDataEditorFindProgress);
|
||||||
|
progress.AddBool("running", false);
|
||||||
|
progress.AddInt64("position", foundAt >= 0 ? foundAt : savedOffset);
|
||||||
|
progressMonitor.SendMessage(&progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetViewOffset(savedOffset, false);
|
||||||
|
// this is to ensure that we're sending an update when
|
||||||
|
// we're set to the found data offset
|
||||||
|
|
||||||
|
if (foundAt < 0 && *stop)
|
||||||
|
return B_INTERRUPTED;
|
||||||
|
|
||||||
|
return foundAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DataEditor::SendNotices(DataChange *change)
|
DataEditor::SendNotices(DataChange *change)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class DataEditor : public BLocker {
|
|||||||
size_t BlockSize() const { return fBlockSize; }
|
size_t BlockSize() const { return fBlockSize; }
|
||||||
|
|
||||||
status_t UpdateIfNeeded(bool *_updated = NULL);
|
status_t UpdateIfNeeded(bool *_updated = NULL);
|
||||||
|
status_t ForceUpdate();
|
||||||
status_t GetViewBuffer(const uint8 **_buffer);
|
status_t GetViewBuffer(const uint8 **_buffer);
|
||||||
|
|
||||||
status_t StartWatching(BMessenger target);
|
status_t StartWatching(BMessenger target);
|
||||||
@@ -72,6 +73,9 @@ class DataEditor : public BLocker {
|
|||||||
void StopWatching(BMessenger target);
|
void StopWatching(BMessenger target);
|
||||||
void StopWatching(BHandler *handler, BLooper *looper = NULL);
|
void StopWatching(BHandler *handler, BLooper *looper = NULL);
|
||||||
|
|
||||||
|
off_t Find(off_t startPosition, const uint8 *data, size_t dataSize, bool cyclic,
|
||||||
|
BMessenger progressMessenger, volatile bool *stop = NULL);
|
||||||
|
|
||||||
BFile &File() { return fFile; }
|
BFile &File() { return fFile; }
|
||||||
const entry_ref &Ref() const { return fRef; }
|
const entry_ref &Ref() const { return fRef; }
|
||||||
|
|
||||||
@@ -113,4 +117,6 @@ static const uint32 kMsgDataEditorStateChange = 'deSC';
|
|||||||
static const uint32 kMsgDataEditorUpdate = 'deUp';
|
static const uint32 kMsgDataEditorUpdate = 'deUp';
|
||||||
static const uint32 kMsgDataEditorParameterChange = 'dePC';
|
static const uint32 kMsgDataEditorParameterChange = 'dePC';
|
||||||
|
|
||||||
|
static const uint32 kMsgDataEditorFindProgress = 'deFP';
|
||||||
|
|
||||||
#endif /* DATA_EDITOR_H */
|
#endif /* DATA_EDITOR_H */
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <StringView.h>
|
#include <StringView.h>
|
||||||
#include <Slider.h>
|
#include <Slider.h>
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
|
#include <Button.h>
|
||||||
#include <Box.h>
|
#include <Box.h>
|
||||||
#include <MenuBar.h>
|
#include <MenuBar.h>
|
||||||
#include <MenuItem.h>
|
#include <MenuItem.h>
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
#include <fs_attr.h>
|
#include <fs_attr.h>
|
||||||
#include <PrintJob.h>
|
#include <PrintJob.h>
|
||||||
|
#include <Beep.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -53,6 +55,10 @@ static const uint32 kMsgAddBookmark = 'bmrk';
|
|||||||
static const uint32 kMsgPrint = 'prnt';
|
static const uint32 kMsgPrint = 'prnt';
|
||||||
static const uint32 kMsgPageSetup = 'pgsp';
|
static const uint32 kMsgPageSetup = 'pgsp';
|
||||||
|
|
||||||
|
static const uint32 kMsgFind = 'find';
|
||||||
|
static const uint32 kMsgFindWindow = 'fndw';
|
||||||
|
static const uint32 kMsgStopFind = 'sfnd';
|
||||||
|
|
||||||
|
|
||||||
class IconView : public BView {
|
class IconView : public BView {
|
||||||
public:
|
public:
|
||||||
@@ -112,7 +118,8 @@ class HeaderView : public BView, public BInvoker {
|
|||||||
|
|
||||||
base_type Base() const { return fBase; }
|
base_type Base() const { return fBase; }
|
||||||
void SetBase(base_type);
|
void SetBase(base_type);
|
||||||
|
|
||||||
|
off_t CursorOffset() const { return fOffset; }
|
||||||
off_t Position() const { return fPosition; }
|
off_t Position() const { return fPosition; }
|
||||||
uint32 BlockSize() const { return fBlockSize; }
|
uint32 BlockSize() const { return fBlockSize; }
|
||||||
void SetTo(off_t position, uint32 blockSize);
|
void SetTo(off_t position, uint32 blockSize);
|
||||||
@@ -140,6 +147,7 @@ class HeaderView : public BView, public BInvoker {
|
|||||||
BStringView *fFileOffsetView;
|
BStringView *fFileOffsetView;
|
||||||
PositionSlider *fPositionSlider;
|
PositionSlider *fPositionSlider;
|
||||||
IconView *fIconView;
|
IconView *fIconView;
|
||||||
|
BButton *fStopButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -155,16 +163,21 @@ class TypeMenuItem : public BMenuItem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class UpdateLooper : public BLooper {
|
class EditorLooper : public BLooper {
|
||||||
public:
|
public:
|
||||||
UpdateLooper(const char *name, DataEditor &editor, BMessenger messenger);
|
EditorLooper(const char *name, DataEditor &editor, BMessenger messenger);
|
||||||
virtual ~UpdateLooper();
|
virtual ~EditorLooper();
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage *message);
|
virtual void MessageReceived(BMessage *message);
|
||||||
|
|
||||||
|
bool FindIsRunning() const { return !fQuitFind; }
|
||||||
|
void Find(off_t startAt, const uint8 *data, size_t dataSize, BMessenger progressMonitor);
|
||||||
|
void QuitFind();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataEditor &fEditor;
|
DataEditor &fEditor;
|
||||||
BMessenger fMessenger;
|
BMessenger fMessenger;
|
||||||
|
volatile bool fQuitFind;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -412,12 +425,20 @@ HeaderView::HeaderView(BRect frame, const entry_ref *ref, DataEditor &editor)
|
|||||||
fIconView = new IconView(BRect(10, 10, 41, 41), ref, editor.IsDevice());
|
fIconView = new IconView(BRect(10, 10, 41, 41), ref, editor.IsDevice());
|
||||||
AddChild(fIconView);
|
AddChild(fIconView);
|
||||||
|
|
||||||
|
BRect rect = Bounds();
|
||||||
|
fStopButton = new BButton(BRect(0, 0, 20, 20), B_EMPTY_STRING, "Stop",
|
||||||
|
new BMessage(kMsgStopFind));
|
||||||
|
fStopButton->ResizeToPreferred();
|
||||||
|
fStopButton->MoveTo(rect.right - 5 - fStopButton->Bounds().Width(), 5);
|
||||||
|
fStopButton->Hide();
|
||||||
|
AddChild(fStopButton);
|
||||||
|
|
||||||
BFont boldFont = *be_bold_font;
|
BFont boldFont = *be_bold_font;
|
||||||
boldFont.SetSize(10.0);
|
boldFont.SetSize(10.0);
|
||||||
BFont plainFont = *be_plain_font;
|
BFont plainFont = *be_plain_font;
|
||||||
plainFont.SetSize(10.0);
|
plainFont.SetSize(10.0);
|
||||||
|
|
||||||
BStringView *stringView = new BStringView(BRect(50, 6, frame.right, 20),
|
BStringView *stringView = new BStringView(BRect(50, 6, rect.right, 20),
|
||||||
B_EMPTY_STRING, editor.IsAttribute() ? "Attribute: " : editor.IsDevice() ? "Device: " : "File: ");
|
B_EMPTY_STRING, editor.IsAttribute() ? "Attribute: " : editor.IsDevice() ? "Device: " : "File: ");
|
||||||
stringView->SetFont(&boldFont);
|
stringView->SetFont(&boldFont);
|
||||||
stringView->ResizeToPreferred();
|
stringView->ResizeToPreferred();
|
||||||
@@ -430,9 +451,9 @@ HeaderView::HeaderView(BRect frame, const entry_ref *ref, DataEditor &editor)
|
|||||||
string.Prepend(fAttribute);
|
string.Prepend(fAttribute);
|
||||||
string.Append(")");
|
string.Append(")");
|
||||||
}
|
}
|
||||||
BRect rect = stringView->Frame();
|
rect = stringView->Frame();
|
||||||
rect.left = rect.right;
|
rect.left = rect.right;
|
||||||
rect.right = frame.right;
|
rect.right = fStopButton->Frame().left - 1;
|
||||||
fPathView = new BStringView(rect, B_EMPTY_STRING, string.String());
|
fPathView = new BStringView(rect, B_EMPTY_STRING, string.String());
|
||||||
fPathView->SetFont(&plainFont);
|
fPathView->SetFont(&plainFont);
|
||||||
AddChild(fPathView);
|
AddChild(fPathView);
|
||||||
@@ -543,6 +564,7 @@ HeaderView::AttachedToWindow()
|
|||||||
{
|
{
|
||||||
SetTarget(Window());
|
SetTarget(Window());
|
||||||
|
|
||||||
|
fStopButton->SetTarget(Parent());
|
||||||
fPositionControl->SetTarget(this);
|
fPositionControl->SetTarget(this);
|
||||||
fPositionSlider->SetTarget(this);
|
fPositionSlider->SetTarget(this);
|
||||||
}
|
}
|
||||||
@@ -698,6 +720,30 @@ HeaderView::MessageReceived(BMessage *message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case kMsgDataEditorFindProgress:
|
||||||
|
{
|
||||||
|
bool state;
|
||||||
|
if (message->FindBool("running", &state) == B_OK && fFileSize > fBlockSize) {
|
||||||
|
fPositionSlider->SetEnabled(!state);
|
||||||
|
if (state)
|
||||||
|
fStopButton->Show();
|
||||||
|
else
|
||||||
|
fStopButton->Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t position;
|
||||||
|
if (message->FindInt64("position", &position) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fPosition = (position / fBlockSize) * fBlockSize;
|
||||||
|
// round to block size
|
||||||
|
|
||||||
|
// update views
|
||||||
|
UpdatePositionViews();
|
||||||
|
fPositionSlider->SetPosition(fPosition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case kMsgPositionUpdate:
|
case kMsgPositionUpdate:
|
||||||
{
|
{
|
||||||
fLastPosition = fPosition;
|
fLastPosition = fPosition;
|
||||||
@@ -815,25 +861,28 @@ TypeMenuItem::DrawContent()
|
|||||||
* That way, simple offset changes will not stop the main
|
* That way, simple offset changes will not stop the main
|
||||||
* looper from operating. Therefore, all offset updates
|
* looper from operating. Therefore, all offset updates
|
||||||
* for the editor will go through this looper.
|
* for the editor will go through this looper.
|
||||||
|
*
|
||||||
|
* Also, it will run the find action in the editor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UpdateLooper::UpdateLooper(const char *name, DataEditor &editor, BMessenger target)
|
EditorLooper::EditorLooper(const char *name, DataEditor &editor, BMessenger target)
|
||||||
: BLooper(name),
|
: BLooper(name),
|
||||||
fEditor(editor),
|
fEditor(editor),
|
||||||
fMessenger(target)
|
fMessenger(target),
|
||||||
|
fQuitFind(true)
|
||||||
{
|
{
|
||||||
fEditor.StartWatching(this);
|
fEditor.StartWatching(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UpdateLooper::~UpdateLooper()
|
EditorLooper::~EditorLooper()
|
||||||
{
|
{
|
||||||
fEditor.StopWatching(this);
|
fEditor.StopWatching(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
UpdateLooper::MessageReceived(BMessage *message)
|
EditorLooper::MessageReceived(BMessage *message)
|
||||||
{
|
{
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case kMsgPositionUpdate:
|
case kMsgPositionUpdate:
|
||||||
@@ -874,6 +923,20 @@ UpdateLooper::MessageReceived(BMessage *message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case kMsgFind:
|
||||||
|
{
|
||||||
|
BMessenger progressMonitor;
|
||||||
|
message->FindMessenger("progress_monitor", &progressMonitor);
|
||||||
|
|
||||||
|
off_t startAt = 0;
|
||||||
|
message->FindInt64("start", &startAt);
|
||||||
|
|
||||||
|
ssize_t dataSize;
|
||||||
|
const uint8 *data;
|
||||||
|
if (message->FindData("data", B_RAW_TYPE, (const void **)&data, &dataSize) == B_OK)
|
||||||
|
Find(startAt, data, dataSize, progressMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BLooper::MessageReceived(message);
|
BLooper::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
@@ -881,12 +944,52 @@ UpdateLooper::MessageReceived(BMessage *message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
EditorLooper::Find(off_t startAt, const uint8 *data, size_t dataSize, BMessenger progressMonitor)
|
||||||
|
{
|
||||||
|
fQuitFind = false;
|
||||||
|
|
||||||
|
BAutolock locker(fEditor);
|
||||||
|
|
||||||
|
bigtime_t startTime = system_time();
|
||||||
|
|
||||||
|
off_t foundAt = fEditor.Find(startAt, data, dataSize, true, progressMonitor, &fQuitFind);
|
||||||
|
if (foundAt >= B_OK) {
|
||||||
|
fEditor.SetViewOffset(foundAt);
|
||||||
|
|
||||||
|
// select the part in our target
|
||||||
|
BMessage message(kMsgSetSelection);
|
||||||
|
message.AddInt64("start", foundAt - fEditor.ViewOffset());
|
||||||
|
message.AddInt64("end", foundAt + dataSize - 1 - fEditor.ViewOffset());
|
||||||
|
fMessenger.SendMessage(&message);
|
||||||
|
} else if (foundAt == B_ENTRY_NOT_FOUND) {
|
||||||
|
if (system_time() > startTime + 8000000LL) {
|
||||||
|
// If the user had to wait more than 8 seconds for the result,
|
||||||
|
// we are trying to please him with a requester...
|
||||||
|
(new BAlert("DiskProbe request",
|
||||||
|
"Could not find pattern", "Ok", NULL, NULL,
|
||||||
|
B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(NULL);
|
||||||
|
} else
|
||||||
|
beep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
EditorLooper::QuitFind()
|
||||||
|
{
|
||||||
|
fQuitFind = true;
|
||||||
|
// this will cleanly stop the find process
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
ProbeView::ProbeView(BRect rect, entry_ref *ref, const char *attribute, const BMessage *settings)
|
ProbeView::ProbeView(BRect rect, entry_ref *ref, const char *attribute, const BMessage *settings)
|
||||||
: BView(rect, "probeView", B_FOLLOW_ALL, B_WILL_DRAW),
|
: BView(rect, "probeView", B_FOLLOW_ALL, B_WILL_DRAW),
|
||||||
fPrintSettings(NULL)
|
fPrintSettings(NULL),
|
||||||
|
fLastSearch(NULL)
|
||||||
{
|
{
|
||||||
fEditor.SetTo(*ref, attribute);
|
fEditor.SetTo(*ref, attribute);
|
||||||
|
|
||||||
@@ -945,9 +1048,11 @@ ProbeView::UpdateSizeLimits()
|
|||||||
void
|
void
|
||||||
ProbeView::DetachedFromWindow()
|
ProbeView::DetachedFromWindow()
|
||||||
{
|
{
|
||||||
if (fUpdateLooper->Lock())
|
fEditorLooper->QuitFind();
|
||||||
fUpdateLooper->Quit();
|
|
||||||
fUpdateLooper = NULL;
|
if (fEditorLooper->Lock())
|
||||||
|
fEditorLooper->Quit();
|
||||||
|
fEditorLooper = NULL;
|
||||||
|
|
||||||
fEditor.StopWatching(this);
|
fEditor.StopWatching(this);
|
||||||
fDataView->StopWatching(fHeaderView, kDataViewCursorPosition);
|
fDataView->StopWatching(fHeaderView, kDataViewCursorPosition);
|
||||||
@@ -1037,8 +1142,8 @@ ProbeView::AddPrintMenuItems(BMenu *menu, int32 index)
|
|||||||
void
|
void
|
||||||
ProbeView::AttachedToWindow()
|
ProbeView::AttachedToWindow()
|
||||||
{
|
{
|
||||||
fUpdateLooper = new UpdateLooper(fEditor.Ref().name, fEditor, BMessenger(fDataView));
|
fEditorLooper = new EditorLooper(fEditor.Ref().name, fEditor, BMessenger(fDataView));
|
||||||
fUpdateLooper->Run();
|
fEditorLooper->Run();
|
||||||
|
|
||||||
fEditor.StartWatching(this);
|
fEditor.StartWatching(this);
|
||||||
fDataView->StartWatching(fHeaderView, kDataViewCursorPosition);
|
fDataView->StartWatching(fHeaderView, kDataViewCursorPosition);
|
||||||
@@ -1086,8 +1191,12 @@ ProbeView::AttachedToWindow()
|
|||||||
menu->AddItem(item = new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A', B_COMMAND_KEY));
|
menu->AddItem(item = new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A', B_COMMAND_KEY));
|
||||||
item->SetTarget(fDataView);
|
item->SetTarget(fDataView);
|
||||||
menu->AddSeparatorItem();
|
menu->AddSeparatorItem();
|
||||||
menu->AddItem(new BMenuItem("Find" B_UTF8_ELLIPSIS, NULL, 'F', B_COMMAND_KEY));
|
menu->AddItem(item = new BMenuItem("Find" B_UTF8_ELLIPSIS, new BMessage(kMsgFindWindow), 'F', B_COMMAND_KEY));
|
||||||
menu->AddItem(new BMenuItem("Find Again", NULL, 'G', B_COMMAND_KEY));
|
item->SetTarget(this);
|
||||||
|
menu->AddItem(fFindAgainMenuItem = new BMenuItem("Find Again", new BMessage(kMsgFind),
|
||||||
|
'G', B_COMMAND_KEY));
|
||||||
|
fFindAgainMenuItem->SetEnabled(false);
|
||||||
|
fFindAgainMenuItem->SetTarget(this);
|
||||||
bar->AddItem(menu);
|
bar->AddItem(menu);
|
||||||
|
|
||||||
// "Block" menu
|
// "Block" menu
|
||||||
@@ -1216,7 +1325,7 @@ ProbeView::AttachedToWindow()
|
|||||||
void
|
void
|
||||||
ProbeView::AllAttached()
|
ProbeView::AllAttached()
|
||||||
{
|
{
|
||||||
fHeaderView->SetTarget(fUpdateLooper);
|
fHeaderView->SetTarget(fEditorLooper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1439,6 +1548,8 @@ ProbeView::Save()
|
|||||||
bool
|
bool
|
||||||
ProbeView::QuitRequested()
|
ProbeView::QuitRequested()
|
||||||
{
|
{
|
||||||
|
fEditorLooper->QuitFind();
|
||||||
|
|
||||||
if (!fEditor.IsModified())
|
if (!fEditor.IsModified())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -1548,6 +1659,49 @@ ProbeView::MessageReceived(BMessage *message)
|
|||||||
PageSetup();
|
PageSetup();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kMsgFindWindow:
|
||||||
|
{
|
||||||
|
fEditorLooper->QuitFind();
|
||||||
|
|
||||||
|
// ToDo: open find window
|
||||||
|
message->AddData("data", B_RAW_TYPE, "test", 4);
|
||||||
|
message->what = kMsgFind;
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMsgFind:
|
||||||
|
{
|
||||||
|
const uint8 *data;
|
||||||
|
ssize_t size;
|
||||||
|
if (message->FindData("data", B_RAW_TYPE, (const void **)&data, &size) != B_OK) {
|
||||||
|
// search again for last pattern
|
||||||
|
BMessage *itemMessage = fFindAgainMenuItem->Message();
|
||||||
|
if (itemMessage == NULL
|
||||||
|
|| itemMessage->FindData("data", B_RAW_TYPE, (const void **)&data, &size) != B_OK) {
|
||||||
|
// this shouldn't ever happen, but well...
|
||||||
|
beep();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// remember the search pattern
|
||||||
|
fFindAgainMenuItem->SetMessage(new BMessage(*message));
|
||||||
|
fFindAgainMenuItem->SetEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 start, end;
|
||||||
|
fDataView->GetSelection(start, end);
|
||||||
|
|
||||||
|
BMessage find(*message);
|
||||||
|
find.AddInt64("start", fHeaderView->Position() + start + 1);
|
||||||
|
find.AddMessenger("progress_monitor", BMessenger(fHeaderView));
|
||||||
|
fEditorLooper->PostMessage(&find);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMsgStopFind:
|
||||||
|
fEditorLooper->QuitFind();
|
||||||
|
break;
|
||||||
|
|
||||||
case B_NODE_MONITOR:
|
case B_NODE_MONITOR:
|
||||||
{
|
{
|
||||||
switch (message->FindInt32("opcode")) {
|
switch (message->FindInt32("opcode")) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class BMenuItem;
|
|||||||
|
|
||||||
class HeaderView;
|
class HeaderView;
|
||||||
class DataView;
|
class DataView;
|
||||||
class UpdateLooper;
|
class EditorLooper;
|
||||||
|
|
||||||
|
|
||||||
class ProbeView : public BView {
|
class ProbeView : public BView {
|
||||||
@@ -52,7 +52,7 @@ class ProbeView : public BView {
|
|||||||
status_t Save();
|
status_t Save();
|
||||||
|
|
||||||
DataEditor fEditor;
|
DataEditor fEditor;
|
||||||
UpdateLooper *fUpdateLooper;
|
EditorLooper *fEditorLooper;
|
||||||
HeaderView *fHeaderView;
|
HeaderView *fHeaderView;
|
||||||
DataView *fDataView;
|
DataView *fDataView;
|
||||||
BScrollView *fScrollView;
|
BScrollView *fScrollView;
|
||||||
@@ -62,6 +62,10 @@ class ProbeView : public BView {
|
|||||||
BMenuItem *fSaveMenuItem;
|
BMenuItem *fSaveMenuItem;
|
||||||
BMessage *fPrintSettings;
|
BMessage *fPrintSettings;
|
||||||
BMenu *fBookmarkMenu;
|
BMenu *fBookmarkMenu;
|
||||||
|
|
||||||
|
BMenuItem *fFindAgainMenuItem;
|
||||||
|
const uint8 *fLastSearch;
|
||||||
|
size_t fLastSearchSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PROBE_VIEW_H */
|
#endif /* PROBE_VIEW_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user