diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 727155ef50..167979b6e7 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -211,6 +211,7 @@ Application Debugger : TeamWindow.cpp ThreadListView.cpp VariablesView.cpp + WatchPromptWindow.cpp # user_interface/gui/util ActionMenuItem.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 75a2df88f3..59ec092cac 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -53,7 +53,8 @@ enum { MSG_INSPECTOR_WINDOW_CLOSED = 'irwc', MSG_INSPECT_ADDRESS = 'isad', MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp', - MSG_TYPECAST_NODE = 'tyno' + MSG_TYPECAST_NODE = 'tyno', + MSG_SHOW_WATCH_VARIABLE_PROMPT = 'swvp' }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 4da2045c39..1fc4fd86dc 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -44,6 +44,7 @@ #include "TypeComponentPath.h" #include "UserInterface.h" #include "Variable.h" +#include "WatchPromptWindow.h" enum { @@ -247,6 +248,27 @@ TeamWindow::MessageReceived(BMessage* message) break; } + case MSG_SHOW_WATCH_VARIABLE_PROMPT: + { + target_addr_t address; + uint32 type; + int32 length; + + if (message->FindUInt64("address", &address) != B_OK + || message->FindUInt32("type", &type) != B_OK + || message->FindInt32("length", &length) != B_OK) { + break; + } + + try { + WatchPromptWindow* window = WatchPromptWindow::Create(address, + type, length, fListener); + window->Show(); + } catch (...) { + // TODO: notify user + } + break; + } case B_REFS_RECEIVED: { entry_ref locatedPath; diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp index e5a6be1c50..744a2d1e86 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include #include @@ -1684,6 +1686,22 @@ VariablesView::MessageReceived(BMessage* message) node->NodeChild()->SetNode(valueNode); break; } + case MSG_SHOW_WATCH_VARIABLE_PROMPT: + { + ModelNode* node = reinterpret_cast( + fVariableTable->SelectionModel()->NodeAt(0)); + ValueLocation* location = node->NodeChild()->Location(); + ValuePieceLocation piece = location->PieceAt(0); + if (piece.type != VALUE_PIECE_LOCATION_MEMORY) + break; + + BMessage looperMessage(*message); + looperMessage.AddUInt64("address", piece.address); + looperMessage.AddInt32("length", piece.size); + looperMessage.AddUInt32("type", B_DATA_READ_WRITE_WATCHPOINT); + Looper()->PostMessage(&looperMessage); + break; + } case MSG_VALUE_NODE_CHANGED: { ValueNodeChild* nodeChild; @@ -1977,34 +1995,45 @@ VariablesView::_GetContextActionsForNode(ModelNode* node, if (location->PieceAt(0).type != VALUE_PIECE_LOCATION_MEMORY) return B_OK; - BMessage* message = new BMessage(MSG_SHOW_INSPECTOR_WINDOW); - if (message == NULL) - return B_NO_MEMORY; + BMessage* message = NULL; + status_t result = _AddContextAction("Inspect", MSG_SHOW_INSPECTOR_WINDOW, + actions, message); + if (result != B_OK) + return result; - ObjectDeleter messageDeleter(message); message->AddUInt64("address", location->PieceAt(0).address); - ActionMenuItem* item = new(std::nothrow) ActionMenuItem("Inspect", - message); + result = _AddContextAction("Cast as" B_UTF8_ELLIPSIS, + MSG_SHOW_TYPECAST_NODE_PROMPT, actions, message); + if (result != B_OK) + return result; + + result = _AddContextAction("Watch" B_UTF8_ELLIPSIS, + MSG_SHOW_WATCH_VARIABLE_PROMPT, actions, message); + if (result != B_OK) + return result; + + return B_OK; +} + + +status_t +VariablesView::_AddContextAction(const char* action, uint32 what, + ContextActionList* actions, BMessage*& _message) +{ + _message = new BMessage(what); + if (_message == NULL) + return B_NO_MEMORY; + + ObjectDeleter messageDeleter(_message); + + ActionMenuItem* item = new(std::nothrow) ActionMenuItem(action, + _message); if (item == NULL) return B_NO_MEMORY; messageDeleter.Detach(); ObjectDeleter actionDeleter(item); - if (!actions->AddItem(item)) - return B_NO_MEMORY; - - message = new(std::nothrow)BMessage(MSG_SHOW_TYPECAST_NODE_PROMPT); - if (message == NULL) - return B_NO_MEMORY; - - item = new(std::nothrow) ActionMenuItem("Cast as" B_UTF8_ELLIPSIS, - message); - if (item == NULL) - return B_NO_MEMORY; - - messageDeleter.Detach(); - if (!actions->AddItem(item)) return B_NO_MEMORY; diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h index 7c09b73f98..974190068d 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h @@ -72,6 +72,9 @@ private: void _RequestNodeValue(ModelNode* node); status_t _GetContextActionsForNode(ModelNode* node, ContextActionList* actions); + status_t _AddContextAction(const char* action, + uint32 what, ContextActionList* actions, + BMessage*& _message); void _FinishContextMenu(bool force); void _SaveViewState() const; void _RestoreViewState(); diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp new file mode 100644 index 0000000000..0c81483ea3 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp @@ -0,0 +1,154 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#include "WatchPromptWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "MessageCodes.h" +#include "UserInterface.h" +#include "Watchpoint.h" + + +WatchPromptWindow::WatchPromptWindow(target_addr_t address, uint32 type, + int32 length, UserInterfaceListener* listener) + : + BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW, + B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), + fInitialAddress(address), + fInitialType(type), + fInitialLength(length), + fAddressInput(NULL), + fLengthInput(NULL), + fTypeField(NULL), + fListener(listener) +{ +} + + +WatchPromptWindow::~WatchPromptWindow() +{ +} + + +WatchPromptWindow* +WatchPromptWindow::Create(target_addr_t address, uint32 type, int32 length, + UserInterfaceListener* listener) +{ + WatchPromptWindow* self = new WatchPromptWindow(address, type, length, + listener); + + try { + self->_Init(); + } catch (...) { + delete self; + throw; + } + + return self; + +} + +void +WatchPromptWindow::_Init() +{ + BString text; + text.SetToFormat("0x%" B_PRIx64, fInitialAddress); + fAddressInput = new BTextControl("Address:", text, NULL); + + text.SetToFormat("%" B_PRId32, fInitialLength); + fLengthInput = new BTextControl("Length:", text, NULL); + + BMenu* typeMenu = new BMenu("Watch Type"); + typeMenu->AddItem(new BMenuItem("Read", NULL)); + typeMenu->AddItem(new BMenuItem("Write", NULL)); + typeMenu->AddItem(new BMenuItem("Read/Write", NULL)); + fTypeField = new BMenuField("Type:", typeMenu); + BLayoutItem* labelItem = fTypeField->CreateLabelLayoutItem(); + labelItem->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BLayoutBuilder::Group<>(this, B_VERTICAL) + .SetInsets(4.0f, 4.0f, 4.0f, 4.0f) + .AddGroup(B_HORIZONTAL, 4.0f) + .Add(fAddressInput) + .End() + .AddGroup(B_HORIZONTAL, 4.0f) + .Add(fLengthInput) + .Add(labelItem) + .Add(fTypeField->CreateMenuBarLayoutItem()) + .End() + .AddGroup(B_HORIZONTAL, 4.0f) + .AddGlue() + .Add((fWatchButton = new BButton("Set", + new BMessage(MSG_SET_WATCHPOINT)))) + .Add((fCancelButton = new BButton("Cancel", + new BMessage(B_QUIT_REQUESTED)))) + .End(); + + fWatchButton->SetTarget(this); + fCancelButton->SetTarget(this); + + fTypeField->Menu()->SetLabelFromMarked(true); + fTypeField->Menu()->ItemAt(fInitialType)->SetMarked(true); +} + +void +WatchPromptWindow::Show() +{ + CenterOnScreen(); + BWindow::Show(); +} + +void +WatchPromptWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_SET_WATCHPOINT: + { + target_addr_t address; + int32 length; + ExpressionParser parser; + parser.SetSupportHexInput(true); + BString errorMessage; + try { + address = parser.EvaluateToInt64(fAddressInput->Text()); + length = (int32)parser.EvaluateToInt64(fLengthInput->Text()); + } catch(ParseException parseError) { + errorMessage.SetToFormat("Failed to parse data: %s", + parseError.message.String()); + } catch(...) { + errorMessage.SetToFormat( + "Unknown error while parsing address"); + } + + if (!errorMessage.IsEmpty()) { + BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint", + errorMessage.String(), "Close"); + if (alert != NULL) + alert->Go(); + break; + } + + fListener->ClearWatchpointRequested(fInitialAddress); + fListener->SetWatchpointRequested(address, fTypeField->Menu() + ->IndexOf(fTypeField->Menu()->FindMarked()), length, true); + + PostMessage(B_QUIT_REQUESTED); + + break; + } + default: + BWindow::MessageReceived(message); + break; + } + +} diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h new file mode 100644 index 0000000000..465fdd696c --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h @@ -0,0 +1,56 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef WATCH_PROMPT_WINDOW_H +#define WATCH_PROMPT_WINDOW_H + + +#include + +#include "types/Types.h" + + +class BTextControl; +class Watchpoint; +class BMenuField; +class UserInterfaceListener; + + +class WatchPromptWindow : public BWindow +{ +public: + // edit existing watchpoint + WatchPromptWindow(target_addr_t address, + uint32 type, int32 length, + UserInterfaceListener* listener); + + ~WatchPromptWindow(); + + static WatchPromptWindow* Create(target_addr_t address, uint32 type, + int32 length, + UserInterfaceListener* listener); + // throws + + + virtual void MessageReceived(BMessage* message); + + virtual void Show(); + +private: + void _Init(); + + +private: + target_addr_t fInitialAddress; + uint32 fInitialType; + int32 fInitialLength; + BTextControl* fAddressInput; + BTextControl* fLengthInput; + BMenuField* fTypeField; + UserInterfaceListener* fListener; + BButton* fWatchButton; + BButton* fCancelButton; +}; + +#endif // WATCH_PROMPT_WINDOW_H