1/* 2 * Copyright 2012, Rene Gollent, rene@gollent.com. 3 * Distributed under the terms of the MIT License. 4 */ 5#include "WatchPromptWindow.h" 6 7#include <Alert.h> 8#include <Button.h> 9#include <LayoutBuilder.h> 10#include <Menu.h> 11#include <MenuField.h> 12#include <MenuItem.h> 13#include <String.h> 14#include <TextControl.h> 15 16#include <ExpressionParser.h> 17 18#include "Architecture.h" 19#include "MessageCodes.h" 20#include "UserInterface.h" 21#include "Watchpoint.h" 22 23 24WatchPromptWindow::WatchPromptWindow(Architecture* architecture, 25 target_addr_t address, uint32 type, int32 length, 26 UserInterfaceListener* listener) 27 : 28 BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW, 29 B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), 30 fInitialAddress(address), 31 fInitialType(type), 32 fInitialLength(length), 33 fArchitecture(architecture), 34 fAddressInput(NULL), 35 fLengthInput(NULL), 36 fTypeField(NULL), 37 fListener(listener) 38{ 39 fArchitecture->AcquireReference(); 40} 41 42 43WatchPromptWindow::~WatchPromptWindow() 44{ 45 fArchitecture->ReleaseReference(); 46} 47 48 49WatchPromptWindow* 50WatchPromptWindow::Create(Architecture* architecture, target_addr_t address, 51 uint32 type, int32 length, UserInterfaceListener* listener) 52{ 53 WatchPromptWindow* self = new WatchPromptWindow(architecture, address, 54 type, length, listener); 55 56 try { 57 self->_Init(); 58 } catch (...) { 59 delete self; 60 throw; 61 } 62 63 return self; 64 65} 66 67void 68WatchPromptWindow::_Init() 69{ 70 BString text; 71 text.SetToFormat("0x%" B_PRIx64, fInitialAddress); 72 fAddressInput = new BTextControl("Address:", text, NULL); 73 74 text.SetToFormat("%" B_PRId32, fInitialLength); 75 fLengthInput = new BTextControl("Length:", text, NULL); 76 77 int32 maxDebugRegisters = 0; 78 int32 maxBytesPerRegister = 0; 79 uint8 debugCapabilityFlags = 0; 80 fArchitecture->GetWatchpointDebugCapabilities(maxDebugRegisters, 81 maxBytesPerRegister, debugCapabilityFlags); 82 83 BMenu* typeMenu = new BMenu("Watch Type"); 84 85 BMenuItem* watchTypeItem = new BMenuItem("Read", NULL); 86 watchTypeItem->SetEnabled( 87 (debugCapabilityFlags & WATCHPOINT_CAPABILITY_FLAG_READ) != 0); 88 typeMenu->AddItem(watchTypeItem); 89 90 watchTypeItem = new BMenuItem("Write", NULL); 91 watchTypeItem->SetEnabled( 92 (debugCapabilityFlags & WATCHPOINT_CAPABILITY_FLAG_WRITE) != 0); 93 typeMenu->AddItem(watchTypeItem); 94 95 watchTypeItem = new BMenuItem("Read/Write", NULL); 96 watchTypeItem->SetEnabled( 97 (debugCapabilityFlags & WATCHPOINT_CAPABILITY_FLAG_READ_WRITE) != 0); 98 typeMenu->AddItem(watchTypeItem); 99 100 fTypeField = new BMenuField("Type:", typeMenu); 101 BLayoutItem* labelItem = fTypeField->CreateLabelLayoutItem(); 102 labelItem->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 103 BLayoutBuilder::Group<>(this, B_VERTICAL) 104 .SetInsets(4.0f, 4.0f, 4.0f, 4.0f) 105 .AddGroup(B_HORIZONTAL, 4.0f) 106 .Add(fAddressInput) 107 .End() 108 .AddGroup(B_HORIZONTAL, 4.0f) 109 .Add(fLengthInput) 110 .Add(labelItem) 111 .Add(fTypeField->CreateMenuBarLayoutItem()) 112 .End() 113 .AddGroup(B_HORIZONTAL, 4.0f) 114 .AddGlue() 115 .Add((fWatchButton = new BButton("Set", 116 new BMessage(MSG_SET_WATCHPOINT)))) 117 .Add((fCancelButton = new BButton("Cancel", 118 new BMessage(B_QUIT_REQUESTED)))) 119 .End(); 120 121 fWatchButton->SetTarget(this); 122 fCancelButton->SetTarget(this); 123 124 fTypeField->Menu()->SetLabelFromMarked(true); 125 fTypeField->Menu()->ItemAt(fInitialType)->SetMarked(true); 126} 127 128void 129WatchPromptWindow::Show() 130{ 131 CenterOnScreen(); 132 BWindow::Show(); 133} 134 135void 136WatchPromptWindow::MessageReceived(BMessage* message) 137{ 138 switch (message->what) { 139 case MSG_SET_WATCHPOINT: 140 { 141 target_addr_t address = 0; 142 int32 length = 0; 143 ExpressionParser parser; 144 parser.SetSupportHexInput(true); 145 BString errorMessage; 146 try { 147 address = parser.EvaluateToInt64(fAddressInput->Text()); 148 length = (int32)parser.EvaluateToInt64(fLengthInput->Text()); 149 } catch(ParseException parseError) { 150 errorMessage.SetToFormat("Failed to parse data: %s", 151 parseError.message.String()); 152 } catch(...) { 153 errorMessage.SetToFormat( 154 "Unknown error while parsing address"); 155 } 156 157 if (!errorMessage.IsEmpty()) { 158 BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint", 159 errorMessage.String(), "Close"); 160 if (alert != NULL) 161 alert->Go(); 162 break; 163 } 164 165 fListener->ClearWatchpointRequested(fInitialAddress); 166 fListener->SetWatchpointRequested(address, fTypeField->Menu() 167 ->IndexOf(fTypeField->Menu()->FindMarked()), length, true); 168 169 PostMessage(B_QUIT_REQUESTED); 170 171 break; 172 } 173 default: 174 BWindow::MessageReceived(message); 175 break; 176 } 177 178} 179