xref: /haiku/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp (revision 3369e03d5cde9709c8aa70c99bfe6ce24ba65bf9)
1 /*
2  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2010-2017, 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 <MessageRunner.h>
23 #include <Path.h>
24 #include <PopUpMenu.h>
25 #include <Query.h>
26 #include <StringView.h>
27 #include <TabView.h>
28 #include <ScrollView.h>
29 #include <SplitView.h>
30 #include <TextView.h>
31 #include <VolumeRoster.h>
32 
33 #include <AutoDeleter.h>
34 #include <AutoLocker.h>
35 
36 #include "AppMessageCodes.h"
37 #include "Breakpoint.h"
38 #include "BreakpointEditWindow.h"
39 #include "ConsoleOutputView.h"
40 #include "CppLanguage.h"
41 #include "CpuState.h"
42 #include "DisassembledCode.h"
43 #include "BreakpointEditWindow.h"
44 #include "ExpressionEvaluationWindow.h"
45 #include "ExpressionPromptWindow.h"
46 #include "FileSourceCode.h"
47 #include "GuiSettingsUtils.h"
48 #include "GuiTeamUiSettings.h"
49 #include "Image.h"
50 #include "ImageDebugInfo.h"
51 #include "InspectorWindow.h"
52 #include "LocatableFile.h"
53 #include "MessageCodes.h"
54 #include "RegistersView.h"
55 #include "StackTrace.h"
56 #include "StackTraceView.h"
57 #include "TeamSettingsWindow.h"
58 #include "Tracing.h"
59 #include "TypeComponentPath.h"
60 #include "UiUtils.h"
61 #include "UserInterface.h"
62 #include "ValueNodeManager.h"
63 #include "Value.h"
64 #include "Variable.h"
65 #include "WatchPromptWindow.h"
66 
67 
68 enum {
69 	MAIN_TAB_INDEX_THREADS	= 0,
70 	MAIN_TAB_INDEX_IMAGES	= 1
71 };
72 
73 
74 enum {
75 	MSG_CHOOSE_DEBUG_REPORT_LOCATION	= 'ccrl',
76 	MSG_DEBUG_REPORT_SAVED				= 'drsa',
77 	MSG_LOCATE_SOURCE_IF_NEEDED			= 'lsin',
78 	MSG_SOURCE_ENTRY_QUERY_COMPLETE		= 'seqc',
79 	MSG_CLEAR_STACK_TRACE				= 'clst',
80 	MSG_HANDLE_LOAD_SETTINGS			= 'hlst',
81 	MSG_UPDATE_STATUS_BAR				= 'upsb'
82 };
83 
84 
85 // #pragma mark - ThreadStackFrameSelectionKey
86 
87 
88 struct TeamWindow::ThreadStackFrameSelectionKey {
89 	::Thread*	thread;
90 
91 	ThreadStackFrameSelectionKey(::Thread* thread)
92 		:
93 		thread(thread)
94 	{
95 		thread->AcquireReference();
96 	}
97 
98 	~ThreadStackFrameSelectionKey()
99 	{
100 		thread->ReleaseReference();
101 	}
102 
103 	uint32 HashValue() const
104 	{
105 		return (uint32)thread->ID();
106 	}
107 
108 	bool operator==(const ThreadStackFrameSelectionKey& other) const
109 	{
110 		return thread == other.thread;
111 	}
112 };
113 
114 
115 // #pragma mark - ThreadStackFrameSelectionEntry
116 
117 
118 struct TeamWindow::ThreadStackFrameSelectionEntry
119 	: ThreadStackFrameSelectionKey {
120 	ThreadStackFrameSelectionEntry* next;
121 	StackFrame* selectedFrame;
122 
123 	ThreadStackFrameSelectionEntry(::Thread* thread, StackFrame* frame)
124 		:
125 		ThreadStackFrameSelectionKey(thread),
126 		selectedFrame(frame)
127 	{
128 	}
129 
130 	inline StackFrame* SelectedFrame() const
131 	{
132 		return selectedFrame;
133 	}
134 
135 	void SetSelectedFrame(StackFrame* frame)
136 	{
137 		selectedFrame = frame;
138 	}
139 };
140 
141 
142 // #pragma mark - ThreadStackFrameSelectionEntryHashDefinition
143 
144 
145 struct TeamWindow::ThreadStackFrameSelectionEntryHashDefinition {
146 	typedef ThreadStackFrameSelectionKey 	KeyType;
147 	typedef ThreadStackFrameSelectionEntry	ValueType;
148 
149 	size_t HashKey(const ThreadStackFrameSelectionKey& key) const
150 	{
151 		return key.HashValue();
152 	}
153 
154 	size_t Hash(const ThreadStackFrameSelectionKey* value) const
155 	{
156 		return value->HashValue();
157 	}
158 
159 	bool Compare(const ThreadStackFrameSelectionKey& key,
160 		const ThreadStackFrameSelectionKey* value) const
161 	{
162 		return key == *value;
163 	}
164 
165 	ThreadStackFrameSelectionEntry*& GetLink(
166 		ThreadStackFrameSelectionEntry* value) const
167 	{
168 		return value->next;
169 	}
170 };
171 
172 
173 // #pragma mark - PathViewMessageFilter
174 
175 
176 class PathViewMessageFilter : public BMessageFilter {
177 public:
178 		PathViewMessageFilter(BMessenger teamWindow)
179 			:
180 			BMessageFilter(B_MOUSE_UP),
181 			fTeamWindowMessenger(teamWindow)
182 		{
183 		}
184 
185 		virtual filter_result Filter(BMessage*, BHandler**)
186 		{
187 			fTeamWindowMessenger.SendMessage(MSG_LOCATE_SOURCE_IF_NEEDED);
188 
189 			return B_DISPATCH_MESSAGE;
190 		}
191 
192 private:
193 		BMessenger fTeamWindowMessenger;
194 };
195 
196 
197 // #pragma mark - TeamWindow
198 
199 
200 TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener)
201 	:
202 	BWindow(BRect(100, 100, 899, 699), "Team", B_TITLED_WINDOW,
203 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
204 	fTeam(team),
205 	fActiveThread(NULL),
206 	fActiveImage(NULL),
207 	fActiveStackTrace(NULL),
208 	fActiveStackFrame(NULL),
209 	fThreadSelectionInfoTable(NULL),
210 	fActiveBreakpoint(NULL),
211 	fActiveFunction(NULL),
212 	fActiveSourceCode(NULL),
213 	fActiveSourceObject(ACTIVE_SOURCE_NONE),
214 	fListener(listener),
215 	fTraceUpdateRunner(NULL),
216 	fTabView(NULL),
217 	fLocalsTabView(NULL),
218 	fThreadListView(NULL),
219 	fImageListView(NULL),
220 	fImageFunctionsView(NULL),
221 	fBreakpointsView(NULL),
222 	fVariablesView(NULL),
223 	fRegistersView(NULL),
224 	fStackTraceView(NULL),
225 	fSourceView(NULL),
226 	fRunButton(NULL),
227 	fStepOverButton(NULL),
228 	fStepIntoButton(NULL),
229 	fStepOutButton(NULL),
230 	fMenuBar(NULL),
231 	fSourcePathView(NULL),
232 	fStatusBarView(NULL),
233 	fConsoleOutputView(NULL),
234 	fFunctionSplitView(NULL),
235 	fSourceSplitView(NULL),
236 	fImageSplitView(NULL),
237 	fThreadSplitView(NULL),
238 	fConsoleSplitView(NULL),
239 	fTeamSettingsWindow(NULL),
240 	fBreakpointEditWindow(NULL),
241 	fInspectorWindow(NULL),
242 	fExpressionEvalWindow(NULL),
243 	fExpressionPromptWindow(NULL),
244 	fFilePanel(NULL),
245 	fActiveSourceWorker(-1)
246 {
247 	_UpdateTitle();
248 
249 	fTeam->AddListener(this);
250 }
251 
252 
253 TeamWindow::~TeamWindow()
254 {
255 	if (fThreadListView != NULL)
256 		fThreadListView->UnsetListener();
257 	if (fStackTraceView != NULL)
258 		fStackTraceView->UnsetListener();
259 	if (fSourceView != NULL)
260 		fSourceView->UnsetListener();
261 	if (fInspectorWindow != NULL) {
262 		if (fInspectorWindow->Lock())
263 			fInspectorWindow->Quit();
264 	}
265 	if (fExpressionEvalWindow != NULL) {
266 		if (fExpressionEvalWindow->Lock())
267 			fExpressionEvalWindow->Quit();
268 	}
269 	if (fExpressionPromptWindow != NULL) {
270 		if (fExpressionPromptWindow->Lock())
271 			fExpressionPromptWindow->Quit();
272 	}
273 
274 	fTeam->RemoveListener(this);
275 
276 	_SetActiveSourceCode(NULL);
277 	_SetActiveFunction(NULL);
278 	_SetActiveBreakpoint(NULL);
279 	_SetActiveStackFrame(NULL);
280 	_SetActiveStackTrace(NULL);
281 	_SetActiveImage(NULL);
282 	_SetActiveThread(NULL);
283 
284 	delete fFilePanel;
285 
286 	ThreadStackFrameSelectionEntry* entry
287 		= fThreadSelectionInfoTable->Clear(true);
288 
289 	while (entry != NULL) {
290 		ThreadStackFrameSelectionEntry* next = entry->next;
291 		delete entry;
292 		entry = next;
293 	}
294 
295 	delete fThreadSelectionInfoTable;
296 
297 	if (fActiveSourceWorker > 0)
298 		wait_for_thread(fActiveSourceWorker, NULL);
299 }
300 
301 
302 /*static*/ TeamWindow*
303 TeamWindow::Create(::Team* team, UserInterfaceListener* listener)
304 {
305 	TeamWindow* self = new TeamWindow(team, listener);
306 
307 	try {
308 		self->_Init();
309 	} catch (...) {
310 		delete self;
311 		throw;
312 	}
313 
314 	return self;
315 }
316 
317 
318 void
319 TeamWindow::DispatchMessage(BMessage* message, BHandler* handler)
320 {
321 	// Handle function key shortcuts for stepping
322 	switch (message->what) {
323 		case B_KEY_DOWN:
324 			if (fActiveThread != NULL && fTraceUpdateRunner == NULL) {
325 				int32 key;
326 				uint32 modifiers;
327 				if (message->FindInt32("key", &key) == B_OK
328 					&& message->FindInt32("modifiers", (int32*)&modifiers)
329 					== B_OK) {
330 					switch (key) {
331 						case B_F5_KEY:
332 							fListener->ThreadActionRequested(
333 								fActiveThread->ID(), MSG_THREAD_RUN);
334 							break;
335 						case B_F10_KEY:
336 							fListener->ThreadActionRequested(
337 								fActiveThread->ID(), MSG_THREAD_STEP_OVER);
338 							break;
339 						case B_F11_KEY:
340 							if ((modifiers & B_SHIFT_KEY) != 0) {
341 								fListener->ThreadActionRequested(
342 									fActiveThread->ID(), MSG_THREAD_STEP_OUT);
343 							} else {
344 								fListener->ThreadActionRequested(
345 									fActiveThread->ID(), MSG_THREAD_STEP_INTO);
346 							}
347 							break;
348 						default:
349 							break;
350 					}
351 				}
352 			}
353 			break;
354 
355 		case B_COPY:
356 		case B_SELECT_ALL:
357 			BView* focusView = CurrentFocus();
358 			if (focusView != NULL) {
359 				focusView->MessageReceived(message);
360 				return;
361 			}
362 			break;
363 	}
364 	BWindow::DispatchMessage(message, handler);
365 }
366 
367 
368 void
369 TeamWindow::MessageReceived(BMessage* message)
370 {
371 	switch (message->what) {
372 		case MSG_TEAM_RESTART_REQUESTED:
373 		{
374 			fListener->TeamRestartRequested();
375 			break;
376 		}
377 		case MSG_CHOOSE_DEBUG_REPORT_LOCATION:
378 		{
379 			try {
380 				char filename[B_FILE_NAME_LENGTH];
381 				UiUtils::ReportNameForTeam(fTeam, filename, sizeof(filename));
382 				BMessenger msgr(this);
383 				fFilePanel = new BFilePanel(B_SAVE_PANEL, &msgr,
384 					NULL, 0, false, new BMessage(MSG_GENERATE_DEBUG_REPORT));
385 				fFilePanel->SetSaveText(filename);
386 				fFilePanel->Show();
387 			} catch (...) {
388 				delete fFilePanel;
389 				fFilePanel = NULL;
390 			}
391 			break;
392 		}
393 		case MSG_GENERATE_DEBUG_REPORT:
394 		{
395 			delete fFilePanel;
396 			fFilePanel = NULL;
397 
398 			BPath path;
399 			entry_ref ref;
400 			if (message->FindRef("directory", &ref) == B_OK
401 				&& message->HasString("name")) {
402 				path.SetTo(&ref);
403 				path.Append(message->FindString("name"));
404 				if (get_ref_for_path(path.Path(), &ref) == B_OK)
405 					fListener->DebugReportRequested(&ref);
406 			}
407 			break;
408 		}
409 		case MSG_DEBUG_REPORT_SAVED:
410 		{
411 			status_t finalStatus = message->GetInt32("status", B_OK);
412 			BString data;
413 			if (finalStatus == B_OK) {
414 				data.SetToFormat("Debug report successfully saved to '%s'",
415 					message->FindString("path"));
416 			} else {
417 				data.SetToFormat("Failed to save debug report: '%s'",
418 					strerror(finalStatus));
419 			}
420 
421 			BAlert *alert = new(std::nothrow) BAlert("Report saved",
422 				data.String(), "Close");
423 			if (alert == NULL)
424 				break;
425 
426 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
427 			alert->Go();
428 			break;
429 		}
430 		case MSG_SHOW_INSPECTOR_WINDOW:
431 		{
432 			if (fInspectorWindow) {
433 				AutoLocker<BWindow> lock(fInspectorWindow);
434 				if (lock.IsLocked())
435 					fInspectorWindow->Activate(true);
436 			} else {
437 				try {
438 					fInspectorWindow = InspectorWindow::Create(fTeam,
439 						fListener, this);
440 					if (fInspectorWindow != NULL) {
441 						fInspectorWindow->LoadSettings(fUiSettings);
442 						fInspectorWindow->Show();
443 					}
444 	           	} catch (...) {
445 	           		// TODO: notify user
446 	           	}
447 			}
448 
449 			target_addr_t address;
450 			if (message->FindUInt64("address", &address) == B_OK) {
451 				BMessage addressMessage(MSG_INSPECT_ADDRESS);
452 				addressMessage.AddUInt64("address", address);
453 				fInspectorWindow->PostMessage(&addressMessage);
454 			}
455            	break;
456 		}
457 		case MSG_INSPECTOR_WINDOW_CLOSED:
458 		{
459 			_SaveInspectorSettings(CurrentMessage());
460 			fInspectorWindow = NULL;
461 			break;
462 
463 		}
464 		case MSG_SHOW_EXPRESSION_WINDOW:
465 		{
466 			if (fExpressionEvalWindow != NULL) {
467 				AutoLocker<BWindow> lock(fExpressionEvalWindow);
468 				if (lock.IsLocked())
469 					fExpressionEvalWindow->Activate(true);
470 			} else {
471 				try {
472 					fExpressionEvalWindow = ExpressionEvaluationWindow::Create(
473 						this, fTeam, fListener);
474 					if (fExpressionEvalWindow != NULL)
475 						fExpressionEvalWindow->Show();
476 				} catch (...) {
477 					// TODO: notify user
478 				}
479 			}
480 			break;
481 		}
482 		case MSG_EXPRESSION_WINDOW_CLOSED:
483 		{
484 			fExpressionEvalWindow = NULL;
485 			break;
486 		}
487 		case MSG_SHOW_EXPRESSION_PROMPT_WINDOW:
488 		{
489 			if (fExpressionPromptWindow != NULL) {
490 				AutoLocker<BWindow> lock(fExpressionPromptWindow);
491 				if (lock.IsLocked())
492 					fExpressionPromptWindow->Activate(true);
493 			} else {
494 				try {
495 					fExpressionPromptWindow = ExpressionPromptWindow::Create(
496 						fVariablesView, this);
497 					if (fExpressionPromptWindow != NULL)
498 						fExpressionPromptWindow->Show();
499 				} catch (...) {
500 					// TODO: notify user
501 				}
502 			}
503 			break;
504 		}
505 		case MSG_EXPRESSION_PROMPT_WINDOW_CLOSED:
506 		{
507 			fExpressionPromptWindow = NULL;
508 			break;
509 		}
510 		case MSG_SHOW_TEAM_SETTINGS_WINDOW:
511 		{
512 			if (fTeamSettingsWindow != NULL) {
513 				AutoLocker<BWindow> lock(fTeamSettingsWindow);
514 				if (lock.IsLocked())
515 					fTeamSettingsWindow->Activate(true);
516 			} else {
517 				try {
518 					fTeamSettingsWindow
519 						= TeamSettingsWindow::Create(
520 						fTeam, fListener, this);
521 					if (fTeamSettingsWindow != NULL)
522 						fTeamSettingsWindow->Show();
523 	           	} catch (...) {
524 	           		// TODO: notify user
525 	           	}
526 			}
527 			break;
528 		}
529 		case MSG_TEAM_SETTINGS_WINDOW_CLOSED:
530 		{
531 			fTeamSettingsWindow = NULL;
532 			break;
533 		}
534 		case MSG_SHOW_BREAKPOINT_EDIT_WINDOW:
535 		{
536 			if (fBreakpointEditWindow != NULL) {
537 				AutoLocker<BWindow> lock(fBreakpointEditWindow);
538 				if (lock.IsLocked())
539 					fBreakpointEditWindow->Activate(true);
540 			} else {
541 				UserBreakpoint* breakpoint;
542 				if (message->FindPointer("breakpoint",
543 					reinterpret_cast<void**>(&breakpoint)) != B_OK) {
544 					break;
545 				}
546 
547 				try {
548 					fBreakpointEditWindow
549 						= BreakpointEditWindow::Create(
550 						fTeam, breakpoint, fListener, this);
551 					if (fBreakpointEditWindow != NULL)
552 						fBreakpointEditWindow->Show();
553 	           	} catch (...) {
554 	           		// TODO: notify user
555 	           	}
556 			}
557 			break;
558 		}
559 		case MSG_BREAKPOINT_EDIT_WINDOW_CLOSED:
560 		{
561 			fBreakpointEditWindow = NULL;
562 			break;
563 		}
564 		case MSG_SHOW_WATCH_VARIABLE_PROMPT:
565 		{
566 			target_addr_t address;
567 			uint32 type;
568 			int32 length;
569 
570 			if (message->FindUInt64("address", &address) != B_OK
571 				|| message->FindUInt32("type", &type) != B_OK
572 				|| message->FindInt32("length", &length) != B_OK) {
573 				break;
574 			}
575 
576 			try {
577 				WatchPromptWindow* window = WatchPromptWindow::Create(
578 					fTeam->GetArchitecture(), address, type, length,
579 					fListener);
580 				window->Show();
581 			} catch (...) {
582 				// TODO: notify user
583 			}
584 			break;
585 		}
586 		case B_REFS_RECEIVED:
587 		{
588 			entry_ref locatedPath;
589 			if (message->FindRef("refs", &locatedPath) != B_OK)
590 				break;
591 
592 			_HandleResolveMissingSourceFile(locatedPath);
593 			delete fFilePanel;
594 			fFilePanel = NULL;
595 			break;
596 		}
597 		case MSG_LOCATE_SOURCE_IF_NEEDED:
598 		{
599 			_HandleLocateSourceRequest();
600 			break;
601 		}
602 		case MSG_SOURCE_ENTRY_QUERY_COMPLETE:
603 		{
604 			BStringList* entries;
605 			if (message->FindPointer("entries", (void**)&entries) == B_OK) {
606 				ObjectDeleter<BStringList> entryDeleter(entries);
607 				_HandleLocateSourceRequest(entries);
608 			}
609 			fActiveSourceWorker = -1;
610 			break;
611 		}
612 		case MSG_THREAD_RUN:
613 		case MSG_THREAD_STOP:
614 		case MSG_THREAD_STEP_OVER:
615 		case MSG_THREAD_STEP_INTO:
616 		case MSG_THREAD_STEP_OUT:
617 			if (fActiveThread != NULL && fTraceUpdateRunner == NULL) {
618 				fListener->ThreadActionRequested(fActiveThread->ID(),
619 					message->what);
620 			}
621 			break;
622 
623 		case MSG_CLEAR_STACK_TRACE:
624 		{
625 			if (fTraceUpdateRunner != NULL) {
626 				_SetActiveStackTrace(NULL);
627 				_UpdateRunButtons();
628 			}
629 			break;
630 		}
631 		case MSG_HANDLE_LOAD_SETTINGS:
632 		{
633 			GuiTeamUiSettings* settings;
634 			if (message->FindPointer("settings",
635 				reinterpret_cast<void**>(&settings)) != B_OK) {
636 				break;
637 			}
638 
639 			_LoadSettings(settings);
640 			break;
641 		}
642 		case MSG_UPDATE_STATUS_BAR:
643 		{
644 			const char* messageText;
645 			if (message->FindString("message", &messageText) == B_OK)
646 				fStatusBarView->SetText(messageText);
647 			break;
648 		}
649 		case MSG_TEAM_RENAMED:
650 		{
651 			_UpdateTitle();
652 			break;
653 		}
654 		case MSG_THREAD_STATE_CHANGED:
655 		{
656 			int32 threadID;
657 			if (message->FindInt32("thread", &threadID) != B_OK)
658 				break;
659 
660 			_HandleThreadStateChanged(threadID);
661 			break;
662 		}
663 		case MSG_THREAD_CPU_STATE_CHANGED:
664 		{
665 			int32 threadID;
666 			if (message->FindInt32("thread", &threadID) != B_OK)
667 				break;
668 
669 			_HandleCpuStateChanged(threadID);
670 			break;
671 		}
672 
673 		case MSG_THREAD_STACK_TRACE_CHANGED:
674 		{
675 			int32 threadID;
676 			if (message->FindInt32("thread", &threadID) != B_OK)
677 				break;
678 
679 			_HandleStackTraceChanged(threadID);
680 			break;
681 		}
682 
683 		case MSG_IMAGE_DEBUG_INFO_CHANGED:
684 		{
685 			int32 imageID;
686 			if (message->FindInt32("image", &imageID) != B_OK)
687 				break;
688 
689 			_HandleImageDebugInfoChanged(imageID);
690 			break;
691 		}
692 
693 		case MSG_CONSOLE_OUTPUT_RECEIVED:
694 		{
695 			int32 fd;
696 			BString output;
697 			if (message->FindInt32("fd", &fd) != B_OK
698 					|| message->FindString("output", &output) != B_OK) {
699 				break;
700 			}
701 			fConsoleOutputView->ConsoleOutputReceived(fd, output);
702 			break;
703 		}
704 
705 		case MSG_USER_BREAKPOINT_CHANGED:
706 		{
707 			UserBreakpoint* breakpoint;
708 			if (message->FindPointer("breakpoint", (void**)&breakpoint) != B_OK)
709 				break;
710 			BReference<UserBreakpoint> breakpointReference(breakpoint, true);
711 
712 			_HandleUserBreakpointChanged(breakpoint);
713 			break;
714 		}
715 
716 		case MSG_WATCHPOINT_CHANGED:
717 		{
718 			Watchpoint* watchpoint;
719 			if (message->FindPointer("watchpoint", (void**)&watchpoint) != B_OK)
720 				break;
721 			BReference<Watchpoint> watchpointReference(watchpoint, true);
722 
723 			_HandleWatchpointChanged(watchpoint);
724 			break;
725 
726 		}
727 
728 		case MSG_FUNCTION_SOURCE_CODE_CHANGED:
729 		{
730 			_HandleSourceCodeChanged();
731 			break;
732 		}
733 
734 		default:
735 			BWindow::MessageReceived(message);
736 			break;
737 	}
738 }
739 
740 
741 bool
742 TeamWindow::QuitRequested()
743 {
744 	fListener->UserInterfaceQuitRequested();
745 
746 	return false;
747 }
748 
749 
750 status_t
751 TeamWindow::LoadSettings(const GuiTeamUiSettings* settings)
752 {
753 	BMessage message(MSG_HANDLE_LOAD_SETTINGS);
754 	message.AddPointer("settings", settings);
755 	return PostMessage(&message);
756 }
757 
758 
759 status_t
760 TeamWindow::SaveSettings(GuiTeamUiSettings* settings)
761 {
762 	AutoLocker<BWindow> lock(this);
763 	if (!lock.IsLocked())
764 		return B_ERROR;
765 
766 	BMessage inspectorSettings;
767 	if (fUiSettings.Settings("inspectorWindow", inspectorSettings) == B_OK) {
768 		if (!settings->AddSettings("inspectorWindow", inspectorSettings))
769 			return B_NO_MEMORY;
770 	}
771 
772 	BMessage archive;
773 	BMessage teamWindowSettings;
774 	if (teamWindowSettings.AddRect("frame", Frame()) != B_OK)
775 		return B_NO_MEMORY;
776 
777 	if (GuiSettingsUtils::ArchiveSplitView(archive, fSourceSplitView) != B_OK)
778 		return B_NO_MEMORY;
779 	if (teamWindowSettings.AddMessage("sourceSplit", &archive) != B_OK)
780 		return B_NO_MEMORY;
781 
782 	if (GuiSettingsUtils::ArchiveSplitView(archive, fFunctionSplitView) != B_OK)
783 		return B_NO_MEMORY;
784 	if (teamWindowSettings.AddMessage("functionSplit", &archive) != B_OK)
785 		return B_NO_MEMORY;
786 
787 	if (GuiSettingsUtils::ArchiveSplitView(archive, fImageSplitView) != B_OK)
788 		return B_NO_MEMORY;
789 	if (teamWindowSettings.AddMessage("imageSplit", &archive))
790 		return B_NO_MEMORY;
791 
792 	if (GuiSettingsUtils::ArchiveSplitView(archive, fThreadSplitView) != B_OK)
793 		return B_NO_MEMORY;
794 	if (teamWindowSettings.AddMessage("threadSplit", &archive))
795 		return B_NO_MEMORY;
796 
797 	if (GuiSettingsUtils::ArchiveSplitView(archive, fConsoleSplitView) != B_OK)
798 		return B_NO_MEMORY;
799 	if (teamWindowSettings.AddMessage("consoleSplit", &archive))
800 		return B_NO_MEMORY;
801 
802 	if (fImageListView->SaveSettings(archive) != B_OK)
803 		return B_NO_MEMORY;
804 	if (teamWindowSettings.AddMessage("imageListView", &archive))
805 		return B_NO_MEMORY;
806 
807 	if (fImageFunctionsView->SaveSettings(archive) != B_OK)
808 		return B_NO_MEMORY;
809 	if (teamWindowSettings.AddMessage("imageFunctionsView", &archive))
810 		return B_NO_MEMORY;
811 
812 	if (fThreadListView->SaveSettings(archive) != B_OK)
813 		return B_NO_MEMORY;
814 	if (teamWindowSettings.AddMessage("threadListView", &archive))
815 		return B_NO_MEMORY;
816 
817 	if (fVariablesView->SaveSettings(archive) != B_OK)
818 		return B_NO_MEMORY;
819 	if (teamWindowSettings.AddMessage("variablesView", &archive))
820 		return B_NO_MEMORY;
821 
822 	if (fRegistersView->SaveSettings(archive) != B_OK)
823 		return B_NO_MEMORY;
824 	if (teamWindowSettings.AddMessage("registersView", &archive))
825 		return B_NO_MEMORY;
826 
827 	if (fStackTraceView->SaveSettings(archive) != B_OK)
828 		return B_NO_MEMORY;
829 	if (teamWindowSettings.AddMessage("stackTraceView", &archive))
830 		return B_NO_MEMORY;
831 
832 	if (fBreakpointsView->SaveSettings(archive) != B_OK)
833 		return B_NO_MEMORY;
834 	if (teamWindowSettings.AddMessage("breakpointsView", &archive))
835 		return B_NO_MEMORY;
836 
837 	if (fConsoleOutputView->SaveSettings(archive) != B_OK)
838 		return B_NO_MEMORY;
839 	if (teamWindowSettings.AddMessage("consoleOutputView", &archive))
840 		return B_NO_MEMORY;
841 
842 	if (!settings->AddSettings("teamWindow", teamWindowSettings))
843 		return B_NO_MEMORY;
844 
845 	return B_OK;
846 }
847 
848 
849 void
850 TeamWindow::DisplayBackgroundStatus(const char* message)
851 {
852 	BMessage updateMessage(MSG_UPDATE_STATUS_BAR);
853 	updateMessage.AddString("message", message);
854 	PostMessage(&updateMessage);
855 }
856 
857 
858 void
859 TeamWindow::ThreadSelectionChanged(::Thread* thread)
860 {
861 	_SetActiveThread(thread);
862 }
863 
864 
865 void
866 TeamWindow::ImageSelectionChanged(Image* image)
867 {
868 	_SetActiveImage(image);
869 }
870 
871 
872 void
873 TeamWindow::StackFrameSelectionChanged(StackFrame* frame)
874 {
875 	_SetActiveStackFrame(frame);
876 }
877 
878 
879 void
880 TeamWindow::FunctionSelectionChanged(FunctionInstance* function)
881 {
882 	// If the function wasn't already active, it was just selected by the user.
883 	if (function != NULL && function != fActiveFunction)
884 		fActiveSourceObject = ACTIVE_SOURCE_FUNCTION;
885 
886 	_SetActiveFunction(function);
887 }
888 
889 
890 void
891 TeamWindow::BreakpointSelectionChanged(BreakpointProxyList &proxies)
892 {
893 	if (proxies.CountItems() == 0 && fActiveBreakpoint != NULL) {
894 		fActiveBreakpoint->ReleaseReference();
895 		fActiveBreakpoint = NULL;
896 	} else if (proxies.CountItems() == 1) {
897 		BreakpointProxy* proxy = proxies.ItemAt(0);
898 		if (proxy->Type() == BREAKPOINT_PROXY_TYPE_BREAKPOINT)
899 			_SetActiveBreakpoint(proxy->GetBreakpoint());
900 	}
901 	// if more than one item is selected, do nothing.
902 }
903 
904 
905 void
906 TeamWindow::SetBreakpointEnabledRequested(UserBreakpoint* breakpoint,
907 	bool enabled)
908 {
909 	fListener->SetBreakpointEnabledRequested(breakpoint, enabled);
910 }
911 
912 
913 void
914 TeamWindow::ClearBreakpointRequested(UserBreakpoint* breakpoint)
915 {
916 	fListener->ClearBreakpointRequested(breakpoint);
917 }
918 
919 
920 void
921 TeamWindow::SetBreakpointRequested(target_addr_t address, bool enabled)
922 {
923 	fListener->SetBreakpointRequested(address, enabled);
924 }
925 
926 
927 void
928 TeamWindow::ClearBreakpointRequested(target_addr_t address)
929 {
930 	fListener->ClearBreakpointRequested(address);
931 }
932 
933 
934 void
935 TeamWindow::ThreadActionRequested(::Thread* thread, uint32 action,
936 	target_addr_t address)
937 {
938 	if (fTraceUpdateRunner == NULL)
939 		fListener->ThreadActionRequested(thread->ID(), action, address);
940 }
941 
942 
943 void
944 TeamWindow::FunctionSourceCodeRequested(FunctionInstance* function,
945 	bool forceDisassembly)
946 {
947 	fListener->FunctionSourceCodeRequested(function, forceDisassembly);
948 }
949 
950 
951 void
952 TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint,
953 	bool enabled)
954 {
955 	fListener->SetWatchpointEnabledRequested(watchpoint, enabled);
956 }
957 
958 
959 void
960 TeamWindow::ClearWatchpointRequested(Watchpoint* watchpoint)
961 {
962 	fListener->ClearWatchpointRequested(watchpoint);
963 }
964 
965 
966 void
967 TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
968 	ValueNodeContainer* container, ValueNode* valueNode)
969 {
970 	fListener->ValueNodeValueRequested(cpuState, container, valueNode);
971 }
972 
973 
974 void
975 TeamWindow::ExpressionEvaluationRequested(ExpressionInfo* info,
976 	StackFrame* frame, ::Thread* thread)
977 {
978 	SourceLanguage* language;
979 	if (_GetActiveSourceLanguage(language) != B_OK)
980 		return;
981 
982 	BReference<SourceLanguage> languageReference(language, true);
983 	fListener->ExpressionEvaluationRequested(language, info, frame, thread);
984 }
985 
986 
987 void
988 TeamWindow::ValueNodeWriteRequested(ValueNode* node, CpuState* state,
989 	Value* newValue)
990 {
991 	fListener->ValueNodeWriteRequested(node, state, newValue);
992 }
993 
994 
995 void
996 TeamWindow::TeamRenamed(const Team::Event& event)
997 {
998 	PostMessage(MSG_TEAM_RENAMED);
999 }
1000 
1001 
1002 void
1003 TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event)
1004 {
1005 	BMessage message(MSG_THREAD_STATE_CHANGED);
1006 	message.AddInt32("thread", event.GetThread()->ID());
1007 	PostMessage(&message);
1008 }
1009 
1010 
1011 void
1012 TeamWindow::ThreadCpuStateChanged(const Team::ThreadEvent& event)
1013 {
1014 	BMessage message(MSG_THREAD_CPU_STATE_CHANGED);
1015 	message.AddInt32("thread", event.GetThread()->ID());
1016 	PostMessage(&message);
1017 }
1018 
1019 
1020 void
1021 TeamWindow::ThreadStackTraceChanged(const Team::ThreadEvent& event)
1022 {
1023 	BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
1024 	message.AddInt32("thread", event.GetThread()->ID());
1025 	PostMessage(&message);
1026 }
1027 
1028 
1029 void
1030 TeamWindow::ImageDebugInfoChanged(const Team::ImageEvent& event)
1031 {
1032 	BMessage message(MSG_IMAGE_DEBUG_INFO_CHANGED);
1033 	message.AddInt32("image", event.GetImage()->ID());
1034 	PostMessage(&message);
1035 }
1036 
1037 
1038 void
1039 TeamWindow::ConsoleOutputReceived(const Team::ConsoleOutputEvent& event)
1040 {
1041 	BMessage message(MSG_CONSOLE_OUTPUT_RECEIVED);
1042 	message.AddInt32("fd", event.Descriptor());
1043 	message.AddString("output", event.Output());
1044 	PostMessage(&message);
1045 }
1046 
1047 
1048 void
1049 TeamWindow::UserBreakpointChanged(const Team::UserBreakpointEvent& event)
1050 {
1051 	BMessage message(MSG_USER_BREAKPOINT_CHANGED);
1052 	BReference<UserBreakpoint> breakpointReference(event.GetBreakpoint());
1053 	if (message.AddPointer("breakpoint", event.GetBreakpoint()) == B_OK
1054 		&& PostMessage(&message) == B_OK) {
1055 		breakpointReference.Detach();
1056 	}
1057 }
1058 
1059 
1060 void
1061 TeamWindow::WatchpointChanged(const Team::WatchpointEvent& event)
1062 {
1063 	BMessage message(MSG_WATCHPOINT_CHANGED);
1064 	BReference<Watchpoint> watchpointReference(event.GetWatchpoint());
1065 	if (message.AddPointer("watchpoint", event.GetWatchpoint()) == B_OK
1066 		&& PostMessage(&message) == B_OK) {
1067 		watchpointReference.Detach();
1068 	}
1069 }
1070 
1071 
1072 void
1073 TeamWindow::DebugReportChanged(const Team::DebugReportEvent& event)
1074 {
1075 	BMessage message(MSG_DEBUG_REPORT_SAVED);
1076 	message.AddString("path", event.GetReportPath());
1077 	message.AddInt32("status", event.GetFinalStatus());
1078 	PostMessage(&message);
1079 }
1080 
1081 
1082 void
1083 TeamWindow::FunctionSourceCodeChanged(Function* function)
1084 {
1085 	TRACE_GUI("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, "
1086 		"state: %d\n", function, function->GetSourceCode(),
1087 		function->SourceCodeState());
1088 
1089 	PostMessage(MSG_FUNCTION_SOURCE_CODE_CHANGED);
1090 }
1091 
1092 
1093 void
1094 TeamWindow::_Init()
1095 {
1096 	fThreadSelectionInfoTable = new ThreadStackFrameSelectionInfoTable;
1097 	if (fThreadSelectionInfoTable->Init() != B_OK) {
1098 		delete fThreadSelectionInfoTable;
1099 		fThreadSelectionInfoTable = NULL;
1100 		throw std::bad_alloc();
1101 	}
1102 
1103 	BScrollView* sourceScrollView;
1104 
1105 	const float splitSpacing = 3.0f;
1106 
1107 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
1108 		.Add(fMenuBar = new BMenuBar("Menu"))
1109 		.AddSplit(B_VERTICAL, splitSpacing)
1110 			.GetSplitView(&fFunctionSplitView)
1111 			.SetInsets(B_USE_SMALL_INSETS)
1112 			.Add(fTabView = new BTabView("tab view"), 0.4f)
1113 			.AddSplit(B_HORIZONTAL, splitSpacing)
1114 				.GetSplitView(&fSourceSplitView)
1115 				.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
1116 					.AddGroup(B_HORIZONTAL, B_USE_SMALL_SPACING)
1117 						.Add(fRunButton = new BButton("Run"))
1118 						.Add(fStepOverButton = new BButton("Step over"))
1119 						.Add(fStepIntoButton = new BButton("Step into"))
1120 						.Add(fStepOutButton = new BButton("Step out"))
1121 						.AddGlue()
1122 					.End()
1123 					.Add(fSourcePathView = new BStringView(
1124 						"source path",
1125 						"Source path unavailable."), 4.0f)
1126 					.Add(sourceScrollView = new BScrollView("source scroll",
1127 						NULL, 0, true, true), splitSpacing)
1128 				.End()
1129 				.Add(fLocalsTabView = new BTabView("locals view"))
1130 			.End()
1131 			.AddSplit(B_VERTICAL, splitSpacing)
1132 				.GetSplitView(&fConsoleSplitView)
1133 				.SetInsets(0.0)
1134 				.Add(fConsoleOutputView = ConsoleOutputView::Create())
1135 			.End()
1136 		.End()
1137 		.Add(fStatusBarView = new BStringView("status", "Ready."));
1138 
1139 	fStatusBarView->SetExplicitMinSize(BSize(50.0, B_SIZE_UNSET));
1140 	fStatusBarView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
1141 
1142 	// add source view
1143 	sourceScrollView->SetTarget(fSourceView = SourceView::Create(fTeam, this));
1144 
1145 	// add threads tab
1146 	BSplitView* threadGroup = new BSplitView(B_HORIZONTAL, splitSpacing);
1147 	threadGroup->SetName("Threads");
1148 	fTabView->AddTab(threadGroup);
1149 	BLayoutBuilder::Split<>(threadGroup)
1150 		.GetSplitView(&fThreadSplitView)
1151 		.Add(fThreadListView = ThreadListView::Create(fTeam, this))
1152 		.Add(fStackTraceView = StackTraceView::Create(this));
1153 
1154 	// add images tab
1155 	BSplitView* imagesGroup = new BSplitView(B_HORIZONTAL, splitSpacing);
1156 	imagesGroup->SetName("Images");
1157 	fTabView->AddTab(imagesGroup);
1158 	BLayoutBuilder::Split<>(imagesGroup)
1159 		.GetSplitView(&fImageSplitView)
1160 		.Add(fImageListView = ImageListView::Create(fTeam, this))
1161 		.Add(fImageFunctionsView = ImageFunctionsView::Create(this));
1162 
1163 	// add breakpoints tab
1164 	BGroupView* breakpointsGroup = new BGroupView(B_HORIZONTAL,
1165 		B_USE_SMALL_SPACING);
1166 	breakpointsGroup->SetName("Breakpoints");
1167 	fTabView->AddTab(breakpointsGroup);
1168 	BLayoutBuilder::Group<>(breakpointsGroup)
1169 //		.SetInsets(0.0f)
1170 		.Add(fBreakpointsView = BreakpointsView::Create(fTeam, this));
1171 
1172 	ValueNodeManager* manager = new ValueNodeManager;
1173 
1174 	// add local variables tab
1175 	BView* tab = fVariablesView = VariablesView::Create(this, manager);
1176 	fLocalsTabView->AddTab(tab);
1177 
1178 	// add registers tab
1179 	tab = fRegistersView = RegistersView::Create(fTeam->GetArchitecture());
1180 	fLocalsTabView->AddTab(tab);
1181 
1182 	fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
1183 	fStepOverButton->SetMessage(new BMessage(MSG_THREAD_STEP_OVER));
1184 	fStepIntoButton->SetMessage(new BMessage(MSG_THREAD_STEP_INTO));
1185 	fStepOutButton->SetMessage(new BMessage(MSG_THREAD_STEP_OUT));
1186 	fRunButton->SetTarget(this);
1187 	fStepOverButton->SetTarget(this);
1188 	fStepIntoButton->SetTarget(this);
1189 	fStepOutButton->SetTarget(this);
1190 
1191 	fSourcePathView->SetExplicitMinSize(BSize(100.0, B_SIZE_UNSET));
1192 	fSourcePathView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
1193 	BMessageFilter* filter = new(std::nothrow) PathViewMessageFilter(
1194 		BMessenger(this));
1195 	if (filter != NULL)
1196 		fSourcePathView->AddFilter(filter);
1197 
1198 	// add menus and menu items
1199 	BMenu* menu = new BMenu("Debugger");
1200 	fMenuBar->AddItem(menu);
1201 	BMenuItem* item = new BMenuItem("Start new team" B_UTF8_ELLIPSIS,
1202 		new BMessage(MSG_SHOW_START_TEAM_WINDOW));
1203 	menu->AddItem(item);
1204 	item->SetTarget(be_app);
1205 	item = new BMenuItem("Show Teams window" B_UTF8_ELLIPSIS,
1206 		new BMessage(MSG_SHOW_TEAMS_WINDOW));
1207 	menu->AddItem(item);
1208 	item->SetTarget(be_app);
1209 	menu = new BMenu("Team");
1210 	fMenuBar->AddItem(menu);
1211 	item = new BMenuItem("Restart", new BMessage(
1212 		MSG_TEAM_RESTART_REQUESTED), 'R', B_SHIFT_KEY);
1213 	menu->AddItem(item);
1214 	item->SetTarget(this);
1215 	item = new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED),
1216 		'W');
1217 	menu->AddItem(item);
1218 	item->SetTarget(this);
1219 	menu->AddSeparatorItem();
1220 	item = new BMenuItem("Settings" B_UTF8_ELLIPSIS, new BMessage(
1221 		MSG_SHOW_TEAM_SETTINGS_WINDOW));
1222 	menu->AddItem(item);
1223 	item->SetTarget(this);
1224 	menu = new BMenu("Edit");
1225 	fMenuBar->AddItem(menu);
1226 	item = new BMenuItem("Copy", new BMessage(B_COPY), 'C');
1227 	menu->AddItem(item);
1228 	item->SetTarget(this);
1229 	item = new BMenuItem("Select all", new BMessage(B_SELECT_ALL), 'A');
1230 	menu->AddItem(item);
1231 	item->SetTarget(this);
1232 	menu = new BMenu("Tools");
1233 	fMenuBar->AddItem(menu);
1234 	item = new BMenuItem("Save debug report",
1235 		new BMessage(MSG_CHOOSE_DEBUG_REPORT_LOCATION));
1236 	menu->AddItem(item);
1237 	item->SetTarget(this);
1238 	item = new BMenuItem("Inspect memory",
1239 		new BMessage(MSG_SHOW_INSPECTOR_WINDOW), 'I');
1240 	menu->AddItem(item);
1241 	item->SetTarget(this);
1242 	item = new BMenuItem("Evaluate expression",
1243 		new BMessage(MSG_SHOW_EXPRESSION_WINDOW), 'E');
1244 	menu->AddItem(item);
1245 	item->SetTarget(this);
1246 
1247 	AutoLocker< ::Team> locker(fTeam);
1248 	_UpdateRunButtons();
1249 }
1250 
1251 
1252 void
1253 TeamWindow::_LoadSettings(const GuiTeamUiSettings* settings)
1254 {
1255 	BMessage teamWindowSettings;
1256 	// no settings stored yet
1257 	if (settings->Settings("teamWindow", teamWindowSettings) != B_OK)
1258 		return;
1259 
1260 	BRect frame;
1261 	if (teamWindowSettings.FindRect("frame", &frame) == B_OK) {
1262 		ResizeTo(frame.Width(), frame.Height());
1263 		MoveTo(frame.left, frame.top);
1264 	}
1265 
1266 	BMessage archive;
1267 	if (teamWindowSettings.FindMessage("sourceSplit", &archive) == B_OK)
1268 		GuiSettingsUtils::UnarchiveSplitView(archive, fSourceSplitView);
1269 
1270 	if (teamWindowSettings.FindMessage("functionSplit", &archive) == B_OK)
1271 		GuiSettingsUtils::UnarchiveSplitView(archive, fFunctionSplitView);
1272 
1273 	if (teamWindowSettings.FindMessage("imageSplit", &archive) == B_OK)
1274 		GuiSettingsUtils::UnarchiveSplitView(archive, fImageSplitView);
1275 
1276 	if (teamWindowSettings.FindMessage("threadSplit", &archive) == B_OK)
1277 		GuiSettingsUtils::UnarchiveSplitView(archive, fThreadSplitView);
1278 
1279 	if (teamWindowSettings.FindMessage("consoleSplit", &archive) == B_OK)
1280 		GuiSettingsUtils::UnarchiveSplitView(archive, fConsoleSplitView);
1281 
1282 	if (teamWindowSettings.FindMessage("imageListView", &archive) == B_OK)
1283 		fImageListView->LoadSettings(archive);
1284 
1285 	if (teamWindowSettings.FindMessage("imageFunctionsView", &archive) == B_OK)
1286 		fImageFunctionsView->LoadSettings(archive);
1287 
1288 	if (teamWindowSettings.FindMessage("threadListView", &archive) == B_OK)
1289 		fThreadListView->LoadSettings(archive);
1290 
1291 	if (teamWindowSettings.FindMessage("variablesView", &archive) == B_OK)
1292 		fVariablesView->LoadSettings(archive);
1293 
1294 	if (teamWindowSettings.FindMessage("registersView", &archive) == B_OK)
1295 		fRegistersView->LoadSettings(archive);
1296 
1297 	if (teamWindowSettings.FindMessage("stackTraceView", &archive) == B_OK)
1298 		fStackTraceView->LoadSettings(archive);
1299 
1300 	if (teamWindowSettings.FindMessage("breakpointsView", &archive) == B_OK)
1301 		fBreakpointsView->LoadSettings(archive);
1302 
1303 	if (teamWindowSettings.FindMessage("consoleOutputView", &archive) == B_OK)
1304 		fConsoleOutputView->LoadSettings(archive);
1305 
1306 	fUiSettings = *settings;
1307 }
1308 
1309 
1310 void
1311 TeamWindow::_UpdateTitle()
1312 {
1313 	AutoLocker< ::Team> lock(fTeam);
1314 	BString name = fTeam->Name();
1315 	if (fTeam->ID() >= 0)
1316 		name << " (" << fTeam->ID() << ")";
1317 	SetTitle(name.String());
1318 }
1319 
1320 
1321 void
1322 TeamWindow::_SetActiveThread(::Thread* thread)
1323 {
1324 	if (thread == fActiveThread)
1325 		return;
1326 
1327 	if (fActiveThread != NULL)
1328 		fActiveThread->ReleaseReference();
1329 
1330 	fActiveThread = thread;
1331 
1332 	if (fActiveThread != NULL)
1333 		fActiveThread->AcquireReference();
1334 
1335 	AutoLocker< ::Team> locker(fTeam);
1336 	_UpdateRunButtons();
1337 
1338 	StackTrace* stackTrace = fActiveThread != NULL
1339 		? fActiveThread->GetStackTrace() : NULL;
1340 	BReference<StackTrace> stackTraceReference(stackTrace);
1341 		// hold a reference until we've set it
1342 
1343 	locker.Unlock();
1344 
1345 	fThreadListView->SetThread(fActiveThread);
1346 
1347 	_SetActiveStackTrace(stackTrace);
1348 	_UpdateCpuState();
1349 }
1350 
1351 
1352 void
1353 TeamWindow::_SetActiveImage(Image* image)
1354 {
1355 	if (image == fActiveImage)
1356 		return;
1357 
1358 	if (fActiveImage != NULL)
1359 		fActiveImage->ReleaseReference();
1360 
1361 	fActiveImage = image;
1362 
1363 	AutoLocker< ::Team> locker(fTeam);
1364 
1365 	ImageDebugInfo* imageDebugInfo = NULL;
1366 	BReference<ImageDebugInfo> imageDebugInfoReference;
1367 
1368 	if (fActiveImage != NULL) {
1369 		fActiveImage->AcquireReference();
1370 
1371 		imageDebugInfo = fActiveImage->GetImageDebugInfo();
1372 		imageDebugInfoReference.SetTo(imageDebugInfo);
1373 
1374 		// If the debug info is not loaded yet, request it.
1375 		if (fActiveImage->ImageDebugInfoState() == IMAGE_DEBUG_INFO_NOT_LOADED)
1376 			fListener->ImageDebugInfoRequested(fActiveImage);
1377 	}
1378 
1379 	locker.Unlock();
1380 
1381 	fImageListView->SetImage(fActiveImage);
1382 	fImageFunctionsView->SetImageDebugInfo(imageDebugInfo);
1383 }
1384 
1385 
1386 void
1387 TeamWindow::_SetActiveStackTrace(StackTrace* stackTrace)
1388 {
1389 	delete fTraceUpdateRunner;
1390 	fTraceUpdateRunner = NULL;
1391 
1392 	if (stackTrace == fActiveStackTrace)
1393 		return;
1394 
1395 	if (fActiveStackTrace != NULL)
1396 		fActiveStackTrace->ReleaseReference();
1397 
1398 	fActiveStackTrace = stackTrace;
1399 
1400 	if (fActiveStackTrace != NULL)
1401 		fActiveStackTrace->AcquireReference();
1402 
1403 	fStackTraceView->SetStackTrace(fActiveStackTrace);
1404 	fSourceView->SetStackTrace(fActiveStackTrace, fActiveThread);
1405 
1406 	StackFrame* frame = NULL;
1407 	if (fActiveStackTrace != NULL) {
1408 		ThreadStackFrameSelectionEntry* entry
1409 			= fThreadSelectionInfoTable->Lookup(fActiveThread);
1410 		if (entry != NULL)
1411 			frame = entry->SelectedFrame();
1412 		else
1413 			frame = fActiveStackTrace->FrameAt(0);
1414 	}
1415 
1416 	_SetActiveStackFrame(frame);
1417 }
1418 
1419 
1420 void
1421 TeamWindow::_SetActiveStackFrame(StackFrame* frame)
1422 {
1423 	if (frame == fActiveStackFrame)
1424 		return;
1425 
1426 	if (fActiveStackFrame != NULL) {
1427 		AutoLocker< ::Team> locker(fTeam);
1428 		fActiveStackFrame->RemoveListener(this);
1429 		locker.Unlock();
1430 
1431 		fActiveStackFrame->ReleaseReference();
1432 	}
1433 
1434 	fActiveStackFrame = frame;
1435 
1436 	if (fActiveStackFrame != NULL) {
1437 		fActiveStackFrame->AcquireReference();
1438 
1439 		AutoLocker< ::Team> locker(fTeam);
1440 		fActiveStackFrame->AddListener(this);
1441 		locker.Unlock();
1442 
1443 		fActiveSourceObject = ACTIVE_SOURCE_STACK_FRAME;
1444 
1445 		ThreadStackFrameSelectionEntry* entry
1446 			= fThreadSelectionInfoTable->Lookup(fActiveThread);
1447 		if (entry == NULL) {
1448 			entry = new(std::nothrow) ThreadStackFrameSelectionEntry(
1449 				fActiveThread, fActiveStackFrame);
1450 			if (entry == NULL)
1451 				return;
1452 
1453 			ObjectDeleter<ThreadStackFrameSelectionEntry> entryDeleter(entry);
1454 			if (fThreadSelectionInfoTable->Insert(entry) == B_OK)
1455 				entryDeleter.Detach();
1456 		} else
1457 			entry->SetSelectedFrame(fActiveStackFrame);
1458 
1459 		_SetActiveFunction(fActiveStackFrame->Function(), false);
1460 	}
1461 
1462 	_UpdateCpuState();
1463 
1464 	fStackTraceView->SetStackFrame(fActiveStackFrame);
1465 	if (fActiveStackFrame != NULL)
1466 		fVariablesView->SetStackFrame(fActiveThread, fActiveStackFrame);
1467 	else
1468 		fVariablesView->SetStackFrame(NULL, NULL);
1469 	fSourceView->SetStackFrame(fActiveStackFrame);
1470 }
1471 
1472 
1473 void
1474 TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint)
1475 {
1476 	if (breakpoint == fActiveBreakpoint)
1477 		return;
1478 
1479 	if (fActiveBreakpoint != NULL)
1480 		fActiveBreakpoint->ReleaseReference();
1481 
1482 	fActiveBreakpoint = breakpoint;
1483 
1484 	if (fActiveBreakpoint != NULL) {
1485 		fActiveBreakpoint->AcquireReference();
1486 
1487 		// get the breakpoint's function (more exactly: some function instance)
1488 		AutoLocker< ::Team> locker(fTeam);
1489 
1490 		Function* function = fTeam->FunctionByID(
1491 			breakpoint->Location().GetFunctionID());
1492 		FunctionInstance* functionInstance = function != NULL
1493 			? function->FirstInstance() : NULL;
1494 		BReference<FunctionInstance> functionInstanceReference(
1495 			functionInstance);
1496 
1497 		locker.Unlock();
1498 
1499 		fActiveSourceObject = ACTIVE_SOURCE_BREAKPOINT;
1500 
1501 		_SetActiveFunction(functionInstance);
1502 
1503 		// scroll to the breakpoint's source code line number (it is not done
1504 		// automatically, if the active function remains the same)
1505 		_ScrollToActiveFunction();
1506 	}
1507 }
1508 
1509 
1510 void
1511 TeamWindow::_SetActiveFunction(FunctionInstance* functionInstance,
1512 	bool searchForFrame)
1513 {
1514 	if (functionInstance == fActiveFunction)
1515 		return;
1516 
1517 	AutoLocker< ::Team> locker(fTeam);
1518 
1519 	if (fActiveFunction != NULL) {
1520 		fActiveFunction->GetFunction()->RemoveListener(this);
1521 		fActiveFunction->ReleaseReference();
1522 	}
1523 
1524 	// to avoid listener feedback problems, first unset the active function and
1525 	// set the new image, if any
1526 	locker.Unlock();
1527 
1528 	fActiveFunction = NULL;
1529 
1530 	if (functionInstance != NULL)
1531 		_SetActiveImage(fTeam->ImageByAddress(functionInstance->Address()));
1532 
1533 	fActiveFunction = functionInstance;
1534 
1535 	locker.Lock();
1536 
1537 	SourceCode* sourceCode = NULL;
1538 	BReference<SourceCode> sourceCodeReference;
1539 
1540 	if (fActiveFunction != NULL) {
1541 		fActiveFunction->AcquireReference();
1542 		fActiveFunction->GetFunction()->AddListener(this);
1543 
1544 		Function* function = fActiveFunction->GetFunction();
1545 		sourceCode = function->GetSourceCode();
1546 		if (sourceCode == NULL)
1547 			sourceCode = fActiveFunction->GetSourceCode();
1548 		sourceCodeReference.SetTo(sourceCode);
1549 
1550 		// If the source code is not loaded yet, request it.
1551 		if (function->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED)
1552 			fListener->FunctionSourceCodeRequested(fActiveFunction);
1553 	}
1554 
1555 	locker.Unlock();
1556 
1557 	_SetActiveSourceCode(sourceCode);
1558 
1559 	fImageFunctionsView->SetFunction(fActiveFunction);
1560 
1561 	locker.Lock();
1562 
1563 	if (!searchForFrame || fActiveStackTrace == NULL)
1564 		return;
1565 
1566 	// look if our current stack trace has a frame matching the selected
1567 	// function. If so, set it to match.
1568 	StackFrame* matchingFrame = NULL;
1569 	BReference<StackFrame> frameRef;
1570 
1571 	for (int32 i = 0; i < fActiveStackTrace->CountFrames(); i++) {
1572 		StackFrame* frame = fActiveStackTrace->FrameAt(i);
1573 		if (frame->Function() == fActiveFunction) {
1574 			matchingFrame = frame;
1575 			frameRef.SetTo(frame);
1576 			break;
1577 		}
1578 	}
1579 
1580 	locker.Unlock();
1581 
1582 	if (matchingFrame != NULL)
1583 		_SetActiveStackFrame(matchingFrame);
1584 }
1585 
1586 
1587 void
1588 TeamWindow::_SetActiveSourceCode(SourceCode* sourceCode)
1589 {
1590 	if (sourceCode == fActiveSourceCode) {
1591 		_ScrollToActiveFunction();
1592 		return;
1593 	}
1594 
1595 	if (fActiveSourceCode != NULL)
1596 		fActiveSourceCode->ReleaseReference();
1597 
1598 	fActiveSourceCode = sourceCode;
1599 
1600 	if (fActiveSourceCode != NULL)
1601 		fActiveSourceCode->AcquireReference();
1602 
1603 	fSourceView->SetSourceCode(fActiveSourceCode);
1604 
1605 	_UpdateSourcePathState();
1606 	_ScrollToActiveFunction();
1607 }
1608 
1609 void
1610 TeamWindow::_UpdateCpuState()
1611 {
1612 	// get the CPU state
1613 	CpuState* cpuState = NULL;
1614 	BReference<CpuState> cpuStateReference;
1615 		// hold a reference until the register view has one
1616 
1617 	if (fActiveThread != NULL) {
1618 		// Get the CPU state from the active stack frame or the thread directly.
1619 		if (fActiveStackFrame == NULL) {
1620 			AutoLocker< ::Team> locker(fTeam);
1621 			cpuState = fActiveThread->GetCpuState();
1622 			cpuStateReference.SetTo(cpuState);
1623 			locker.Unlock();
1624 		} else
1625 			cpuState = fActiveStackFrame->GetCpuState();
1626 	}
1627 
1628 	fRegistersView->SetCpuState(cpuState);
1629 }
1630 
1631 
1632 void
1633 TeamWindow::_UpdateRunButtons()
1634 {
1635 	uint32 threadState = fActiveThread != NULL
1636 		? fActiveThread->State() : THREAD_STATE_UNKNOWN;
1637 
1638 	switch (threadState) {
1639 		case THREAD_STATE_UNKNOWN:
1640 			fRunButton->SetEnabled(false);
1641 			fStepOverButton->SetEnabled(false);
1642 			fStepIntoButton->SetEnabled(false);
1643 			fStepOutButton->SetEnabled(false);
1644 			break;
1645 		case THREAD_STATE_RUNNING:
1646 			if (fTraceUpdateRunner == NULL) {
1647 				fRunButton->SetLabel("Debug");
1648 				fRunButton->SetMessage(new BMessage(MSG_THREAD_STOP));
1649 				fRunButton->SetEnabled(true);
1650 				fStepOverButton->SetEnabled(false);
1651 				fStepIntoButton->SetEnabled(false);
1652 				fStepOutButton->SetEnabled(false);
1653 			}
1654 			break;
1655 		case THREAD_STATE_STOPPED:
1656 			fRunButton->SetLabel("Run");
1657 			fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
1658 			fRunButton->SetEnabled(true);
1659 			fStepOverButton->SetEnabled(true);
1660 			fStepIntoButton->SetEnabled(true);
1661 			fStepOutButton->SetEnabled(true);
1662 			break;
1663 	}
1664 }
1665 
1666 
1667 void
1668 TeamWindow::_UpdateSourcePathState()
1669 {
1670 	LocatableFile* sourceFile = NULL;
1671 	BString sourceText = "Source file unavailable.";
1672 	BString truncatedText;
1673 
1674 	if (fActiveSourceCode != NULL) {
1675 		sourceFile = fActiveFunction->GetFunctionDebugInfo()->SourceFile();
1676 
1677 		if (sourceFile != NULL && !sourceFile->GetLocatedPath(sourceText))
1678 			sourceFile->GetPath(sourceText);
1679 
1680 		function_source_state state = fActiveFunction->GetFunction()
1681 			->SourceCodeState();
1682 		if (state == FUNCTION_SOURCE_SUPPRESSED)
1683 			sourceText.Prepend("Disassembly for: ");
1684 		else if (state != FUNCTION_SOURCE_NOT_LOADED
1685 			&& fActiveSourceCode->GetSourceFile() == NULL
1686 			&& sourceFile != NULL) {
1687 			sourceText.Prepend("Click to locate source file '");
1688 			sourceText += "'";
1689 			truncatedText = sourceText;
1690 			fSourcePathView->TruncateString(&truncatedText, B_TRUNCATE_MIDDLE,
1691 				fSourcePathView->Bounds().Width());
1692 		} else if (sourceFile != NULL)
1693 			sourceText.Prepend("File: ");
1694 	}
1695 
1696 	if (!truncatedText.IsEmpty() && truncatedText != sourceText) {
1697 		fSourcePathView->SetToolTip(sourceText);
1698 		fSourcePathView->SetText(truncatedText);
1699 	} else {
1700 		fSourcePathView->SetText(sourceText);
1701 		fSourcePathView->SetToolTip((const char*)NULL);
1702 	}
1703 }
1704 
1705 
1706 void
1707 TeamWindow::_ScrollToActiveFunction()
1708 {
1709 	// Scroll to the active function, if it has been selected manually.
1710 	if (fActiveFunction == NULL || fActiveSourceCode == NULL)
1711 		return;
1712 
1713 	switch (fActiveSourceObject) {
1714 		case ACTIVE_SOURCE_FUNCTION:
1715 			fSourceView->ScrollToAddress(fActiveFunction->Address());
1716 			break;
1717 		case ACTIVE_SOURCE_BREAKPOINT:
1718 		{
1719 			if (fActiveBreakpoint == NULL)
1720 				break;
1721 
1722 			const UserBreakpointLocation& location
1723 				= fActiveBreakpoint->Location();
1724 			int32 line = location.GetSourceLocation().Line();
1725 
1726 			if (location.SourceFile() != NULL && line >= 0
1727 				&& fActiveSourceCode->GetSourceFile()
1728 					== location.SourceFile()) {
1729 				fSourceView->ScrollToLine(line);
1730 			} else {
1731 				fSourceView->ScrollToAddress(
1732 					fActiveFunction->Address()
1733 						+ location.RelativeAddress());
1734 			}
1735 			break;
1736 		}
1737 		case ACTIVE_SOURCE_NONE:
1738 		case ACTIVE_SOURCE_STACK_FRAME:
1739 			break;
1740 	}
1741 }
1742 
1743 
1744 void
1745 TeamWindow::_HandleThreadStateChanged(thread_id threadID)
1746 {
1747 	AutoLocker< ::Team> locker(fTeam);
1748 
1749 	::Thread* thread = fTeam->ThreadByID(threadID);
1750 	if (thread == NULL)
1751 		return;
1752 
1753 	if (thread->State() != THREAD_STATE_STOPPED) {
1754 		ThreadStackFrameSelectionEntry* entry
1755 			= fThreadSelectionInfoTable->Lookup(thread);
1756 		if (entry != NULL) {
1757 			fThreadSelectionInfoTable->Remove(entry);
1758 			delete entry;
1759 		}
1760 	}
1761 
1762 	// If the thread has been stopped and we don't have an active thread yet
1763 	// (or it isn't stopped), switch to this thread. Otherwise ignore the event.
1764 	if (thread->State() == THREAD_STATE_STOPPED
1765 		&& (fActiveThread == NULL
1766 			|| (thread != fActiveThread
1767 				&& fActiveThread->State() != THREAD_STATE_STOPPED))) {
1768 		_SetActiveThread(thread);
1769 	} else if (thread != fActiveThread) {
1770 		// otherwise ignore the event, if the thread is not the active one
1771 		return;
1772 	}
1773 
1774 	// Switch to the threads tab view when the thread has stopped.
1775 	if (thread->State() == THREAD_STATE_STOPPED) {
1776 		fTabView->Select(MAIN_TAB_INDEX_THREADS);
1777 
1778 		// if we hit a breakpoint or exception, raise the window to the
1779 		// foreground, since if this occurs while e.g. debugging a GUI
1780 		// app, it might not be immediately obvious that such an event
1781 		// occurred as the app may simply appear to hang.
1782 		Activate();
1783 	}
1784 
1785 	_UpdateRunButtons();
1786 }
1787 
1788 
1789 void
1790 TeamWindow::_HandleCpuStateChanged(thread_id threadID)
1791 {
1792 	// We're only interested in the currently selected thread
1793 	if (fActiveThread == NULL || threadID != fActiveThread->ID())
1794 		return;
1795 
1796 	_UpdateCpuState();
1797 }
1798 
1799 
1800 void
1801 TeamWindow::_HandleStackTraceChanged(thread_id threadID)
1802 {
1803 	// We're only interested in the currently selected thread
1804 	if (fActiveThread == NULL || threadID != fActiveThread->ID())
1805 		return;
1806 
1807 	AutoLocker< ::Team> locker(fTeam);
1808 
1809 	StackTrace* stackTrace = fActiveThread != NULL
1810 		? fActiveThread->GetStackTrace() : NULL;
1811 	BReference<StackTrace> stackTraceReference(stackTrace);
1812 		// hold a reference until the register view has one
1813 
1814 	locker.Unlock();
1815 
1816 	if (stackTrace == NULL) {
1817 		if (fTraceUpdateRunner != NULL)
1818 			return;
1819 
1820 		BMessage message(MSG_CLEAR_STACK_TRACE);
1821 		fTraceUpdateRunner = new(std::nothrow) BMessageRunner(this,
1822 			message, 250000, 1);
1823 		if (fTraceUpdateRunner != NULL
1824 			&& fTraceUpdateRunner->InitCheck() == B_OK) {
1825 			fStackTraceView->SetStackTraceClearPending();
1826 			fVariablesView->SetStackFrameClearPending();
1827 			return;
1828 		}
1829 	}
1830 
1831 	_SetActiveStackTrace(stackTrace);
1832 }
1833 
1834 
1835 void
1836 TeamWindow::_HandleImageDebugInfoChanged(image_id imageID)
1837 {
1838 	TRACE_GUI("TeamWindow::_HandleImageDebugInfoChanged(%" B_PRId32 ")\n",
1839 		imageID);
1840 
1841 	// We're only interested in the currently selected thread
1842 	if (fActiveImage == NULL || imageID != fActiveImage->ID())
1843 		return;
1844 
1845 	AutoLocker< ::Team> locker(fTeam);
1846 
1847 	ImageDebugInfo* imageDebugInfo = fActiveImage != NULL
1848 		? fActiveImage->GetImageDebugInfo() : NULL;
1849 
1850 	TRACE_GUI("  image debug info: %p\n", imageDebugInfo);
1851 
1852 	BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo);
1853 		// hold a reference until we've set it
1854 
1855 	locker.Unlock();
1856 
1857 	fImageFunctionsView->SetImageDebugInfo(imageDebugInfo);
1858 }
1859 
1860 
1861 void
1862 TeamWindow::_HandleSourceCodeChanged()
1863 {
1864 	// If we don't have an active function anymore, the message is obsolete.
1865 	if (fActiveFunction == NULL)
1866 		return;
1867 
1868 	// get a reference to the source code
1869 	AutoLocker< ::Team> locker(fTeam);
1870 
1871 	SourceCode* sourceCode = NULL;
1872 	if (fActiveFunction->GetFunction()->SourceCodeState()
1873 		== FUNCTION_SOURCE_LOADED) {
1874 		sourceCode = fActiveFunction->GetFunction()->GetSourceCode();
1875 	} else
1876 		sourceCode = fActiveFunction->GetSourceCode();
1877 
1878 	BReference<SourceCode> sourceCodeReference(sourceCode);
1879 
1880 	locker.Unlock();
1881 
1882 	_SetActiveSourceCode(sourceCode);
1883 }
1884 
1885 
1886 void
1887 TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint)
1888 {
1889 	fSourceView->UserBreakpointChanged(breakpoint);
1890 	fBreakpointsView->UserBreakpointChanged(breakpoint);
1891 }
1892 
1893 
1894 void
1895 TeamWindow::_HandleWatchpointChanged(Watchpoint* watchpoint)
1896 {
1897 	fBreakpointsView->WatchpointChanged(watchpoint);
1898 }
1899 
1900 
1901 status_t
1902 TeamWindow::_RetrieveMatchingSourceWorker(void* arg)
1903 {
1904 	TeamWindow* window = (TeamWindow*)arg;
1905 
1906 	BStringList* entries = new(std::nothrow) BStringList();
1907 	if (entries == NULL)
1908 		return B_NO_MEMORY;
1909 	ObjectDeleter<BStringList> stringListDeleter(entries);
1910 
1911 	if (!window->Lock())
1912 		return B_BAD_VALUE;
1913 
1914 	BString path;
1915 	window->fActiveFunction->GetFunctionDebugInfo()->SourceFile()
1916 		->GetPath(path);
1917 	window->Unlock();
1918 
1919 	status_t error = window->_RetrieveMatchingSourceEntries(path, entries);
1920 
1921 	entries->Sort();
1922 	BMessenger messenger(window);
1923 	if (messenger.IsValid() && messenger.LockTarget()) {
1924 		if (window->fActiveSourceWorker == find_thread(NULL)) {
1925 			BMessage message(MSG_SOURCE_ENTRY_QUERY_COMPLETE);
1926 			message.AddInt32("error", error);
1927 			message.AddPointer("entries", entries);
1928 			if (messenger.SendMessage(&message) == B_OK)
1929 				stringListDeleter.Detach();
1930 		}
1931 		window->Unlock();
1932 	}
1933 
1934 	return B_OK;
1935 }
1936 
1937 
1938 void
1939 TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath)
1940 {
1941 	if (fActiveFunction != NULL) {
1942 		LocatableFile* sourceFile = fActiveFunction->GetFunctionDebugInfo()
1943 			->SourceFile();
1944 		if (sourceFile != NULL) {
1945 			BString sourcePath;
1946 			sourceFile->GetPath(sourcePath);
1947 			BString sourceFileName(sourcePath);
1948 			int32 index = sourcePath.FindLast('/');
1949 			if (index >= 0)
1950 				sourceFileName.Remove(0, index + 1);
1951 
1952 			BPath targetFilePath(&locatedPath);
1953 			if (targetFilePath.InitCheck() != B_OK)
1954 				return;
1955 
1956 			if (strcmp(sourceFileName.String(), targetFilePath.Leaf()) != 0) {
1957 				BString message;
1958 				message.SetToFormat("The names of source file '%s' and located"
1959 					" file '%s' differ. Use file anyway?",
1960 					sourceFileName.String(), targetFilePath.Leaf());
1961 				BAlert* alert = new(std::nothrow) BAlert(
1962 					"Source path mismatch", message.String(), "Cancel", "Use");
1963 				if (alert == NULL)
1964 					return;
1965 
1966 				int32 choice = alert->Go();
1967 				if (choice <= 0)
1968 					return;
1969 			}
1970 
1971 			LocatableFile* foundSourceFile = fActiveSourceCode
1972 				->GetSourceFile();
1973 			if (foundSourceFile != NULL)
1974 				fListener->SourceEntryInvalidateRequested(foundSourceFile);
1975 			fListener->SourceEntryLocateRequested(sourcePath,
1976 				targetFilePath.Path());
1977 			fListener->FunctionSourceCodeRequested(fActiveFunction);
1978 		}
1979 	}
1980 }
1981 
1982 
1983 void
1984 TeamWindow::_HandleLocateSourceRequest(BStringList* entries)
1985 {
1986 	if (fActiveFunction == NULL)
1987 		return;
1988 	else if (fActiveFunction->GetFunctionDebugInfo()->SourceFile() == NULL)
1989 		return;
1990 	else if (fActiveSourceCode == NULL)
1991 		return;
1992 	else if (fActiveFunction->GetFunction()->SourceCodeState()
1993 		== FUNCTION_SOURCE_NOT_LOADED) {
1994 		return;
1995 	}
1996 
1997 	if (entries == NULL) {
1998 		if (fActiveSourceWorker < 0) {
1999 			fActiveSourceWorker = spawn_thread(&_RetrieveMatchingSourceWorker,
2000 				"source file query worker", B_NORMAL_PRIORITY, this);
2001 			if (fActiveSourceWorker > 0)
2002 				resume_thread(fActiveSourceWorker);
2003 		}
2004 		return;
2005 	}
2006 
2007 	int32 count = entries->CountStrings();
2008 	if (count > 0) {
2009 		BPopUpMenu* menu = new(std::nothrow) BPopUpMenu("");
2010 		if (menu == NULL)
2011 			return;
2012 
2013 		BPrivate::ObjectDeleter<BPopUpMenu> menuDeleter(menu);
2014 		BMenuItem* item = NULL;
2015 		for (int32 i = 0; i < count; i++) {
2016 			item = new(std::nothrow) BMenuItem(entries->StringAt(i).String(),
2017 				NULL);
2018 			if (item == NULL || !menu->AddItem(item)) {
2019 				delete item;
2020 				return;
2021 			}
2022 		}
2023 
2024 		menu->AddSeparatorItem();
2025 		BMenuItem* manualItem = new(std::nothrow) BMenuItem(
2026 			"Locate manually" B_UTF8_ELLIPSIS, NULL);
2027 		if (manualItem == NULL || !menu->AddItem(manualItem)) {
2028 			delete manualItem;
2029 			return;
2030 		}
2031 
2032 		BPoint point;
2033 		fSourcePathView->GetMouse(&point, NULL, false);
2034 		fSourcePathView->ConvertToScreen(&point);
2035 		item = menu->Go(point, false, true);
2036 		if (item == NULL)
2037 			return;
2038 		else if (item != manualItem) {
2039 			// if the user picks to locate the entry manually,
2040 			// then fall through to the usual file panel logic
2041 			// as if we'd found no matches at all.
2042 			entry_ref ref;
2043 			if (get_ref_for_path(item->Label(), &ref) == B_OK) {
2044 				_HandleResolveMissingSourceFile(ref);
2045 				return;
2046 			}
2047 		}
2048 	}
2049 
2050 	try {
2051 		if (fFilePanel == NULL) {
2052 			fFilePanel = new BFilePanel(B_OPEN_PANEL,
2053 				new BMessenger(this));
2054 		}
2055 		fFilePanel->Show();
2056 	} catch (...) {
2057 		delete fFilePanel;
2058 		fFilePanel = NULL;
2059 	}
2060 }
2061 
2062 
2063 status_t
2064 TeamWindow::_RetrieveMatchingSourceEntries(const BString& path,
2065 	BStringList* _entries)
2066 {
2067 	BPath filePath(path);
2068 	status_t error = filePath.InitCheck();
2069 	if (error != B_OK)
2070 		return error;
2071 
2072 	_entries->MakeEmpty();
2073 
2074 	BQuery query;
2075 	BString predicate;
2076 	query.PushAttr("name");
2077 	query.PushString(filePath.Leaf());
2078 	query.PushOp(B_EQ);
2079 
2080 	error = query.GetPredicate(&predicate);
2081 	if (error != B_OK)
2082 		return error;
2083 
2084 	BVolumeRoster roster;
2085 	BVolume volume;
2086 	while (roster.GetNextVolume(&volume) == B_OK) {
2087 		if (!volume.KnowsQuery())
2088 			continue;
2089 
2090 		if (query.SetVolume(&volume) != B_OK)
2091 			continue;
2092 
2093 		error = query.SetPredicate(predicate.String());
2094 		if (error != B_OK)
2095 			continue;
2096 
2097 		if (query.Fetch() != B_OK)
2098 			continue;
2099 
2100 		entry_ref ref;
2101 		while (query.GetNextRef(&ref) == B_OK) {
2102 			filePath.SetTo(&ref);
2103 			_entries->Add(filePath.Path());
2104 		}
2105 
2106 		query.Clear();
2107 	}
2108 
2109 	return B_OK;
2110 }
2111 
2112 
2113 status_t
2114 TeamWindow::_SaveInspectorSettings(const BMessage* settings)
2115 {
2116 	if (fUiSettings.AddSettings("inspectorWindow", *settings) != B_OK)
2117 		return B_NO_MEMORY;
2118 
2119 	return B_OK;
2120 }
2121 
2122 
2123 status_t
2124 TeamWindow::_GetActiveSourceLanguage(SourceLanguage*& _language)
2125 {
2126 	AutoLocker< ::Team> locker(fTeam);
2127 
2128 	if (!locker.IsLocked())
2129 		return B_ERROR;
2130 
2131 	if (fActiveSourceCode != NULL) {
2132 		_language = fActiveSourceCode->GetSourceLanguage();
2133 		_language->AcquireReference();
2134 		return B_OK;
2135 	}
2136 
2137 	// if we made it this far, we were unable to acquire a source
2138 	// language corresponding to the active function. As such,
2139 	// try to fall back to the C++-style parser.
2140 	_language = new(std::nothrow) CppLanguage();
2141 	if (_language == NULL)
2142 		return B_NO_MEMORY;
2143 
2144 	return B_OK;
2145 }
2146