vfs: check userland buffers before reading them.
[haiku.git] / src / apps / debugger / user_interface / gui / GraphicalUserInterface.cpp
bloba6e50afdc98122991c9e5d5e0b3e7085b9d02573
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2011-2016, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
8 #include "GraphicalUserInterface.h"
10 #include <Alert.h>
11 #include <AutoDeleter.h>
12 #include <Autolock.h>
13 #include <FilePanel.h>
14 #include <Locker.h>
16 #include "GuiTeamUiSettings.h"
17 #include "MessageCodes.h"
18 #include "TeamWindow.h"
19 #include "Tracing.h"
22 // #pragma mark - GraphicalUserInterface::FilePanelHandler
25 class GraphicalUserInterface::FilePanelHandler : public BHandler {
26 public:
27 FilePanelHandler();
28 virtual ~FilePanelHandler();
30 status_t Init();
32 virtual void MessageReceived(BMessage* message);
34 status_t WaitForPanel();
36 void SetCurrentRef(entry_ref* ref);
38 BLocker& Locker()
39 { return fPanelLock; }
41 private:
42 entry_ref* fCurrentRef;
43 BLocker fPanelLock;
44 sem_id fPanelWaitSem;
48 GraphicalUserInterface::FilePanelHandler::FilePanelHandler()
50 BHandler("GuiPanelHandler"),
51 fCurrentRef(NULL),
52 fPanelLock(),
53 fPanelWaitSem(-1)
58 GraphicalUserInterface::FilePanelHandler::~FilePanelHandler()
60 if (fPanelWaitSem >= 0)
61 delete_sem(fPanelWaitSem);
65 status_t
66 GraphicalUserInterface::FilePanelHandler::Init()
68 fPanelWaitSem = create_sem(0, "FilePanelWaitSem");
70 if (fPanelWaitSem < 0)
71 return fPanelWaitSem;
73 return B_OK;
77 void
78 GraphicalUserInterface::FilePanelHandler::MessageReceived(BMessage* message)
80 switch (message->what) {
81 case MSG_USER_INTERFACE_FILE_CHOSEN:
83 entry_ref ref;
84 if (message->FindRef("refs", &ref) == B_OK
85 && fCurrentRef != NULL) {
86 *fCurrentRef = ref;
87 fCurrentRef = NULL;
89 // fall through
92 case B_CANCEL:
94 release_sem(fPanelWaitSem);
95 break;
98 default:
99 BHandler::MessageReceived(message);
100 break;
105 status_t
106 GraphicalUserInterface::FilePanelHandler::WaitForPanel()
108 status_t result = B_OK;
109 do {
110 result = acquire_sem(fPanelWaitSem);
111 } while (result == B_INTERRUPTED);
113 return result;
117 void
118 GraphicalUserInterface::FilePanelHandler::SetCurrentRef(entry_ref* ref)
120 fCurrentRef = ref;
124 // #pragma mark - GraphicalUserInterface
127 GraphicalUserInterface::GraphicalUserInterface()
129 fTeamWindow(NULL),
130 fTeamWindowMessenger(NULL),
131 fFilePanelHandler(NULL),
132 fFilePanel(NULL)
137 GraphicalUserInterface::~GraphicalUserInterface()
139 delete fTeamWindowMessenger;
140 delete fFilePanel;
144 const char*
145 GraphicalUserInterface::ID() const
147 return "GraphicalUserInterface";
151 status_t
152 GraphicalUserInterface::Init(Team* team, UserInterfaceListener* listener)
154 try {
155 fTeamWindow = TeamWindow::Create(team, listener);
156 fTeamWindowMessenger = new BMessenger(fTeamWindow);
157 fFilePanelHandler = new FilePanelHandler();
158 status_t error = fFilePanelHandler->Init();
159 if (error != B_OK) {
160 ERROR("Error: Failed to create file panel semaphore!\n");
161 return error;
163 fTeamWindow->AddHandler(fFilePanelHandler);
165 // start the message loop
166 fTeamWindow->Hide();
167 fTeamWindow->Show();
168 } catch (...) {
169 // TODO: Notify the user!
170 ERROR("Error: Failed to create team window!\n");
171 return B_NO_MEMORY;
174 return B_OK;
178 void
179 GraphicalUserInterface::Show()
181 if (fTeamWindow->IsHidden())
182 fTeamWindow->Show();
183 else
184 fTeamWindow->Activate();
188 void
189 GraphicalUserInterface::Terminate()
191 // quit window
192 if (fTeamWindowMessenger && fTeamWindowMessenger->LockTarget())
193 fTeamWindow->Quit();
197 UserInterface*
198 GraphicalUserInterface::Clone() const
200 return new(std::nothrow) GraphicalUserInterface;
204 bool
205 GraphicalUserInterface::IsInteractive() const
207 return true;
211 status_t
212 GraphicalUserInterface::LoadSettings(const TeamUiSettings* settings)
214 status_t result = fTeamWindow->LoadSettings((GuiTeamUiSettings*)settings);
216 return result;
220 status_t
221 GraphicalUserInterface::SaveSettings(TeamUiSettings*& settings) const
223 settings = new(std::nothrow) GuiTeamUiSettings(ID());
224 if (settings == NULL)
225 return B_NO_MEMORY;
227 fTeamWindow->SaveSettings((GuiTeamUiSettings*)settings);
229 return B_OK;
233 void
234 GraphicalUserInterface::NotifyUser(const char* title, const char* message,
235 user_notification_type type)
237 // convert notification type to alert type
238 alert_type alertType;
239 switch (type) {
240 case USER_NOTIFICATION_INFO:
241 alertType = B_INFO_ALERT;
242 break;
243 case USER_NOTIFICATION_WARNING:
244 case USER_NOTIFICATION_ERROR:
245 default:
246 alertType = B_WARNING_ALERT;
247 break;
250 BAlert* alert = new(std::nothrow) BAlert(title, message, "OK",
251 NULL, NULL, B_WIDTH_AS_USUAL, alertType);
252 if (alert != NULL)
253 alert->Go(NULL);
255 // TODO: We need to let the alert run asynchronously, but we shouldn't just
256 // create it and don't care anymore. Maybe an error window, which can
257 // display a list of errors would be the better choice.
261 void
262 GraphicalUserInterface::NotifyBackgroundWorkStatus(const char* message)
264 fTeamWindow->DisplayBackgroundStatus(message);
268 int32
269 GraphicalUserInterface::SynchronouslyAskUser(const char* title,
270 const char* message, const char* choice1, const char* choice2,
271 const char* choice3)
273 BAlert* alert = new(std::nothrow) BAlert(title, message,
274 choice1, choice2, choice3);
275 if (alert == NULL)
276 return 0;
277 return alert->Go();
281 status_t
282 GraphicalUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref)
284 BAutolock lock(&fFilePanelHandler->Locker());
286 if (fFilePanel == NULL) {
287 BMessenger messenger(fFilePanelHandler);
288 BMessage* message = new(std::nothrow) BMessage(
289 MSG_USER_INTERFACE_FILE_CHOSEN);
290 if (message == NULL)
291 return B_NO_MEMORY;
292 ObjectDeleter<BMessage> messageDeleter(message);
293 fFilePanel = new(std::nothrow) BFilePanel(B_OPEN_PANEL,
294 &messenger, NULL, B_FILE_NODE, false, message);
295 if (fFilePanel == NULL)
296 return B_NO_MEMORY;
297 messageDeleter.Detach();
300 fFilePanelHandler->SetCurrentRef(_ref);
301 fFilePanel->Show();
302 return fFilePanelHandler->WaitForPanel();