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