xref: /haiku/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp (revision ff3409e005096a604d862a776e470aae2089865d)
1 /*
2  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2010-2012, Rene Gollent, rene@gollent.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "TeamWindow.h"
9 
10 #include <stdio.h>
11 
12 #include <Alert.h>
13 #include <Button.h>
14 #include <FilePanel.h>
15 #include <FindDirectory.h>
16 #include <LayoutBuilder.h>
17 #include <Menu.h>
18 #include <MenuBar.h>
19 #include <MenuItem.h>
20 #include <Message.h>
21 #include <MessageFilter.h>
22 #include <Path.h>
23 #include <StringView.h>
24 #include <TabView.h>
25 #include <ScrollView.h>
26 #include <SplitView.h>
27 #include <TextView.h>
28 
29 #include <AutoLocker.h>
30 
31 #include "Breakpoint.h"
32 #include "CpuState.h"
33 #include "DisassembledCode.h"
34 #include "FileSourceCode.h"
35 #include "GuiSettingsUtils.h"
36 #include "GuiTeamUiSettings.h"
37 #include "Image.h"
38 #include "ImageDebugInfo.h"
39 #include "InspectorWindow.h"
40 #include "LocatableFile.h"
41 #include "MessageCodes.h"
42 #include "RegistersView.h"
43 #include "StackTrace.h"
44 #include "StackTraceView.h"
45 #include "Tracing.h"
46 #include "TypeComponentPath.h"
47 #include "UiUtils.h"
48 #include "UserInterface.h"
49 #include "Variable.h"
50 #include "WatchPromptWindow.h"
51 
52 
53 enum {
54 	MAIN_TAB_INDEX_THREADS	= 0,
55 	MAIN_TAB_INDEX_IMAGES	= 1
56 };
57 
58 
59 enum {
60 	MSG_CHOOSE_DEBUG_REPORT_LOCATION = 'ccrl',
61 	MSG_DEBUG_REPORT_SAVED = 'drsa',
62 	MSG_LOCATE_SOURCE_IF_NEEDED = 'lsin'
63 };
64 
65 
66 class PathViewMessageFilter : public BMessageFilter {
67 public:
68 		PathViewMessageFilter(BMessenger teamWindow)
69 			:
70 			BMessageFilter(B_MOUSE_UP),
71 			fTeamWindowMessenger(teamWindow)
72 		{
73 		}
74 
75 		virtual filter_result Filter(BMessage*, BHandler**)
76 		{
77 			fTeamWindowMessenger.SendMessage(MSG_LOCATE_SOURCE_IF_NEEDED);
78 
79 			return B_DISPATCH_MESSAGE;
80 		}
81 
82 private:
83 		BMessenger fTeamWindowMessenger;
84 };
85 
86 
87 // #pragma mark - TeamWindow
88 
89 
90 TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener)
91 	:
92 	BWindow(BRect(100, 100, 899, 699), "Team", B_TITLED_WINDOW,
93 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
94 	fTeam(team),
95 	fActiveThread(NULL),
96 	fActiveImage(NULL),
97 	fActiveStackTrace(NULL),
98 	fActiveStackFrame(NULL),
99 	fActiveBreakpoint(NULL),
100 	fActiveFunction(NULL),
101 	fActiveSourceCode(NULL),
102 	fActiveSourceObject(ACTIVE_SOURCE_NONE),
103 	fListener(listener),
104 	fTabView(NULL),
105 	fLocalsTabView(NULL),
106 	fThreadListView(NULL),
107 	fImageListView(NULL),
108 	fImageFunctionsView(NULL),
109 	fBreakpointsView(NULL),
110 	fVariablesView(NULL),
111 	fRegistersView(NULL),
112 	fStackTraceView(NULL),
113 	fSourceView(NULL),
114 	fRunButton(NULL),
115 	fStepOverButton(NULL),
116 	fStepIntoButton(NULL),
117 	fStepOutButton(NULL),
118 	fInspectorWindow(NULL),
119 	fFilePanel(NULL)
120 {
121 	fTeam->Lock();
122 	BString name = fTeam->Name();
123 	fTeam->Unlock();
124 	if (fTeam->ID() >= 0)
125 		name << " (" << fTeam->ID() << ")";
126 	SetTitle(name.String());
127 
128 	fTeam->AddListener(this);
129 }
130 
131 
132 TeamWindow::~TeamWindow()
133 {
134 	if (fThreadListView != NULL)
135 		fThreadListView->UnsetListener();
136 	if (fStackTraceView != NULL)
137 		fStackTraceView->UnsetListener();
138 	if (fSourceView != NULL)
139 		fSourceView->UnsetListener();
140 
141 	fTeam->RemoveListener(this);
142 
143 	_SetActiveSourceCode(NULL);
144 	_SetActiveFunction(NULL);
145 	_SetActiveBreakpoint(NULL);
146 	_SetActiveStackFrame(NULL);
147 	_SetActiveStackTrace(NULL);
148 	_SetActiveImage(NULL);
149 	_SetActiveThread(NULL);
150 
151 	delete fFilePanel;
152 }
153 
154 
155 /*static*/ TeamWindow*
156 TeamWindow::Create(::Team* team, UserInterfaceListener* listener)
157 {
158 	TeamWindow* self = new TeamWindow(team, listener);
159 
160 	try {
161 		self->_Init();
162 	} catch (...) {
163 		delete self;
164 		throw;
165 	}
166 
167 	return self;
168 }
169 
170 
171 void
172 TeamWindow::DispatchMessage(BMessage* message, BHandler* handler)
173 {
174 	// Handle function key shortcuts for stepping
175 	switch (message->what) {
176 		case B_KEY_DOWN:
177 			if (fActiveThread != NULL) {
178 				int32 key;
179 				uint32 modifiers;
180 				if (message->FindInt32("key", &key) == B_OK
181 					&& message->FindInt32("modifiers", (int32*)&modifiers)
182 					== B_OK) {
183 					switch (key) {
184 						case B_F5_KEY:
185 							fListener->ThreadActionRequested(
186 								fActiveThread->ID(), MSG_THREAD_RUN);
187 							break;
188 						case B_F10_KEY:
189 							fListener->ThreadActionRequested(
190 								fActiveThread->ID(), MSG_THREAD_STEP_OVER);
191 							break;
192 						case B_F11_KEY:
193 							if ((modifiers & B_SHIFT_KEY) != 0) {
194 								fListener->ThreadActionRequested(
195 									fActiveThread->ID(), MSG_THREAD_STEP_OUT);
196 							} else {
197 								fListener->ThreadActionRequested(
198 									fActiveThread->ID(), MSG_THREAD_STEP_INTO);
199 							}
200 							break;
201 						default:
202 							break;
203 					}
204 				}
205 			}
206 			break;
207 
208 		case B_COPY:
209 		case B_SELECT_ALL:
210 			BView* focusView = CurrentFocus();
211 			if (focusView != NULL)
212 				focusView->MessageReceived(message);
213 			break;
214 	}
215 	BWindow::DispatchMessage(message, handler);
216 }
217 
218 
219 void
220 TeamWindow::MessageReceived(BMessage* message)
221 {
222 	switch (message->what) {
223 		case MSG_CHOOSE_DEBUG_REPORT_LOCATION:
224 		{
225 			try {
226 				char filename[B_FILE_NAME_LENGTH];
227 				UiUtils::ReportNameForTeam(fTeam, filename, sizeof(filename));
228 				BMessenger msgr(this);
229 				fFilePanel = new BFilePanel(B_SAVE_PANEL, &msgr,
230 					NULL, 0, false, new BMessage(MSG_GENERATE_DEBUG_REPORT));
231 				fFilePanel->SetSaveText(filename);
232 				fFilePanel->Show();
233 			} catch (...) {
234 				delete fFilePanel;
235 				fFilePanel = NULL;
236 			}
237 			break;
238 		}
239 		case MSG_GENERATE_DEBUG_REPORT:
240 		{
241 			delete fFilePanel;
242 			fFilePanel = NULL;
243 
244 			BPath path;
245 			entry_ref ref;
246 			if (message->FindRef("directory", &ref) == B_OK
247 				&& message->HasString("name")) {
248 				path.SetTo(&ref);
249 				path.Append(message->FindString("name"));
250 				if (get_ref_for_path(path.Path(), &ref) == B_OK)
251 					fListener->DebugReportRequested(&ref);
252 			}
253 			break;
254 		}
255 		case MSG_DEBUG_REPORT_SAVED:
256 		{
257 			BString data;
258 			data.SetToFormat("Debug report successfully saved to '%s'",
259 				message->FindString("path"));
260 			BAlert *alert = new BAlert("Report saved", data.String(),
261 				"OK");
262 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
263 			alert->Go();
264 			break;
265 		}
266 		case MSG_SHOW_INSPECTOR_WINDOW:
267 		{
268 			if (fInspectorWindow) {
269 				fInspectorWindow->Activate(true);
270 			} else {
271 				try {
272 					fInspectorWindow = InspectorWindow::Create(fTeam,
273 						fListener, this);
274 					if (fInspectorWindow != NULL) {
275 						BMessage settings;
276 						fInspectorWindow->LoadSettings(fUiSettings);
277 						fInspectorWindow->Show();
278 					}
279 	           	} catch (...) {
280 	           		// TODO: notify user
281 	           	}
282 			}
283 
284 			target_addr_t address;
285 			if (message->FindUInt64("address", &address) == B_OK) {
286 				BMessage addressMessage(MSG_INSPECT_ADDRESS);
287 				addressMessage.AddUInt64("address", address);
288 				fInspectorWindow->PostMessage(&addressMessage);
289 			}
290            	break;
291 		}
292 		case MSG_INSPECTOR_WINDOW_CLOSED:
293 		{
294 			_SaveInspectorSettings(CurrentMessage());
295 			fInspectorWindow = NULL;
296 			break;
297 
298 		}
299 		case MSG_SHOW_WATCH_VARIABLE_PROMPT:
300 		{
301 			target_addr_t address;
302 			uint32 type;
303 			int32 length;
304 
305 			if (message->FindUInt64("address", &address) != B_OK
306 				|| message->FindUInt32("type", &type) != B_OK
307 				|| message->FindInt32("length", &length) != B_OK) {
308 				break;
309 			}
310 
311 			try {
312 				WatchPromptWindow* window = WatchPromptWindow::Create(
313 					fTeam->GetArchitecture(), address, type, length,
314 					fListener);
315 				window->Show();
316 			} catch (...) {
317 				// TODO: notify user
318 			}
319 			break;
320 		}
321 		case B_REFS_RECEIVED:
322 		{
323 			entry_ref locatedPath;
324 			message->FindRef("refs", &locatedPath);
325 			_HandleResolveMissingSourceFile(locatedPath);
326 			break;
327 		}
328 		case MSG_LOCATE_SOURCE_IF_NEEDED:
329 		{
330 			if (fActiveFunction != NULL
331 				&& fActiveFunction->GetFunctionDebugInfo()
332 					->SourceFile() != NULL && fActiveSourceCode != NULL
333 				&& fActiveSourceCode->GetSourceFile() == NULL) {
334 				try {
335 					if (fFilePanel == NULL) {
336 						fFilePanel = new BFilePanel(B_OPEN_PANEL,
337 							new BMessenger(this));
338 					}
339 					fFilePanel->Show();
340 				} catch (...) {
341 					delete fFilePanel;
342 					fFilePanel = NULL;
343 				}
344 			}
345 			break;
346 		}
347 		case MSG_THREAD_RUN:
348 		case MSG_THREAD_STOP:
349 		case MSG_THREAD_STEP_OVER:
350 		case MSG_THREAD_STEP_INTO:
351 		case MSG_THREAD_STEP_OUT:
352 			if (fActiveThread != NULL) {
353 				fListener->ThreadActionRequested(fActiveThread->ID(),
354 					message->what);
355 			}
356 			break;
357 
358 		case MSG_THREAD_STATE_CHANGED:
359 		{
360 			int32 threadID;
361 			if (message->FindInt32("thread", &threadID) != B_OK)
362 				break;
363 
364 			_HandleThreadStateChanged(threadID);
365 			break;
366 		}
367 		case MSG_THREAD_CPU_STATE_CHANGED:
368 		{
369 			int32 threadID;
370 			if (message->FindInt32("thread", &threadID) != B_OK)
371 				break;
372 
373 			_HandleCpuStateChanged(threadID);
374 			break;
375 		}
376 
377 		case MSG_THREAD_STACK_TRACE_CHANGED:
378 		{
379 			int32 threadID;
380 			if (message->FindInt32("thread", &threadID) != B_OK)
381 				break;
382 
383 			_HandleStackTraceChanged(threadID);
384 			break;
385 		}
386 
387 		case MSG_IMAGE_DEBUG_INFO_CHANGED:
388 		{
389 			int32 imageID;
390 			if (message->FindInt32("image", &imageID) != B_OK)
391 				break;
392 
393 			_HandleImageDebugInfoChanged(imageID);
394 			break;
395 		}
396 
397 		case MSG_USER_BREAKPOINT_CHANGED:
398 		{
399 			UserBreakpoint* breakpoint;
400 			if (message->FindPointer("breakpoint", (void**)&breakpoint) != B_OK)
401 				break;
402 			BReference<UserBreakpoint> breakpointReference(breakpoint, true);
403 
404 			_HandleUserBreakpointChanged(breakpoint);
405 			break;
406 		}
407 
408 		case MSG_WATCHPOINT_CHANGED:
409 		{
410 			Watchpoint* watchpoint;
411 			if (message->FindPointer("watchpoint", (void**)&watchpoint) != B_OK)
412 				break;
413 			BReference<Watchpoint> watchpointReference(watchpoint, true);
414 
415 			_HandleWatchpointChanged(watchpoint);
416 			break;
417 
418 		}
419 
420 		case MSG_FUNCTION_SOURCE_CODE_CHANGED:
421 		{
422 			_HandleSourceCodeChanged();
423 			break;
424 		}
425 
426 		default:
427 			BWindow::MessageReceived(message);
428 			break;
429 	}
430 }
431 
432 
433 bool
434 TeamWindow::QuitRequested()
435 {
436 	fListener->UserInterfaceQuitRequested();
437 
438 	return false;
439 }
440 
441 
442 status_t
443 TeamWindow::LoadSettings(const GuiTeamUiSettings* settings)
444 {
445 	AutoLocker<BWindow> lock(this);
446 	if (!lock.IsLocked())
447 		return B_ERROR;
448 
449 	BMessage teamWindowSettings;
450 	// no settings stored yet
451 	if (settings->Settings("teamWindow", teamWindowSettings) != B_OK)
452 		return B_OK;
453 
454 	BRect frame;
455 	if (teamWindowSettings.FindRect("frame", &frame) == B_OK) {
456 		ResizeTo(frame.Width(), frame.Height());
457 		MoveTo(frame.left, frame.top);
458 	}
459 
460 	BMessage archive;
461 	if (teamWindowSettings.FindMessage("sourceSplit", &archive) == B_OK)
462 		GuiSettingsUtils::UnarchiveSplitView(archive, fSourceSplitView);
463 
464 	if (teamWindowSettings.FindMessage("functionSplit", &archive) == B_OK)
465 		GuiSettingsUtils::UnarchiveSplitView(archive, fFunctionSplitView);
466 
467 	if (teamWindowSettings.FindMessage("imageSplit", &archive) == B_OK)
468 		GuiSettingsUtils::UnarchiveSplitView(archive, fImageSplitView);
469 
470 	if (teamWindowSettings.FindMessage("threadSplit", &archive) == B_OK)
471 		GuiSettingsUtils::UnarchiveSplitView(archive, fThreadSplitView);
472 
473 	if (teamWindowSettings.FindMessage("imageListView", &archive) == B_OK)
474 		fImageListView->LoadSettings(archive);
475 
476 	if (teamWindowSettings.FindMessage("imageFunctionsView", &archive) == B_OK)
477 		fImageFunctionsView->LoadSettings(archive);
478 
479 	if (teamWindowSettings.FindMessage("threadListView", &archive) == B_OK)
480 		fThreadListView->LoadSettings(archive);
481 
482 	if (teamWindowSettings.FindMessage("variablesView", &archive) == B_OK)
483 		fVariablesView->LoadSettings(archive);
484 
485 	if (teamWindowSettings.FindMessage("registersView", &archive) == B_OK)
486 		fRegistersView->LoadSettings(archive);
487 
488 	if (teamWindowSettings.FindMessage("stackTraceView", &archive) == B_OK)
489 		fStackTraceView->LoadSettings(archive);
490 
491 	if (teamWindowSettings.FindMessage("breakpointsView", &archive) == B_OK)
492 		fBreakpointsView->LoadSettings(archive);
493 
494 	fUiSettings = *settings;
495 
496 	return B_OK;
497 }
498 
499 
500 status_t
501 TeamWindow::SaveSettings(GuiTeamUiSettings* settings)
502 {
503 	AutoLocker<BWindow> lock(this);
504 	if (!lock.IsLocked())
505 		return B_ERROR;
506 
507 	BMessage inspectorSettings;
508 	if (fUiSettings.Settings("inspectorWindow", inspectorSettings) == B_OK) {
509 		if (!settings->AddSettings("inspectorWindow", inspectorSettings))
510 			return B_NO_MEMORY;
511 	}
512 
513 	BMessage archive;
514 	BMessage teamWindowSettings;
515 	if (teamWindowSettings.AddRect("frame", Frame()) != B_OK)
516 		return B_NO_MEMORY;
517 
518 	if (GuiSettingsUtils::ArchiveSplitView(archive, fSourceSplitView) != B_OK)
519 		return B_NO_MEMORY;
520 	if (teamWindowSettings.AddMessage("sourceSplit", &archive) != B_OK)
521 		return B_NO_MEMORY;
522 
523 	if (GuiSettingsUtils::ArchiveSplitView(archive, fFunctionSplitView) != B_OK)
524 		return B_NO_MEMORY;
525 	if (teamWindowSettings.AddMessage("functionSplit", &archive) != B_OK)
526 		return B_NO_MEMORY;
527 
528 	if (GuiSettingsUtils::ArchiveSplitView(archive, fImageSplitView) != B_OK)
529 		return B_NO_MEMORY;
530 	if (teamWindowSettings.AddMessage("imageSplit", &archive))
531 		return B_NO_MEMORY;
532 
533 	if (GuiSettingsUtils::ArchiveSplitView(archive, fThreadSplitView) != B_OK)
534 		return B_NO_MEMORY;
535 	if (teamWindowSettings.AddMessage("threadSplit", &archive))
536 		return B_NO_MEMORY;
537 
538 	if (fImageListView->SaveSettings(archive) != B_OK)
539 		return B_NO_MEMORY;
540 	if (teamWindowSettings.AddMessage("imageListView", &archive))
541 		return B_NO_MEMORY;
542 
543 	if (fImageFunctionsView->SaveSettings(archive) != B_OK)
544 		return B_NO_MEMORY;
545 	if (teamWindowSettings.AddMessage("imageFunctionsView", &archive))
546 		return B_NO_MEMORY;
547 
548 	if (fThreadListView->SaveSettings(archive) != B_OK)
549 		return B_NO_MEMORY;
550 	if (teamWindowSettings.AddMessage("threadListView", &archive))
551 		return B_NO_MEMORY;
552 
553 	if (fVariablesView->SaveSettings(archive) != B_OK)
554 		return B_NO_MEMORY;
555 	if (teamWindowSettings.AddMessage("variablesView", &archive))
556 		return B_NO_MEMORY;
557 
558 	if (fRegistersView->SaveSettings(archive) != B_OK)
559 		return B_NO_MEMORY;
560 	if (teamWindowSettings.AddMessage("registersView", &archive))
561 		return B_NO_MEMORY;
562 
563 	if (fStackTraceView->SaveSettings(archive) != B_OK)
564 		return B_NO_MEMORY;
565 	if (teamWindowSettings.AddMessage("stackTraceView", &archive))
566 		return B_NO_MEMORY;
567 
568 	if (fBreakpointsView->SaveSettings(archive) != B_OK)
569 		return B_NO_MEMORY;
570 	if (teamWindowSettings.AddMessage("breakpointsView", &archive))
571 		return B_NO_MEMORY;
572 
573 	if (!settings->AddSettings("teamWindow", teamWindowSettings))
574 		return B_NO_MEMORY;
575 
576 	return B_OK;
577 }
578 
579 
580 void
581 TeamWindow::ThreadSelectionChanged(::Thread* thread)
582 {
583 	_SetActiveThread(thread);
584 }
585 
586 
587 void
588 TeamWindow::ImageSelectionChanged(Image* image)
589 {
590 	_SetActiveImage(image);
591 }
592 
593 
594 void
595 TeamWindow::StackFrameSelectionChanged(StackFrame* frame)
596 {
597 	_SetActiveStackFrame(frame);
598 }
599 
600 
601 void
602 TeamWindow::FunctionSelectionChanged(FunctionInstance* function)
603 {
604 	// If the function wasn't already active, it was just selected by the user.
605 	if (function != NULL && function != fActiveFunction)
606 		fActiveSourceObject = ACTIVE_SOURCE_FUNCTION;
607 
608 	_SetActiveFunction(function);
609 }
610 
611 
612 void
613 TeamWindow::BreakpointSelectionChanged(UserBreakpoint* breakpoint)
614 {
615 	_SetActiveBreakpoint(breakpoint);
616 }
617 
618 
619 void
620 TeamWindow::SetBreakpointEnabledRequested(UserBreakpoint* breakpoint,
621 	bool enabled)
622 {
623 	fListener->SetBreakpointEnabledRequested(breakpoint, enabled);
624 }
625 
626 
627 void
628 TeamWindow::ClearBreakpointRequested(UserBreakpoint* breakpoint)
629 {
630 	fListener->ClearBreakpointRequested(breakpoint);
631 }
632 
633 
634 void
635 TeamWindow::SetBreakpointRequested(target_addr_t address, bool enabled)
636 {
637 	fListener->SetBreakpointRequested(address, enabled);
638 }
639 
640 
641 void
642 TeamWindow::ClearBreakpointRequested(target_addr_t address)
643 {
644 	fListener->ClearBreakpointRequested(address);
645 }
646 
647 
648 void
649 TeamWindow::WatchpointSelectionChanged(Watchpoint* watchpoint)
650 {
651 	fBreakpointsView->SetBreakpoint(NULL, watchpoint);
652 }
653 
654 
655 void
656 TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint,
657 	bool enabled)
658 {
659 	fListener->SetWatchpointEnabledRequested(watchpoint, enabled);
660 }
661 
662 
663 void
664 TeamWindow::ClearWatchpointRequested(Watchpoint* watchpoint)
665 {
666 	fListener->ClearWatchpointRequested(watchpoint);
667 }
668 
669 
670 void
671 TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
672 	ValueNodeContainer* container, ValueNode* valueNode)
673 {
674 	fListener->ValueNodeValueRequested(cpuState, container, valueNode);
675 }
676 
677 
678 void
679 TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event)
680 {
681 	BMessage message(MSG_THREAD_STATE_CHANGED);
682 	message.AddInt32("thread", event.GetThread()->ID());
683 	PostMessage(&message);
684 }
685 
686 
687 void
688 TeamWindow::ThreadCpuStateChanged(const Team::ThreadEvent& event)
689 {
690 	BMessage message(MSG_THREAD_CPU_STATE_CHANGED);
691 	message.AddInt32("thread", event.GetThread()->ID());
692 	PostMessage(&message);
693 }
694 
695 
696 void
697 TeamWindow::ThreadStackTraceChanged(const Team::ThreadEvent& event)
698 {
699 	BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
700 	message.AddInt32("thread", event.GetThread()->ID());
701 	PostMessage(&message);
702 }
703 
704 
705 void
706 TeamWindow::ImageDebugInfoChanged(const Team::ImageEvent& event)
707 {
708 	BMessage message(MSG_IMAGE_DEBUG_INFO_CHANGED);
709 	message.AddInt32("image", event.GetImage()->ID());
710 	PostMessage(&message);
711 }
712 
713 
714 void
715 TeamWindow::UserBreakpointChanged(const Team::UserBreakpointEvent& event)
716 {
717 	BMessage message(MSG_USER_BREAKPOINT_CHANGED);
718 	BReference<UserBreakpoint> breakpointReference(event.GetBreakpoint());
719 	if (message.AddPointer("breakpoint", event.GetBreakpoint()) == B_OK
720 		&& PostMessage(&message) == B_OK) {
721 		breakpointReference.Detach();
722 	}
723 }
724 
725 
726 void
727 TeamWindow::WatchpointChanged(const Team::WatchpointEvent& event)
728 {
729 	BMessage message(MSG_WATCHPOINT_CHANGED);
730 	BReference<Watchpoint> watchpointReference(event.GetWatchpoint());
731 	if (message.AddPointer("watchpoint", event.GetWatchpoint()) == B_OK
732 		&& PostMessage(&message) == B_OK) {
733 		watchpointReference.Detach();
734 	}
735 }
736 
737 
738 void
739 TeamWindow::DebugReportChanged(const Team::DebugReportEvent& event)
740 {
741 	BMessage message(MSG_DEBUG_REPORT_SAVED);
742 	message.AddString("path", event.GetReportPath());
743 	PostMessage(&message);
744 }
745 
746 
747 void
748 TeamWindow::FunctionSourceCodeChanged(Function* function)
749 {
750 	TRACE_GUI("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, "
751 		"state: %d\n", function, function->GetSourceCode(),
752 		function->SourceCodeState());
753 
754 	PostMessage(MSG_FUNCTION_SOURCE_CODE_CHANGED);
755 }
756 
757 
758 void
759 TeamWindow::_Init()
760 {
761 	BScrollView* sourceScrollView;
762 
763 	BLayoutBuilder::Group<>(this, B_VERTICAL)
764 		.Add(fMenuBar = new BMenuBar("Menu"))
765 		.AddSplit(B_VERTICAL, 3.0f)
766 			.GetSplitView(&fFunctionSplitView)
767 			.SetInsets(4.0f, 4.0f, 4.0f, 4.0f)
768 			.Add(fTabView = new BTabView("tab view"), 0.4f)
769 			.AddGroup(B_VERTICAL, 4.0f)
770 				.AddGroup(B_HORIZONTAL, 4.0f)
771 					.Add(fRunButton = new BButton("Run"))
772 					.Add(fStepOverButton = new BButton("Step Over"))
773 					.Add(fStepIntoButton = new BButton("Step Into"))
774 					.Add(fStepOutButton = new BButton("Step Out"))
775 					.AddGlue()
776 				.End()
777 				.Add(fSourcePathView = new BStringView(
778 					"source path",
779 					"Source path unavailable."), 4.0f)
780 				.AddSplit(B_HORIZONTAL, 3.0f)
781 					.GetSplitView(&fSourceSplitView)
782 					.Add(sourceScrollView = new BScrollView("source scroll",
783 						NULL, 0, true, true), 3.0f)
784 					.Add(fLocalsTabView = new BTabView("locals view"))
785 				.End()
786 			.End()
787 		.End();
788 
789 	// add source view
790 	sourceScrollView->SetTarget(fSourceView = SourceView::Create(fTeam, this));
791 
792 	// add threads tab
793 	BSplitView* threadGroup = new BSplitView(B_HORIZONTAL);
794 	threadGroup->SetName("Threads");
795 	fTabView->AddTab(threadGroup);
796 	BLayoutBuilder::Split<>(threadGroup)
797 		.GetSplitView(&fThreadSplitView)
798 		.Add(fThreadListView = ThreadListView::Create(fTeam, this))
799 		.Add(fStackTraceView = StackTraceView::Create(this));
800 
801 	// add images tab
802 	BSplitView* imagesGroup = new BSplitView(B_HORIZONTAL);
803 	imagesGroup->SetName("Images");
804 	fTabView->AddTab(imagesGroup);
805 	BLayoutBuilder::Split<>(imagesGroup)
806 		.GetSplitView(&fImageSplitView)
807 		.Add(fImageListView = ImageListView::Create(fTeam, this))
808 		.Add(fImageFunctionsView = ImageFunctionsView::Create(this));
809 
810 	// add breakpoints tab
811 	BGroupView* breakpointsGroup = new BGroupView(B_HORIZONTAL, 4.0f);
812 	breakpointsGroup->SetName("Breakpoints");
813 	fTabView->AddTab(breakpointsGroup);
814 	BLayoutBuilder::Group<>(breakpointsGroup)
815 		.SetInsets(4.0f, 4.0f, 4.0f, 4.0f)
816 		.Add(fBreakpointsView = BreakpointsView::Create(fTeam, this));
817 
818 	// add local variables tab
819 	BView* tab = fVariablesView = VariablesView::Create(this);
820 	fLocalsTabView->AddTab(tab);
821 
822 	// add registers tab
823 	tab = fRegistersView = RegistersView::Create(fTeam->GetArchitecture());
824 	fLocalsTabView->AddTab(tab);
825 
826 	fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
827 	fStepOverButton->SetMessage(new BMessage(MSG_THREAD_STEP_OVER));
828 	fStepIntoButton->SetMessage(new BMessage(MSG_THREAD_STEP_INTO));
829 	fStepOutButton->SetMessage(new BMessage(MSG_THREAD_STEP_OUT));
830 	fRunButton->SetTarget(this);
831 	fStepOverButton->SetTarget(this);
832 	fStepIntoButton->SetTarget(this);
833 	fStepOutButton->SetTarget(this);
834 
835 	fSourcePathView->SetExplicitMinSize(BSize(100.0, B_SIZE_UNSET));
836 	fSourcePathView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
837 	BMessageFilter* filter = new(std::nothrow) PathViewMessageFilter(
838 		BMessenger(this));
839 	if (filter != NULL)
840 		fSourcePathView->AddFilter(filter);
841 
842 	// add menus and menu items
843 	BMenu* menu = new BMenu("File");
844 	fMenuBar->AddItem(menu);
845 	BMenuItem* item = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED),
846 		'Q');
847 	menu->AddItem(item);
848 	item->SetTarget(this);
849 	menu = new BMenu("Edit");
850 	fMenuBar->AddItem(menu);
851 	item = new BMenuItem("Copy", new BMessage(B_COPY), 'C');
852 	menu->AddItem(item);
853 	item->SetTarget(this);
854 	item = new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A');
855 	menu->AddItem(item);
856 	item->SetTarget(this);
857 	menu = new BMenu("Tools");
858 	fMenuBar->AddItem(menu);
859 	item = new BMenuItem("Save Debug Report",
860 		new BMessage(MSG_CHOOSE_DEBUG_REPORT_LOCATION));
861 	menu->AddItem(item);
862 	item->SetTarget(this);
863 	item = new BMenuItem("Inspect Memory",
864 		new BMessage(MSG_SHOW_INSPECTOR_WINDOW), 'I');
865 	menu->AddItem(item);
866 	item->SetTarget(this);
867 
868 	AutoLocker< ::Team> locker(fTeam);
869 	_UpdateRunButtons();
870 }
871 
872 
873 void
874 TeamWindow::_SetActiveThread(::Thread* thread)
875 {
876 	if (thread == fActiveThread)
877 		return;
878 
879 	if (fActiveThread != NULL)
880 		fActiveThread->ReleaseReference();
881 
882 	fActiveThread = thread;
883 
884 	if (fActiveThread != NULL)
885 		fActiveThread->AcquireReference();
886 
887 	AutoLocker< ::Team> locker(fTeam);
888 	_UpdateRunButtons();
889 
890 	StackTrace* stackTrace = fActiveThread != NULL
891 		? fActiveThread->GetStackTrace() : NULL;
892 	BReference<StackTrace> stackTraceReference(stackTrace);
893 		// hold a reference until we've set it
894 
895 	locker.Unlock();
896 
897 	fThreadListView->SetThread(fActiveThread);
898 
899 	_SetActiveStackTrace(stackTrace);
900 	_UpdateCpuState();
901 }
902 
903 
904 void
905 TeamWindow::_SetActiveImage(Image* image)
906 {
907 	if (image == fActiveImage)
908 		return;
909 
910 	if (fActiveImage != NULL)
911 		fActiveImage->ReleaseReference();
912 
913 	fActiveImage = image;
914 
915 	AutoLocker< ::Team> locker(fTeam);
916 
917 	ImageDebugInfo* imageDebugInfo = NULL;
918 	BReference<ImageDebugInfo> imageDebugInfoReference;
919 
920 	if (fActiveImage != NULL) {
921 		fActiveImage->AcquireReference();
922 
923 		imageDebugInfo = fActiveImage->GetImageDebugInfo();
924 		imageDebugInfoReference.SetTo(imageDebugInfo);
925 
926 		// If the debug info is not loaded yet, request it.
927 		if (fActiveImage->ImageDebugInfoState() == IMAGE_DEBUG_INFO_NOT_LOADED)
928 			fListener->ImageDebugInfoRequested(fActiveImage);
929 	}
930 
931 	locker.Unlock();
932 
933 	fImageListView->SetImage(fActiveImage);
934 	fImageFunctionsView->SetImageDebugInfo(imageDebugInfo);
935 }
936 
937 
938 void
939 TeamWindow::_SetActiveStackTrace(StackTrace* stackTrace)
940 {
941 	if (stackTrace == fActiveStackTrace)
942 		return;
943 
944 	if (fActiveStackTrace != NULL)
945 		fActiveStackTrace->ReleaseReference();
946 
947 	fActiveStackTrace = stackTrace;
948 
949 	if (fActiveStackTrace != NULL)
950 		fActiveStackTrace->AcquireReference();
951 
952 	fStackTraceView->SetStackTrace(fActiveStackTrace);
953 	fSourceView->SetStackTrace(fActiveStackTrace);
954 
955 	if (fActiveStackTrace != NULL)
956 		_SetActiveStackFrame(fActiveStackTrace->FrameAt(0));
957 }
958 
959 
960 void
961 TeamWindow::_SetActiveStackFrame(StackFrame* frame)
962 {
963 	if (frame == fActiveStackFrame)
964 		return;
965 
966 	if (fActiveStackFrame != NULL) {
967 		AutoLocker< ::Team> locker(fTeam);
968 		fActiveStackFrame->RemoveListener(this);
969 		locker.Unlock();
970 
971 		fActiveStackFrame->ReleaseReference();
972 	}
973 
974 	fActiveStackFrame = frame;
975 
976 	if (fActiveStackFrame != NULL) {
977 		fActiveStackFrame->AcquireReference();
978 
979 		AutoLocker< ::Team> locker(fTeam);
980 		fActiveStackFrame->AddListener(this);
981 		locker.Unlock();
982 
983 		fActiveSourceObject = ACTIVE_SOURCE_STACK_FRAME;
984 
985 		_SetActiveFunction(fActiveStackFrame->Function());
986 	}
987 
988 	_UpdateCpuState();
989 
990 	fStackTraceView->SetStackFrame(fActiveStackFrame);
991 	if (fActiveStackFrame != NULL)
992 		fVariablesView->SetStackFrame(fActiveThread, fActiveStackFrame);
993 	else
994 		fVariablesView->SetStackFrame(NULL, NULL);
995 	fSourceView->SetStackFrame(fActiveStackFrame);
996 }
997 
998 
999 void
1000 TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint)
1001 {
1002 	if (breakpoint == fActiveBreakpoint)
1003 		return;
1004 
1005 	if (fActiveBreakpoint != NULL)
1006 		fActiveBreakpoint->ReleaseReference();
1007 
1008 	fActiveBreakpoint = breakpoint;
1009 
1010 	if (fActiveBreakpoint != NULL) {
1011 		fActiveBreakpoint->AcquireReference();
1012 
1013 		// get the breakpoint's function (more exactly: some function instance)
1014 		AutoLocker< ::Team> locker(fTeam);
1015 
1016 		Function* function = fTeam->FunctionByID(
1017 			breakpoint->Location().GetFunctionID());
1018 		FunctionInstance* functionInstance = function != NULL
1019 			? function->FirstInstance() : NULL;
1020 		BReference<FunctionInstance> functionInstanceReference(
1021 			functionInstance);
1022 
1023 		locker.Unlock();
1024 
1025 		fActiveSourceObject = ACTIVE_SOURCE_BREAKPOINT;
1026 
1027 		_SetActiveFunction(functionInstance);
1028 
1029 		// scroll to the breakpoint's source code line number (it is not done
1030 		// automatically, if the active function remains the same)
1031 		_ScrollToActiveFunction();
1032 	}
1033 
1034 	fBreakpointsView->SetBreakpoint(fActiveBreakpoint, NULL);
1035 }
1036 
1037 
1038 void
1039 TeamWindow::_SetActiveFunction(FunctionInstance* functionInstance)
1040 {
1041 	if (functionInstance == fActiveFunction)
1042 		return;
1043 
1044 	AutoLocker< ::Team> locker(fTeam);
1045 
1046 	if (fActiveFunction != NULL) {
1047 		fActiveFunction->GetFunction()->RemoveListener(this);
1048 		fActiveFunction->ReleaseReference();
1049 	}
1050 
1051 	// to avoid listener feedback problems, first unset the active function and
1052 	// set the new image, if any
1053 	locker.Unlock();
1054 
1055 	fActiveFunction = NULL;
1056 
1057 	if (functionInstance != NULL)
1058 		_SetActiveImage(fTeam->ImageByAddress(functionInstance->Address()));
1059 
1060 	fActiveFunction = functionInstance;
1061 
1062 	locker.Lock();
1063 
1064 	SourceCode* sourceCode = NULL;
1065 	BReference<SourceCode> sourceCodeReference;
1066 
1067 	if (fActiveFunction != NULL) {
1068 		fActiveFunction->AcquireReference();
1069 		fActiveFunction->GetFunction()->AddListener(this);
1070 
1071 		Function* function = fActiveFunction->GetFunction();
1072 		sourceCode = function->GetSourceCode();
1073 		if (sourceCode == NULL)
1074 			sourceCode = fActiveFunction->GetSourceCode();
1075 		sourceCodeReference.SetTo(sourceCode);
1076 
1077 		// If the source code is not loaded yet, request it.
1078 		if (function->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED)
1079 			fListener->FunctionSourceCodeRequested(fActiveFunction);
1080 	}
1081 
1082 	locker.Unlock();
1083 
1084 	_SetActiveSourceCode(sourceCode);
1085 
1086 	fImageFunctionsView->SetFunction(fActiveFunction);
1087 
1088 	locker.Lock();
1089 
1090 	// look if our current stack trace has a frame matching the selected
1091 	// function. If so, set it to match.
1092 	StackFrame* matchingFrame = NULL;
1093 	BReference<StackFrame> frameRef;
1094 
1095 	if (fActiveStackTrace != NULL) {
1096 		for (int32 i = 0; i < fActiveStackTrace->CountFrames(); i++) {
1097 			StackFrame* frame = fActiveStackTrace->FrameAt(i);
1098 			if (frame->Function() == fActiveFunction) {
1099 				matchingFrame = frame;
1100 				frameRef.SetTo(frame);
1101 				break;
1102 			}
1103 		}
1104 	}
1105 
1106 	locker.Unlock();
1107 
1108 	if (matchingFrame != NULL)
1109 		_SetActiveStackFrame(matchingFrame);
1110 }
1111 
1112 
1113 void
1114 TeamWindow::_SetActiveSourceCode(SourceCode* sourceCode)
1115 {
1116 	if (sourceCode == fActiveSourceCode) {
1117 		_ScrollToActiveFunction();
1118 		return;
1119 	}
1120 
1121 	if (fActiveSourceCode != NULL)
1122 		fActiveSourceCode->ReleaseReference();
1123 
1124 	fActiveSourceCode = sourceCode;
1125 
1126 	if (fActiveSourceCode != NULL)
1127 		fActiveSourceCode->AcquireReference();
1128 
1129 	fSourceView->SetSourceCode(fActiveSourceCode);
1130 
1131 	_UpdateSourcePathState();
1132 	_ScrollToActiveFunction();
1133 }
1134 
1135 void
1136 TeamWindow::_UpdateCpuState()
1137 {
1138 	// get the CPU state
1139 	CpuState* cpuState = NULL;
1140 	BReference<CpuState> cpuStateReference;
1141 		// hold a reference until the register view has one
1142 
1143 	if (fActiveThread != NULL) {
1144 		// Get the CPU state from the active stack frame or the thread directly.
1145 		if (fActiveStackFrame == NULL) {
1146 			AutoLocker< ::Team> locker(fTeam);
1147 			cpuState = fActiveThread->GetCpuState();
1148 			cpuStateReference.SetTo(cpuState);
1149 			locker.Unlock();
1150 		} else
1151 			cpuState = fActiveStackFrame->GetCpuState();
1152 	}
1153 
1154 	fRegistersView->SetCpuState(cpuState);
1155 }
1156 
1157 
1158 void
1159 TeamWindow::_UpdateRunButtons()
1160 {
1161 	uint32 threadState = fActiveThread != NULL
1162 		? fActiveThread->State() : THREAD_STATE_UNKNOWN;
1163 
1164 	switch (threadState) {
1165 		case THREAD_STATE_UNKNOWN:
1166 			fRunButton->SetEnabled(false);
1167 			fStepOverButton->SetEnabled(false);
1168 			fStepIntoButton->SetEnabled(false);
1169 			fStepOutButton->SetEnabled(false);
1170 			break;
1171 		case THREAD_STATE_RUNNING:
1172 			fRunButton->SetLabel("Debug");
1173 			fRunButton->SetMessage(new BMessage(MSG_THREAD_STOP));
1174 			fRunButton->SetEnabled(true);
1175 			fStepOverButton->SetEnabled(false);
1176 			fStepIntoButton->SetEnabled(false);
1177 			fStepOutButton->SetEnabled(false);
1178 			break;
1179 		case THREAD_STATE_STOPPED:
1180 			fRunButton->SetLabel("Run");
1181 			fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
1182 			fRunButton->SetEnabled(true);
1183 			fStepOverButton->SetEnabled(true);
1184 			fStepIntoButton->SetEnabled(true);
1185 			fStepOutButton->SetEnabled(true);
1186 			break;
1187 	}
1188 }
1189 
1190 
1191 void
1192 TeamWindow::_UpdateSourcePathState()
1193 {
1194 	LocatableFile* sourceFile = NULL;
1195 	BString sourceText = "Source file unavailable.";
1196 	BString truncatedText;
1197 
1198 	if (fActiveSourceCode != NULL) {
1199 		sourceFile = fActiveFunction->GetFunctionDebugInfo()->SourceFile();
1200 
1201 		if (sourceFile != NULL && !sourceFile->GetLocatedPath(sourceText))
1202 			sourceFile->GetPath(sourceText);
1203 
1204 		if (fActiveSourceCode->GetSourceFile() == NULL && sourceFile != NULL) {
1205 			sourceText.Prepend("Click to locate source file '");
1206 			sourceText += "'";
1207 			truncatedText = sourceText;
1208 			fSourcePathView->TruncateString(&truncatedText, B_TRUNCATE_MIDDLE,
1209 				fSourcePathView->Bounds().Width());
1210 		} else if (sourceFile != NULL) {
1211 			sourceText.Prepend("File: ");
1212 		}
1213 	}
1214 
1215 	if (!truncatedText.IsEmpty() && truncatedText != sourceText) {
1216 		fSourcePathView->SetToolTip(sourceText);
1217 		fSourcePathView->SetText(truncatedText);
1218 	} else
1219 		fSourcePathView->SetText(sourceText);
1220 }
1221 
1222 
1223 void
1224 TeamWindow::_ScrollToActiveFunction()
1225 {
1226 	// Scroll to the active function, if it has been selected manually.
1227 	if (fActiveFunction == NULL || fActiveSourceCode == NULL)
1228 		return;
1229 
1230 	switch (fActiveSourceObject) {
1231 		case ACTIVE_SOURCE_FUNCTION:
1232 			fSourceView->ScrollToAddress(fActiveFunction->Address());
1233 			break;
1234 		case ACTIVE_SOURCE_BREAKPOINT:
1235 		{
1236 			if (fActiveBreakpoint == NULL)
1237 				break;
1238 
1239 			const UserBreakpointLocation& location
1240 				= fActiveBreakpoint->Location();
1241 			int32 line = location.GetSourceLocation().Line();
1242 
1243 			if (location.SourceFile() != NULL && line >= 0
1244 				&& fActiveSourceCode->GetSourceFile()
1245 					== location.SourceFile()) {
1246 				fSourceView->ScrollToLine(line);
1247 			} else {
1248 				fSourceView->ScrollToAddress(
1249 					fActiveFunction->Address()
1250 						+ location.RelativeAddress());
1251 			}
1252 			break;
1253 		}
1254 		case ACTIVE_SOURCE_NONE:
1255 		case ACTIVE_SOURCE_STACK_FRAME:
1256 			break;
1257 	}
1258 }
1259 
1260 
1261 void
1262 TeamWindow::_HandleThreadStateChanged(thread_id threadID)
1263 {
1264 	AutoLocker< ::Team> locker(fTeam);
1265 
1266 	::Thread* thread = fTeam->ThreadByID(threadID);
1267 	if (thread == NULL)
1268 		return;
1269 
1270 	// If the thread has been stopped and we don't have an active thread yet
1271 	// (or it isn't stopped), switch to this thread. Otherwise ignore the event.
1272 	if (thread->State() == THREAD_STATE_STOPPED
1273 		&& (fActiveThread == NULL
1274 			|| (thread != fActiveThread
1275 				&& fActiveThread->State() != THREAD_STATE_STOPPED))) {
1276 		_SetActiveThread(thread);
1277 	} else if (thread != fActiveThread) {
1278 		// otherwise ignore the event, if the thread is not the active one
1279 		return;
1280 	}
1281 
1282 	// Switch to the threads tab view when the thread has stopped.
1283 	if (thread->State() == THREAD_STATE_STOPPED)
1284 		fTabView->Select(MAIN_TAB_INDEX_THREADS);
1285 
1286 	_UpdateRunButtons();
1287 }
1288 
1289 
1290 void
1291 TeamWindow::_HandleCpuStateChanged(thread_id threadID)
1292 {
1293 	// We're only interested in the currently selected thread
1294 	if (fActiveThread == NULL || threadID != fActiveThread->ID())
1295 		return;
1296 
1297 	_UpdateCpuState();
1298 }
1299 
1300 
1301 void
1302 TeamWindow::_HandleStackTraceChanged(thread_id threadID)
1303 {
1304 	// We're only interested in the currently selected thread
1305 	if (fActiveThread == NULL || threadID != fActiveThread->ID())
1306 		return;
1307 
1308 	AutoLocker< ::Team> locker(fTeam);
1309 
1310 	StackTrace* stackTrace = fActiveThread != NULL
1311 		? fActiveThread->GetStackTrace() : NULL;
1312 	BReference<StackTrace> stackTraceReference(stackTrace);
1313 		// hold a reference until the register view has one
1314 
1315 	locker.Unlock();
1316 
1317 	_SetActiveStackTrace(stackTrace);
1318 }
1319 
1320 
1321 void
1322 TeamWindow::_HandleImageDebugInfoChanged(image_id imageID)
1323 {
1324 	TRACE_GUI("TeamWindow::_HandleImageDebugInfoChanged(%" B_PRId32 ")\n",
1325 		imageID);
1326 
1327 	// We're only interested in the currently selected thread
1328 	if (fActiveImage == NULL || imageID != fActiveImage->ID())
1329 		return;
1330 
1331 	AutoLocker< ::Team> locker(fTeam);
1332 
1333 	ImageDebugInfo* imageDebugInfo = fActiveImage != NULL
1334 		? fActiveImage->GetImageDebugInfo() : NULL;
1335 
1336 	TRACE_GUI("  image debug info: %p\n", imageDebugInfo);
1337 
1338 	BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo);
1339 		// hold a reference until we've set it
1340 
1341 	locker.Unlock();
1342 
1343 	fImageFunctionsView->SetImageDebugInfo(imageDebugInfo);
1344 }
1345 
1346 
1347 void
1348 TeamWindow::_HandleSourceCodeChanged()
1349 {
1350 	// If we don't have an active function anymore, the message is obsolete.
1351 	if (fActiveFunction == NULL)
1352 		return;
1353 
1354 	// get a reference to the source code
1355 	AutoLocker< ::Team> locker(fTeam);
1356 
1357 	SourceCode* sourceCode = fActiveFunction->GetFunction()->GetSourceCode();
1358 	if (sourceCode == NULL)
1359 		sourceCode = fActiveFunction->GetSourceCode();
1360 
1361 	BReference<SourceCode> sourceCodeReference(sourceCode);
1362 
1363 	locker.Unlock();
1364 
1365 	_SetActiveSourceCode(sourceCode);
1366 }
1367 
1368 
1369 void
1370 TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint)
1371 {
1372 	fSourceView->UserBreakpointChanged(breakpoint);
1373 	fBreakpointsView->UserBreakpointChanged(breakpoint);
1374 }
1375 
1376 
1377 void
1378 TeamWindow::_HandleWatchpointChanged(Watchpoint* watchpoint)
1379 {
1380 	fBreakpointsView->WatchpointChanged(watchpoint);
1381 }
1382 
1383 
1384 void
1385 TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath)
1386 {
1387 	if (fActiveFunction != NULL) {
1388 		LocatableFile* sourceFile = fActiveFunction->GetFunctionDebugInfo()
1389 			->SourceFile();
1390 		if (sourceFile != NULL) {
1391 			BString sourcePath;
1392 			BString targetPath;
1393 			sourceFile->GetPath(sourcePath);
1394 			BPath path(&locatedPath);
1395 			targetPath = path.Path();
1396 			fListener->SourceEntryLocateRequested(sourcePath, targetPath);
1397 			fListener->FunctionSourceCodeRequested(fActiveFunction);
1398 		}
1399 	}
1400 }
1401 
1402 
1403 status_t
1404 TeamWindow::_SaveInspectorSettings(const BMessage* settings)
1405 {
1406 	if (fUiSettings.AddSettings("inspectorWindow", *settings) != B_OK)
1407 		return B_NO_MEMORY;
1408 
1409 	return B_OK;
1410 }
1411