* Refactored MemoryView to be more flexible ; it can now show a configurable

choice of hexadecimal and/or character displays of the memory data, with
  different digit grouping sizes. Still needs some work but is basically
  functional.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42204 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rene Gollent
2011-06-16 04:21:18 +00:00
parent f7f3828178
commit 2acfac81cd
5 changed files with 259 additions and 40 deletions
@@ -18,16 +18,22 @@
#include "MemoryView.h" #include "MemoryView.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "Team.h"
#include "UserInterface.h" #include "UserInterface.h"
InspectorWindow::InspectorWindow(UserInterfaceListener* listener) InspectorWindow::InspectorWindow(::Team* team, UserInterfaceListener* listener)
: :
BWindow(BRect(100, 100, 500, 250), "Inspector", B_TITLED_WINDOW, BWindow(BRect(100, 100, 700, 500), "Inspector", B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS), B_ASYNCHRONOUS_CONTROLS),
fListener(listener), fListener(listener),
fAddressInput(NULL),
fHexMode(NULL),
fTextMode(NULL),
fMemoryView(NULL), fMemoryView(NULL),
fCurrentBlock(NULL) fCurrentBlock(NULL),
fCurrentAddress(0LL),
fTeam(team)
{ {
} }
@@ -38,9 +44,9 @@ InspectorWindow::~InspectorWindow()
/* static */ InspectorWindow* /* static */ InspectorWindow*
InspectorWindow::Create(UserInterfaceListener* listener) InspectorWindow::Create(::Team* team, UserInterfaceListener* listener)
{ {
InspectorWindow* self = new InspectorWindow(listener); InspectorWindow* self = new InspectorWindow(team, listener);
try { try {
self->_Init(); self->_Init();
@@ -58,17 +64,72 @@ InspectorWindow::_Init()
{ {
BScrollView* scrollView; BScrollView* scrollView;
BMenu* hexMenu = new BMenu("Hex Mode");
BMessage* message = new BMessage(MSG_SET_HEX_MODE);
message->AddInt32("mode", HexModeNone);
BMenuItem* item = new BMenuItem("<None>", message, '0');
hexMenu->AddItem(item);
message = new BMessage(*message);
message->ReplaceInt32("mode", HexMode8BitInt);
item = new BMenuItem("8-bit integer", message, '1');
hexMenu->AddItem(item);
message = new BMessage(*message);
message->ReplaceInt32("mode", HexMode16BitInt);
item = new BMenuItem("16-bit integer", message, '2');
hexMenu->AddItem(item);
message = new BMessage(*message);
message->ReplaceInt32("mode", HexMode32BitInt);
item = new BMenuItem("32-bit integer", message, '3');
hexMenu->AddItem(item);
// TODO: enable once problem with 64-bit hex string formatting is found
/*
message = new BMessage(*message);
message->ReplaceInt32("mode", HexMode64BitInt);
item = new BMenuItem("64-bit integer", message, '3');
hexMenu->AddItem(item);
*/
BMenu* textMenu = new BMenu("Text Mode");
message = new BMessage(MSG_SET_TEXT_MODE);
message->AddInt32("mode", TextModeNone);
item = new BMenuItem("<None>", message, 'N');
textMenu->AddItem(item);
message = new BMessage(*message);
message->ReplaceInt32("mode", TextModeASCII);
item = new BMenuItem("ASCII", message, 'A');
textMenu->AddItem(item);
BLayoutBuilder::Group<>(this, B_VERTICAL) BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(4.0f, 4.0f, 4.0f, 4.0f)
.Add(fAddressInput = new BTextControl("addrInput", .Add(fAddressInput = new BTextControl("addrInput",
"Target Address:", "", "Target Address:", "",
new BMessage(MSG_INSPECT_ADDRESS))) new BMessage(MSG_INSPECT_ADDRESS)))
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(fHexMode = new BMenuField("outputStyle", "Hex Mode:",
hexMenu))
.AddGlue()
.Add(fTextMode = new BMenuField("viewMode", "Text Mode:",
textMenu))
.End()
.Add(scrollView = new BScrollView("memory scroll", .Add(scrollView = new BScrollView("memory scroll",
NULL, 0, false, true), 3.0f) NULL, 0, false, true), 3.0f)
.End(); .End();
fHexMode->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fTextMode->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
scrollView->SetTarget(fMemoryView = MemoryView::Create()); scrollView->SetTarget(fMemoryView = MemoryView::Create());
fAddressInput->SetTarget(this); fAddressInput->SetTarget(this);
hexMenu->SetLabelFromMarked(true);
hexMenu->SetTargetForItems(fMemoryView);
textMenu->SetLabelFromMarked(true);
textMenu->SetTargetForItems(fMemoryView);
// default to 8-bit format w/ text display
hexMenu->ItemAt(1)->SetMarked(true);
textMenu->ItemAt(1)->SetMarked(true);
} }
@@ -13,19 +13,22 @@
class BButton; class BButton;
class BMenuField;
class BTextControl; class BTextControl;
class MemoryView; class MemoryView;
class Team;
class UserInterfaceListener; class UserInterfaceListener;
class InspectorWindow : public BWindow, class InspectorWindow : public BWindow,
public TeamMemoryBlock::Listener { public TeamMemoryBlock::Listener {
public: public:
InspectorWindow( InspectorWindow(::Team* team,
UserInterfaceListener* listener); UserInterfaceListener* listener);
virtual ~InspectorWindow(); virtual ~InspectorWindow();
static InspectorWindow* Create(UserInterfaceListener* listener); static InspectorWindow* Create(::Team* team,
UserInterfaceListener* listener);
// throws // throws
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
@@ -39,9 +42,12 @@ private:
private: private:
UserInterfaceListener* fListener; UserInterfaceListener* fListener;
BTextControl* fAddressInput; BTextControl* fAddressInput;
BMenuField* fHexMode;
BMenuField* fTextMode;
MemoryView* fMemoryView; MemoryView* fMemoryView;
TeamMemoryBlock* fCurrentBlock; TeamMemoryBlock* fCurrentBlock;
target_addr_t fCurrentAddress; target_addr_t fCurrentAddress;
::Team* fTeam;
}; };
#endif // INSPECTOR_WINDOW_H #endif // INSPECTOR_WINDOW_H
@@ -6,6 +6,8 @@
#include "MemoryView.h" #include "MemoryView.h"
#include <algorithm>
#include <stdio.h> #include <stdio.h>
#include <Messenger.h> #include <Messenger.h>
@@ -24,7 +26,13 @@ MemoryView::MemoryView()
: :
BView("memoryView", B_WILL_DRAW | B_FRAME_EVENTS | B_SUBPIXEL_PRECISE), BView("memoryView", B_WILL_DRAW | B_FRAME_EVENTS | B_SUBPIXEL_PRECISE),
fTargetBlock(NULL), fTargetBlock(NULL),
fTargetAddress(0) fTargetAddress(0LL),
fCharWidth(0.0),
fLineHeight(0.0),
fTextCharsPerLine(0),
fHexBlocksPerLine(0),
fHexMode(HexMode8BitInt),
fTextMode(TextModeASCII)
{ {
} }
@@ -92,42 +100,77 @@ MemoryView::Draw(BRect rect)
{ {
BView::Draw(rect); BView::Draw(rect);
StrokeLine(BPoint(9 * fCharWidth, rect.top), float divider = 9 * fCharWidth;
BPoint(9 * fCharWidth, rect.bottom)); StrokeLine(BPoint(divider, rect.top),
BPoint(divider, rect.bottom));
if (fTargetBlock == NULL) if (fTargetBlock == NULL)
return; return;
char buffer[16]; uint32 hexBlockSize = 1 << fHexMode;
if (fHexMode != HexModeNone && fTextMode != TextModeNone) {
divider += (fHexBlocksPerLine * (hexBlockSize + 1) + 1) * fCharWidth;
StrokeLine(BPoint(divider, rect.top),
BPoint(divider, rect.bottom));
}
int32 startLine = int32(rect.top / fLineHeight); char buffer[32];
char textbuffer[512];
int32 startLine = int32(rect.top / fLineHeight) - 1;
if (startLine < 0)
startLine = 0;
int32 endLine = int32(rect.bottom / fLineHeight) + 1; int32 endLine = int32(rect.bottom / fLineHeight) + 1;
int32 startByte = fNybblesPerLine / 2 * startLine; int32 startByte = fHexBlocksPerLine * hexBlockSize * startLine;
uint16* currentAddress = (uint16*)(fTargetBlock->BaseAddress() const char* currentAddress = (const char*)(fTargetBlock->BaseAddress()
+ startByte); + startByte);
uint16* maxAddress = (uint16*)(fTargetBlock->BaseAddress() const char* maxAddress = (const char*)(fTargetBlock->BaseAddress()
+ fTargetBlock->Size()); + fTargetBlock->Size());
BPoint drawPoint(1.0, (startLine + 1) * fLineHeight); BPoint drawPoint(1.0, (startLine + 1) * fLineHeight);
int32 currentWordsPerLine = fNybblesPerLine / 4; int32 currentBlocksPerLine = fHexBlocksPerLine;
int32 currentCharsPerLine = fTextCharsPerLine;
rgb_color addressColor = tint_color(HighColor(), B_LIGHTEN_1_TINT);
rgb_color dataColor = HighColor();
for (int32 i = startLine; i <= endLine && currentAddress < maxAddress; for (int32 i = startLine; i <= endLine && currentAddress < maxAddress;
i++, drawPoint.y += fLineHeight) { i++, drawPoint.y += fLineHeight) {
drawPoint.x = 1.0; drawPoint.x = 1.0;
snprintf(buffer, sizeof(buffer), "%" B_PRIx32, snprintf(buffer, sizeof(buffer), "%" B_PRIx32,
(uint32)currentAddress); (uint32)currentAddress);
SetHighColor(addressColor);
DrawString(buffer, drawPoint); DrawString(buffer, drawPoint);
drawPoint.x += fCharWidth * 10; drawPoint.x += fCharWidth * 10;
SetHighColor(dataColor);
if (currentAddress + currentWordsPerLine > maxAddress) if (fHexMode != HexModeNone) {
currentWordsPerLine = (maxAddress - currentAddress) / 2; if (currentAddress + (currentBlocksPerLine * hexBlockSize)
> maxAddress) {
for (int32 j = 0; j < currentWordsPerLine; j++) { currentCharsPerLine = maxAddress - currentAddress;
snprintf(buffer, sizeof(buffer), "%04" B_PRIx16, currentBlocksPerLine = currentCharsPerLine
currentAddress[j]); / hexBlockSize;
DrawString(buffer, drawPoint);
drawPoint.x += fCharWidth * 5;
} }
currentAddress += currentWordsPerLine;
for (int32 j = 0; j < currentBlocksPerLine; j++) {
_GetNextHexBlock(buffer,
std::min(hexBlockSize + 1, sizeof(buffer)),
currentAddress + (j * hexBlockSize / 2));
DrawString(buffer, drawPoint);
drawPoint.x += fCharWidth * (hexBlockSize + 1);
}
}
if (fTextMode != TextModeNone) {
drawPoint.x += fCharWidth;
for (int32 j = 0; j < currentCharsPerLine; j++) {
// filter non-printable characters
textbuffer[j] = currentAddress[j] > 32 ? currentAddress[j]
: '.';
}
textbuffer[fTextCharsPerLine] = '\0';
DrawString(textbuffer, drawPoint);
}
if (currentBlocksPerLine > 0)
currentAddress += currentBlocksPerLine * hexBlockSize / 2;
else
currentAddress += fTextCharsPerLine;
} }
} }
@@ -151,6 +194,26 @@ MemoryView::MessageReceived(BMessage* message)
Invalidate(); Invalidate();
break; break;
} }
case MSG_SET_HEX_MODE:
{
int32 mode;
if (message->FindInt32("mode", &mode) == B_OK) {
fHexMode = mode;
_RecalcScrollBars();
Invalidate();
}
break;
}
case MSG_SET_TEXT_MODE:
{
int32 mode;
if (message->FindInt32("mode", &mode) == B_OK) {
fTextMode = mode;
_RecalcScrollBars();
Invalidate();
}
break;
}
default: default:
{ {
BView::MessageReceived(message); BView::MessageReceived(message);
@@ -174,19 +237,83 @@ MemoryView::_RecalcScrollBars()
BScrollBar *scrollBar = ScrollBar(B_VERTICAL); BScrollBar *scrollBar = ScrollBar(B_VERTICAL);
if (fTargetBlock != NULL) { if (fTargetBlock != NULL) {
BRect bounds = Bounds(); BRect bounds = Bounds();
fNybblesPerLine = int32(bounds.Width() / fCharWidth); // the left portion of the view is off limits since it
// we allocate 8 characters for the starting address of the current // houses the address offset of the current line
// line plus some spacing to separate that from the data float baseWidth = bounds.Width() - (10.0 * fCharWidth);
fNybblesPerLine -= 10; float hexWidth = 0.0;
// also allocate a space between each 16-bit grouping float textWidth = 0.0;
fNybblesPerLine -= (fNybblesPerLine / 4) - 1; int32 hexDigits = 1 << fHexMode;
fNybblesPerLine &= ~3; int32 sizeFactor = 1 + hexDigits;
int32 lineCount if (fHexMode != HexModeNone) {
= (int32)ceil(2 * fTargetBlock->Size() / fNybblesPerLine); if (fTextMode != TextModeNone) {
float totalHeight = lineCount * fLineHeight; float hexProportion = sizeFactor / (float)(sizeFactor
+ hexDigits / 2);
hexWidth = baseWidth * hexProportion;
// when sharing the display between hex and text,
// we allocate a 2 character space to separate the views
hexWidth -= 2 * fCharWidth;
textWidth = baseWidth - hexWidth;
} else
hexWidth = baseWidth;
} else if (fTextMode != TextModeNone)
textWidth = baseWidth;
int32 nybblesPerLine = int32(hexWidth / fCharWidth);
fHexBlocksPerLine = 0;
fTextCharsPerLine = 0;
if (fHexMode != HexModeNone) {
fHexBlocksPerLine = nybblesPerLine / sizeFactor;
fHexBlocksPerLine &= ~1;
if (fTextMode != TextModeNone)
fTextCharsPerLine = fHexBlocksPerLine * (hexDigits / 2);
} else if (fTextMode != TextModeNone)
fTextCharsPerLine = int32(textWidth / fCharWidth);
int32 lineCount = 0;
float totalHeight = 0.0;
if (fHexBlocksPerLine > 0) {
lineCount = fTargetBlock->Size() / (fHexBlocksPerLine
* hexDigits);
} else if (fTextCharsPerLine > 0)
lineCount = fTargetBlock->Size() / fTextCharsPerLine;
totalHeight = lineCount * fLineHeight;
if (totalHeight > 0.0) {
max = totalHeight - bounds.Height(); max = totalHeight - bounds.Height();
scrollBar->SetProportion(bounds.Height() / totalHeight); scrollBar->SetProportion(bounds.Height() / totalHeight);
scrollBar->SetSteps(fLineHeight, bounds.Height()); scrollBar->SetSteps(fLineHeight, bounds.Height());
} }
}
scrollBar->SetRange(0.0, max); scrollBar->SetRange(0.0, max);
} }
void
MemoryView::_GetNextHexBlock(char* buffer, int32 bufferSize,
const char* address)
{
switch(fHexMode) {
case HexMode8BitInt:
{
snprintf(buffer, bufferSize, "%02" B_PRIx8, *address);
break;
}
case HexMode16BitInt:
{
snprintf(buffer, bufferSize, "%04" B_PRIx16,
*((const uint16*)address));
break;
}
case HexMode32BitInt:
{
snprintf(buffer, bufferSize, "%08" B_PRIx32,
*((const uint32*)address));
break;
}
case HexMode64BitInt:
{
snprintf(buffer, bufferSize, "%0*" B_PRIx64,
16, *((const uint64*)address));
break;
}
}
}
@@ -12,6 +12,26 @@
#include "Types.h" #include "Types.h"
enum {
MSG_SET_HEX_MODE = 'sofm',
MSG_SET_TEXT_MODE = 'some'
};
enum {
HexModeNone = 0,
HexMode8BitInt,
HexMode16BitInt,
HexMode32BitInt,
HexMode64BitInt
// TODO: floating point representation?
};
enum {
TextModeNone = 0,
TextModeASCII
};
class TeamMemoryBlock; class TeamMemoryBlock;
@@ -39,13 +59,18 @@ public:
private: private:
void _Init(); void _Init();
void _RecalcScrollBars(); void _RecalcScrollBars();
void _GetNextHexBlock(char* buffer,
int32 bufferSize, const char* address);
private: private:
TeamMemoryBlock* fTargetBlock; TeamMemoryBlock* fTargetBlock;
target_addr_t fTargetAddress; target_addr_t fTargetAddress;
float fCharWidth; float fCharWidth;
float fLineHeight; float fLineHeight;
int32 fNybblesPerLine; int32 fTextCharsPerLine;
int32 fHexBlocksPerLine;
int32 fHexMode;
int32 fTextMode;
}; };
#endif // MEMORY_VIEW_H #endif // MEMORY_VIEW_H
@@ -212,7 +212,7 @@ TeamWindow::MessageReceived(BMessage* message)
} }
try { try {
fInspectorWindow = InspectorWindow::Create(fListener); fInspectorWindow = InspectorWindow::Create(fTeam, fListener);
if (fInspectorWindow != NULL) if (fInspectorWindow != NULL)
fInspectorWindow->Show(); fInspectorWindow->Show();
} catch (...) { } catch (...) {