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