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