From 9a14c8a25d0830ca07334ad3339d3f3b1bb588e3 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sun, 7 Jul 2013 00:34:12 -0400 Subject: [PATCH] Implement configuration for stop on image load with names. - BreakConditionConfigWindow is now a team listener so it can watch for the appropriate events. - Implement reading/maintaining state in response to the various notifications. - Implement adding/removing names and enabling/disabling the use of the name list. --- .../BreakConditionConfigWindow.cpp | 225 +++++++++++++++--- .../team_window/BreakConditionConfigWindow.h | 21 +- 2 files changed, 215 insertions(+), 31 deletions(-) diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.cpp index 5a9afbb81b..a6428f2229 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include "FunctionInstance.h" @@ -33,6 +34,22 @@ enum { }; +static int SortStringItems(const void* a, const void* b) +{ + BStringItem* item1 = *(BStringItem**)a; + BStringItem* item2 = *(BStringItem**)b; + + return strcmp(item1->Text(), item2->Text()); +} + + +static bool UpdateItemState(BListItem* item, void* enabled) +{ + item->SetEnabled((bool)enabled); + return false; +} + + BreakConditionConfigWindow::BreakConditionConfigWindow(::Team* team, UserInterfaceListener* listener, BHandler* target) : @@ -48,14 +65,17 @@ BreakConditionConfigWindow::BreakConditionConfigWindow(::Team* team, fStopImageNameInput(NULL), fAddImageNameButton(NULL), fRemoveImageNameButton(NULL), + fUseCustomImages(false), fCloseButton(NULL), fTarget(target) { + fTeam->AddListener(this); } BreakConditionConfigWindow::~BreakConditionConfigWindow() { + fTeam->RemoveListener(this); BMessenger(fTarget).SendMessage(MSG_BREAK_CONDITION_CONFIG_WINDOW_CLOSED); } @@ -96,28 +116,27 @@ BreakConditionConfigWindow::MessageReceived(BMessage* message) case MSG_SET_STOP_FOR_ALL_IMAGES: { - for (int32 i = 0; i < fStopImageNames->CountItems(); i++) - fStopImageNames->ItemAt(i)->SetEnabled(false); - fStopImageNameInput->SetEnabled(false); - fAddImageNameButton->SetEnabled(false); - fRemoveImageNameButton->SetEnabled(false); + fUseCustomImages = false; + fListener->SetStopOnImageLoadRequested( + fStopOnImageLoad->Value() == B_CONTROL_ON, + fUseCustomImages); break; } case MSG_SET_STOP_FOR_CUSTOM_IMAGES: { - for (int32 i = 0; i < fStopImageNames->CountItems(); i++) - fStopImageNames->ItemAt(i)->SetEnabled(true); - fStopImageNameInput->SetEnabled(true); - fAddImageNameButton->SetEnabled( - fStopImageNameInput->TextView()->TextLength() > 0); - fRemoveImageNameButton->SetEnabled( - fStopImageNames->CurrentSelection() >= 0); + fUseCustomImages = true; + fListener->SetStopOnImageLoadRequested( + fStopOnImageLoad->Value() == B_CONTROL_ON, + fUseCustomImages); break; } case MSG_IMAGE_NAME_SELECTION_CHANGED: { + if (!fUseCustomImages) + break; + fRemoveImageNameButton->SetEnabled( fStopImageNames->CurrentSelection() >= 0); break; @@ -126,10 +145,79 @@ BreakConditionConfigWindow::MessageReceived(BMessage* message) case MSG_STOP_ON_IMAGE_LOAD: { fListener->SetStopOnImageLoadRequested( - fStopOnImageLoad->Value() == B_CONTROL_ON); + fStopOnImageLoad->Value() == B_CONTROL_ON, + fUseCustomImages); break; } + case MSG_STOP_IMAGE_SETTINGS_CHANGED: + { + _UpdateStopImageButtons(); + break; + } + + case MSG_ADD_IMAGE_NAME: + { + BString imageName(fStopImageNameInput->Text()); + AutoLocker< ::Team> teamLocker(fTeam); + if (fTeam->StopImageNames().HasString(imageName)) + break; + + fStopImageNameInput->SetText(""); + fListener->AddStopImageNameRequested(imageName.String()); + break; + } + + case MSG_STOP_IMAGE_NAME_ADDED: + { + const char* imageName; + if (message->FindString("name", &imageName) != B_OK) + break; + + BStringItem* item = new(std::nothrow) BStringItem(imageName); + if (item == NULL) + break; + + ObjectDeleter itemDeleter(item); + if (!fStopImageNames->AddItem(item)) { + break; + } + itemDeleter.Detach(); + fStopImageNames->SortItems(SortStringItems); + break; + } + + case MSG_REMOVE_IMAGE_NAME: + { + BStringItem* item; + int32 selectedIndex; + AutoLocker< ::Team> teamLocker(fTeam); + int32 i = 0; + while ((selectedIndex = fStopImageNames->CurrentSelection(i++)) + >= 0) { + item = (BStringItem*)fStopImageNames->ItemAt(selectedIndex); + fListener->RemoveStopImageNameRequested(item->Text()); + } + break; + } + + case MSG_STOP_IMAGE_NAME_REMOVED: + { + const char* imageName; + if (message->FindString("name", &imageName) != B_OK) + break; + + for (int32 i = 0; i < fStopImageNames->CountItems(); i++) { + BStringItem* item = (BStringItem*)fStopImageNames->ItemAt(i); + if (strcmp(item->Text(), imageName) == 0) { + fStopImageNames->RemoveItem(i); + delete item; + } + } + break; + } + + default: BWindow::MessageReceived(message); break; @@ -146,6 +234,37 @@ BreakConditionConfigWindow::Show() } +void +BreakConditionConfigWindow::StopOnImageLoadSettingsChanged( + const Team::ImageLoadEvent& event) +{ + BMessage message(MSG_STOP_IMAGE_SETTINGS_CHANGED); + message.AddBool("enabled", event.StopOnImageLoad()); + message.AddBool("useNameList", event.StopImageNameListEnabled()); + PostMessage(&message); +} + + +void +BreakConditionConfigWindow::StopOnImageLoadNameAdded( + const Team::ImageLoadNameEvent& event) +{ + BMessage message(MSG_STOP_IMAGE_NAME_ADDED); + message.AddString("name", event.ImageName()); + PostMessage(&message); +} + + +void +BreakConditionConfigWindow::StopOnImageLoadNameRemoved( + const Team::ImageLoadNameEvent& event) +{ + BMessage message(MSG_STOP_IMAGE_NAME_REMOVED); + message.AddString("name", event.ImageName()); + PostMessage(&message); +} + + void BreakConditionConfigWindow::_Init() { @@ -179,7 +298,7 @@ BreakConditionConfigWindow::_Init() stopImageMenu->AddItem(new BMenuItem("Custom", new BMessage(MSG_SET_STOP_FOR_CUSTOM_IMAGES))); - BListView* fStopImageNames = new BListView("customImageList", + fStopImageNames = new BListView("customImageList", B_MULTIPLE_SELECTION_LIST); fStopImageNames->SetSelectionMessage( new BMessage(MSG_IMAGE_NAME_SELECTION_CHANGED)); @@ -226,24 +345,11 @@ BreakConditionConfigWindow::_Init() fCloseButton->SetTarget(this); stopImageMenu->SetTargetForItems(this); stopImageMenu->SetLabelFromMarked(true); - stopImageMenu->ItemAt(0L)->SetMarked(true); - // check if the exception breakpoints are already installed AutoLocker< ::Team> teamLocker(fTeam); - for (ImageList::ConstIterator it = fTeam->Images().GetIterator(); - it.HasNext();) { - Image* image = it.Next(); + _UpdateStopImageState(); + _UpdateExceptionState(); - ImageDebugInfo* info = image->GetImageDebugInfo(); - target_addr_t address; - if (_FindExceptionFunction(info, address) != B_OK) - continue; - - if (fTeam->BreakpointAtAddress(address) != NULL) { - fExceptionThrown->SetValue(B_CONTROL_ON); - break; - } - } } @@ -286,3 +392,64 @@ BreakConditionConfigWindow::_FindExceptionFunction(ImageDebugInfo* info, return B_NAME_NOT_FOUND; } + + +void +BreakConditionConfigWindow::_UpdateExceptionState() +{ + // check if the exception breakpoints are already installed + for (ImageList::ConstIterator it = fTeam->Images().GetIterator(); + it.HasNext();) { + Image* image = it.Next(); + + ImageDebugInfo* info = image->GetImageDebugInfo(); + target_addr_t address; + if (_FindExceptionFunction(info, address) != B_OK) + continue; + + if (fTeam->BreakpointAtAddress(address) != NULL) { + fExceptionThrown->SetValue(B_CONTROL_ON); + break; + } + } +} + + +void +BreakConditionConfigWindow::_UpdateStopImageState() +{ + fUseCustomImages = fTeam->StopImageNameListEnabled(); + fStopImageConstraints->Menu()->ItemAt(0)->SetMarked(!fUseCustomImages); + fStopImageConstraints->Menu()->ItemAt(1)->SetMarked(fUseCustomImages); + + fStopImageNames->MakeEmpty(); + const BStringList& imageNames = fTeam->StopImageNames(); + for (int32 i = 0; i < imageNames.CountStrings(); i++) { + BStringItem* item = new(std::nothrow) BStringItem( + imageNames.StringAt(i)); + if (item == NULL) + return; + item->SetEnabled(fUseCustomImages); + ObjectDeleter itemDeleter(item); + if (!fStopImageNames->AddItem(item)) + return; + itemDeleter.Detach(); + } + + _UpdateStopImageButtons(); +} + + +void +BreakConditionConfigWindow::_UpdateStopImageButtons() +{ + bool stopOnImageLoad = fTeam->StopOnImageLoad(); + fStopOnImageLoad->SetValue(stopOnImageLoad ? B_CONTROL_ON : B_CONTROL_OFF); + bool enabled = stopOnImageLoad && fUseCustomImages; + fStopImageConstraints->SetEnabled(stopOnImageLoad); + fAddImageNameButton->SetEnabled(enabled); + fRemoveImageNameButton->SetEnabled(enabled + && fStopImageNames->CurrentSelection() >= 0); + fStopImageNames->DoForEach(UpdateItemState, (void*)enabled); + fStopImageNameInput->TextView()->MakeEditable(enabled); +} diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.h b/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.h index 3c51bc83e4..e1478935f6 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/BreakConditionConfigWindow.h @@ -8,6 +8,8 @@ #include +#include "Team.h" + #include "types/Types.h" @@ -17,11 +19,10 @@ class BListView; class BMenuField; class BTextControl; class ImageDebugInfo; -class Team; class UserInterfaceListener; -class BreakConditionConfigWindow : public BWindow { +class BreakConditionConfigWindow : public BWindow, private Team::Listener { public: BreakConditionConfigWindow(::Team* team, UserInterfaceListener* listener, @@ -38,12 +39,27 @@ public: virtual void Show(); + // Team::Listener + virtual void StopOnImageLoadSettingsChanged( + const Team::ImageLoadEvent& event); + virtual void StopOnImageLoadNameAdded( + const Team::ImageLoadNameEvent& event); + virtual void StopOnImageLoadNameRemoved( + const Team::ImageLoadNameEvent& event); + + private: void _Init(); void _UpdateThrownBreakpoints(bool enable); status_t _FindExceptionFunction(ImageDebugInfo* info, target_addr_t& _foundAddress) const; + void _UpdateExceptionState(); + void _UpdateStopImageState(); + void _UpdateStopImageButtons(); + // must be called with team lock held + + private: ::Team* fTeam; @@ -56,6 +72,7 @@ private: BTextControl* fStopImageNameInput; BButton* fAddImageNameButton; BButton* fRemoveImageNameButton; + bool fUseCustomImages; BButton* fCloseButton; BHandler* fTarget; };