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