Repository: packagesdev/unexpectedly Branch: master Commit: 875181c29c77 Files: 786 Total size: 4.3 MB Directory structure: gitextract_4sdmyxfy/ ├── .gitignore ├── .gitmodules ├── Configs/ │ ├── CodeSigningConfigurationSettings.xcconfig │ └── SharedConfigurationSettings.xcconfig ├── Documents Pages/ │ ├── Unexpectedly_Acknowledgements.pages │ └── Unexpectedly_License.pages ├── LICENSE.txt ├── README.md ├── app_unexpectedly/ │ ├── AppKit + Extensions/ │ │ ├── NSColor+LabelColor.h │ │ ├── NSColor+LabelColor.m │ │ ├── NSColor+String.h │ │ ├── NSColor+String.m │ │ ├── NSResponder+Appearance.h │ │ ├── NSResponder+Appearance.m │ │ ├── NSTableView+Selection.h │ │ ├── NSTableView+Selection.m │ │ ├── NSToolbar+Packages.h │ │ └── NSToolbar+Packages.m │ ├── Foundation + Extensions/ │ │ ├── NSArray+UniqueName.h │ │ ├── NSArray+UniqueName.m │ │ ├── NSArray+WBExtensions.h │ │ ├── NSArray+WBExtensions.m │ │ ├── NSDictionary+MutableDeepCopy.h │ │ ├── NSDictionary+MutableDeepCopy.m │ │ ├── NSDictionary+WBExtensions.h │ │ ├── NSDictionary+WBExtensions.m │ │ ├── NSIndexSet+Analysis.h │ │ ├── NSIndexSet+Analysis.m │ │ ├── NSSet+WBExtensions.h │ │ ├── NSSet+WBExtensions.m │ │ ├── NSString+CPU.h │ │ └── NSString+CPU.m │ ├── RSCore/ │ │ ├── LICENSE.txt │ │ ├── NSMenuItem+RSCore.h │ │ └── NSMenuItem+RSCore.m │ ├── app_unexpectedly/ │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── CUIAATextFieldCell.h │ │ ├── CUIAATextFieldCell.m │ │ ├── CUIAboutBoxFooterView.h │ │ ├── CUIAboutBoxFooterView.m │ │ ├── CUIAboutBoxWindow.h │ │ ├── CUIAboutBoxWindow.m │ │ ├── CUIAboutBoxWindowController.h │ │ ├── CUIAboutBoxWindowController.m │ │ ├── CUIApplicationItemAttributes.h │ │ ├── CUIApplicationItemAttributes.m │ │ ├── CUIApplicationPreferences+Themes.h │ │ ├── CUIApplicationPreferences+Themes.m │ │ ├── CUIApplicationPreferences.h │ │ ├── CUIApplicationPreferences.m │ │ ├── CUIApplicationSpecificBacktraceRowView.h │ │ ├── CUIApplicationSpecificBacktraceRowView.m │ │ ├── CUIBinaryImage.h │ │ ├── CUIBinaryImage.m │ │ ├── CUIBinaryImageUtility.h │ │ ├── CUIBinaryImageUtility.m │ │ ├── CUIBinaryImagesViewController.h │ │ ├── CUIBinaryImagesViewController.m │ │ ├── CUICallStackBacktrace.h │ │ ├── CUICallStackBacktrace.m │ │ ├── CUICallTableCellView.h │ │ ├── CUICallTableCellView.m │ │ ├── CUICallsSelection.h │ │ ├── CUICallsSelection.m │ │ ├── CUICaptionView.h │ │ ├── CUICaptionView.m │ │ ├── CUICategoriesClipView.h │ │ ├── CUICategoriesClipView.m │ │ ├── CUICenteredLabelViewController.h │ │ ├── CUICenteredLabelViewController.m │ │ ├── CUICenteredLabelViewController.xib │ │ ├── CUICodeSigningFlagsTableView.h │ │ ├── CUICodeSigningFlagsTableView.m │ │ ├── CUICodeSigningInformationViewController.h │ │ ├── CUICodeSigningInformationViewController.m │ │ ├── CUICodeType.h │ │ ├── CUICollectionViewDockedThreadItem.h │ │ ├── CUICollectionViewDockedThreadItem.m │ │ ├── CUICollectionViewDockedThreadItem.xib │ │ ├── CUICollectionViewDockedThreadsLayout.h │ │ ├── CUICollectionViewDockedThreadsLayout.m │ │ ├── CUICollectionViewRegisterItem.h │ │ ├── CUICollectionViewRegisterItem.m │ │ ├── CUICollectionViewThreadItem.h │ │ ├── CUICollectionViewThreadItem.m │ │ ├── CUICollectionViewVisibleThreadItem.h │ │ ├── CUICollectionViewVisibleThreadItem.m │ │ ├── CUICollectionViewVisibleThreadItem.xib │ │ ├── CUICollectionViewVisibleThreadsLayout.h │ │ ├── CUICollectionViewVisibleThreadsLayout.m │ │ ├── CUIContentBox.h │ │ ├── CUIContentBox.m │ │ ├── CUIContentsViewController.h │ │ ├── CUIContentsViewController.m │ │ ├── CUIContentsViewController.xib │ │ ├── CUICrashDataTransform.h │ │ ├── CUICrashDataTransform.m │ │ ├── CUICrashLog+Transform.h │ │ ├── CUICrashLog+Transform.m │ │ ├── CUICrashLog+UI.h │ │ ├── CUICrashLog+UI.m │ │ ├── CUICrashLog.h │ │ ├── CUICrashLog.m │ │ ├── CUICrashLogBacktraces+Utilities.h │ │ ├── CUICrashLogBacktraces+Utilities.m │ │ ├── CUICrashLogBacktraces.h │ │ ├── CUICrashLogBacktraces.m │ │ ├── CUICrashLogBinaryImages.h │ │ ├── CUICrashLogBinaryImages.m │ │ ├── CUICrashLogBrowsingState.h │ │ ├── CUICrashLogBrowsingState.m │ │ ├── CUICrashLogBrowsingStateRegistry.h │ │ ├── CUICrashLogBrowsingStateRegistry.m │ │ ├── CUICrashLogContentsViewController.h │ │ ├── CUICrashLogContentsViewController.m │ │ ├── CUICrashLogContentsViewController.xib │ │ ├── CUICrashLogDianosticMessages.h │ │ ├── CUICrashLogDianosticMessages.m │ │ ├── CUICrashLogErrors.h │ │ ├── CUICrashLogErrors.m │ │ ├── CUICrashLogExceptionInformation+QuickHelp.h │ │ ├── CUICrashLogExceptionInformation+QuickHelp.m │ │ ├── CUICrashLogExceptionInformation+UI.h │ │ ├── CUICrashLogExceptionInformation+UI.m │ │ ├── CUICrashLogExceptionInformation.h │ │ ├── CUICrashLogExceptionInformation.m │ │ ├── CUICrashLogHeader.h │ │ ├── CUICrashLogHeader.m │ │ ├── CUICrashLogPresentationOutlineViewController.h │ │ ├── CUICrashLogPresentationOutlineViewController.m │ │ ├── CUICrashLogPresentationTextViewController.h │ │ ├── CUICrashLogPresentationTextViewController.m │ │ ├── CUICrashLogPresentationViewController.h │ │ ├── CUICrashLogPresentationViewController.m │ │ ├── CUICrashLogSectionsDetector.h │ │ ├── CUICrashLogSectionsDetector.m │ │ ├── CUICrashLogTableCellView.h │ │ ├── CUICrashLogTableCellView.m │ │ ├── CUICrashLogTextView.h │ │ ├── CUICrashLogTextView.m │ │ ├── CUICrashLogThreadState+UI.h │ │ ├── CUICrashLogThreadState+UI.m │ │ ├── CUICrashLogThreadState.h │ │ ├── CUICrashLogThreadState.m │ │ ├── CUICrashLogsListViewController.h │ │ ├── CUICrashLogsListViewController.m │ │ ├── CUICrashLogsMainViewController.h │ │ ├── CUICrashLogsMainViewController.m │ │ ├── CUICrashLogsMainViewController.xib │ │ ├── CUICrashLogsOpenErrorPanel.h │ │ ├── CUICrashLogsOpenErrorPanel.m │ │ ├── CUICrashLogsOpenErrorRecord+UI.h │ │ ├── CUICrashLogsOpenErrorRecord+UI.m │ │ ├── CUICrashLogsOpenErrorRecord.h │ │ ├── CUICrashLogsOpenErrorRecord.m │ │ ├── CUICrashLogsOpenErrorWindowController.xib │ │ ├── CUICrashLogsProvider.h │ │ ├── CUICrashLogsProvider.m │ │ ├── CUICrashLogsSelection.h │ │ ├── CUICrashLogsSelection.m │ │ ├── CUICrashLogsSource+UI.h │ │ ├── CUICrashLogsSource+UI.m │ │ ├── CUICrashLogsSource.h │ │ ├── CUICrashLogsSource.m │ │ ├── CUICrashLogsSourceAll+UI.h │ │ ├── CUICrashLogsSourceAll+UI.m │ │ ├── CUICrashLogsSourceAll.h │ │ ├── CUICrashLogsSourceAll.m │ │ ├── CUICrashLogsSourceDirectory.h │ │ ├── CUICrashLogsSourceDirectory.m │ │ ├── CUICrashLogsSourceFile.h │ │ ├── CUICrashLogsSourceFile.m │ │ ├── CUICrashLogsSourceFileSystemItem.h │ │ ├── CUICrashLogsSourceFileSystemItem.m │ │ ├── CUICrashLogsSourceSeparator.h │ │ ├── CUICrashLogsSourceSeparator.m │ │ ├── CUICrashLogsSourceSmart.h │ │ ├── CUICrashLogsSourceSmart.m │ │ ├── CUICrashLogsSourceSmartEditorPanel.h │ │ ├── CUICrashLogsSourceSmartEditorPanel.m │ │ ├── CUICrashLogsSourceStandardDirectory+UI.h │ │ ├── CUICrashLogsSourceStandardDirectory+UI.m │ │ ├── CUICrashLogsSourceStandardDirectory.h │ │ ├── CUICrashLogsSourceStandardDirectory.m │ │ ├── CUICrashLogsSourceTableCellView.h │ │ ├── CUICrashLogsSourceTableCellView.m │ │ ├── CUICrashLogsSourceToday+UI.h │ │ ├── CUICrashLogsSourceToday+UI.m │ │ ├── CUICrashLogsSourceToday.h │ │ ├── CUICrashLogsSourceToday.m │ │ ├── CUICrashLogsSourcesManager.h │ │ ├── CUICrashLogsSourcesManager.m │ │ ├── CUICrashLogsSourcesSelection.h │ │ ├── CUICrashLogsSourcesSelection.m │ │ ├── CUICrashLogsSourcesViewController.h │ │ ├── CUICrashLogsSourcesViewController.m │ │ ├── CUICrashReporterDefaults.h │ │ ├── CUICrashReporterDefaults.m │ │ ├── CUICrashedThreadCallRowView.h │ │ ├── CUICrashedThreadCallRowView.m │ │ ├── CUICrashedThreadRowView.h │ │ ├── CUICrashedThreadRowView.m │ │ ├── CUIDataTransform.h │ │ ├── CUIDataTransform.m │ │ ├── CUIExceptionTypePopUpViewController.h │ │ ├── CUIExceptionTypePopUpViewController.m │ │ ├── CUIExportAccessoryViewController.h │ │ ├── CUIExportAccessoryViewController.m │ │ ├── CUIFileDeadDropView.h │ │ ├── CUIFileDeadDropView.m │ │ ├── CUIFontAndColorsFramedView.h │ │ ├── CUIFontAndColorsFramedView.m │ │ ├── CUIFontBoxView.h │ │ ├── CUIFontBoxView.m │ │ ├── CUIHopperDisassemblerManager.h │ │ ├── CUIHopperDisassemblerManager.m │ │ ├── CUIIPSTransform.h │ │ ├── CUIIPSTransform.m │ │ ├── CUIInactiveButton.h │ │ ├── CUIInactiveButton.m │ │ ├── CUIInspectorAlternateBackgroundView.h │ │ ├── CUIInspectorAlternateBackgroundView.m │ │ ├── CUIInspectorExecutableViewController.h │ │ ├── CUIInspectorExecutableViewController.m │ │ ├── CUIInspectorGeneralViewController.h │ │ ├── CUIInspectorGeneralViewController.m │ │ ├── CUIInspectorProcessesViewController.h │ │ ├── CUIInspectorProcessesViewController.m │ │ ├── CUIInspectorStackableViewController.h │ │ ├── CUIInspectorStackableViewController.m │ │ ├── CUIInspectorUserViewController.h │ │ ├── CUIInspectorUserViewController.m │ │ ├── CUIInspectorViewController.h │ │ ├── CUIInspectorViewController.m │ │ ├── CUIInspectorViewController.xib │ │ ├── CUIKeyViews.h │ │ ├── CUILightTableDockedThreadView.h │ │ ├── CUILightTableDockedThreadView.m │ │ ├── CUILightTableThreadView.h │ │ ├── CUILightTableThreadView.m │ │ ├── CUILightTableViewController.h │ │ ├── CUILightTableViewController.m │ │ ├── CUILightTableViewController.xib │ │ ├── CUILightTableVisibleInterGapView.h │ │ ├── CUILightTableVisibleInterGapView.m │ │ ├── CUILightTableVisibleThreadView.h │ │ ├── CUILightTableVisibleThreadView.m │ │ ├── CUILineJumperWindowController.h │ │ ├── CUILineJumperWindowController.m │ │ ├── CUIMainWindow.h │ │ ├── CUIMainWindow.m │ │ ├── CUIMainWindowController.h │ │ ├── CUIMainWindowController.m │ │ ├── CUINavigationChevronView.h │ │ ├── CUINavigationChevronView.m │ │ ├── CUINavigationView.h │ │ ├── CUINavigationView.m │ │ ├── CUIOperatingSystemVersion.h │ │ ├── CUIOperatingSystemVersion.m │ │ ├── CUIOutlineModeDisplaySettings.h │ │ ├── CUIOutlineModeDisplaySettings.m │ │ ├── CUIParsingErrors.h │ │ ├── CUIParsingErrors.m │ │ ├── CUIPreferencePaneAdvancedViewController.h │ │ ├── CUIPreferencePaneAdvancedViewController.m │ │ ├── CUIPreferencePaneCrashreporterViewController.h │ │ ├── CUIPreferencePaneCrashreporterViewController.m │ │ ├── CUIPreferencePaneFontscolorsViewController.h │ │ ├── CUIPreferencePaneFontscolorsViewController.m │ │ ├── CUIPreferencePaneGeneralViewController.h │ │ ├── CUIPreferencePaneGeneralViewController.m │ │ ├── CUIPreferencePanePresentationOutlineViewController.h │ │ ├── CUIPreferencePanePresentationOutlineViewController.m │ │ ├── CUIPreferencePanePresentationTextViewController.h │ │ ├── CUIPreferencePanePresentationTextViewController.m │ │ ├── CUIPreferencePanePresentationViewController.h │ │ ├── CUIPreferencePanePresentationViewController.m │ │ ├── CUIPreferencePaneSymbolicationViewController.h │ │ ├── CUIPreferencePaneSymbolicationViewController.m │ │ ├── CUIPreferencePaneViewController.h │ │ ├── CUIPreferencePaneViewController.m │ │ ├── CUIPreferencesTabBox.h │ │ ├── CUIPreferencesTabBox.m │ │ ├── CUIPreferencesTabButton.h │ │ ├── CUIPreferencesTabButton.m │ │ ├── CUIPreferencesTabHeaderView.h │ │ ├── CUIPreferencesTabHeaderView.m │ │ ├── CUIPreferencesWindow.h │ │ ├── CUIPreferencesWindow.m │ │ ├── CUIPreferencesWindowController+Convenience.h │ │ ├── CUIPreferencesWindowController+Convenience.m │ │ ├── CUIPreferencesWindowController.h │ │ ├── CUIPreferencesWindowController.m │ │ ├── CUIPresentationTextNavigationViewController.h │ │ ├── CUIPresentationTextNavigationViewController.m │ │ ├── CUIPresentationTextNavigationViewController.xib │ │ ├── CUIQuickHelpPopUpViewController.h │ │ ├── CUIQuickHelpPopUpViewController.m │ │ ├── CUIQuickHelpPopUpViewController.xib │ │ ├── CUIRawCrashLog+Path.h │ │ ├── CUIRawCrashLog+Path.m │ │ ├── CUIRawCrashLog+UI.h │ │ ├── CUIRawCrashLog+UI.m │ │ ├── CUIRawCrashLog.h │ │ ├── CUIRawCrashLog.m │ │ ├── CUIRegister.h │ │ ├── CUIRegister.m │ │ ├── CUIRegisterLabel.h │ │ ├── CUIRegisterLabel.m │ │ ├── CUIRegistersMainViewController.h │ │ ├── CUIRegistersMainViewController.m │ │ ├── CUIRegistersMainViewController.xib │ │ ├── CUIRegistersViewController.h │ │ ├── CUIRegistersViewController.m │ │ ├── CUIRegistersViewController.xib │ │ ├── CUIRegistersWindowController.h │ │ ├── CUIRegistersWindowController.m │ │ ├── CUIRegistersWindowController.xib │ │ ├── CUIReportThemedTransform.h │ │ ├── CUIReportThemedTransform.m │ │ ├── CUIRightViewController.h │ │ ├── CUIRightViewController.m │ │ ├── CUIRightViewController.xib │ │ ├── CUIRoundedRectBezelView.h │ │ ├── CUIRoundedRectBezelView.m │ │ ├── CUISelectedWhiteTextFieldCell.h │ │ ├── CUISelectedWhiteTextFieldCell.m │ │ ├── CUISidebarViewController.h │ │ ├── CUISidebarViewController.m │ │ ├── CUISidebarViewController.xib │ │ ├── CUISourceFileTableCellView.h │ │ ├── CUISourceFileTableCellView.m │ │ ├── CUIStackFrame+UI.h │ │ ├── CUIStackFrame+UI.m │ │ ├── CUIStackFrame.h │ │ ├── CUIStackFrame.m │ │ ├── CUIStackFrameComponents.h │ │ ├── CUISymbolicationData.h │ │ ├── CUISymbolicationData.m │ │ ├── CUISymbolicationDataCache.h │ │ ├── CUISymbolicationDataCache.m │ │ ├── CUISymbolicationDataFormatter.h │ │ ├── CUISymbolicationDataFormatter.m │ │ ├── CUISymbolicationManager.h │ │ ├── CUISymbolicationManager.m │ │ ├── CUISymbolsFilesLibraryViewController.h │ │ ├── CUISymbolsFilesLibraryViewController.m │ │ ├── CUITableCustomSelectionColorRowView.h │ │ ├── CUITableCustomSelectionColorRowView.m │ │ ├── CUITableViewNoSpace.h │ │ ├── CUITableViewNoSpace.m │ │ ├── CUITerminationReasonPopUpViewController.h │ │ ├── CUITerminationReasonPopUpViewController.m │ │ ├── CUITextModeDisplaySettings.h │ │ ├── CUITextModeDisplaySettings.m │ │ ├── CUITheme.h │ │ ├── CUITheme.m │ │ ├── CUIThemeItemAttributes.h │ │ ├── CUIThemeItemAttributes.m │ │ ├── CUIThemeItemsGroup+UI.h │ │ ├── CUIThemeItemsGroup+UI.m │ │ ├── CUIThemeItemsGroup.h │ │ ├── CUIThemeItemsGroup.m │ │ ├── CUIThemesManager.h │ │ ├── CUIThemesManager.m │ │ ├── CUIThemesTableView.h │ │ ├── CUIThemesTableView.m │ │ ├── CUIThread.h │ │ ├── CUIThread.m │ │ ├── CUIThreadImageCell.h │ │ ├── CUIThreadImageCell.m │ │ ├── CUIThreadImageView.h │ │ ├── CUIThreadImageView.m │ │ ├── CUIThreadNamedTableCellView.h │ │ ├── CUIThreadNamedTableCellView.m │ │ ├── CUIThreadsColumnViewController.h │ │ ├── CUIThreadsColumnViewController.m │ │ ├── CUIThreadsColumnViewController.xib │ │ ├── CUIThreadsColumnViewController_RTL.xib │ │ ├── CUIThreadsListViewController.h │ │ ├── CUIThreadsListViewController.m │ │ ├── CUIThreadsListViewController.xib │ │ ├── CUIThreadsListViewController_RTL.xib │ │ ├── CUIThreadsViewController.h │ │ ├── CUIThreadsViewController.m │ │ ├── CUIdSYMBundlesManager.h │ │ ├── CUIdSYMBundlesManager.m │ │ ├── CUIdSYMDropView.h │ │ ├── CUIdSYMDropView.m │ │ ├── CUIdSYMHunter.h │ │ ├── CUIdSYMHunter.m │ │ ├── CodeSigningFlags.plist │ │ ├── DWARF/ │ │ │ ├── DWRFEnums.h │ │ │ ├── DWRFFileObject.h │ │ │ ├── DWRFFileObject.m │ │ │ ├── DWRFObject.h │ │ │ ├── DWRFObject.m │ │ │ ├── DWRFSection_debug_abbrev.h │ │ │ ├── DWRFSection_debug_abbrev.m │ │ │ ├── DWRFSection_debug_addr.h │ │ │ ├── DWRFSection_debug_addr.m │ │ │ ├── DWRFSection_debug_aranges.h │ │ │ ├── DWRFSection_debug_aranges.m │ │ │ ├── DWRFSection_debug_info.h │ │ │ ├── DWRFSection_debug_info.m │ │ │ ├── DWRFSection_debug_line.h │ │ │ ├── DWRFSection_debug_line.m │ │ │ ├── DWRFSection_debug_str.h │ │ │ ├── DWRFSection_debug_str.m │ │ │ ├── DWRFSection_debug_str_offsets.h │ │ │ ├── DWRFSection_debug_str_offsets.m │ │ │ ├── LEB128.c │ │ │ └── LEB128.h │ │ ├── Demangling/ │ │ │ ├── CUICXXDemangler.h │ │ │ ├── CUICXXDemangler.mm │ │ │ ├── CUISwiftDemangler.h │ │ │ └── CUISwiftDemangler.m │ │ ├── Extemal/ │ │ │ └── Line View Test/ │ │ │ ├── Controller.h │ │ │ ├── Controller.m │ │ │ ├── English.lproj/ │ │ │ │ ├── InfoPlist.strings │ │ │ │ └── MainMenu.nib/ │ │ │ │ ├── designable.nib │ │ │ │ └── keyedobjects.nib │ │ │ ├── Info.plist │ │ │ ├── Line View Test.xcodeproj/ │ │ │ │ ├── TemplateIcon.icns │ │ │ │ ├── project.pbxproj │ │ │ │ └── project.xcworkspace/ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata/ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ ├── Line View Test_Prefix.pch │ │ │ ├── MarkerLineNumberView.h │ │ │ ├── MarkerLineNumberView.m │ │ │ ├── NoodleLineNumberMarker.h │ │ │ ├── NoodleLineNumberMarker.m │ │ │ ├── NoodleLineNumberView.h │ │ │ ├── NoodleLineNumberView.m │ │ │ ├── Read Me.rtf │ │ │ └── main.m │ │ ├── Help/ │ │ │ ├── en.lproj/ │ │ │ │ ├── ENDPOINTSECURITY_2.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGBUS.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGSEGV.html │ │ │ │ ├── EXC_BAD_INSTRUCTION_SIGILL.html │ │ │ │ ├── EXC_BREAKPOINT_SIGTRAP.html │ │ │ │ ├── EXC_CRASH_Code Signature Invalid.html │ │ │ │ ├── EXC_CRASH_SIGABRT.html │ │ │ │ ├── EXC_CRASH_SIGKILL.html │ │ │ │ ├── EXC_CRASH_SIGQUIT.html │ │ │ │ ├── EXC_CRASH_SIGSEGV.html │ │ │ │ ├── EXC_GUARD.html │ │ │ │ ├── unknown_exception_type.html │ │ │ │ └── unknown_termination_reason.html │ │ │ ├── es.lproj/ │ │ │ │ ├── ENDPOINTSECURITY_2.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGBUS.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGSEGV.html │ │ │ │ ├── EXC_BAD_INSTRUCTION_SIGILL.html │ │ │ │ ├── EXC_BREAKPOINT_SIGTRAP.html │ │ │ │ ├── EXC_CRASH_Code Signature Invalid.html │ │ │ │ ├── EXC_CRASH_SIGABRT.html │ │ │ │ ├── EXC_CRASH_SIGKILL.html │ │ │ │ ├── EXC_CRASH_SIGQUIT.html │ │ │ │ ├── EXC_CRASH_SIGSEGV.html │ │ │ │ ├── EXC_GUARD.html │ │ │ │ ├── unknown_exception_type.html │ │ │ │ └── unknown_termination_reason.html │ │ │ ├── fr.lproj/ │ │ │ │ ├── ENDPOINTSECURITY_2.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGBUS.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGSEGV.html │ │ │ │ ├── EXC_BAD_INSTRUCTION_SIGILL.html │ │ │ │ ├── EXC_BREAKPOINT_SIGTRAP.html │ │ │ │ ├── EXC_CRASH_Code Signature Invalid.html │ │ │ │ ├── EXC_CRASH_SIGABRT.html │ │ │ │ ├── EXC_CRASH_SIGKILL.html │ │ │ │ ├── EXC_CRASH_SIGQUIT.html │ │ │ │ ├── EXC_CRASH_SIGSEGV.html │ │ │ │ ├── EXC_GUARD.html │ │ │ │ ├── unknown_exception_type.html │ │ │ │ └── unknown_termination_reason.html │ │ │ ├── he.lproj/ │ │ │ │ ├── ENDPOINTSECURITY_2.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGBUS.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGSEGV.html │ │ │ │ ├── EXC_BAD_INSTRUCTION_SIGILL.html │ │ │ │ ├── EXC_BREAKPOINT_SIGTRAP.html │ │ │ │ ├── EXC_CRASH_Code Signature Invalid.html │ │ │ │ ├── EXC_CRASH_SIGABRT.html │ │ │ │ ├── EXC_CRASH_SIGKILL.html │ │ │ │ ├── EXC_CRASH_SIGQUIT.html │ │ │ │ ├── EXC_CRASH_SIGSEGV.html │ │ │ │ ├── EXC_GUARD.html │ │ │ │ ├── unknown_exception_type.html │ │ │ │ └── unknown_termination_reason.html │ │ │ ├── ja.lproj/ │ │ │ │ ├── ENDPOINTSECURITY_2.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGBUS.html │ │ │ │ ├── EXC_BAD_ACCESS_SIGSEGV.html │ │ │ │ ├── EXC_BAD_INSTRUCTION_SIGILL.html │ │ │ │ ├── EXC_BREAKPOINT_SIGTRAP.html │ │ │ │ ├── EXC_CRASH_Code Signature Invalid.html │ │ │ │ ├── EXC_CRASH_SIGABRT.html │ │ │ │ ├── EXC_CRASH_SIGKILL.html │ │ │ │ ├── EXC_CRASH_SIGQUIT.html │ │ │ │ ├── EXC_CRASH_SIGSEGV.html │ │ │ │ ├── EXC_GUARD.html │ │ │ │ ├── unknown_exception_type.html │ │ │ │ └── unknown_termination_reason.html │ │ │ ├── known_exceptions.css │ │ │ └── known_termination_reasons.css │ │ ├── Images.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── FontPanelButton.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── TextMode.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── binaryImage_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── bottom_disclose_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── bottom_hide_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── bytesOffset_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-appkit.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-audiospeech.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-database.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-foundation.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-framework.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-generic.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-graphics.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-languages.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-network.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-security.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-system.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-usercode.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── call-webinternet.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── crashedThread_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── crashreporter.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── filter_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── left_switch_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuBacktraces.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuBinaryImage.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuDiagnostic.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuException.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuHeader.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuThread.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuThreadCrashed.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── menuThreadState.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── middle_switch_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── presentation_structured_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── presentation_text_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── quote_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── right_switch_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── sidebar_recents_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── smallColumn_RTL_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── smallColumn_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── smallCrashedThread_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── smallLightTable_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── symbolication_Template.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── templateBlue.imageset/ │ │ │ │ └── Contents.json │ │ │ └── thread_Template.imageset/ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── Mach-o/ │ │ │ ├── MCHLoadCommand.h │ │ │ ├── MCHLoadCommand.m │ │ │ ├── MCHMachBinary.h │ │ │ ├── MCHMachBinary.m │ │ │ ├── MCHMemoryBufferWrapper.h │ │ │ ├── MCHMemoryBufferWrapper.m │ │ │ ├── MCHObjectFile.h │ │ │ ├── MCHObjectFile.m │ │ │ ├── MCHSection.h │ │ │ ├── MCHSection.m │ │ │ ├── MCHSegment.h │ │ │ ├── MCHSegment.m │ │ │ ├── MCHSegmentLoadCommand.h │ │ │ ├── MCHSegmentLoadCommand.m │ │ │ ├── MCHUUIDLoadCommand.h │ │ │ └── MCHUUIDLoadCommand.m │ │ ├── NSBundle+dSYM.h │ │ ├── NSBundle+dSYM.m │ │ ├── NSCrashLogTextScrollView.h │ │ ├── NSCrashLogTextScrollView.m │ │ ├── NSFileManager+ExtendedAttributes.h │ │ ├── NSFileManager+ExtendedAttributes.m │ │ ├── WBRemoteVersionChecker.h │ │ ├── WBRemoteVersionChecker.m │ │ ├── app_unexpectedly_Prefix.pch │ │ ├── clock/ │ │ │ ├── CUIApplicationIconView.h │ │ │ ├── CUIApplicationIconView.m │ │ │ ├── CUIWatchAxis.h │ │ │ ├── CUIWatchAxis.m │ │ │ ├── CUIWatchBridge.h │ │ │ ├── CUIWatchBridge.m │ │ │ ├── CUIWatchDrawablePart.h │ │ │ ├── CUIWatchGear.h │ │ │ ├── CUIWatchGear.m │ │ │ ├── CUIWatchJewel.h │ │ │ ├── CUIWatchJewel.m │ │ │ ├── CUIWatchPart.h │ │ │ ├── CUIWatchPart.m │ │ │ ├── CUIWatchScrew.h │ │ │ └── CUIWatchScrew.m │ │ ├── dSYM/ │ │ │ ├── CUIdSYMBundle+UI.h │ │ │ ├── CUIdSYMBundle+UI.m │ │ │ ├── CUIdSYMBundle.h │ │ │ └── CUIdSYMBundle.m │ │ ├── default_themes.plist │ │ ├── en.lproj/ │ │ │ ├── CUIAboutBoxWindowController.xib │ │ │ ├── CUIBinaryImagesViewController.xib │ │ │ ├── CUICodeSigningInformationViewController.xib │ │ │ ├── CUICollectionViewRegisterItem.xib │ │ │ ├── CUICrashLogPresentationOutlineViewController.xib │ │ │ ├── CUICrashLogPresentationTextViewController.xib │ │ │ ├── CUICrashLogsListViewController.xib │ │ │ ├── CUICrashLogsSourceSmartEditorWindowController.xib │ │ │ ├── CUICrashLogsSourcesViewController.xib │ │ │ ├── CUIExportAccessoryViewController.xib │ │ │ ├── CUIInspectorExecutableViewController.xib │ │ │ ├── CUIInspectorGeneralViewController.xib │ │ │ ├── CUIInspectorProcessesViewController.xib │ │ │ ├── CUIInspectorUserViewController.xib │ │ │ ├── CUILineJumperWindowController.xib │ │ │ ├── CUIMainWindowController.xib │ │ │ ├── CUIPreferencePaneAdvancedViewController.xib │ │ │ ├── CUIPreferencePaneCrashreporterViewController.xib │ │ │ ├── CUIPreferencePaneFontscolorsViewController.xib │ │ │ ├── CUIPreferencePaneGeneralViewController.xib │ │ │ ├── CUIPreferencePanePresentationOutlineViewController.xib │ │ │ ├── CUIPreferencePanePresentationTextViewController.xib │ │ │ ├── CUIPreferencePanePresentationViewController.xib │ │ │ ├── CUIPreferencePaneSymbolicationViewController.xib │ │ │ ├── CUIPreferencesWindowController.xib │ │ │ ├── CUISymbolsFilesLibraryViewController.xib │ │ │ ├── CodeSigning.strings │ │ │ ├── InfoPlist.strings │ │ │ ├── Localizable.strings │ │ │ ├── MainMenu.xib │ │ │ ├── Predicates.strings │ │ │ └── RemoteCheck.strings │ │ ├── es.lproj/ │ │ │ ├── CUIAboutBoxWindowController.xib │ │ │ ├── CUIBinaryImagesViewController.xib │ │ │ ├── CUICodeSigningInformationViewController.xib │ │ │ ├── CUICollectionViewRegisterItem.xib │ │ │ ├── CUICrashLogPresentationOutlineViewController.xib │ │ │ ├── CUICrashLogPresentationTextViewController.xib │ │ │ ├── CUICrashLogsListViewController.xib │ │ │ ├── CUICrashLogsSourceSmartEditorWindowController.xib │ │ │ ├── CUICrashLogsSourcesViewController.xib │ │ │ ├── CUIExportAccessoryViewController.xib │ │ │ ├── CUIInspectorExecutableViewController.xib │ │ │ ├── CUIInspectorGeneralViewController.xib │ │ │ ├── CUIInspectorProcessesViewController.xib │ │ │ ├── CUIInspectorUserViewController.xib │ │ │ ├── CUILineJumperWindowController.xib │ │ │ ├── CUIMainWindowController.xib │ │ │ ├── CUIPreferencePaneAdvancedViewController.xib │ │ │ ├── CUIPreferencePaneCrashreporterViewController.xib │ │ │ ├── CUIPreferencePaneFontscolorsViewController.xib │ │ │ ├── CUIPreferencePaneGeneralViewController.xib │ │ │ ├── CUIPreferencePanePresentationOutlineViewController.xib │ │ │ ├── CUIPreferencePanePresentationTextViewController.xib │ │ │ ├── CUIPreferencePanePresentationViewController.xib │ │ │ ├── CUIPreferencePaneSymbolicationViewController.xib │ │ │ ├── CUIPreferencesWindowController.xib │ │ │ ├── CUISymbolsFilesLibraryViewController.xib │ │ │ ├── CodeSigning.strings │ │ │ ├── InfoPlist.strings │ │ │ ├── Localizable.strings │ │ │ ├── MainMenu.xib │ │ │ ├── Predicates.strings │ │ │ └── RemoteCheck.strings │ │ ├── fr.lproj/ │ │ │ ├── CUIAboutBoxWindowController.xib │ │ │ ├── CUIBinaryImagesViewController.xib │ │ │ ├── CUICodeSigningInformationViewController.xib │ │ │ ├── CUICollectionViewRegisterItem.xib │ │ │ ├── CUICrashLogPresentationOutlineViewController.xib │ │ │ ├── CUICrashLogPresentationTextViewController.xib │ │ │ ├── CUICrashLogsListViewController.xib │ │ │ ├── CUICrashLogsSourceSmartEditorWindowController.xib │ │ │ ├── CUICrashLogsSourcesViewController.xib │ │ │ ├── CUIExportAccessoryViewController.xib │ │ │ ├── CUIInspectorExecutableViewController.xib │ │ │ ├── CUIInspectorGeneralViewController.xib │ │ │ ├── CUIInspectorProcessesViewController.xib │ │ │ ├── CUIInspectorUserViewController.xib │ │ │ ├── CUILineJumperWindowController.xib │ │ │ ├── CUIMainWindowController.xib │ │ │ ├── CUIPreferencePaneAdvancedViewController.xib │ │ │ ├── CUIPreferencePaneCrashreporterViewController.xib │ │ │ ├── CUIPreferencePaneFontscolorsViewController.xib │ │ │ ├── CUIPreferencePaneGeneralViewController.xib │ │ │ ├── CUIPreferencePanePresentationOutlineViewController.xib │ │ │ ├── CUIPreferencePanePresentationTextViewController.xib │ │ │ ├── CUIPreferencePanePresentationViewController.xib │ │ │ ├── CUIPreferencePaneSymbolicationViewController.xib │ │ │ ├── CUIPreferencesWindowController.xib │ │ │ ├── CUISymbolsFilesLibraryViewController.xib │ │ │ ├── CodeSigning.strings │ │ │ ├── InfoPlist.strings │ │ │ ├── Localizable.strings │ │ │ ├── MainMenu.xib │ │ │ ├── Predicates.strings │ │ │ └── RemoteCheck.strings │ │ ├── he.lproj/ │ │ │ ├── CUIAboutBoxWindowController.xib │ │ │ ├── CUIBinaryImagesViewController.xib │ │ │ ├── CUICodeSigningInformationViewController.xib │ │ │ ├── CUICollectionViewRegisterItem.xib │ │ │ ├── CUICrashLogPresentationOutlineViewController.xib │ │ │ ├── CUICrashLogPresentationTextViewController.xib │ │ │ ├── CUICrashLogsListViewController.xib │ │ │ ├── CUICrashLogsSourceSmartEditorWindowController.xib │ │ │ ├── CUICrashLogsSourcesViewController.xib │ │ │ ├── CUIExportAccessoryViewController.xib │ │ │ ├── CUIInspectorExecutableViewController.xib │ │ │ ├── CUIInspectorGeneralViewController.xib │ │ │ ├── CUIInspectorProcessesViewController.xib │ │ │ ├── CUIInspectorUserViewController.xib │ │ │ ├── CUILineJumperWindowController.xib │ │ │ ├── CUIMainWindowController.xib │ │ │ ├── CUIPreferencePaneAdvancedViewController.xib │ │ │ ├── CUIPreferencePaneCrashreporterViewController.xib │ │ │ ├── CUIPreferencePaneFontscolorsViewController.xib │ │ │ ├── CUIPreferencePaneGeneralViewController.xib │ │ │ ├── CUIPreferencePanePresentationOutlineViewController.xib │ │ │ ├── CUIPreferencePanePresentationTextViewController.xib │ │ │ ├── CUIPreferencePanePresentationViewController.xib │ │ │ ├── CUIPreferencePaneSymbolicationViewController.xib │ │ │ ├── CUIPreferencesWindowController.xib │ │ │ ├── CUISymbolsFilesLibraryViewController.xib │ │ │ ├── CodeSigning.strings │ │ │ ├── InfoPlist.strings │ │ │ ├── Localizable.strings │ │ │ ├── MainMenu.xib │ │ │ ├── Predicates.strings │ │ │ └── RemoteCheck.strings │ │ ├── images/ │ │ │ ├── philo_stone.psd │ │ │ ├── recents.psd │ │ │ ├── recents@2x.psd │ │ │ └── symbolication@2x.psd │ │ ├── ips + Extensions/ │ │ │ ├── IPSImage+Offset.h │ │ │ └── IPSImage+Offset.m │ │ ├── ja.lproj/ │ │ │ ├── CUIAboutBoxWindowController.xib │ │ │ ├── CUIBinaryImagesViewController.xib │ │ │ ├── CUICodeSigningInformationViewController.xib │ │ │ ├── CUICollectionViewRegisterItem.xib │ │ │ ├── CUICrashLogPresentationOutlineViewController.xib │ │ │ ├── CUICrashLogPresentationTextViewController.xib │ │ │ ├── CUICrashLogsListViewController.xib │ │ │ ├── CUICrashLogsSourceSmartEditorWindowController.xib │ │ │ ├── CUICrashLogsSourcesViewController.xib │ │ │ ├── CUIExportAccessoryViewController.xib │ │ │ ├── CUIInspectorExecutableViewController.xib │ │ │ ├── CUIInspectorGeneralViewController.xib │ │ │ ├── CUIInspectorProcessesViewController.xib │ │ │ ├── CUIInspectorUserViewController.xib │ │ │ ├── CUILineJumperWindowController.xib │ │ │ ├── CUIMainWindowController.xib │ │ │ ├── CUIPreferencePaneAdvancedViewController.xib │ │ │ ├── CUIPreferencePaneCrashreporterViewController.xib │ │ │ ├── CUIPreferencePaneFontscolorsViewController.xib │ │ │ ├── CUIPreferencePaneGeneralViewController.xib │ │ │ ├── CUIPreferencePanePresentationOutlineViewController.xib │ │ │ ├── CUIPreferencePanePresentationTextViewController.xib │ │ │ ├── CUIPreferencePanePresentationViewController.xib │ │ │ ├── CUIPreferencePaneSymbolicationViewController.xib │ │ │ ├── CUIPreferencesWindowController.xib │ │ │ ├── CUISymbolsFilesLibraryViewController.xib │ │ │ ├── CodeSigning.strings │ │ │ ├── InfoPlist.strings │ │ │ ├── Localizable.strings │ │ │ ├── MainMenu.xib │ │ │ ├── Predicates.strings │ │ │ └── RemoteCheck.strings │ │ ├── main.m │ │ └── template.source │ └── app_unexpectedly.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata/ │ │ └── xcschemes/ │ │ └── app_unexpectedly.xcscheme │ └── xcuserdata/ │ └── stephane.xcuserdatad/ │ ├── xcdebugger/ │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes/ │ └── xcschememanagement.plist ├── build.sh ├── distribution/ │ ├── Documents/ │ │ └── ReadMe.rtf │ ├── Template/ │ │ └── Template_ro.dmg │ ├── Unexpectedly.pkgproj │ └── Version └── plugin_quicklook/ ├── crashreport/ │ ├── GeneratePreviewForURL.m │ ├── GenerateThumbnailForURL.m │ ├── Info.plist │ ├── NSUserDefaults+UNXQuickLookGenerator.h │ ├── NSUserDefaults+UNXQuickLookGenerator.m │ ├── QLCUIThemesProvider.h │ ├── QLCUIThemesProvider.m │ └── main.c └── crashreport.xcodeproj/ ├── project.pbxproj ├── project.xcworkspace/ │ └── xcshareddata/ │ └── IDEWorkspaceChecks.plist └── xcuserdata/ └── stephane.xcuserdatad/ └── xcschemes/ └── xcschememanagement.plist ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # General .DS_Store # Build distribution/build distribution/artifacts distribution/Template/Template_rw.dmg # Xcode project project.xcworkspace/xcuserdata/ *.xcodeproj/xcuserdata/ *.xcuserdata *.xcuserstate ================================================ FILE: .gitmodules ================================================ [submodule "submodules/ips2crash"] path = submodules/ips2crash url = https://github.com/packagesdev/ips2crash ================================================ FILE: Configs/CodeSigningConfigurationSettings.xcconfig ================================================ // Code Signing Settings // CODE_SIGN_IDENTITY = Developer ID Application: Your Identifity (SomeValue) ================================================ FILE: Configs/SharedConfigurationSettings.xcconfig ================================================ // Shared Configuration Settings for Unexpectedly Xcode Projects #include "CodeSigningConfigurationSettings.xcconfig" // Universal ARCHS = $(ARCHS_STANDARD_64_BIT) // Use Latest OS X SDK SDKROOT = macosx // Deployment Target MACOSX_DEPLOYMENT_TARGET = 10.13 MACOSX_DEPLOYMENT_TARGET[arch=arm64] = 11.0 // COPY_PHASE_STRIP[config=Debug] = NO COPY_PHASE_STRIP = YES // Codesigning OTHER_CODE_SIGN_FLAGS = --timestamp ================================================ FILE: LICENSE.txt ================================================ Copyright © 2021-2025, Stéphane Sudre. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. License for the third party code Included in this software: NoodleLineNumberView & NoodleLineNumberMarker Created by Paul Kim on 9/28/08. Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ## Synopsis Unexpectedly is a macOS utility to browse and inspect crash reports of Mac applications. ## Screenshot ![Alt text](http://s.sudre.free.fr/Software/Unexpectedly/images/about_top.png "Unexpectedly text mode") ## Motivation The macOS system utility Console.app is pretty limited and confusing when it comes to browsing crash reports. Minimum OS requirement is macOS 10.13 at this time. ## Development Environment - macOS 10.14 or later - Xcode 10.1 or later - Objective-C 2.x ## License Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## Attributions Unexpectedly uses an updated implementation of the Line View Test project Copyright (c) 2008 Noodlesoft, LLC. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Potentially Interesting Implementations In The Code - Code to access the segments and sections of a Mach-O file is available in the app_unexpectedly project/app_unexpectedly project/Mach-o directory. - Code to analyze DWARF files is available in the app_unexpectedly project/app_unexpectedly project/DWARF directory. Unexpectedly does not rely on LLVM. - A solution to deal with a NSTextView when it comes to vertical scrolling when a vertical ruleview is visible is available in the CUICrashLogTextView class. - How the project uses - forwardingTargetForSelector: , - respondsToSelector: to go downward in the responders chain might be interesting. - Code to implement a thick NSSplitView divider with subviews as in Xcode can be found in the CUICrashLogPresentationOutlineViewController class. ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSColor+LabelColor.h ================================================ /* Copyright (c) 2018, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSColor () + (NSColor *)labelColor; + (NSColor *)secondaryLabelColor; + (NSColor *)tertiaryLabelColor; + (NSColor *)quaternaryLabelColor; + (NSColor *)containerBorderColor; + (NSColor *)systemBlueColor; @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSColor+LabelColor.m ================================================ /* Copyright (c) 2018, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSColor+LabelColor.h" #import @interface NSColor (LabelColor_WB) + (NSColor *)WB_labelColor; + (NSColor *)WB_secondaryLabelColor; + (NSColor *)WB_tertiaryLabelColor; + (NSColor *)WB_quaternaryLabelColor; + (NSColor *)WB_containerBorderColor; + (NSColor *)WB_systemBlueColor; @end @implementation NSColor (LabelColor_WB) + (void)load { Class tClass = object_getClass(self); if ([self respondsToSelector:@selector(labelColor)]==NO) { Method origMethod = class_getClassMethod(tClass, @selector(WB_labelColor)); class_addMethod(tClass, @selector(labelColor), method_getImplementation(origMethod),method_getTypeEncoding(origMethod)); } if ([self respondsToSelector:@selector(secondaryLabelColor)]==NO) { Method origMethod = class_getClassMethod(tClass, @selector(WB_secondaryLabelColor)); class_addMethod(tClass, @selector(secondaryLabelColor), method_getImplementation(origMethod),method_getTypeEncoding(origMethod)); } if ([self respondsToSelector:@selector(tertiaryLabelColor)]==NO) { Method origMethod = class_getClassMethod(tClass, @selector(WB_tertiaryLabelColor)); class_addMethod(tClass, @selector(tertiaryLabelColor), method_getImplementation(origMethod),method_getTypeEncoding(origMethod)); } if ([self respondsToSelector:@selector(quaternaryLabelColor)]==NO) { Method origMethod = class_getClassMethod(tClass, @selector(WB_quaternaryLabelColor)); class_addMethod(tClass, @selector(quaternaryLabelColor), method_getImplementation(origMethod),method_getTypeEncoding(origMethod)); } if ([self respondsToSelector:@selector(containerBorderColor)]==NO) { Method origMethod = class_getClassMethod(tClass, @selector(WB_containerBorderColor)); class_addMethod(tClass, @selector(containerBorderColor), method_getImplementation(origMethod),method_getTypeEncoding(origMethod)); } if ([self respondsToSelector:@selector(systemBlueColor)]==NO) { Method origMethod = class_getClassMethod(tClass, @selector(WB_systemBlueColor)); class_addMethod(tClass, @selector(systemBlueColor), method_getImplementation(origMethod),method_getTypeEncoding(origMethod)); } } #pragma mark - + (NSColor *)WB_labelColor { return [NSColor colorWithDeviceWhite:0.0 alpha:0.85]; } + (NSColor *)WB_secondaryLabelColor { return [NSColor colorWithDeviceWhite:0.0 alpha:0.5]; } + (NSColor *)WB_tertiaryLabelColor { return [NSColor colorWithDeviceWhite:0.0 alpha:0.25]; } + (NSColor *)WB_quaternaryLabelColor { return [NSColor colorWithDeviceWhite:0.0 alpha:0.10]; } + (NSColor *)WB_containerBorderColor { if ([[NSColor class] respondsToSelector:@selector(tertiaryLabelColor)]==YES) return [[NSColor class] performSelector:@selector(tertiaryLabelColor) withObject:nil]; return [NSColor colorWithDeviceWhite:0.0 alpha:0.25]; } + (NSColor *)WB_systemBlueColor { return [NSColor colorWithDeviceRed:0.4 green:0.69 blue:0.94 alpha:1.0]; } @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSColor+String.h ================================================ /* Copyright (c) 2019, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSColor (String) + (NSColor *)colorFromString:(NSString *)inString; - (NSString *)stringValue; @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSColor+String.m ================================================ /* Copyright (c) 2019, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSColor+String.h" @implementation NSColor (String) + (NSColor *)colorFromString:(NSString *)inString { NSColor * tColor=nil; if (inString!=nil) { NSArray * tComponents=[inString componentsSeparatedByString:@"|"]; if (tComponents.count==3) { tColor=[NSColor colorWithCalibratedRed:[tComponents[0] floatValue] green:[tComponents[1] floatValue] blue:[tComponents[2] floatValue] alpha:1.0]; } } return tColor; } #pragma mark - - (NSString *)stringValue { NSColorSpace * tColorSpace = [NSColorSpace genericRGBColorSpace]; NSColor * tColor = [self colorUsingColorSpace:tColorSpace]; return([NSString stringWithFormat:@"%f|%f|%f",(float)[tColor redComponent],(float)[tColor greenComponent],(float)[tColor blueComponent]]); } @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSResponder+Appearance.h ================================================ /* Copyright (c) 2018, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #ifndef NSAppKitVersionNumber10_14 #define NSAppKitVersionNumber10_14 1641.10 #endif typedef NS_ENUM(NSUInteger, WB_AppearanceMode) { WB_AppearanceAqua=0, WB_AppearanceDarkAqua }; extern NSString * const WB_NSAppearanceNameAqua; extern NSString * const WB_NSAppearanceNameDarkAqua; @interface NSResponder (WB_Appearance) + (WB_AppearanceMode) WB_appearanceModeForAppearanceName:(NSString *)inAppearanceName; + (NSString *)WB_appearanceNameForAppearanceMode:(WB_AppearanceMode)inAppearanceMode; - (NSString *)WB_effectiveAppearanceName; - (BOOL)WB_isEffectiveAppearanceDarkAqua; @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSResponder+Appearance.m ================================================ /* Copyright (c) 2018, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSResponder+Appearance.h" NSString * const WB_NSAppearanceNameAqua=@"NSAppearanceNameAqua"; NSString * const WB_NSAppearanceNameDarkAqua=@"NSAppearanceNameDarkAqua"; @implementation NSResponder (Appearance_WB) + (WB_AppearanceMode)WB_appearanceModeForAppearanceName:(NSString *)inAppearanceName { if ([inAppearanceName isEqualToString:WB_NSAppearanceNameDarkAqua]==YES) return WB_AppearanceDarkAqua; return WB_AppearanceAqua; } + (NSString *)WB_appearanceNameForAppearanceMode:(WB_AppearanceMode)inAppearanceMode { switch(inAppearanceMode) { case WB_AppearanceAqua: return WB_NSAppearanceNameAqua; case WB_AppearanceDarkAqua: return WB_NSAppearanceNameDarkAqua; } return WB_NSAppearanceNameAqua; } #pragma mark - - (NSString *)WB_effectiveAppearanceName { if (NSAppKitVersionNumber @interface NSTableView (Selection_WB) @property (readonly, copy) NSIndexSet *WB_selectedOrClickedRowIndexes; @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSTableView+Selection.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSTableView+Selection.h" @implementation NSTableView (Selection_WB) - (NSIndexSet *)WB_selectedOrClickedRowIndexes { NSIndexSet * tSelectionIndexSet=self.selectedRowIndexes; NSInteger tClickedRow=self.clickedRow; if (tClickedRow!=-1 && [tSelectionIndexSet containsIndex:tClickedRow]==NO) tSelectionIndexSet=[NSIndexSet indexSetWithIndex:tClickedRow]; return tSelectionIndexSet; } @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSToolbar+Packages.h ================================================ /* Copyright (c) 2016, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSToolbar (Packages) - (NSToolbarItem *)PKG_toolBarItemWithIdentifier:(NSString *)inIdentifier; @end ================================================ FILE: app_unexpectedly/AppKit + Extensions/NSToolbar+Packages.m ================================================ /* Copyright (c) 2016, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSToolbar+Packages.h" @implementation NSToolbar (Packages) - (NSToolbarItem *)PKG_toolBarItemWithIdentifier:(NSString *)inIdentifier { if (inIdentifier==nil) return nil; for(NSToolbarItem * tItem in self.items) { if ([tItem.itemIdentifier isEqualToString:inIdentifier]==YES) return tItem; } return nil; } @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSArray+UniqueName.h ================================================ /* Copyright (c) 2017, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSArray (UniqueName) - (NSString *)uniqueNameWithBaseName:(NSString *)inBaseName usingNameExtractor:(NSString * (^)(id,NSUInteger))nameExtractor; - (NSString *)uniqueNameWithBaseName:(NSString *)inBaseName options:(NSStringCompareOptions)inOptions usingNameExtractor:(NSString * (^)(id,NSUInteger))nameExtractor; - (NSString *)uniqueNameWithBaseName:(NSString *)inBaseName format:(NSString *)inFormat options:(NSStringCompareOptions)inOptions usingNameExtractor:(NSString * (^)(id,NSUInteger))nameExtractor; @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSArray+UniqueName.m ================================================ /* Copyright (c) 2017, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSArray+UniqueName.h" #import "NSArray+WBExtensions.h" #define UNIQUENAME_ATTEMPTS_MAX 65535 @implementation NSArray (UniqueName) - (NSString *)uniqueNameWithBaseName:(NSString *)inBaseName usingNameExtractor:(NSString * (^)(id bObject,NSUInteger bIndex))nameExtractor { return [self uniqueNameWithBaseName:inBaseName options:NSCaseInsensitiveSearch usingNameExtractor:nameExtractor]; } - (NSString *)uniqueNameWithBaseName:(NSString *)inBaseName options:(NSStringCompareOptions)inOptions usingNameExtractor:(NSString * (^)(id bObject,NSUInteger bIndex))nameExtractor { return [self uniqueNameWithBaseName:inBaseName format: @"%@ %lu" options:inOptions usingNameExtractor:nameExtractor]; } - (NSString *)uniqueNameWithBaseName:(NSString *)inBaseName format:(NSString *)inFormat options:(NSStringCompareOptions)inOptions usingNameExtractor:(NSString * (^)(id bObject,NSUInteger bIndex))nameExtractor { if (inBaseName==nil || nameExtractor==nil) return nil; if (inFormat.length==0 || [inFormat rangeOfString:@"%@"].location==NSNotFound || [inFormat rangeOfString:@"%lu"].location==NSNotFound) return nil; NSArray * tNamesArray=[self WB_arrayByMappingObjectsUsingBlock:nameExtractor]; if (tNamesArray==nil) return nil; NSString * tFileName=inBaseName; NSUInteger tIndex=1; do { if ([tNamesArray indexOfObjectPassingTest:^BOOL(NSString * bName, NSUInteger bIndex, BOOL * bOutStop){ return ([bName compare:tFileName options:inOptions]==NSOrderedSame); }]==NSNotFound) return tFileName; tFileName=[NSString stringWithFormat:inFormat,inBaseName,(unsigned long)tIndex]; tIndex++; } while (tIndex @interface NSArray (WBExtensions) - (instancetype)WB_arrayByMappingObjectsUsingBlock:(id (^)(id bObject, NSUInteger bIndex))inBlock; - (instancetype)WB_arrayByMappingObjectsLenientlyUsingBlock:(id (^)(id bObject, NSUInteger bIndex))inBlock; - (instancetype)WB_filteredArrayUsingBlock:(BOOL (^)(id bObject, NSUInteger bIndex))inBlock; @end @interface NSMutableArray (WBExtensions) - (void)WB_mergeWithArray:(NSArray *)inArray; @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSArray+WBExtensions.m ================================================ /* Copyright (c) 2016, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSArray+WBExtensions.h" @implementation NSArray (WBExtensions) - (instancetype)WB_arrayByMappingObjectsUsingBlock:(id (^)(id bObject, NSUInteger bIndex))inBlock { if (inBlock==nil) return self; __block NSMutableArray * tMutableArray=[NSMutableArray array]; [self enumerateObjectsUsingBlock:^(id bOject,NSUInteger bIndex,BOOL * bOutStop){ id tObject=inBlock(bOject,bIndex); if (tObject==nil) { *bOutStop=YES; tMutableArray=nil; } else { [tMutableArray addObject:tObject]; } }]; if ([self isKindOfClass:NSMutableArray.class]==YES) return tMutableArray; return [tMutableArray copy]; } - (instancetype)WB_arrayByMappingObjectsLenientlyUsingBlock:(id (^)(id bObject, NSUInteger bIndex))inBlock { if (inBlock==nil) return self; NSMutableArray * tMutableArray=[NSMutableArray array]; [self enumerateObjectsUsingBlock:^(id bOject,NSUInteger bIndex,__attribute__((unused))BOOL * bOutStop){ id tObject=inBlock(bOject,bIndex); if (tObject!=nil) [tMutableArray addObject:tObject]; }]; if ([self isKindOfClass:NSMutableArray.class]==YES) return tMutableArray; return [tMutableArray copy]; } - (instancetype)WB_filteredArrayUsingBlock:(BOOL (^)(id bObject, NSUInteger bIndex))inBlock { if (inBlock==nil) return self; __block NSMutableArray * tMutableArray=[NSMutableArray array]; [self enumerateObjectsUsingBlock:^(id bOject,NSUInteger bIndex,__attribute__((unused))BOOL * bOutStop){ if (inBlock(bOject,bIndex)==YES) [tMutableArray addObject:bOject]; }]; if ([self isKindOfClass:NSMutableArray.class]==YES) return tMutableArray; return [tMutableArray copy]; } @end @implementation NSMutableArray (WBExtensions) - (void)WB_mergeWithArray:(NSArray *)inArray { if (inArray==nil) return; [inArray enumerateObjectsUsingBlock:^(id bObject,__attribute__((unused))NSUInteger bIndex,__attribute__((unused))BOOL * bOutStop){ if ([self containsObject:bObject]==NO) [self addObject:bObject]; }]; } @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSDictionary+MutableDeepCopy.h ================================================ /* Copyright (c) 2017, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSDictionary (WBMutableDeepCopy) - (id)mutableDeepCopy; @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSDictionary+MutableDeepCopy.m ================================================ /* Copyright (c) 2017, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSDictionary+MutableDeepCopy.h" @implementation NSDictionary (WBMutableDeepCopy) - (id)mutableDeepCopy { NSError * tError=nil; NSData * tData=[NSPropertyListSerialization dataWithPropertyList:self format:NSPropertyListXMLFormat_v1_0 options:0 error:&tError]; if (tData==nil) { if (tError!=nil) NSLog(@"[NSDictionary mutableDeepCopy] : %@",tError.localizedDescription); return nil; } NSPropertyListFormat tFormat; NSMutableDictionary * tMutableDictionary=(NSMutableDictionary *) [NSPropertyListSerialization propertyListWithData:tData options:NSPropertyListMutableContainersAndLeaves format:&tFormat error:&tError]; if (tMutableDictionary==nil) { if (tError!=nil) NSLog(@"[NSDictionary mutableDeepCopy] : %@",tError.localizedDescription); } return tMutableDictionary; } @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSDictionary+WBExtensions.h ================================================ #import @interface NSDictionary (WBExtensions) - (instancetype)WB_dictionaryByMappingKeysUsingBlock:(id (^)(id bKey,id bObject))inBlock; - (instancetype)WB_dictionaryByMappingObjectsUsingBlock:(id (^)(id bKey,id bObject))inBlock; - (instancetype)WB_dictionaryByMappingObjectsLenientlyUsingBlock:(id (^)(id bKey,id bObject))inBlock; - (instancetype)WB_filteredDictionaryUsingBlock:(BOOL (^)(id bKey,id bObject))inBlock; @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSDictionary+WBExtensions.m ================================================ #import "NSDictionary+WBExtensions.h" @implementation NSDictionary (WBExtensions) - (instancetype)WB_dictionaryByMappingKeysUsingBlock:(id (^)(id bKey,id bObject))inBlock { if (inBlock==nil) return self; __block NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; [self enumerateKeysAndObjectsUsingBlock:^(id bKey, id bObject, BOOL *bOutStop) { id tKey=inBlock(bKey,bObject); if (tKey==nil) { *bOutStop=YES; tMutableDictionary=nil; } else { tMutableDictionary[tKey]=bObject; } }]; if ([self isKindOfClass:NSMutableDictionary.class]==YES) return tMutableDictionary; return [tMutableDictionary copy]; } - (instancetype)WB_dictionaryByMappingObjectsUsingBlock:(id (^)(id bKey,id bObject))inBlock { if (inBlock==nil) return self; __block NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; [self enumerateKeysAndObjectsUsingBlock:^(id bKey, id bObject, BOOL *bOutStop) { id tObject=inBlock(bKey,bObject); if (tObject==nil) { *bOutStop=YES; tMutableDictionary=nil; } else { tMutableDictionary[bKey]=tObject; } }]; if ([self isKindOfClass:NSMutableDictionary.class]==YES) return tMutableDictionary; return [tMutableDictionary copy]; } - (instancetype)WB_dictionaryByMappingObjectsLenientlyUsingBlock:(id (^)(id bKey,id bObject))inBlock { if (inBlock==nil) return self; NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; [self enumerateKeysAndObjectsUsingBlock:^(id bKey, id bObject,__attribute__((unused))BOOL *bOutStop) { id tObject=inBlock(bKey,bObject); if (tObject!=nil) tMutableDictionary[bKey]=tObject; }]; if ([self isKindOfClass:NSMutableDictionary.class]==YES) return tMutableDictionary; return [tMutableDictionary copy]; } - (instancetype)WB_filteredDictionaryUsingBlock:(BOOL (^)(id bKey,id bObject))inBlock { if (inBlock==nil) return self; NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; [self enumerateKeysAndObjectsUsingBlock:^(id bKey, id bObject,__attribute__((unused))BOOL *bOutStop) { BOOL tDoNotFilter=inBlock(bKey,bObject); if (tDoNotFilter==YES) tMutableDictionary[bKey]=bObject; }]; if ([self isKindOfClass:NSMutableDictionary.class]==YES) return tMutableDictionary; return [tMutableDictionary copy]; } @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSIndexSet+Analysis.h ================================================ #import @interface NSIndexSet (Analysis) - (BOOL)WB_containsOnlyOneRange; @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSIndexSet+Analysis.m ================================================ #import "NSIndexSet+Analysis.h" @implementation NSIndexSet (Analysis) - (BOOL)WB_containsOnlyOneRange { NSUInteger tCount=self.count; if (tCount>0) { NSUInteger tFirstIndex=self.firstIndex; NSUInteger tLastIndex=self.lastIndex; return ((tLastIndex-tFirstIndex+1)==tCount); } return NO; } @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSSet+WBExtensions.h ================================================ /* Copyright (c) 2017, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSSet (WBExtensions) - (instancetype)WB_setByMappingObjectsUsingBlock:(id (^)(id bObject))inBlock; @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSSet+WBExtensions.m ================================================ /* Copyright (c) 2017, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSSet+WBExtensions.h" @implementation NSSet (WBExtensions) - (instancetype)WB_setByMappingObjectsUsingBlock:(id (^)(id bObject))inBlock { if (inBlock==nil) return self; __block NSMutableSet * tMutableSet=[NSMutableSet set]; [self enumerateObjectsUsingBlock:^(id bObject,BOOL * bOutStop){ id tObject=inBlock(bObject); if (tObject==nil) { *bOutStop=YES; tMutableSet=nil; } else { [tMutableSet addObject:tObject]; } }]; if ([self isKindOfClass:NSMutableSet.class]==YES) return tMutableSet; return [tMutableSet copy]; } @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSString+CPU.h ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSString (CPU) - (cpu_type_t)CUI_CPUType; @end ================================================ FILE: app_unexpectedly/Foundation + Extensions/NSString+CPU.m ================================================ /* Copyright (c) 2021-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSString+CPU.h" @implementation NSString (CPU) - (cpu_type_t)CUI_CPUType { static NSDictionary * sCPUFamiliesRegistry=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sCPUFamiliesRegistry=@{ @"X86-64":@(CPU_TYPE_X86_64), @"x86_64":@(CPU_TYPE_X86_64), @"ARM-64":@(CPU_TYPE_ARM64), @"arm64":@(CPU_TYPE_ARM64), }; }); NSNumber * tCPUFamily=sCPUFamiliesRegistry[self]; return (tCPUFamily!=nil) ? [tCPUFamily intValue] : CPU_TYPE_X86; } @end ================================================ FILE: app_unexpectedly/RSCore/LICENSE.txt ================================================ MIT License Copyright (c) 2002-2025 Brent Simmons Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: app_unexpectedly/RSCore/NSMenuItem+RSCore.h ================================================ // // NSMenuItem+RSCore.h // RSCore // // Created by Brent Simmons on 1/5/26. // #if TARGET_OS_MAC && !TARGET_OS_IPHONE @import AppKit; @interface NSMenuItem (RSCore) /// When YES, the menu item’s image will be shown (if it exists) despite icon disabling. /// Defaults to NO. @property (nonatomic, assign) BOOL rs_shouldShowImage; /// Disables icons in all menu items (except where `rs_shouldShowImage == YES`) /// and those that are likely toolbar item representations. /// /// Call +[NSMenuItem rs_disableIcons] early (from AppDelegate init is good). + (void)rs_disableIcons; @end #endif ================================================ FILE: app_unexpectedly/RSCore/NSMenuItem+RSCore.m ================================================ // // NSMenuItem+RSCore.m // RSCore // // Created by Brent Simmons on 1/7/26. // #if TARGET_OS_MAC && !TARGET_OS_IPHONE #import "NSMenuItem+RSCore.h" #import static void *kShouldShowImageKey = &kShouldShowImageKey; @implementation NSMenuItem (RSCore) + (void)rs_disableIcons { Method originalMethod = class_getInstanceMethod(self, @selector(image)); Method swizzledMethod = class_getInstanceMethod(self, @selector(rs_swizzledImage)); if (originalMethod && swizzledMethod) { method_exchangeImplementations(originalMethod, swizzledMethod); } } - (NSImage *)rs_swizzledImage { if (self.rs_shouldShowImage || [self rs_isToolbarItemRepresentation] || ![self rs_isMainMenuItem] || self.title.length < 1) { // Call the original getter (now swapped to rs_swizzledImage) return [self rs_swizzledImage]; } return nil; } - (BOOL)rs_isToolbarItemRepresentation { // Menu items not attached to any menu are likely toolbar button representations return self.menu == nil; } - (BOOL)rs_isMainMenuItem { // Return true if the parent menu is the main menu. // This allows images to show for (for instance) the traffic light menus // and for menu items in submenus such as Move & Resize and Full Screen Tile. return self.menu.supermenu == NSApplication.sharedApplication.mainMenu; } - (BOOL)rs_shouldShowImage { NSNumber *value = objc_getAssociatedObject(self, kShouldShowImageKey); return value.boolValue; } - (void)setRs_shouldShowImage:(BOOL)shouldShowImage { objc_setAssociatedObject(self, kShouldShowImageKey, @(shouldShowImage), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end #endif ================================================ FILE: app_unexpectedly/app_unexpectedly/AppDelegate.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface AppDelegate : NSObject @end ================================================ FILE: app_unexpectedly/app_unexpectedly/AppDelegate.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "AppDelegate.h" #import "CUIBinaryImage.h" #import "CUIMainWindowController.h" #import "CUICrashLogsSourcesManager.h" #import "CUICrashLogsSourceAll.h" #import "CUICrashLogsSourceFile.h" #import "CUICrashLogsSourcesSelection.h" #import "CUICrashLogsSelection.h" #import "CUICallStackBacktrace.h" #import "CUIApplicationPreferences.h" #import "CUIThemesManager.h" #import "CUIPreferencesWindowController.h" #import "CUIPreferencesWindowController+Convenience.h" #import "CUIRegistersWindowController.h" #import "CUIdSYMBundlesManager.h" #import "CUIAboutBoxWindowController.h" #import "CUICrashReporterDefaults.h" #import "CUICrashLogsOpenErrorRecord.h" #import "CUICrashLogsOpenErrorPanel.h" #import "WBRemoteVersionChecker.h" #import "NSMenuItem+RSCore.h" NSString * const CUIApplicationShowDebugMenuKey=@"ui.menu.debug.show"; NSString * const CUIApplicationShowDebugDidChangeNotification=@"CUIApplicationShowDebugDidChangeNotification"; @interface AppDelegate () { IBOutlet NSMenu * _themesMenu; IBOutlet NSMenuItem * _debugMenuBarItem; CUIMainWindowController * _mainWindowController; } - (IBAction)showAboutBox:(id)sender; - (IBAction)showPreferences:(id)sender; - (IBAction)editThemes:(id)sender; // Help Menu - (IBAction)showUserGuide:(id)sender; - (IBAction)sendFeedback:(id)sender; - (IBAction)showUnexpectedlyWebSite:(id)sender; // Notifications - (void)themesListDidChange:(NSNotification *)inNotification; - (void)showDebugMenuDidChange:(NSNotification *)inNotification; @end @implementation AppDelegate + (void)initialize { [[NSUserDefaults standardUserDefaults] registerDefaults:@{ CUIApplicationShowDebugMenuKey:@(NO), @"NSScrollViewShouldFlipRulerForRTL":@(NO) }]; [NSMenuItem rs_disableIcons]; } - (void)awakeFromNib { [self refreshThemesMenu]; NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; if ([tUserDefaults boolForKey:CUIApplicationShowDebugMenuKey]==YES) _debugMenuBarItem.hidden=NO; // Register for notifications NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(themesListDidChange:) name:CUIThemesManagerThemesListDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(showDebugMenuDidChange:) name:CUIApplicationShowDebugDidChangeNotification object:nil]; } #pragma mark - - (void)refreshThemesMenu { // Cleanup menu NSUInteger tMenuItemsCount=_themesMenu.numberOfItems; if (tMenuItemsCount>2) { for(NSUInteger tIndex=tMenuItemsCount-2;tIndex>0;tIndex--) { [_themesMenu removeItemAtIndex:tIndex-1]; } } // Populate menu CUIThemesManager * tThemesManager=[CUIThemesManager sharedManager]; NSArray * tThemes=[tThemesManager allThemes]; SEL selector=NSSelectorFromString(@"CUI_MENUACTION_switchTheme:"); [tThemes enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(CUITheme * bTheme, NSUInteger bIndex, BOOL * bOutStop) { NSMenuItem * tMenuItem=[[NSMenuItem alloc] initWithTitle:bTheme.name action:selector keyEquivalent:@""]; tMenuItem.representedObject=bTheme.UUID; [self->_themesMenu insertItem:tMenuItem atIndex:0]; }]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(switchCrashReporterDialogType:)) { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; inMenuItem.state=(tDefaults.dialogType==inMenuItem.tag) ? NSControlStateValueOn : NSControlStateValueOff; return YES; } if (tAction==@selector(switchCrashReporterNotificationMode:)) { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; inMenuItem.state=(tDefaults.notificationMode==inMenuItem.tag) ? NSControlStateValueOn : NSControlStateValueOff; return YES; } if (tAction==@selector(switchReportUncaughtException:)) { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; inMenuItem.state=(tDefaults.reportUncaughtExceptions==YES) ? NSControlStateValueOn : NSControlStateValueOff; } return YES; } // Application Menu - (IBAction)showAboutBox:(id)sender { [CUIAboutBoxWindowController showAbouxBox]; } - (IBAction)showPreferences:(id)sender { CUIPreferencesWindowController * tPreferencesWindowController=[CUIPreferencesWindowController sharedPreferencesWindowController]; [tPreferencesWindowController showWindow:nil]; } - (IBAction)editThemes:(id)sender { CUIPreferencesWindowController * tPreferencesWindowController=[CUIPreferencesWindowController sharedPreferencesWindowController]; [tPreferencesWindowController showFontsAndColorsPrefPane]; } // Windows Menu // Help Menu - (IBAction)showUserGuide:(id)sender { NSURL * tURL=[NSURL URLWithString:NSLocalizedString(@"http://s.sudre.free.fr/Software/documentation/Unexpectedly/index.html",@"No comment")]; if (tURL!=nil) [[NSWorkspace sharedWorkspace] openURL:tURL]; } - (IBAction)sendFeedback:(id)sender { NSDictionary * tDictionary=[NSBundle mainBundle].infoDictionary; NSString * tString=[NSString stringWithFormat:NSLocalizedString(@"mailto:dev.unexpectedly@gmail.com?subject=[Unexpectedly%%20%@]%%20Feedback%%20(build%%20%@)",@"No comment"),tDictionary[@"CFBundleShortVersionString"], tDictionary[@"CFBundleVersion"]]; NSURL * tURL=[NSURL URLWithString:tString]; if (tURL!=nil) [[NSWorkspace sharedWorkspace] openURL:tURL]; } - (IBAction)showUnexpectedlyWebSite:(id)sender { NSURL * tURL=[NSURL URLWithString:NSLocalizedString(@"http://s.sudre.free.fr/Software/Unexpectedly/about.html",@"No comment")]; if (tURL!=nil) [[NSWorkspace sharedWorkspace] openURL:tURL]; } // Debug Menu - (IBAction)switchCrashReporterDialogType:(NSMenuItem *)sender { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; tDefaults.dialogType=sender.tag; } - (IBAction)switchCrashReporterNotificationMode:(NSMenuItem *)sender { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; tDefaults.notificationMode=sender.tag; } - (IBAction)switchReportUncaughtException:(NSMenuItem *)sender { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; tDefaults.reportUncaughtExceptions=!(tDefaults.reportUncaughtExceptions); } #pragma mark - NSApplicationDelegate - (void)application:(NSApplication *)sender openFiles:(NSArray *)inFilePaths { NSMutableArray * tOpenErrorsArray=[NSMutableArray array]; for(NSString * tFilePath in inFilePaths) { BOOL tIsDirectory=NO; if ([[NSFileManager defaultManager] fileExistsAtPath:tFilePath isDirectory:&tIsDirectory]==NO) { continue; } if (tIsDirectory==NO) { CUICrashLogsSourcesManager * tSourcesManager=[CUICrashLogsSourcesManager sharedManager]; CUICrashLogsSourcesSelection * tSharedSourcesSelection=[CUICrashLogsSourcesSelection sharedSourcesSelection]; CUICrashLogsSourceAll * tSourcesAll=[CUICrashLogsSourceAll crashLogsSourceAll]; if ([tSourcesAll containsCrashLogForFileAtPath:tFilePath]==YES) { NSArray * tCrashLogSources=[tSourcesManager sourcesOfTypes:[NSSet setWithObjects:@(CUICrashLogsSourceTypeStandardDirectory),@(CUICrashLogsSourceTypeDirectory),@(CUICrashLogsSourceTypeFile),nil]]; for(CUICrashLogsSource * tSource in tCrashLogSources) { CUIRawCrashLog * tCrashLog=[tSource crashLogForFileAtPath:tFilePath]; if (tCrashLog!=nil) { tSharedSourcesSelection.sources=[NSSet setWithObject:tSource]; [[CUICrashLogsSelection sharedSelection] setSource:tSource crashLogs:@[tCrashLog]]; break; } } continue; } NSError * tError; CUICrashLogsSourceFile * tSource=[[CUICrashLogsSourceFile alloc] initWithContentsOfFileSystemItemAtPath:tFilePath error:&tError]; if (tSource==nil) { if (tError!=nil) { if ([tError.domain isEqualToString:IPSErrorDomain]==YES) { switch(tError.code) { case IPSUnsupportedBugTypeError: // Open file in Console.app if ([[NSWorkspace sharedWorkspace] openFile:tFilePath withApplication:@"/Applications/Utilities/Console.app"]==YES) { return; } break; } } } CUICrashLogsOpenErrorRecord * tRecord=[CUICrashLogsOpenErrorRecord new]; tRecord.sourceURL=[NSURL fileURLWithPath:tFilePath]; tRecord.openError=tError; [tOpenErrorsArray addObject:tRecord]; continue; } [tSourcesManager addSources:@[tSource]]; tSharedSourcesSelection.sources=[NSSet setWithObject:tSource]; [[CUICrashLogsSelection sharedSelection] setSource:tSource crashLogs:tSource.crashLogs]; } else { CUIdSYMBundle * tBundle=[[CUIdSYMBundle alloc] initWithPath:tFilePath]; if (tBundle.isDSYMBundle==NO) continue; [[CUIdSYMBundlesManager sharedManager] addBundle:tBundle]; } } if (tOpenErrorsArray.count>0) { CUICrashLogsOpenErrorPanel * tErrorPanel=[CUICrashLogsOpenErrorPanel crashLogsOpenErrorPanel]; tErrorPanel.errors=tOpenErrorsArray; [tErrorPanel runModal]; } [NSApp replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; } - (BOOL)application:(NSApplication *)sender openFile:(NSString *)inFilePath { BOOL tIsDirectory=NO; if ([[NSFileManager defaultManager] fileExistsAtPath:inFilePath isDirectory:&tIsDirectory]==NO) { return NO; } if (tIsDirectory==NO) { CUICrashLogsSourcesManager * tSourcesManager=[CUICrashLogsSourcesManager sharedManager]; CUICrashLogsSourcesSelection * tSharedSourcesSelection=[CUICrashLogsSourcesSelection sharedSourcesSelection]; CUICrashLogsSourceAll * tSourcesAll=[CUICrashLogsSourceAll crashLogsSourceAll]; if ([tSourcesAll containsCrashLogForFileAtPath:inFilePath]==YES) { NSArray * tCrashLogSources=[tSourcesManager sourcesOfTypes:[NSSet setWithObjects:@(CUICrashLogsSourceTypeStandardDirectory),@(CUICrashLogsSourceTypeDirectory),@(CUICrashLogsSourceTypeFile),nil]]; for(CUICrashLogsSource * tSource in tCrashLogSources) { CUIRawCrashLog * tCrashLog=[tSource crashLogForFileAtPath:inFilePath]; if (tCrashLog!=nil) { tSharedSourcesSelection.sources=[NSSet setWithObject:tSource]; [[CUICrashLogsSelection sharedSelection] setSource:tSource crashLogs:@[tCrashLog]]; break; } } return YES; } NSError * tError; CUICrashLogsSourceFile * tSource=[[CUICrashLogsSourceFile alloc] initWithContentsOfFileSystemItemAtPath:inFilePath error:&tError]; if (tSource==nil) { NSLog(@"Unable to create Source from file at \"%@\"",inFilePath); return NO; } [tSourcesManager addSources:@[tSource]]; tSharedSourcesSelection.sources=[NSSet setWithObject:tSource]; [[CUICrashLogsSelection sharedSelection] setSource:tSource crashLogs:tSource.crashLogs]; } else { CUIdSYMBundle * tBundle=[[CUIdSYMBundle alloc] initWithPath:inFilePath]; if (tBundle.isDSYMBundle==NO) return NO; [[CUIdSYMBundlesManager sharedManager] addBundle:tBundle]; } return YES; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [WBRemoteVersionChecker sharedChecker]; _mainWindowController=[CUIMainWindowController new]; //NSLog(@"%@",_mainWindowController.window.frameAutosaveName); [_mainWindowController showWindow:self]; } - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } #pragma mark - Notifications - (void)themesListDidChange:(NSNotification *)inNotification { [self refreshThemesMenu]; } - (void)showDebugMenuDidChange:(NSNotification *)inNotification { NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; _debugMenuBarItem.hidden=([tUserDefaults boolForKey:CUIApplicationShowDebugMenuKey]==NO); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAATextFieldCell.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIAATextFieldCell : NSTextFieldCell @property BOOL selected; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAATextFieldCell.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIAATextFieldCell.h" void CGContextSetFontSmoothingBackgroundColor(CGContextRef,CGColorRef); @implementation CUIAATextFieldCell - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { CGContextRef tContextRef=[NSGraphicsContext currentContext].CGContext; CGContextSetFontSmoothingBackgroundColor(tContextRef,self.backgroundColor.CGColor); CGContextSetShouldSmoothFonts(tContextRef,TRUE); CGContextSetAllowsFontSmoothing(tContextRef,TRUE); CGContextSetShouldSubpixelQuantizeFonts(tContextRef,TRUE); CGContextSetAllowsFontSubpixelQuantization(tContextRef,TRUE); [super drawInteriorWithFrame:cellFrame inView:controlView]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAboutBoxFooterView.h ================================================ /* Copyright (c) 2007-2016, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIAboutBoxFooterView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAboutBoxFooterView.m ================================================ /* Copyright (c) 2007-2018, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIAboutBoxFooterView.h" @implementation CUIAboutBoxFooterView - (void)drawRect:(NSRect)inRect { NSRect tRefreshRect=NSIntersectionRect(self.bounds, inRect); // Draw background BOOL tIsDarkMode=[self WB_isEffectiveAppearanceDarkAqua]; if (tIsDarkMode==NO) [[NSColor colorWithDeviceWhite:0.898 alpha:1.0] set]; else [[NSColor colorWithDeviceWhite:0.0 alpha:0.18] set]; NSRectFillUsingOperation(tRefreshRect,NSCompositingOperationSourceOver); // Draw top line if (tIsDarkMode==NO) [[NSColor colorWithDeviceWhite:0.698 alpha:1.0] set]; else [[NSColor colorWithDeviceWhite:0.42 alpha:0.35] set]; NSRect tLineRect; if (tIsDarkMode==NO) tLineRect=NSMakeRect(NSMinX(tRefreshRect),NSMaxY(tRefreshRect)-1.0,NSWidth(tRefreshRect),1.0); else tLineRect=NSMakeRect(NSMinX(tRefreshRect)+1.0,NSMaxY(tRefreshRect)-1.0,NSWidth(tRefreshRect)-3.0,1.0); NSRectFillUsingOperation(tLineRect,NSCompositingOperationSourceOver); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAboutBoxWindow.h ================================================ // // CUIAboutBoxWindow.h // Unexpectedly // // Created by stephane on 09/04/2021. // Copyright © 2021 Acme, Inc. All rights reserved. // #import extern NSString * const CUIOptionKeyStateDidChangeNotification; extern NSString * const CUIOptionKeyState; @interface CUIAboutBoxWindow : NSWindow @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAboutBoxWindow.m ================================================ // // CUIAboutBoxWindow.m // Unexpectedly // // Created by stephane on 09/04/2021. // Copyright © 2021 Acme, Inc. All rights reserved. // #import "CUIAboutBoxWindow.h" NSString * const CUIOptionKeyStateDidChangeNotification=@"CUIOptionKeyStateDidChangeNotification"; NSString * const CUIOptionKeyState=@"CUIOptionKeyState"; @interface CUIAboutBoxWindow () { BOOL _optionKeyDown; } @end @implementation CUIAboutBoxWindow - (void)becomeKeyWindow { NSEvent * tEvent=[NSApp currentEvent]; if (tEvent!=nil) { NSUInteger tModifierFlags=tEvent.modifierFlags; BOOL isDown=((tModifierFlags & NSEventModifierFlagOption) == NSEventModifierFlagOption); if (isDown!=_optionKeyDown) { _optionKeyDown=isDown; [NSNotificationCenter.defaultCenter postNotificationName:CUIOptionKeyStateDidChangeNotification object:self userInfo:@{CUIOptionKeyState:@(_optionKeyDown)}]; } } [super becomeKeyWindow]; } - (void)resignKeyWindow { if (_optionKeyDown==YES) { _optionKeyDown=NO; // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUIOptionKeyStateDidChangeNotification object:self userInfo:@{CUIOptionKeyState:@(_optionKeyDown)}]; } [super resignKeyWindow]; } - (void)flagsChanged:(NSEvent *)inEvent { if (inEvent==nil) return; NSUInteger tModifierFlags=inEvent.modifierFlags; BOOL isDown=((tModifierFlags & NSEventModifierFlagOption) == NSEventModifierFlagOption); if (isDown!=_optionKeyDown) { _optionKeyDown=isDown; // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUIOptionKeyStateDidChangeNotification object:self userInfo:@{CUIOptionKeyState:@(_optionKeyDown)}]; } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAboutBoxWindowController.h ================================================ // // CUIAboutBoxWindowController.h // Unexpectedly // // Created by stephane on 15/11/2020. // Copyright © 2020 Stephane Sudre All rights reserved. // #import @interface CUIAboutBoxWindowController : NSWindowController + (void)showAbouxBox; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIAboutBoxWindowController.m ================================================ // // CUIAboutBoxWindowController.m // Unexpectedly // // Created by stephane on 15/11/2020. // Copyright © 2020 Stephane Sudre. All rights reserved. // #import "CUIAboutBoxWindowController.h" #import "CUIAboutBoxWindow.h" #import "CUIApplicationIconView.h" @interface CUIAboutBoxWindowController () { IBOutlet CUIApplicationIconView * _applicationIconView; IBOutlet NSTextField * _versionLabel; } - (IBAction)showLicenseAgreement:(id)sender; - (IBAction)showAcknowledgments:(id)sender; // Notifications - (void)optionKeyStateDidChange:(NSNotification *)inNotification; @end @implementation CUIAboutBoxWindowController + (void)showAbouxBox { static dispatch_once_t onceToken; static CUIAboutBoxWindowController * sAbouxBoxWindowController=nil; dispatch_once(&onceToken, ^{ sAbouxBoxWindowController=[CUIAboutBoxWindowController new]; }); [sAbouxBoxWindowController showWindow:nil]; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSString *)windowNibName { return @"CUIAboutBoxWindowController"; } #pragma mark - - (void)windowDidLoad { NSDictionary * tDictionary=[NSBundle mainBundle].infoDictionary; _versionLabel.stringValue=[NSString stringWithFormat:NSLocalizedString(@"version %@ (%@)",@""),tDictionary[@"CFBundleShortVersionString"],tDictionary[@"CFBundleVersion"]]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(optionKeyStateDidChange:) name:CUIOptionKeyStateDidChangeNotification object:self.window]; [self.window center]; } #pragma mark - - (IBAction)showLicenseAgreement:(id)sender { NSString * tPath=[[NSBundle mainBundle] pathForResource:@"Unexpectedly_License" ofType:@"pdf"]; if (tPath==nil) { NSLog(@"[CUIAboutBoxWindowController showLicenseAgreement:] Missing License file"); return; } [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:tPath]]; } - (IBAction)showAcknowledgments:(id)sender { NSString * tPath=[[NSBundle mainBundle] pathForResource:@"Unexpectedly_Acknowledgements" ofType:@"pdf"]; if (tPath==nil) { NSLog(@"[CUIAboutBoxWindowController showAcknowledgments:] Missing Acknowledgements file"); return; } [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:tPath]]; } #pragma mark - Notifications - (void)optionKeyStateDidChange:(NSNotification *)inNotification { BOOL tPressed=[inNotification.userInfo[CUIOptionKeyState] boolValue]; _applicationIconView.renderingMode=(tPressed==YES) ? CUIWatchRenderingModeWireframe : CUIWatchRenderingModeFull; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationItemAttributes.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIApplicationItemAttributes : NSObject @property (readonly) NSURL * applicationURL; @property NSString * displayName; @property NSString * bundleIdentifier; @property NSImage * icon; @property NSString * version; @property (nonatomic,readonly) NSMenuItem * applicationMenuItem; @property BOOL showsVersion; @property BOOL duplicate; - (instancetype)initWithURL:(NSURL *)inApplicationURL; - (NSComparisonResult)compare:(CUIApplicationItemAttributes *)inOther; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationItemAttributes.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIApplicationItemAttributes.h" @implementation CUIApplicationItemAttributes - (instancetype)initWithURL:(NSURL *)inApplicationURL { if (inApplicationURL.isFileURL==NO) return nil; self=[super init]; if (self!=nil) { _applicationURL=inApplicationURL; _icon=[[NSWorkspace sharedWorkspace] iconForFile:inApplicationURL.path]; if (_icon!=nil) _icon.size=NSMakeSize(16.0f,16.0f); _displayName=[[NSFileManager defaultManager] displayNameAtPath:inApplicationURL.path]; // Get Version NSBundle * tBundle=[NSBundle bundleWithURL:inApplicationURL]; NSString * tVersion=@"1.0"; if (tBundle!=nil) { _bundleIdentifier=tBundle.bundleIdentifier; NSDictionary * tInfoDictionary; tInfoDictionary=[tBundle infoDictionary]; if (tInfoDictionary!=nil) { tVersion=[tInfoDictionary objectForKey:@"CFBundleShortVersionString"]; if (tVersion==nil) { tVersion=@"1.0"; } } } _version=tVersion; } return self; } #pragma mark - - (NSMenuItem *)applicationMenuItem { NSString * tTitle=(self.showsVersion==YES) ? [NSString stringWithFormat:@"%@ (%@)",self.displayName,self.version] : self.displayName; NSMenuItem * tMenuItem=[[NSMenuItem alloc] initWithTitle:tTitle action:nil keyEquivalent:@""]; tMenuItem.image=self.icon; tMenuItem.representedObject=self; return tMenuItem; } #pragma mark - - (NSComparisonResult)compare:(CUIApplicationItemAttributes *)inOther { NSComparisonResult tResult=NSOrderedSame; if ([self.bundleIdentifier isEqualToString:inOther.bundleIdentifier]==YES) { self.showsVersion=YES; inOther.showsVersion=YES; } else { tResult=[self.displayName caseInsensitiveCompare:inOther.displayName]; } if (tResult!=NSOrderedSame) return tResult; // Compare version tResult=[self.version caseInsensitiveCompare:inOther.version]; if (tResult==NSOrderedSame) { if ([self.applicationURL.path hasPrefix:@"/Volumes/"]==YES) self.duplicate=YES; else inOther.duplicate=YES; } return -tResult; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationPreferences+Themes.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIApplicationPreferences.h" @interface CUIApplicationPreferences (Themes) + (NSString *)groupIdentifierForPresentationMode:(CUIPresentationMode)inPresentationMode; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationPreferences+Themes.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIApplicationPreferences+Themes.h" @implementation CUIApplicationPreferences (Themes) + (NSString *)groupIdentifierForPresentationMode:(CUIPresentationMode)inPresentationMode { switch (inPresentationMode) { case CUIPresentationModeText: return @"Text"; case CUIPresentationModeOutline: return @"Outline"; default: break; } return nil; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationPreferences.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUITextModeDisplaySettings.h" #import "CUIOutlineModeDisplaySettings.h" typedef NS_ENUM(NSInteger, CUIPresentationMode) { CUIPresentationModeUnknown=-1, CUIPresentationModeText=0, CUIPresentationModeOutline, }; typedef NS_ENUM(NSUInteger, CUICrashLogsSortType) { CUICrashLogsSortDateDescending=0, CUICrashLogsSortProcessNameAscending }; @interface CUIApplicationPreferences : NSObject // General @property (nonatomic) CUIPresentationMode defaultPresentationMode; @property (nonatomic) BOOL showsRegistersWindowAutomaticallyAtLaunch; @property (nonatomic) NSURL * preferedSourceCodeEditorURL; // Text Mode @property (nonatomic) BOOL showsLineNumbers; @property (nonatomic) BOOL lineWrapping; @property (nonatomic) CUITextModeDisplaySettings * defaultTextModeDisplaySettings; // Outline Mode @property (nonatomic) CUIOutlineModeDisplaySettings * defaultOutlineModeDisplaySettings; // Fonts and Colors // Symbolication @property (nonatomic) BOOL symbolicateAutomatically; @property (nonatomic) BOOL searchForSymbolsFilesAutomatically; // Crash Logs List @property (nonatomic) CUICrashLogsSortType crashLogsSortType; @property (nonatomic) BOOL crashLogsShowFileNames; + (CUIApplicationPreferences *)sharedPreferences; + (NSURL *)defaultSourceCodeEditorURL; @end extern NSString * const CUIPreferencesTextModeShowsLineNumbersDidChangeNotification; extern NSString * const CUIPreferencesTextModeLineWrappingDidChangeNotification; extern NSString * const CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification; extern NSString * const CUIPreferencesCrashLogsSortTypeDidChangeNotification; extern NSString * const CUIPreferencesCrashLogsShowFileNamesDidChangeNotification; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationPreferences.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIApplicationPreferences.h" #import "NSDictionary+MutableDeepCopy.h" #import "NSColor+String.h" // General NSString * const CUIPreferencesGeneralDefaultPresentationModeKey=@"general.defaultPresentationMode"; NSString * const CUIPreferencesGeneralShowsRegistersWindowAtLaunchKey=@"general.registers-window.showsAtLaunch"; NSString * const CUIPreferencesGeneralPreferedSourceCodeEditorPathKey=@"general.preferedSourceCodeEditor.path"; // Text Mode NSString * const CUIPreferencesTextModeDefaultDisplaySettings=@"textmode.displaySettings.defaults"; NSString * const CUIPreferencesTextModeShowsLineNumbersKey=@"textmode.showsLineNumbers"; NSString * const CUIPreferencesTextModeLineWrappingKey=@"textmode.lineWrapping"; extern NSString * const CUITextModeDisplaySettingsVisibleSectionKey; extern NSString * const CUITextModeDisplaySettingsVisibleStackFrameComponentsKey; // Outline Mode NSString * const CUIPreferencesOutlineModeDefaultDisplaySettings=@"outlinemode.displaySettings.defaults"; extern NSString * const CUIOutlineModeDisplaySettingsShowOnlyCrashedThreadKey; extern NSString * const CUIOutlineModeDisplaySettingsVisibleStackFrameComponentsKey; // Fonts & Colors // Symbolication NSString * const CUIPreferencesSymbolicationSearchSymbolsFilesKey=@"symbolication.searchForSymbolsFiles"; NSString * const CUIPreferencesSymbolicationSymbolicateAutomaticallyKey=@"symbolication.symbolicateAutomatically"; // Crash Logs List NSString * const CUIPreferencesCrashLogsShowFileNamesKey=@"showFileNames"; NSString * const CUIPreferencesCrashLogsSortTypeKey=@"crashLogs.list.sort"; // Notifications NSString * const CUIPreferencesTextModeShowsLineNumbersDidChangeNotification=@"CUIPreferencesTextModeShowsLineNumbersDidChangeNotification"; NSString * const CUIPreferencesTextModeLineWrappingDidChangeNotification=@"CUIPreferencesTextModeLineWrappingDidChangeNotification"; NSString * const CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification=@"CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification"; NSString * const CUIPreferencesCrashLogsSortTypeDidChangeNotification=@"CUIPreferencesCrashLogsSortTypeDidChangeNotification"; NSString * const CUIPreferencesCrashLogsShowFileNamesDidChangeNotification=@"CUIPreferencesCrashLogsShowFileNamesDidChangeNotification"; @interface CUIApplicationPreferences () { NSUserDefaults * _defaults; } @end @implementation CUIApplicationPreferences + (CUIApplicationPreferences *)sharedPreferences { static dispatch_once_t onceToken; static CUIApplicationPreferences * sPreferences=nil; dispatch_once(&onceToken, ^{ sPreferences=[CUIApplicationPreferences new]; }); return sPreferences; } + (NSURL *)defaultSourceCodeEditorURL { return (__bridge_transfer NSURL *)LSCopyDefaultApplicationURLForContentType(CFSTR("public.c-source"),kLSRolesEditor,NULL); } - (instancetype)init { self=[super init]; if (self!=nil) { _defaults=[NSUserDefaults standardUserDefaults]; [_defaults registerDefaults:@{ // General CUIPreferencesGeneralDefaultPresentationModeKey:@(CUIPresentationModeText), CUIPreferencesGeneralShowsRegistersWindowAtLaunchKey:@(NO), CUIPreferencesSymbolicationSearchSymbolsFilesKey:@(YES), CUIPreferencesSymbolicationSymbolicateAutomaticallyKey:@(YES), // Text Mode CUIPreferencesTextModeShowsLineNumbersKey:@(NO), CUIPreferencesTextModeLineWrappingKey:@(YES), CUIPreferencesTextModeDefaultDisplaySettings:@{ CUITextModeDisplaySettingsVisibleSectionKey:@(CUIDocumentAllSections), CUITextModeDisplaySettingsVisibleStackFrameComponentsKey:@(CUIStackFrameAllComponents) }, // Outline Mode CUIPreferencesOutlineModeDefaultDisplaySettings:@{ CUIOutlineModeDisplaySettingsShowOnlyCrashedThreadKey:@(NO), CUIOutlineModeDisplaySettingsVisibleStackFrameComponentsKey:@(CUIStackFrameByteOffsetComponent) }, // Fonts & Colors // Crash Logs CUIPreferencesCrashLogsSortTypeKey:@(CUICrashLogsSortDateDescending), CUIPreferencesCrashLogsSortTypeKey:@(NO) }]; // General _defaultPresentationMode=[_defaults integerForKey:CUIPreferencesGeneralDefaultPresentationModeKey]; _showsRegistersWindowAutomaticallyAtLaunch=[_defaults boolForKey:CUIPreferencesGeneralShowsRegistersWindowAtLaunchKey]; _searchForSymbolsFilesAutomatically=[_defaults boolForKey:CUIPreferencesSymbolicationSearchSymbolsFilesKey]; NSString * tPath=[_defaults stringForKey:CUIPreferencesGeneralPreferedSourceCodeEditorPathKey]; if (tPath==nil || [[NSFileManager defaultManager] fileExistsAtPath:tPath]==NO) { _preferedSourceCodeEditorURL=[CUIApplicationPreferences defaultSourceCodeEditorURL]; } else { _preferedSourceCodeEditorURL=[NSURL fileURLWithPath:tPath]; } _symbolicateAutomatically=[_defaults integerForKey:CUIPreferencesSymbolicationSymbolicateAutomaticallyKey]; // Text Mode _showsLineNumbers=[_defaults boolForKey:CUIPreferencesTextModeShowsLineNumbersKey]; _lineWrapping=[_defaults boolForKey:CUIPreferencesTextModeLineWrappingKey]; _defaultTextModeDisplaySettings=[[CUITextModeDisplaySettings alloc] initWithRepresentation:[_defaults objectForKey:CUIPreferencesTextModeDefaultDisplaySettings]]; // Outline Mode _defaultOutlineModeDisplaySettings=[[CUIOutlineModeDisplaySettings alloc] initWithRepresentation:[_defaults objectForKey:CUIPreferencesOutlineModeDefaultDisplaySettings]]; // Fonts and Colors // Crash Logs _crashLogsSortType=[_defaults integerForKey:CUIPreferencesCrashLogsSortTypeKey]; _crashLogsShowFileNames=[_defaults boolForKey:CUIPreferencesCrashLogsShowFileNamesKey]; } return self; } #pragma mark - - (void)setDefaultPresentationMode:(CUIPresentationMode)inMode { _defaultPresentationMode=inMode; [_defaults setInteger:inMode forKey:CUIPreferencesGeneralDefaultPresentationModeKey]; } - (void)setShowsRegistersWindowAutomaticallyAtLaunch:(BOOL)inShowsRegistersWindowAutomaticallyAtLaunch { _showsRegistersWindowAutomaticallyAtLaunch=inShowsRegistersWindowAutomaticallyAtLaunch; [_defaults setBool:inShowsRegistersWindowAutomaticallyAtLaunch forKey:CUIPreferencesGeneralShowsRegistersWindowAtLaunchKey]; } - (void)setSearchForSymbolsFilesAutomatically:(BOOL)inSearchForSymbolsFilesAutomatically { _searchForSymbolsFilesAutomatically=inSearchForSymbolsFilesAutomatically; [_defaults setBool:inSearchForSymbolsFilesAutomatically forKey:CUIPreferencesSymbolicationSearchSymbolsFilesKey]; } - (void)setSymbolicateAutomatically:(BOOL)inSymbolicateAutomatically { _symbolicateAutomatically=inSymbolicateAutomatically; [_defaults setBool:inSymbolicateAutomatically forKey:CUIPreferencesSymbolicationSymbolicateAutomaticallyKey]; [NSNotificationCenter.defaultCenter postNotificationName:CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification object:nil]; } - (void)setPreferedSourceCodeEditorURL:(NSURL *)inURL { if (inURL.isFileURL==NO) return; _preferedSourceCodeEditorURL=inURL; NSString * tPath=inURL.path; [_defaults setObject:tPath forKey:CUIPreferencesGeneralPreferedSourceCodeEditorPathKey]; } - (void)setShowsLineNumbers:(BOOL)inShowsLineNumber { _showsLineNumbers=inShowsLineNumber; [_defaults setBool:inShowsLineNumber forKey:CUIPreferencesTextModeShowsLineNumbersKey]; [NSNotificationCenter.defaultCenter postNotificationName:CUIPreferencesTextModeShowsLineNumbersDidChangeNotification object:nil]; } - (void)setLineWrapping:(BOOL)inLineWrapping { _lineWrapping=inLineWrapping; [_defaults setBool:inLineWrapping forKey:CUIPreferencesTextModeLineWrappingKey]; [NSNotificationCenter.defaultCenter postNotificationName:CUIPreferencesTextModeLineWrappingDidChangeNotification object:nil]; } - (void)setDefaultTextModeDisplaySettings:(CUITextModeDisplaySettings *)inDisplaySettings { _defaultTextModeDisplaySettings=[inDisplaySettings copy]; [_defaults setObject:[_defaultTextModeDisplaySettings representation] forKey:CUIPreferencesTextModeDefaultDisplaySettings]; } - (void)setDefaultOutlineModeDisplaySettings:(CUIOutlineModeDisplaySettings *)inDisplaySettings { _defaultOutlineModeDisplaySettings=[inDisplaySettings copy]; [_defaults setObject:[_defaultOutlineModeDisplaySettings representation] forKey:CUIPreferencesOutlineModeDefaultDisplaySettings]; } #pragma mark - - (void)setCrashLogsSortType:(CUICrashLogsSortType)inCrashLogsSortType { if (_crashLogsSortType==inCrashLogsSortType) return; _crashLogsSortType=inCrashLogsSortType; [_defaults setObject:@(_crashLogsSortType) forKey:CUIPreferencesCrashLogsSortTypeKey]; [NSNotificationCenter.defaultCenter postNotificationName:CUIPreferencesCrashLogsSortTypeDidChangeNotification object:nil]; } - (void)setCrashLogsShowFileNames:(BOOL)inCrashLogsShowFileNames { if (_crashLogsShowFileNames==inCrashLogsShowFileNames) return; _crashLogsShowFileNames=inCrashLogsShowFileNames; [_defaults setObject:@(_crashLogsShowFileNames) forKey:CUIPreferencesCrashLogsShowFileNamesKey]; [NSNotificationCenter.defaultCenter postNotificationName:CUIPreferencesCrashLogsShowFileNamesDidChangeNotification object:nil]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationSpecificBacktraceRowView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUIApplicationSpecificBacktraceRowViewIdentifier; @interface CUIApplicationSpecificBacktraceRowView : NSTableRowView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIApplicationSpecificBacktraceRowView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIApplicationSpecificBacktraceRowView.h" NSString * const CUIApplicationSpecificBacktraceRowViewIdentifier=@"CUIApplicationSpecificBacktraceRowViewIdentifier"; @implementation CUIApplicationSpecificBacktraceRowView - (void)drawRect:(NSRect)inRect { if (self.isSelected==YES) { [super drawRect:inRect]; return; } NSRect tBounds=self.bounds; BOOL tIsDark=[self WB_isEffectiveAppearanceDarkAqua]; if (tIsDark==NO) { [[NSColor colorWithCalibratedRed:1.0 green:233.0/255.0 blue:203.0/255.0 alpha:1.0] set]; } else { [[NSColor colorWithCalibratedRed:119.0/255.0 green:100.0/255.0 blue:43.0/255.0 alpha:1.0] set]; } NSRectFill(tBounds); if (tIsDark==NO) { [[NSColor colorWithCalibratedRed:1.0 green:184.0/255.0 blue:115.0/255.0 alpha:1.0] set]; } else { [[NSColor colorWithCalibratedRed:106.0/255.0 green:88.0/255.0 blue:29.0/255.0 alpha:1.0] set]; } [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMinY(tBounds)+0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMinY(tBounds)+0.5)]; [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMaxY(tBounds)-0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMaxY(tBounds)-0.5)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIBinaryImage.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "IPSImage.h" @interface CUIAddressesRange : NSObject @property NSUInteger loadAddress; @property NSUInteger length; @property (nonatomic,readonly) NSUInteger max; - (NSString *)stringValue; - (NSComparisonResult)compare:(CUIAddressesRange *)inOtherAddressesRange; @end @interface CUIBinaryImage : NSObject @property (readonly,getter=isUserCode) BOOL userCode; @property (readonly,copy) NSString * identifier; @property (readonly) cpu_type_t architecture; // Future (iOS only) @property (readonly,copy) NSString * version; // macOS only @property (readonly,copy) NSString * buildNumber; // macOS only @property (readonly,copy) NSString * UUID; // can be nil @property (readonly,copy) NSString * path; @property (readonly) CUIAddressesRange * addressesRange; @property (nonatomic,readonly) NSUInteger binaryImageOffset; - (instancetype)initWithString:(NSString *)inString reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError; - (instancetype)initWithImage:(IPSImage *)inImage error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIBinaryImage.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIBinaryImage.h" #import "NSString+CPU.h" #import "IPSImage+UserCode.h" @interface CUIAddressesRange () + (CUIAddressesRange *)addressesRangeWithLocation:(NSUInteger)inLocation length:(NSUInteger)inLength; - (instancetype)initWithLocation:(NSUInteger)inLocation length:(NSUInteger)inLength; @end @implementation CUIAddressesRange + (CUIAddressesRange *)addressesRangeWithLocation:(NSUInteger)inLocation length:(NSUInteger)inLength { return [[CUIAddressesRange alloc] initWithLocation:inLocation length:inLength]; } - (instancetype)initWithLocation:(NSUInteger)inLocation length:(NSUInteger)inLength { self=[super init]; if (self!=nil) { _loadAddress=inLocation; _length=inLength; } return self; } #pragma mark - - (NSUInteger)max { return self.loadAddress+self.length; } #pragma mark - - (NSString *)stringValue { return [NSString stringWithFormat:@"0x%012lx - 0x%012lx",self.loadAddress,self.max]; } #pragma mark - - (NSComparisonResult)compare:(CUIAddressesRange *)inOtherAddressesRange { if (inOtherAddressesRange==nil) return NSOrderedDescending; if (self.loadAddress>inOtherAddressesRange.loadAddress) return NSOrderedDescending; if (self.loadAddressinOtherAddressesRange.length) return NSOrderedDescending; if (self.length /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate @implementation CUIBinaryImage - (instancetype)initWithString:(NSString *)inString reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError { if ([inString isKindOfClass:NSString.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { NSCharacterSet * tWhitespaceCharacterSet=[NSCharacterSet whitespaceCharacterSet]; NSScanner * tScanner=[NSScanner scannerWithString:inString]; tScanner.charactersToBeSkipped=tWhitespaceCharacterSet; unsigned long long tAddressRangeStart=0; if ([tScanner scanHexLongLong:&tAddressRangeStart]==NO) return nil; if ([tScanner scanUpToString:@"0" intoString:NULL]==NO) return nil; unsigned long long tAddressRangeEnd=0; if ([tScanner scanHexLongLong:&tAddressRangeEnd]==NO) return nil; _addressesRange=[CUIAddressesRange addressesRangeWithLocation:tAddressRangeStart length:tAddressRangeEnd-tAddressRangeStart+1]; NSString * tString; NSString * tOriginalString; BOOL tIsMissingVersion=NO; NSUInteger tSavedScannerScanLocation=tScanner.scanLocation; if ([tScanner scanUpToString:@"(" intoString:&tOriginalString]==NO) { return nil; } else { // Maybe only the version is missing if (tScanner.scanLocation==inString.length) { tScanner.scanLocation=tSavedScannerScanLocation; if ([tScanner scanUpToString:@"<" intoString:&tOriginalString]==NO) return nil; tIsMissingVersion=YES; } } if (inReportVersion==6) { // Remove the version NSUInteger tLength=tOriginalString.length; NSRange tRange=[tOriginalString rangeOfCharacterFromSet:tWhitespaceCharacterSet options:NSBackwardsSearch range:NSMakeRange(0,tLength-1)]; if (tRange.location==NSNotFound) { NSLog(@"Unable to find version for binary image"); return nil; } tString=[tOriginalString substringToIndex:tRange.location]; } else { tString=tOriginalString; } if ([tString hasPrefix:@"+"]==YES && tString.length>1) // Cheap way to find that a binary image is user code. { _userCode=YES; tString=[tString substringFromIndex:1]; } _identifier=[[tString stringByTrimmingCharactersInSet:tWhitespaceCharacterSet] copy]; // Version if (tScanner.scanLocation>=inString.length) return nil; if (tIsMissingVersion==NO) { if (inReportVersion==6) { NSUInteger tLength=tOriginalString.length; NSRange tRange=[tOriginalString rangeOfCharacterFromSet:tWhitespaceCharacterSet options:NSBackwardsSearch range:NSMakeRange(0,tLength-1)]; _version=[[tOriginalString substringFromIndex:tRange.location] stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; tScanner.scanLocation+=1; if ([tScanner scanUpToString:@")" intoString:&tString]==NO) return nil; _buildNumber=[tString stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; } else { tScanner.scanLocation+=1; if ([tScanner scanUpToString:@")" intoString:&tString]==NO) return nil; NSArray * tVersions=[tString componentsSeparatedByString:@" - "]; switch(tVersions.count) { case 2: _buildNumber=[tVersions[1] stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; case 1: _version=[tVersions.firstObject stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; break; } } tScanner.scanLocation+=2; } else { _version=@"???"; _buildNumber=@"???"; } // UUID if ([inString characterAtIndex:tScanner.scanLocation]=='<') { if ([tScanner scanUpToString:@">" intoString:&tString]==NO) return nil; _UUID=[tString substringFromIndex:1]; } else { tScanner.scanLocation-=2; } if ([tScanner scanUpToString:@"/" intoString:NULL]==NO) return nil; _path=[[inString substringFromIndex:tScanner.scanLocation] stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; // User Code _userCode = (_userCode == YES) ? YES : [self _isUserCode]; } return self; } - (instancetype)initWithImage:(IPSImage *)inImage error:(NSError **)outError { if ([inImage isKindOfClass:IPSImage.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _userCode=inImage.isUserCode; _identifier=[((inImage.bundleIdentifier!=nil) ? inImage.bundleIdentifier : inImage.name) copy]; _architecture=[inImage.architecture CUI_CPUType]; _version=[inImage.bundleShortVersionString copy]; _buildNumber=[inImage.bundleVersion copy]; _UUID=[inImage.UUID.UUIDString copy]; _path=[inImage.path copy]; _addressesRange=[CUIAddressesRange new]; _addressesRange.loadAddress=inImage.loadAddress; _addressesRange.length=inImage.size; } return self; } #pragma mark - - (NSUInteger)binaryImageOffset { NSUInteger tLoadAddress=self.addressesRange.loadAddress; if (tLoadAddress>0x7fff00000000) // Won't happen with ARM-64. return tLoadAddress; if (tLoadAddress>=0x100000000) return (tLoadAddress-0x100000000); return tLoadAddress; // 32-bit } - (BOOL)_isUserCode { NSString * tIdentifier=self.identifier; if (tIdentifier!=nil) { if ([tIdentifier hasPrefix:@"com.apple."]==YES) return NO; } NSString * tPath=self.path; if (tPath!=nil) { if ([tPath hasPrefix:@"/System/"]==YES) return NO; if ([tPath hasPrefix:@"/usr/"]==YES) { if ([tPath hasPrefix:@"/usr/bin"]==YES) return NO; if ([tPath hasPrefix:@"/usr/sbin"]==YES) return NO; if ([tPath hasPrefix:@"/usr/lib"]==YES) return NO; if ([tPath hasPrefix:@"/usr/libexec"]==YES) return NO; if ([tPath hasPrefix:@"/usr/share"]==YES) return NO; } if ([tPath hasPrefix:@"/bin/"]==YES) return NO; if ([tPath hasPrefix:@"/sbin/"]==YES) return NO; if ([tPath hasPrefix:@"/Library/Apple"]==YES) return NO; } return YES; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIBinaryImageUtility.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUIBinaryImageGroupAppKitUIKit; extern NSString * const CUIBinaryImageGroupAudioSpeech; extern NSString * const CUIBinaryImageGroupDatabaseStorage; extern NSString * const CUIBinaryImageGroupFoundation; extern NSString * const CUIBinaryImageGroupGenericUncategorized; extern NSString * const CUIBinaryImageGroupGraphics; extern NSString * const CUIBinaryImageGroupLanguages; extern NSString * const CUIBinaryImageGroupNetworkIO; extern NSString * const CUIBinaryImageGroupOtherFrameworks; extern NSString * const CUIBinaryImageGroupSecurity; extern NSString * const CUIBinaryImageGroupSystem; extern NSString * const CUIBinaryImageGroupUserCode; extern NSString * const CUIBinaryImageGroupWebInternet; @interface CUIBinaryImageUtility : NSObject + (NSString *)binaryImageGroupForIdentifier:(NSString *)inIdentifier; + (NSImage *)iconForBinaryImageGroup:(NSString *)inBinaryImageGroup; + (NSColor *)colorForBinaryImageGroup:(NSString *)inBinaryImageGroup; + (NSImage *)iconForIdentifier:(NSString *)inIdentifier; + (NSImage *)iconForPath:(NSString *)inPath; + (NSColor *)colorForUserCode; + (NSColor *)colorForIdentifier:(NSString *)inIdentifier; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIBinaryImageUtility.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIBinaryImageUtility.h" NSString * const CUIBinaryImageGroupAppKitUIKit=@"AppKit/UIKit"; NSString * const CUIBinaryImageGroupAudioSpeech=@"Audio/Speech"; NSString * const CUIBinaryImageGroupDatabaseStorage=@"Database/Storage"; NSString * const CUIBinaryImageGroupFoundation=@"Foundation"; NSString * const CUIBinaryImageGroupGenericUncategorized=@"Generic/Uncategorized"; NSString * const CUIBinaryImageGroupGraphics=@"Graphics"; NSString * const CUIBinaryImageGroupLanguages=@"Languages"; NSString * const CUIBinaryImageGroupNetworkIO=@"Network or I/O"; NSString * const CUIBinaryImageGroupOtherFrameworks=@"Other frameworks"; NSString * const CUIBinaryImageGroupSecurity=@"Security"; NSString * const CUIBinaryImageGroupSystem=@"System"; NSString * const CUIBinaryImageGroupUserCode=@"User Code"; NSString * const CUIBinaryImageGroupWebInternet=@"Web/Internet"; @implementation CUIBinaryImageUtility + (NSString *)binaryImageGroupForIdentifier:(NSString *)inIdentifier { if (inIdentifier==nil) return CUIBinaryImageGroupGenericUncategorized; static NSDictionary * sGroupRegistry=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sGroupRegistry=@{ // Application UI @"libswiftAppKit.dylib":CUIBinaryImageGroupAppKitUIKit, @"com.apple.AppKit":CUIBinaryImageGroupAppKitUIKit, @"com.apple.UIKit":CUIBinaryImageGroupAppKitUIKit, // Audio Speech @"libswiftCoreAudio.dylib":CUIBinaryImageGroupAudioSpeech, @"com.apple.audio.CoreAudio":CUIBinaryImageGroupAudioSpeech, @"com.apple.audio.AppleHDAHALPlugIn":CUIBinaryImageGroupAudioSpeech, @"com.apple.audio.AVFAudio":CUIBinaryImageGroupAudioSpeech, @"com.apple.audio.toolbox.AudioToolbox":CUIBinaryImageGroupAudioSpeech, @"com.apple.audio.units.AudioUnit":CUIBinaryImageGroupAudioSpeech, @"com.apple.speech.recognition.framework":CUIBinaryImageGroupAudioSpeech, @"com.apple.speech.synthesis.framework":CUIBinaryImageGroupAudioSpeech, @"com.apple.SpeechRecognitionCore":CUIBinaryImageGroupAudioSpeech, // Database @"libswiftCoreData.dylib":CUIBinaryImageGroupDatabaseStorage, @"com.apple.CoreData":CUIBinaryImageGroupDatabaseStorage, @"libsqlite3.dylib":CUIBinaryImageGroupDatabaseStorage, // Foundation @"libswiftCoreFoundation.dylib":CUIBinaryImageGroupFoundation, @"libswiftFoundation.dylib":CUIBinaryImageGroupFoundation, @"com.apple.Foundation":CUIBinaryImageGroupFoundation, @"com.apple.CoreFoundation":CUIBinaryImageGroupFoundation, // Graphics @"libswiftAVFoundation.dylib":CUIBinaryImageGroupGraphics, @"libswiftCoreGraphics.dylib":CUIBinaryImageGroupGraphics, @"libswiftCoreImage.dylib":CUIBinaryImageGroupGraphics, @"libswiftMetal.dylib":CUIBinaryImageGroupGraphics, @"libswiftQuartzCore.dylib":CUIBinaryImageGroupGraphics, @"com.apple.ApplicationServices.ATS":CUIBinaryImageGroupGraphics, @"com.apple.opencl":CUIBinaryImageGroupGraphics, @"com.apple.IOSurface":CUIBinaryImageGroupGraphics, @"com.apple.avfoundation":CUIBinaryImageGroupGraphics, @"com.apple.AVKit":CUIBinaryImageGroupGraphics, @"com.apple.ColorSync":CUIBinaryImageGroupGraphics, @"com.apple.ColorSyncLegacy":CUIBinaryImageGroupGraphics, @"com.apple.CoreGraphics":CUIBinaryImageGroupGraphics, @"com.apple.CoreImage":CUIBinaryImageGroupGraphics, @"com.apple.ImageCapture":CUIBinaryImageGroupGraphics, @"com.apple.imageCaptureCore":CUIBinaryImageGroupGraphics, @"com.apple.ImageIO.framework":CUIBinaryImageGroupGraphics, @"com.apple.CoreMedia":CUIBinaryImageGroupGraphics, @"com.apple.CoreMediaAccessibility":CUIBinaryImageGroupGraphics, @"com.apple.CoreMediaAuthoring":CUIBinaryImageGroupGraphics, @"com.apple.CoreMediaIO":CUIBinaryImageGroupGraphics, @"com.apple.CoreMediaKit":CUIBinaryImageGroupGraphics, @"com.apple.MediaPlayer":CUIBinaryImageGroupGraphics, @"com.apple.MediaToolbox":CUIBinaryImageGroupGraphics, @"com.apple.CoreText":CUIBinaryImageGroupGraphics, @"com.apple.CoreVideo":CUIBinaryImageGroupGraphics, @"com.apple.VideoToolbox":CUIBinaryImageGroupGraphics, @"com.apple.opengl":CUIBinaryImageGroupGraphics, @"com.apple.QuartzCore":CUIBinaryImageGroupGraphics, @"libGL.dylib":CUIBinaryImageGroupGraphics, @"libGLImage.dylib":CUIBinaryImageGroupGraphics, @"libGLU.dylib":CUIBinaryImageGroupGraphics, @"com.apple.QD":CUIBinaryImageGroupGraphics, @"libmetal_timestamp.dylib":CUIBinaryImageGroupGraphics, @"com.apple.gpusw.MetalTools":CUIBinaryImageGroupGraphics, @"com.apple.PDFKit":CUIBinaryImageGroupGraphics, @"com.apple.CorePDF":CUIBinaryImageGroupGraphics, @"com.apple.AppleJPEG":CUIBinaryImageGroupGraphics, @"libGIF.dylib":CUIBinaryImageGroupGraphics, @"libJP2.dylib":CUIBinaryImageGroupGraphics, @"libJPEG.dylib":CUIBinaryImageGroupGraphics, @"libPng.dylib":CUIBinaryImageGroupGraphics, @"libRadiance.dylib":CUIBinaryImageGroupGraphics, @"libTIFF.dylib":CUIBinaryImageGroupGraphics, // Languages @"libswiftObjectiveC.dylib":CUIBinaryImageGroupLanguages, // Network @"com.apple.CFNetwork":CUIBinaryImageGroupNetworkIO, @"libnetwork.dylib":CUIBinaryImageGroupNetworkIO, @"libsystem_networkextension.dylib":CUIBinaryImageGroupNetworkIO, @"libapple_nghttp2.dylib":CUIBinaryImageGroupNetworkIO, // Security @"com.apple.Kerberos":CUIBinaryImageGroupSecurity, @"libcommonCrypto.dylib":CUIBinaryImageGroupSecurity, @"libcorecrypto.dylib":CUIBinaryImageGroupSecurity, // System @"libdyld.dylib":CUIBinaryImageGroupSystem, @"libdispatch.dylib":CUIBinaryImageGroupSystem, // Web Internet @"com.apple.JavaScriptCore":CUIBinaryImageGroupWebInternet, @"com.apple.WebCore":CUIBinaryImageGroupWebInternet, @"com.apple.WebKitLegacy":CUIBinaryImageGroupWebInternet, @"com.apple.WebKit":CUIBinaryImageGroupWebInternet, @"libwebrtc.dylib":CUIBinaryImageGroupWebInternet, }; }); NSString * tBinaryImageGroup=sGroupRegistry[inIdentifier]; if (tBinaryImageGroup!=nil) return tBinaryImageGroup; // Try to figure out differently if ([inIdentifier hasPrefix:@"libc++"]==YES || [inIdentifier hasPrefix:@"libobjc"]==YES) return CUIBinaryImageGroupLanguages; if ([inIdentifier hasPrefix:@"com.apple.Metal"]==YES) return CUIBinaryImageGroupGraphics; if ([inIdentifier hasPrefix:@"com.apple.security"]==YES) return CUIBinaryImageGroupSecurity; if ([inIdentifier hasPrefix:@"com.apple."]==YES) return CUIBinaryImageGroupOtherFrameworks; if ([inIdentifier hasPrefix:@"libsystem_"]==YES) return CUIBinaryImageGroupSystem; return CUIBinaryImageGroupGenericUncategorized; } + (NSImage *)iconForBinaryImageGroup:(NSString *)inBinaryImageGroup { if (inBinaryImageGroup==nil) inBinaryImageGroup=CUIBinaryImageGroupGenericUncategorized; static NSDictionary * sIconsRegistry=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sIconsRegistry=@{ CUIBinaryImageGroupAppKitUIKit:[NSImage imageNamed:@"call-appkit"], CUIBinaryImageGroupAudioSpeech:[NSImage imageNamed:@"call-audiospeech"], CUIBinaryImageGroupDatabaseStorage:[NSImage imageNamed:@"call-database"], CUIBinaryImageGroupFoundation:[NSImage imageNamed:@"call-foundation"], CUIBinaryImageGroupGenericUncategorized:[NSImage imageNamed:@"call-generic"], CUIBinaryImageGroupGraphics:[NSImage imageNamed:@"call-graphics"], CUIBinaryImageGroupLanguages:[NSImage imageNamed:@"call-languages"], CUIBinaryImageGroupNetworkIO:[NSImage imageNamed:@"call-network"], CUIBinaryImageGroupOtherFrameworks:[NSImage imageNamed:@"call-framework"], CUIBinaryImageGroupSecurity:[NSImage imageNamed:@"call-security"], CUIBinaryImageGroupSystem:[NSImage imageNamed:@"call-system"], CUIBinaryImageGroupUserCode:[NSImage imageNamed:@"call-usercode"], CUIBinaryImageGroupWebInternet:[NSImage imageNamed:@"call-webinternet"], }; }); NSImage * tImage=sIconsRegistry[inBinaryImageGroup]; if (tImage!=nil) return tImage; return sIconsRegistry[CUIBinaryImageGroupGenericUncategorized]; } + (NSColor *)colorForBinaryImageGroup:(NSString *)inBinaryImageGroup { if (inBinaryImageGroup==nil) inBinaryImageGroup=CUIBinaryImageGroupGenericUncategorized; static NSDictionary * sColorsRegistry=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sColorsRegistry=@{ CUIBinaryImageGroupAppKitUIKit:[NSColor colorWithDeviceRed:176/255.0 green:155/255.0 blue:202/255.0 alpha:1.0], CUIBinaryImageGroupAudioSpeech:[NSColor colorWithDeviceRed:169/255.0 green:184/255.0 blue:192/255.0 alpha:1.0], CUIBinaryImageGroupDatabaseStorage:[NSColor colorWithDeviceRed:212/255.0 green:194/255.0 blue:87/255.0 alpha:1.0], CUIBinaryImageGroupFoundation:[NSColor colorWithDeviceRed:185/255.0 green:181/255.0 blue:160/255.0 alpha:1.0], CUIBinaryImageGroupGenericUncategorized:[NSColor colorWithDeviceRed:167/255.0 green:146/255.0 blue:126/255.0 alpha:1.0], CUIBinaryImageGroupGraphics:[NSColor colorWithDeviceRed:155/255.0 green:152/255.0 blue:210/255.0 alpha:1.0], CUIBinaryImageGroupLanguages:[NSColor colorWithDeviceRed:158/255.0 green:111/255.0 blue:147/255.0 alpha:1.0], CUIBinaryImageGroupNetworkIO:[NSColor colorWithDeviceRed:215/255.0 green:137/255.0 blue:101/255.0 alpha:1.0], CUIBinaryImageGroupOtherFrameworks:[NSColor colorWithDeviceRed:190/255.0 green:154/255.0 blue:150/255.0 alpha:1.0], CUIBinaryImageGroupSecurity:[NSColor colorWithDeviceRed:85/255.0 green:138/255.0 blue:82/255.0 alpha:1.0], CUIBinaryImageGroupSystem:[NSColor colorWithDeviceRed:201/255.0 green:185/255.0 blue:156/255.0 alpha:1.0], CUIBinaryImageGroupUserCode:[NSColor colorWithDeviceRed:133/255.0 green:168/255.0 blue:210/255.0 alpha:1.0], CUIBinaryImageGroupWebInternet:[NSColor colorWithDeviceRed:106/255.0 green:131/255.0 blue:141/255.0 alpha:1.0], }; }); NSColor * tColor=sColorsRegistry[inBinaryImageGroup]; if (tColor!=nil) return tColor; return sColorsRegistry[CUIBinaryImageGroupGenericUncategorized]; } + (NSImage *)iconForIdentifier:(NSString *)inIdentifier { NSString * tBinaryImageGroup=[CUIBinaryImageUtility binaryImageGroupForIdentifier:inIdentifier]; return [CUIBinaryImageUtility iconForBinaryImageGroup:tBinaryImageGroup]; } + (NSImage *)iconForPath:(NSString *)inPath { return nil; } + (NSColor *)colorForUserCode { static NSColor * sUserCodeColor=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sUserCodeColor=[NSColor colorWithDeviceRed:133/255.0 green:168/255.0 blue:210/255.0 alpha:1.0]; }); return sUserCodeColor; } + (NSColor *)colorForIdentifier:(NSString *)inIdentifier { NSString * tBinaryImageGroup=[CUIBinaryImageUtility binaryImageGroupForIdentifier:inIdentifier]; return [CUIBinaryImageUtility colorForBinaryImageGroup:tBinaryImageGroup]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIBinaryImagesViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" @interface CUIBinaryImagesViewController : NSViewController @property (nonatomic) CUICrashLog * crashLog; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIBinaryImagesViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIBinaryImagesViewController.h" #import "CUIBinaryImage.h" #import "CUIBinaryImageUtility.h" #import "CUICallsSelection.h" #import "CUIApplicationItemAttributes.h" #import "NSArray+WBExtensions.h" #import "NSTableView+Selection.h" #import "NSSet+WBExtensions.h" #import "CUIRawCrashLog+Path.h" #import "CUIHopperDisassemblerManager.h" @interface CUIBinaryImagesViewController () { IBOutlet NSTableView * _tableView; IBOutlet NSMenuItem * _openWithMenuItem; IBOutlet NSSearchField * _filterField; NSMutableArray * _sortedAndFilteredBinaryImagesArray; NSString * _filterPattern; NSSet * _highlightedBinaryImagesSet; } @property (nonatomic,copy) NSString * userCodeBinaryImageIdentifier; @property (nonatomic) NSArray * binaryImages; - (void)refreshList; - (IBAction)showInFinder:(id)sender; - (IBAction)takeFilterPatternFrom:(id)sender; // Notifications - (void)callsSelectionDidChange:(NSNotification *)inNotification; @end @implementation CUIBinaryImagesViewController - (instancetype)init { self=[super init]; if (self!=nil) { _filterPattern=@""; } return self; } #pragma mark - - (NSString *)nibName { return @"CUIBinaryImagesViewController"; } - (void)viewDidLoad { [super viewDidLoad]; // Table NSSortDescriptor *buildETASortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"addressesRange" ascending:YES]; _tableView.sortDescriptors=@[buildETASortDescriptor]; // Open With menu NSMenu * tHopperMenu=[[CUIHopperDisassemblerManager sharedManager] availableApplicationsMenuWithTarget:self]; _openWithMenuItem.submenu=tHopperMenu; _openWithMenuItem.hidden=(tHopperMenu==nil); // Filter Field _filterField.centersPlaceholder=NO; NSSearchFieldCell * tSearchFieldCell=_filterField.cell; NSButtonCell * tButtonCell=tSearchFieldCell.searchButtonCell; tButtonCell.image=[NSImage imageNamed:@"filter_Template"]; tButtonCell.alternateImage=tButtonCell.image; // Notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(callsSelectionDidChange:) name:CUICallsSelectionDidChangeNotification object:[CUICallsSelection sharedCallsSelection]]; } #pragma mark - - (void)setCrashLog:(CUICrashLog *)inCrashLog { if (_crashLog==inCrashLog) return; _crashLog=inCrashLog; _binaryImages=_crashLog.binaryImages.binaryImages; _userCodeBinaryImageIdentifier=_crashLog.header.bundleIdentifier; [_tableView sizeLastColumnToFit]; [self refreshList]; } #pragma mark - - (void)refreshList { NSIndexSet * tIndexSet=_tableView.selectedRowIndexes; NSArray * tSelectedItems=[_sortedAndFilteredBinaryImagesArray objectsAtIndexes:tIndexSet]; NSArray * tSelectedPaths=[tSelectedItems WB_arrayByMappingObjectsUsingBlock:^id(CUIBinaryImage * bBinaryImage, NSUInteger bIndex) { return bBinaryImage.path; }]; NSArray * tArray=_binaryImages; if (_filterPattern.length>0) { _sortedAndFilteredBinaryImagesArray=[NSMutableArray array]; [tArray enumerateObjectsUsingBlock:^(CUIBinaryImage * bBinaryImage, NSUInteger bIndex, BOOL * bOutStop) { if ([bBinaryImage.identifier rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound || [bBinaryImage.addressesRange.stringValue rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound || [bBinaryImage.path rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound) { [self->_sortedAndFilteredBinaryImagesArray addObject:bBinaryImage]; } }]; } else { _sortedAndFilteredBinaryImagesArray=[tArray mutableCopy]; } [_sortedAndFilteredBinaryImagesArray sortUsingDescriptors: _tableView.sortDescriptors]; [_tableView reloadData]; NSMutableIndexSet * tNewSelectionIndexSet=[NSMutableIndexSet indexSet]; [_sortedAndFilteredBinaryImagesArray enumerateObjectsUsingBlock:^(CUIBinaryImage * bBinaryImage, NSUInteger bIndex,BOOL * bOutStop) { if ([tSelectedPaths containsObject:bBinaryImage.path]==YES) [tNewSelectionIndexSet addIndex:bIndex]; }]; if (tNewSelectionIndexSet.count>0) [_tableView selectRowIndexes:tNewSelectionIndexSet byExtendingSelection:NO]; NSMutableIndexSet * tMutableIndexSet=[NSMutableIndexSet indexSet]; [_sortedAndFilteredBinaryImagesArray enumerateObjectsUsingBlock:^(CUIBinaryImage * bBinaryImage, NSUInteger bIndex, BOOL * bOutStop) { if ([self->_highlightedBinaryImagesSet containsObject:bBinaryImage.identifier]==YES) [tMutableIndexSet addIndex:bIndex]; }]; if (tMutableIndexSet.count>0) [_tableView scrollRowToVisible:tMutableIndexSet.firstIndex]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; NSIndexSet * tSelectedRows=[_tableView WB_selectedOrClickedRowIndexes]; if (tAction==@selector(showInFinder:) || tAction==@selector(openWithHopperDisassembler:)) { if (tSelectedRows.count==0) return NO; NSArray * tArray=[_sortedAndFilteredBinaryImagesArray objectsAtIndexes:tSelectedRows]; NSFileManager * tFileManager=[NSFileManager defaultManager]; for(CUIBinaryImage * tBinaryImage in tArray) { NSString * tPath=tBinaryImage.path; if (tPath.length==0) return NO; if ([tFileManager fileExistsAtPath:tPath]==NO) return NO; } return (tSelectedRows.count>0); } return YES; } - (IBAction)showInFinder:(id)sender { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; NSWorkspace * tSharedWorkspace=[NSWorkspace sharedWorkspace]; [_sortedAndFilteredBinaryImagesArray enumerateObjectsAtIndexes:tSelectionIndexSet options:0 usingBlock:^(CUIBinaryImage * bBinaryImage, NSUInteger bIndex, BOOL * bOutStop) { if (bBinaryImage.path.length>0) [tSharedWorkspace selectFile:bBinaryImage.path inFileViewerRootedAtPath:@""]; }]; } - (IBAction)openWithHopperDisassembler:(NSMenuItem *)sender { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; CUIApplicationItemAttributes * tApplicationItemAttributes=sender.representedObject; [_sortedAndFilteredBinaryImagesArray enumerateObjectsAtIndexes:tSelectionIndexSet options:0 usingBlock:^(CUIBinaryImage * bBinaryImage, NSUInteger bIndex, BOOL * bOutStop) { if (bBinaryImage.path.length>0) { [[CUIHopperDisassemblerManager sharedManager] openBinaryImage:bBinaryImage.path withApplicationAttributes:tApplicationItemAttributes codeType:self.crashLog.header.codeType fileOffSet:NULL]; } }]; } - (IBAction)takeFilterPatternFrom:(NSSearchField *)sender { _filterPattern=sender.stringValue; [self refreshList]; } #pragma mark - NSTableViewDataSource - (NSInteger)numberOfRowsInTableView:(NSTableView *)inTableView { return _sortedAndFilteredBinaryImagesArray.count; } #pragma mark - NSTableViewDelegate - (NSView *)tableView:(NSTableView *)inTableView viewForTableColumn:(NSTableColumn *)inTableColumn row:(NSInteger)inRow { NSString * tTableColumnIdentifier=inTableColumn.identifier; NSTableCellView * tTableCellView=[inTableView makeViewWithIdentifier:tTableColumnIdentifier owner:self]; CUIBinaryImage * tBinaryImage=_sortedAndFilteredBinaryImagesArray[inRow]; tTableCellView.textField.textColor=(_highlightedBinaryImagesSet.count>0) ? [NSColor secondaryLabelColor] : [NSColor labelColor]; if ([_highlightedBinaryImagesSet containsObject:tBinaryImage.identifier]==YES) { tTableCellView.textField.textColor=[NSColor labelColor]; tTableCellView.textField.font=[[NSFontManager sharedFontManager] convertFont:tTableCellView.textField.font toHaveTrait:NSBoldFontMask]; } else { tTableCellView.textField.font=[[NSFontManager sharedFontManager] convertFont:tTableCellView.textField.font toHaveTrait:NSUnboldFontMask]; } if ([tTableColumnIdentifier isEqualToString:@"identifier"]==YES) { tTableCellView.textField.stringValue=tBinaryImage.identifier; if (tBinaryImage.isUserCode==YES) tTableCellView.imageView.image=[NSImage imageNamed:@"call-usercode"]; else tTableCellView.imageView.image=[CUIBinaryImageUtility iconForIdentifier:tBinaryImage.identifier]; } else if ([tTableColumnIdentifier isEqualToString:@"version"]==YES) { if (tBinaryImage.buildNumber==nil) tTableCellView.textField.stringValue=(tBinaryImage.version!=nil) ? tBinaryImage.version : @"-"; else tTableCellView.textField.stringValue=[NSString stringWithFormat:NSLocalizedString(@"%@ (%@)",@""),tBinaryImage.version,tBinaryImage.buildNumber]; } else if ([tTableColumnIdentifier isEqualToString:@"addresses"]==YES) { //tTableCellView.textField.font=[NSFont monospacedDigitSystemFontOfSize:18.0 weight:NSFontWeightRegular]; tTableCellView.textField.stringValue=tBinaryImage.addressesRange.stringValue; } else if ([tTableColumnIdentifier isEqualToString:@"path"]==YES) { tTableCellView.textField.stringValue=[self.crashLog stringByResolvingUSERInPath:tBinaryImage.path]; } return tTableCellView; } - (void)tableView:(NSTableView *)inTableView sortDescriptorsDidChange:(NSArray *)inOldDescriptors { [self refreshList]; } #pragma mark - Notifications - (void)callsSelectionDidChange:(NSNotification *)inNotification { CUICallsSelection * tCallSelection=inNotification.object; if ([tCallSelection isKindOfClass:[CUICallsSelection class]]==NO) return; _highlightedBinaryImagesSet=tCallSelection.binaryImageIdentifiers; NSMutableIndexSet * tMutableIndexSet=[NSMutableIndexSet indexSet]; [_sortedAndFilteredBinaryImagesArray enumerateObjectsUsingBlock:^(CUIBinaryImage * bBinaryImage, NSUInteger bIndex, BOOL * bOutStop) { if ([self->_highlightedBinaryImagesSet containsObject:bBinaryImage.identifier]==YES) { [tMutableIndexSet addIndex:bIndex]; } }]; [_tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, _sortedAndFilteredBinaryImagesArray.count)] columnIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 4)]]; if (tMutableIndexSet.count>0) [_tableView scrollRectToVisible:[_tableView rectOfRow:tMutableIndexSet.firstIndex]]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICallStackBacktrace.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIStackFrame.h" #import "IPSThreadFrame.h" #import "IPSImage.h" @interface CUICallStackBacktrace : NSObject @property (readonly) NSArray * stackFrames; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError; - (instancetype)initWithFrames:(NSArray *)inFrames binaryImages:(NSArray *)inImages error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICallStackBacktrace.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICallStackBacktrace.h" #import "NSArray+WBExtensions.h" @interface CUICallStackBacktrace () @property NSArray * stackFrames; @end @implementation CUICallStackBacktrace - (instancetype)initWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError { if ([inLines isKindOfClass:[NSArray class]]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { __block NSError * tError=nil; _stackFrames=[inLines WB_arrayByMappingObjectsUsingBlock:^id(NSString * bLine, NSUInteger bLineNumber) { CUIStackFrame * tCall=[[CUIStackFrame alloc] initWithString:bLine error:&tError]; if (tCall==nil) { NSLog(@"Error parsing line: %@",bLine); return nil; } return tCall; }]; if (_stackFrames==nil) { if (outError!=NULL) *outError=tError; return nil; } } return self; } - (instancetype)initWithFrames:(NSArray *)inFrames binaryImages:(NSArray *)inImages error:(NSError **)outError { if ([inFrames isKindOfClass:[NSArray class]]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _stackFrames=[inFrames WB_arrayByMappingObjectsUsingBlock:^CUIStackFrame *(IPSThreadFrame * bFrame, NSUInteger bIndex) { CUIStackFrame * tStackFrame=[[CUIStackFrame alloc] initWithThreadFrame:bFrame atIndex:bIndex image:inImages[bFrame.imageIndex] error:NULL]; if (tStackFrame==nil) { return nil; } return tStackFrame; }]; } return self; } #pragma mark - - (NSString *)description { return self.stackFrames.description; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICallTableCellView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICallTableCellView : NSTableCellView @property (assign) IBOutlet NSTextField * callIndexLabel; @property (assign) IBOutlet NSTextField * binaryImageLabel; @property (assign) IBOutlet NSTextField * addressLabel; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICallTableCellView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICallTableCellView.h" @implementation CUICallTableCellView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICallsSelection.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUICallsSelectionDidChangeNotification; @interface CUICallsSelection : NSObject @property (nonatomic) NSSet * calls; @property (nonatomic,readonly) NSSet * binaryImageIdentifiers; + (CUICallsSelection *)sharedCallsSelection; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICallsSelection.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICallsSelection.h" #import "CUICallStackBacktrace.h" NSString * const CUICallsSelectionDidChangeNotification=@"CUICallsSelectionDidChangeNotification"; @implementation CUICallsSelection + (CUICallsSelection *)sharedCallsSelection { static CUICallsSelection * sSharedCallsSelection=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSharedCallsSelection=[CUICallsSelection new]; }); return sSharedCallsSelection; } #pragma mark - - (void)setCalls:(NSSet *)inCalls { _calls=inCalls; [NSNotificationCenter.defaultCenter postNotificationName:CUICallsSelectionDidChangeNotification object:self]; } - (NSSet *)binaryImageIdentifiers { NSMutableSet * tMutableSet=[NSMutableSet set]; [self.calls enumerateObjectsUsingBlock:^(CUIStackFrame * bCall,BOOL * bOutStop) { NSString * tBinaryImageIdentifier=bCall.binaryImageIdentifier; if (tBinaryImageIdentifier!=nil) [tMutableSet addObject:tBinaryImageIdentifier]; }]; return [tMutableSet copy]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICaptionView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICaptionView : NSTextField @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICaptionView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICaptionView.h" #define CUICaptionMinWidth 40.0 @implementation CUICaptionView - (NSSize)badgeSizeForString:(NSString*)string { NSSize tSize = [self.attributedStringValue size]; // Paddings tSize.width += 12.0; if (tSize.width @interface CUICategoriesClipView : NSClipView @property (nonatomic) NSColor * themeBackgroundColor; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICategoriesClipView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICategoriesClipView.h" @implementation CUICategoriesClipView - (void)setThemeBackgroundColor:(NSColor *)inColor { _themeBackgroundColor=inColor; [self setNeedsDisplay:YES]; } #pragma mark - - (void)drawRect:(NSRect)dirtyRect { [self.themeBackgroundColor set]; NSRectFill(dirtyRect); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICenteredLabelViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_ENUM(NSUInteger, CUILabelSize) { CUILabelSizeRegular, CUILabelSizeBig, }; @interface CUICenteredLabelViewController : NSViewController @property (nonatomic) CUILabelSize labelSize; @property (nonatomic,copy) NSString * label; @property (nonatomic) CGFloat verticalOffset; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICenteredLabelViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICenteredLabelViewController.h" #define H_MARGIN_REGULAR 15.0 #define H_MARGIN_BIG 20.0 #define MARGIN_REGULAR_TOP 10.0 #define MARGIN_REGULAR_BOTTOM 12.0 #define MARGIN_BIG_TOP 14.0 #define MARGIN_BIG_BOTTOM 16.0 @interface CUICenteredLabelViewController () { IBOutlet NSView * _frameView; IBOutlet NSTextField * _labelTextField; } - (void)viewFrameDidChange:(NSNotification *)inNotification; @end @implementation CUICenteredLabelViewController - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } - (NSString *)nibName { return @"CUICenteredLabelViewController"; } - (void)viewDidLoad { [super viewDidLoad]; if (self.label!=nil) { _labelTextField.stringValue=self.label; } } - (void)viewWillAppear { [super viewWillAppear]; // Center view [self resizeLabel]; [self layout]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(viewFrameDidChange:) name:NSViewFrameDidChangeNotification object:self.view]; } - (void)viewWillDisappear { [NSNotificationCenter.defaultCenter removeObserver:self name:NSViewFrameDidChangeNotification object:self.view]; } #pragma mark - - (void)setLabelSize:(CUILabelSize)inLabelSize { if (_labelSize==inLabelSize) return; _labelSize=inLabelSize; [self resizeLabel]; } - (void)setLabel:(NSString *)inLabel { if (inLabel==nil) return; if (_label==inLabel) return; _label=[inLabel copy]; _labelTextField.stringValue=inLabel; [self resizeLabel]; } #pragma mark - - (void)setVerticalOffset:(CGFloat)inVerticalOffset { if (_verticalOffset==inVerticalOffset) return; _verticalOffset=inVerticalOffset; [self layout]; } CGFloat verticalOffset; - (void)resizeLabel { CGFloat tFontSize=13.0; switch(self.labelSize) { case CUILabelSizeBig: tFontSize=30.0f; break; case CUILabelSizeRegular: tFontSize=14.0f; break; } _labelTextField.font=[NSFont systemFontOfSize:tFontSize weight:NSFontWeightLight]; [_labelTextField sizeToFit]; NSRect tLabelFrame=_labelTextField.frame; NSRect tFrameFrame=_frameView.frame; CGFloat tMargin=H_MARGIN_REGULAR; CGFloat tMarginTop=MARGIN_REGULAR_TOP; CGFloat tMarginBottom=MARGIN_REGULAR_BOTTOM; switch(self.labelSize) { case CUILabelSizeBig: tMargin=H_MARGIN_BIG; tMarginTop=MARGIN_BIG_TOP; tMarginBottom=MARGIN_BIG_BOTTOM; break; case CUILabelSizeRegular: tMargin=H_MARGIN_REGULAR; tMarginTop=MARGIN_REGULAR_TOP; tMarginBottom=MARGIN_REGULAR_BOTTOM; break; } tFrameFrame.size.width=NSWidth(tLabelFrame)+2*tMargin; tFrameFrame.size.height=NSHeight(tLabelFrame)+tMarginTop+tMarginBottom; _frameView.frame=tFrameFrame; tLabelFrame.origin.x=tMargin; tLabelFrame.origin.y=tMarginBottom; _labelTextField.frame=tLabelFrame; } - (void)layout { NSRect tBounds=self.view.bounds; NSRect tFrame=_frameView.frame; tFrame.origin.x=round(NSMidX(tBounds)-NSWidth(tFrame)*0.5); tFrame.origin.y=round(NSMidY(tBounds)+(self.verticalOffset-NSHeight(tFrame))*0.5); _frameView.frame=tFrame; } #pragma mark - Notifications - (void)viewFrameDidChange:(NSNotification *)inNotification { [self layout]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICenteredLabelViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICodeSigningFlagsTableView.h ================================================ /* Copyright (c) 2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import NS_ASSUME_NONNULL_BEGIN @interface CUICodeSigningFlagsTableView : NSTableView @end NS_ASSUME_NONNULL_END ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICodeSigningFlagsTableView.m ================================================ /* Copyright (c) 2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICodeSigningFlagsTableView.h" @implementation CUICodeSigningFlagsTableView - (BOOL)isOpaque { return NO; } - (NSColor *)backgroundColor { return [NSColor clearColor]; } #pragma mark - - (BOOL)acceptsFirstResponder { return NO; } - (NSView *)hitTest:(NSPoint)point { return nil; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICodeSigningInformationViewController.h ================================================ /* Copyright (c) 2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "IPSIncidentHeader.h" @interface CUICodeSigningInformationViewController : NSViewController - (instancetype)initWithCodeSigningInfo:(IPSCodeSigningInfo *)inCodeSigningInfo; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICodeSigningInformationViewController.m ================================================ /* Copyright (c) 2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICodeSigningInformationViewController.h" #import "NSDictionary+WBExtensions.h" @interface IPSCodeSigningInfo (UI) @property (nonatomic, readonly) NSString *validationCategoryDisplayString; @end @implementation IPSCodeSigningInfo (UI) - (NSString *)validationCategoryDisplayString { switch(self.validationCategory) { case IPSCodeSigningValidationCategoryPlatform: return NSLocalizedStringFromTable(@"",@"CodeSigning",@""); case IPSCodeSigningValidationCategoryTestFlight: return NSLocalizedStringFromTable(@"TestFlight",@"CodeSigning",@""); case IPSCodeSigningValidationCategoryDevelopment: return NSLocalizedStringFromTable(@"Development",@"CodeSigning",@""); case IPSCodeSigningValidationCategoryAppStore: return NSLocalizedStringFromTable(@"AppStore",@"CodeSigning",@""); case IPSCodeSigningValidationCategoryEnterprise: return NSLocalizedStringFromTable(@"Enterprise",@"CodeSigning",@""); case IPSCodeSigningValidationCategoryDeveloperID: return NSLocalizedStringFromTable(@"Developer ID",@"CodeSigning",@""); case IPSCodeSigningValidationCategoryNone: return NSLocalizedStringFromTable(@"None",@"CodeSigning",@""); } return @"-"; } @end @interface CUICodeSigningInformationViewController () { IPSCodeSigningInfo * _info; IBOutlet NSTextField * _identifierTextField; IBOutlet NSTextField * _teamIdentifierTextField; IBOutlet NSTextField * _validationCategoryTextField; IBOutlet NSTextField * _flagsRichTextField; IBOutlet NSTextField * _trustLevelTextField; } @end @implementation CUICodeSigningInformationViewController + (NSDictionary *)flagsToLocalizedNameDictionary { static dispatch_once_t onceToken; static NSDictionary * sConversionDictionary=nil; dispatch_once(&onceToken, ^{ NSURL * tResourceURL=[[NSBundle bundleForClass:self] URLForResource:@"CodeSigningFlags" withExtension:@"plist"]; NSError * tError; sConversionDictionary=[[NSDictionary alloc] initWithContentsOfURL:tResourceURL error:&tError]; if (sConversionDictionary==nil) NSLog(@"Could not get the list of codesigning flags: %@",tError); }); return sConversionDictionary; } - (instancetype)initWithCodeSigningInfo:(IPSCodeSigningInfo *)inCodeSigningInfo { self=[super init]; if (self!=nil) { _info=[inCodeSigningInfo copy]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; _identifierTextField.stringValue=_info.identifier ?: @"-"; _teamIdentifierTextField.stringValue=_info.teamIdentifier ?: @"-"; _validationCategoryTextField.stringValue=_info.validationCategoryDisplayString; _flagsRichTextField.attributedStringValue=[self codeSigningFlagsDisplayString]; _trustLevelTextField.stringValue=[NSString stringWithFormat:@"0x%x",_info.trustLevel]; } #pragma mark - - (NSAttributedString *)codeSigningFlagsDisplayString { NSMutableAttributedString * tMutableAttributedString=[[NSMutableAttributedString alloc] initWithString:@""]; NSDictionary *tFlagsToLocalizedNameDictionary = [CUICodeSigningInformationViewController flagsToLocalizedNameDictionary]; static dispatch_once_t onceToken; static NSArray * sAllFlags=nil; dispatch_once(&onceToken, ^{ sAllFlags=[tFlagsToLocalizedNameDictionary.allKeys sortedArrayUsingSelector:@selector(compare:)]; }); BOOL tFirstLine=YES; NSAttributedString * tNewLine=[[NSAttributedString alloc] initWithString:@"\n" attributes:nil]; BOOL tShouldIncreaseContrast=NSWorkspace.sharedWorkspace.accessibilityDisplayShouldIncreaseContrast; NSFont * tSystemFont=[NSFont systemFontOfSize:NSFont.systemFontSize];; NSFont * tBoldSystemFont=[NSFont boldSystemFontOfSize:NSFont.systemFontSize]; for(NSString * tKey in sAllFlags) { if (tFirstLine==NO) [tMutableAttributedString appendAttributedString:tNewLine]; else tFirstLine=NO; NSNumber * tFlagNumber=tFlagsToLocalizedNameDictionary[tKey]; BOOL tIsFlagSet=((tFlagNumber.unsignedIntValue & _info.flags)!=0); NSDictionary * tAttributes; if (tIsFlagSet==YES) { NSFont * tFont; if (tShouldIncreaseContrast==YES) tFont = tBoldSystemFont; else tFont = tSystemFont; tAttributes = @{ NSForegroundColorAttributeName : NSColor.labelColor, NSFontAttributeName : tFont }; } else { tAttributes = @{ NSForegroundColorAttributeName : NSColor.tertiaryLabelColor, NSFontAttributeName : tSystemFont }; } NSAttributedString * tAttributedLine=[[NSAttributedString alloc] initWithString:tKey attributes:tAttributes]; [tMutableAttributedString appendAttributedString:tAttributedLine]; } return tMutableAttributedString; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICodeType.h ================================================ // // CUICodeType.h // app_unexpectedly // // Created by stephane on 09/03/2021. // Copyright © 2021 Acme, Inc. All rights reserved. // #ifndef CUICodeType_h #define CUICodeType_h typedef NS_ENUM(NSInteger, CUICodeType) { CUICodeTypeUnknown=-1, CUICodeTypeX86=0, CUICodeTypeX86_64, CUICodeTypeARM_64, CUICodeTypePPC=601, }; #endif /* CUICodeType_h */ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewDockedThreadItem.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewThreadItem.h" @interface CUICollectionViewDockedThreadItem : CUICollectionViewThreadItem @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewDockedThreadItem.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewDockedThreadItem.h" #import "CUILightTableDockedThreadView.h" #import "CUIThread.h" @interface CUICollectionViewDockedThreadItem () { IBOutlet NSTextField * _threadNumberLabel; IBOutlet NSTextField * _threadNumberBigLabel; IBOutlet NSTextField * _threadNameLabel; } - (IBAction)openThreadView:(id)sender; @end @implementation CUICollectionViewDockedThreadItem - (void)setRepresentedObject:(id)inRepresentedObject { [super setRepresentedObject:inRepresentedObject]; CUILightTableDockedThreadView * tView=(CUILightTableDockedThreadView *)self.view; CUIThread * tThread=(CUIThread *)inRepresentedObject; tView.crashed=tThread.isCrashed; tView.applicationSpecificBacktrace=tThread.isApplicationSpecificBacktrace; self.imageView.image=(tThread.isCrashed==YES) ? [NSImage imageNamed:@"crashedThread_Template"] : [NSImage imageNamed:@"thread_Template"]; if (tThread.isApplicationSpecificBacktrace==YES) { _threadNumberBigLabel.stringValue=tThread.name; _threadNumberLabel.stringValue=@""; _threadNameLabel.stringValue=@""; } else { if (tThread.name==nil) { _threadNumberBigLabel.stringValue=[NSString stringWithFormat:NSLocalizedString(@"Thread %ld",@""),tThread.number]; _threadNumberLabel.stringValue=@""; _threadNameLabel.stringValue=@""; } else { _threadNumberBigLabel.stringValue=@""; _threadNumberLabel.stringValue=[NSString stringWithFormat:NSLocalizedString(@"Thread %ld",@""),tThread.number]; _threadNameLabel.stringValue=tThread.name; } } } - (IBAction)openThreadView:(id)sender { id tDataSource=self.collectionView.dataSource; if ([tDataSource respondsToSelector:@selector(openThread:)]==YES) [tDataSource performSelector:@selector(openThread:) withObject:self.representedObject]; // A COMPLETER } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewDockedThreadItem.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewDockedThreadsLayout.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICollectionViewDockedThreadsLayout : NSCollectionViewLayout @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewDockedThreadsLayout.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewDockedThreadsLayout.h" #define CUIColumnInterGapWidth 16.0 #define CUICardMinimumWidth 150.0 #define CUICardMaximumWidth 300.0 #define CUICardHeight 32.0 #define CUICardVerticalMargin 5.0 @interface CUICollectionViewDockedThreadsLayout () { NSEdgeInsets _cachedEdgeInsets; NSSize _cachedContentSize; CGFloat _cardWidth; } @end @implementation CUICollectionViewDockedThreadsLayout - (NSSize)itemSize { NSSize tSize; tSize.width=_cardWidth; tSize.height=CUICardHeight; return tSize; } - (NSCollectionViewScrollDirection)scrollDirection { return NSCollectionViewScrollDirectionHorizontal; } - (void) prepareLayout { if (self.collectionView==nil) return; [super prepareLayout]; NSView * tSuperView=self.collectionView.superview; NSRect tReferenceBounds=NSZeroRect; if ([tSuperView isKindOfClass:[NSClipView class]]==YES) { tReferenceBounds=tSuperView.bounds; } else { tReferenceBounds=self.collectionView.bounds; } NSInteger tNumberOfItems = [self.collectionView numberOfItemsInSection:0]; CGFloat tVisibleWidth=NSWidth(tReferenceBounds); _cardWidth=(tVisibleWidth-((tNumberOfItems+1) * CUIColumnInterGapWidth))/tNumberOfItems; if (_cardWidthCUICardMaximumWidth) _cardWidth=CUICardMaximumWidth; //NSSize tSize=NSMakeSize((tNumberOfItems * _cardWidth) + ((tNumberOfItems+1) * CUIColumnInterGapWidth), NSHeight(self.collectionView.frame)); //NSRect tBounds=tReferenceBounds; _cachedEdgeInsets.top=_cachedEdgeInsets.bottom=0.0; _cachedEdgeInsets.left=5.0; _cachedEdgeInsets.right=5.0; } - (NSSize)collectionViewContentSize { NSView * tSuperView=self.collectionView.superview; NSRect tReferenceBounds=NSZeroRect; if ([tSuperView isKindOfClass:[NSClipView class]]==YES) { tReferenceBounds=tSuperView.bounds; } else { tReferenceBounds=self.collectionView.bounds; } NSInteger tNumberOfItems = [self.collectionView numberOfItemsInSection:0]; CGFloat tVisibleWidth=NSWidth(tReferenceBounds); CGFloat tTotalWidth=(tNumberOfItems * _cardWidth) + ((tNumberOfItems+1) * CUIColumnInterGapWidth); if (tTotalWidth(_cachedEdgeInsets.left+CUIColumnInterGapWidth+_cardWidth*0.5)) tIndex=(tX-_cachedEdgeInsets.left-CUIColumnInterGapWidth-_cardWidth*0.5)/(CUIColumnInterGapWidth+_cardWidth)+1; NSCollectionViewLayoutAttributes* tAttributes = [NSCollectionViewLayoutAttributes layoutAttributesForInterItemGapBeforeIndexPath:[NSIndexPath indexPathForItem:tIndex inSection:0]]; NSRect tFrame; tFrame.origin.x=_cachedEdgeInsets.left+CUIColumnInterGapWidth*0.5+tIndex * CUIColumnInterGapWidth + (tIndex * _cardWidth)-1; tFrame.size.width=2; tFrame.origin.y=5; tFrame.size.height=_cachedContentSize.height-10; tAttributes.frame=tFrame; return tAttributes; } - (NSArray<__kindof NSCollectionViewLayoutAttributes *> *) layoutAttributesForElementsInRect:(NSRect)rect { NSInteger tNumberOfItems = [self.collectionView numberOfItemsInSection:0]; NSMutableArray* tAttributesArray = [NSMutableArray arrayWithCapacity:tNumberOfItems]; for (NSInteger tIndex=0; tIndex extern NSString * const CUIRegisterItemViewAsValueDidChangeNotification; @interface CUICollectionViewRegisterItem : NSCollectionViewItem @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewRegisterItem.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewRegisterItem.h" #import "CUIRegister.h" #import "CUIRegisterLabel.h" #define MACOS_BIGSUR_WIDTH_INSET 3.0 NSString * const CUIRegisterItemViewAsValueDidChangeNotification=@"CUIRegisterItemViewAsValueDidChangeNotification"; @interface CUICollectionViewRegisterItem () { IBOutlet NSTextField * _registerNameLabel; IBOutlet CUIRegisterLabel * _registerValueLabel; IBOutlet NSPopUpButton* _registerValueDisplayFormatPopUpButton; } @end @implementation CUICollectionViewRegisterItem - (void)viewDidLoad { [super viewDidLoad]; if (NSAppKitVersionNumber>0/*2022.00*/) // A VERIFIER { // Deal with macOS Big Sur different UI metrics NSRect tFrame=_registerValueDisplayFormatPopUpButton.frame; tFrame.origin.x+=MACOS_BIGSUR_WIDTH_INSET; tFrame.size.width-=MACOS_BIGSUR_WIDTH_INSET; _registerValueDisplayFormatPopUpButton.frame=tFrame; } } #pragma mark - - (NSString *)toolTipForRegisterName:(NSString *)inRegisterName { if (inRegisterName==nil) return nil; static NSDictionary * sRegistersExpandedNamesRegistry=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sRegistersExpandedNamesRegistry=@{ @"cpsr":@"Current Program Status Register", @"cr2":@"Control Register 2", @"esr":@"Exception Syndrome Register", @"far":@"Fault Address Register", @"lr":@"Link Register", @"pc":@"Program Counter", @"rbp":@"Register Base Pointer", @"rdi":@"Register Destination Index", @"rip":@"Instruction Pointer Register", @"rsi":@"Register Source Index", @"rsp":@"Register Stack Pointer", @"sp":@"Stack Pointer", }; }); return sRegistersExpandedNamesRegistry[inRegisterName.lowercaseString]; } - (void)setRepresentedObject:(id)inRepresentedObject { [super setRepresentedObject:inRepresentedObject]; if (inRepresentedObject==nil) return; NSDictionary * tRepresentation=(NSDictionary *)inRepresentedObject; CUIRegister * tRegister=(CUIRegister *)tRepresentation[@"register"]; if (tRegister.name==nil) { NSLog(@"Missing register name"); return; } _registerNameLabel.stringValue=[NSString stringWithFormat:NSLocalizedString(@"%@:",@""),tRegister.name]; _registerNameLabel.toolTip=[self toolTipForRegisterName:tRegister.name]; _registerValueLabel.delegate=self; _registerValueLabel.registerValue=tRegister.value; CUIRegisterViewValueAsType tType=CUIRegisterViewValueAsHex; NSNumber * tRegisterViewAs=tRepresentation[@"viewAs"]; if (tRegisterViewAs!=nil) tType=[tRegisterViewAs unsignedIntegerValue]; _registerValueLabel.viewValueAs=tType; } #pragma mark - - (void)registerLabel:(CUIRegisterLabel *)inRegisterLabel viewValueAsDidChange:(CUIRegisterViewValueAsType)inType { NSDictionary * tRepresentation=(NSDictionary *)self.representedObject; CUIRegister * tRegister=(CUIRegister *)tRepresentation[@"register"]; if (tRegister==nil) return; // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUIRegisterItemViewAsValueDidChangeNotification object:tRegister userInfo:@{ @"viewAs":@(inType) }]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewThreadItem.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" @interface CUICollectionViewThreadItem : NSCollectionViewItem @property (nonatomic) BOOL showsOffset; @property (nonatomic) BOOL showsMemoryAddress; @property (nonatomic) BOOL showsBinaryImageIdentifier; @property CUICrashLog * crashLog; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewThreadItem.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewThreadItem.h" @interface CUICollectionViewThreadItem () @end @implementation CUICollectionViewThreadItem - (void)setShowsOffset:(BOOL)aBool { _showsOffset=aBool; } - (void)setShowsMemoryAddress:(BOOL)aBool { } - (void)setShowsBinaryImageIdentifier:(BOOL)aBool { } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewVisibleThreadItem.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewThreadItem.h" @interface CUICollectionViewVisibleThreadItem : CUICollectionViewThreadItem @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewVisibleThreadItem.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewVisibleThreadItem.h" #import "CUILightTableVisibleThreadView.h" #import "CUIThread.h" #import "CUIStackFrame+UI.h" #import "CUICallsSelection.h" @interface CUICollectionViewVisibleThreadItem () { IBOutlet NSTextField * _threadNumberLabel; IBOutlet NSTextField * _threadNumberBigLabel; IBOutlet NSTextField * _threadNameLabel; IBOutlet NSTableView * _backtraceTableView; } - (IBAction)minimizeThreadView:(id)sender; @end @implementation CUICollectionViewVisibleThreadItem #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; self.imageView.cell.backgroundStyle=NSBackgroundStyleEmphasized; _threadNumberBigLabel.cell.backgroundStyle=NSBackgroundStyleEmphasized; _threadNumberLabel.cell.backgroundStyle=NSBackgroundStyleEmphasized; _threadNameLabel.cell.backgroundStyle=NSBackgroundStyleEmphasized; NSScrollView * tScrollView=_backtraceTableView.enclosingScrollView; tScrollView.wantsLayer=YES; tScrollView.layer.cornerRadius=8.0; //tScrollView.layer.maskedCorners=kCALayerMinXMinYCorner|kCALayerMaxXMinYCorner; tScrollView.contentView.wantsLayer=YES; tScrollView.contentView.layer.cornerRadius=8.0; //tScrollView.contentView.layer.maskedCorners=kCALayerMinXMinYCorner|kCALayerMaxXMinYCorner; } #pragma mark - - (void)setRepresentedObject:(id)inRepresentedObject { [super setRepresentedObject:inRepresentedObject]; CUIThread * tThread=(CUIThread *)inRepresentedObject; CUILightTableVisibleThreadView * tView=(CUILightTableVisibleThreadView *)self.view; tView.crashed=tThread.isCrashed; tView.applicationSpecificBacktrace=tThread.isApplicationSpecificBacktrace; self.imageView.image=(tThread.isCrashed==YES) ? [NSImage imageNamed:@"crashedThread_Template"] : [NSImage imageNamed:@"thread_Template"]; if (tThread.isApplicationSpecificBacktrace==YES) { _threadNumberBigLabel.stringValue=tThread.name; _threadNumberLabel.stringValue=@""; _threadNameLabel.stringValue=@""; } else { if (tThread.name==nil) { _threadNumberBigLabel.stringValue=[NSString stringWithFormat:NSLocalizedString(@"Thread %ld",@""),tThread.number]; _threadNumberLabel.stringValue=@""; _threadNameLabel.stringValue=@""; } else { _threadNumberBigLabel.stringValue=@""; _threadNumberLabel.stringValue=[NSString stringWithFormat:NSLocalizedString(@"Thread %ld",@""),tThread.number]; _threadNameLabel.stringValue=tThread.name; } } [_backtraceTableView reloadData]; } - (void)setHighlightState:(NSCollectionViewItemHighlightState)newHighlightState { [super setHighlightState:newHighlightState]; //((MyView *)self.view).highlightState=newHighlightState; } - (void)setSelected:(BOOL)inSelected { [super setSelected:inSelected]; //((MyView *)self.view).selected=inSelected; } - (void)setShowsOffset:(BOOL)aBool { super.showsOffset=aBool; [_backtraceTableView reloadData]; } #pragma mark - - (NSArray *)draggingImageComponents { NSView *itemRootView = self.view; NSRect itemBounds = itemRootView.bounds; NSBitmapImageRep *bitmap = [itemRootView bitmapImageRepForCachingDisplayInRect:itemBounds]; unsigned char *bitmapData = bitmap.bitmapData; if (bitmapData) { bzero(bitmapData, bitmap.bytesPerRow * bitmap.pixelsHigh); } [itemRootView cacheDisplayInRect:itemBounds toBitmapImageRep:bitmap]; NSImage *image = [[NSImage alloc] initWithSize:[bitmap size]]; [image addRepresentation:bitmap]; NSDraggingImageComponent *component = [[NSDraggingImageComponent alloc] initWithKey:NSDraggingImageComponentIconKey]; component.frame = itemBounds; component.contents = image; return [NSArray arrayWithObject:component]; } #pragma mark - - (IBAction)minimizeThreadView:(id)sender { id tDataSource=self.collectionView.dataSource; if ([tDataSource respondsToSelector:@selector(minimizeThread:)]==YES) [tDataSource performSelector:@selector(minimizeThread:) withObject:self.representedObject]; // A COMPLETER } #pragma mark - NSTableViewDataSource - (NSInteger)numberOfRowsInTableView:(NSTableView *)inTableView { CUIThread * tThread=(CUIThread *)self.representedObject; if (tThread==nil) return 0; return tThread.callStackBacktrace.stackFrames.count; } #pragma mark - NSTableViewDelegate - (NSView *)tableView:(NSTableView *)inTableView viewForTableColumn:(NSTableColumn *)inTableColumn row:(NSInteger)inRow { if (inTableView!=_backtraceTableView) return nil; CUIThread * tThread=(CUIThread *)self.representedObject; CUIStackFrame * tCall=(CUIStackFrame *)tThread.callStackBacktrace.stackFrames[inRow]; NSString * tTableColumnIdentifier=inTableColumn.identifier; NSTableCellView * tTableCellView=[inTableView makeViewWithIdentifier:tTableColumnIdentifier owner:self]; if ([tTableColumnIdentifier isEqualToString:@"symbol"]==YES) { NSMutableString * tCallLine=[NSMutableString stringWithFormat:@"%lu ",tCall.index]; [tCallLine appendString:tCall.symbol]; if (self.showsOffset==YES) { [tCallLine appendFormat:@" + %lu",tCall.byteOffset]; } tTableCellView.textField.stringValue=tCallLine; NSString * tBinaryImageIdentifier=tCall.binaryImageIdentifier; BOOL tIsUserCode=NO; CUICrashLogBinaryImages * tBinaryImages=self.crashLog.binaryImages; CUIBinaryImage * tBinaryImage=[tBinaryImages binaryImageWithIdentifierOrName:tBinaryImageIdentifier identifier:&tBinaryImageIdentifier]; if (tBinaryImage!=nil) { NSString * tPath=tBinaryImage.path; if ([tPath isEqualToString:self.crashLog.header.executablePath]==YES) tIsUserCode=YES; } if (tIsUserCode==NO) tIsUserCode=[tBinaryImages isUserCodeAtMemoryAddress:tCall.machineInstructionAddress inBinaryImage:tBinaryImageIdentifier]; if (tIsUserCode==YES) { tTableCellView.imageView.image=[NSImage imageNamed:@"call-usercode"]; tTableCellView.textField.textColor=[NSColor labelColor]; } else { tTableCellView.imageView.image=tCall.binaryImageIcon; tTableCellView.textField.textColor=[NSColor secondaryLabelColor]; } } else if ([tTableColumnIdentifier isEqualToString:@"address"]==YES) { tTableCellView.textField.stringValue=[NSString stringWithFormat:@"0x%012lx",tCall.machineInstructionAddress]; } else if ([tTableColumnIdentifier isEqualToString:@"binary"]==YES) { tTableCellView.textField.stringValue=[NSString stringWithFormat:@"%@",tCall.binaryImageIdentifier]; } /*if ([tCall.binaryImageIdentifier isEqualToString:self.crashLog.header.bundleIdentifier]==YES) { tTableCellView.textField.textColor=[NSColor labelColor]; } else { tTableCellView.textField.textColor=[NSColor secondaryLabelColor]; }*/ return tTableCellView; } - (void)tableViewSelectionDidChange:(NSNotification *)inNotification { NSIndexSet * tIndexSet=[_backtraceTableView selectedRowIndexes]; NSMutableSet * tMutableSet=[NSMutableSet set]; CUIThread * tThread=(CUIThread *)self.representedObject; [tIndexSet enumerateIndexesUsingBlock:^(NSUInteger bIndex, BOOL * bOutStop) { CUIStackFrame * tCall=(CUIStackFrame *)tThread.callStackBacktrace.stackFrames[bIndex]; [tMutableSet addObject:tCall]; }]; [CUICallsSelection sharedCallsSelection].calls=tMutableSet; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewVisibleThreadItem.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewVisibleThreadsLayout.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICollectionViewVisibleThreadsLayout : NSCollectionViewLayout @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICollectionViewVisibleThreadsLayout.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICollectionViewVisibleThreadsLayout.h" #define CUIColumnInterGapWidth 16.0 #define CUICardMinimumWidth 300.0 #define CUICardMaximumWidth 600.0 #define CUICardVerticalMargin 5.0 @interface CUICollectionViewVisibleThreadsLayout () { NSEdgeInsets _cachedEdgeInsets; NSSize _cachedContentSize; CGFloat _cardWidth; CGFloat _cardHeight; } @end @implementation CUICollectionViewVisibleThreadsLayout - (NSSize)itemSize { NSSize tSize; tSize.width=_cardWidth; tSize.height=_cardHeight; return tSize; } - (NSCollectionViewScrollDirection)scrollDirection { return NSCollectionViewScrollDirectionHorizontal; } - (void) prepareLayout { if (self.collectionView==nil) return; [super prepareLayout]; NSView * tSuperView=self.collectionView.superview; NSRect tReferenceBounds=NSZeroRect; if ([tSuperView isKindOfClass:[NSClipView class]]==YES) { tReferenceBounds=tSuperView.bounds; } else { tReferenceBounds=self.collectionView.bounds; } NSInteger tNumberOfItems = [self.collectionView numberOfItemsInSection:0]; CGFloat tVisibleWidth=NSWidth(tReferenceBounds); _cardWidth=(tVisibleWidth-((tNumberOfItems+1) * CUIColumnInterGapWidth))/tNumberOfItems; if (_cardWidthCUICardMaximumWidth) _cardWidth=CUICardMaximumWidth; _cardHeight=NSHeight(tReferenceBounds)-2*CUICardVerticalMargin; NSSize tSize=NSMakeSize((tNumberOfItems * _cardWidth) + ((tNumberOfItems+1) * CUIColumnInterGapWidth), NSHeight(self.collectionView.frame)); NSRect tBounds=tReferenceBounds; CGFloat tHDiff=tBounds.size.width-tSize.width; if (tHDiff>0) { _cachedEdgeInsets.top=_cachedEdgeInsets.bottom=0.0; _cachedEdgeInsets.left=round(tHDiff*0.5); _cachedEdgeInsets.right=tHDiff-_cachedEdgeInsets.left; _cachedContentSize.width+=tHDiff; } else { _cachedEdgeInsets=NSEdgeInsetsZero; } } - (NSSize)collectionViewContentSize { NSView * tSuperView=self.collectionView.superview; NSRect tReferenceBounds=NSZeroRect; if ([tSuperView isKindOfClass:[NSClipView class]]==YES) { tReferenceBounds=tSuperView.bounds; } else { tReferenceBounds=self.collectionView.bounds; } NSInteger tNumberOfItems = [self.collectionView numberOfItemsInSection:0]; CGFloat tVisibleWidth=NSWidth(tReferenceBounds); /*CGFloat _cardWidth=(tVisibleWidth-((tNumberOfItems+1) * CUIColumnInterGapWidth))/tNumberOfItems; if (_cardWidthCUICardMaximumWidth) _cardWidth=CUICardMaximumWidth;*/ CGFloat tTotalWidth=(tNumberOfItems * _cardWidth) + ((tNumberOfItems+1) * CUIColumnInterGapWidth); if (tTotalWidth(_cachedEdgeInsets.left+CUIColumnInterGapWidth+_cardWidth*0.5)) tIndex=(tX-_cachedEdgeInsets.left-CUIColumnInterGapWidth-_cardWidth*0.5)/(CUIColumnInterGapWidth+_cardWidth)+1; NSCollectionViewLayoutAttributes* tAttributes = [NSCollectionViewLayoutAttributes layoutAttributesForInterItemGapBeforeIndexPath:[NSIndexPath indexPathForItem:tIndex inSection:0]]; NSRect tFrame; tFrame.origin.x=_cachedEdgeInsets.left+CUIColumnInterGapWidth*0.5+tIndex * CUIColumnInterGapWidth + (tIndex * _cardWidth)-1; tFrame.size.width=2; tFrame.origin.y=30; tFrame.size.height=_cachedContentSize.height-60; tAttributes.frame=tFrame; return tAttributes; } - (NSArray<__kindof NSCollectionViewLayoutAttributes *> *) layoutAttributesForElementsInRect:(NSRect)rect { NSInteger tNumberOfItems = [self.collectionView numberOfItemsInSection:0]; NSMutableArray* tAttributesArray = [NSMutableArray arrayWithCapacity:tNumberOfItems]; for (NSInteger tIndex=0; tIndex @interface CUIContentBox : NSBox @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIContentBox.m ================================================ /* Copyright (c) 2018, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIContentBox.h" @implementation CUIContentBox - (void)awakeFromNib { self.boxType=NSBoxCustom; self.fillColor=(NSAppKitVersionNumber>=NSAppKitVersionNumber10_14) ? [NSColor controlBackgroundColor] : [NSColor whiteColor]; if (self.borderType!=NSLineBorder) { self.borderType=NSNoBorder; } else { self.borderColor=[NSColor containerBorderColor]; } self.contentViewMargins=NSZeroSize; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIContentsViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIApplicationPreferences.h" #import "CUICrashLogContentsViewController.h" #import "CUIKeyViews.h" @interface CUIContentsViewController : NSViewController @property (nonatomic) CUIPresentationMode presentationMode; @property (nonatomic,readonly) BOOL isEmptySelection; @property (nonatomic,getter=isBottomViewCollapsed) BOOL bottomViewCollapsed; - (IBAction)showHideBottomView:(id)sender; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIContentsViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIContentsViewController.h" #import "CUIPresentationTextNavigationViewController.h" #import "CUICenteredLabelViewController.h" #import "CUICrashLogContentsViewController.h" #import "CUICrashLogsSelection.h" @interface CUIContentsViewController () { IBOutlet NSView * _topView; IBOutlet NSView * _contentsView; CUICenteredLabelViewController * _emptySelectionViewController; CUICrashLogContentsViewController * _contentsViewController; NSViewController * _currentController; CUIPresentationTextNavigationViewController * _navigationViewController; } @property (nonatomic,copy) CUICrashLogsSelection * selection; @end @implementation CUIContentsViewController - (instancetype)init { self=[super init]; if (self!=nil) { _emptySelectionViewController=[CUICenteredLabelViewController new]; _emptySelectionViewController.label=NSLocalizedString(@"No Selection",@""); _emptySelectionViewController.verticalOffset=24.0; _contentsViewController=[CUICrashLogContentsViewController new]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(crashLogsSelectionDidChange:) name:CUICrashLogsSelectionDidChangeNotification object:nil]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSString *)nibName { return @"CUIContentsViewController"; } - (void)viewDidLoad { [super viewDidLoad]; _navigationViewController=[CUIPresentationTextNavigationViewController new]; _navigationViewController.view.frame=_topView.bounds; [_topView addSubview:_navigationViewController.view]; self.selection=[CUICrashLogsSelection new]; } #pragma mark - NSObject - (id)forwardingTargetForSelector:(SEL)aSelector { if (_currentController!=_contentsViewController) return nil; return _contentsViewController; } - (BOOL)respondsToSelector:(SEL)aSelector { BOOL tResponds=[super respondsToSelector:aSelector]; if (tResponds==YES) return YES; if (_currentController!=_contentsViewController) return NO; NSString * tSelectorName=NSStringFromSelector(aSelector); if ([tSelectorName hasPrefix:@"CUI_MENUACTION_"]==NO && [tSelectorName isEqualToString:@"performTextFinderAction:"]==NO) return NO; tResponds=[_contentsViewController respondsToSelector:aSelector]; if (tResponds==YES) return YES; return NO; } #pragma mark - - (BOOL)isBottomViewCollapsed { return _contentsViewController.isBottomViewCollapsed; } - (CUIPresentationMode)presentationMode { if (_currentController==nil || _currentController!=_contentsViewController) return CUIPresentationModeUnknown; return _contentsViewController.presentationMode; } - (void)setPresentationMode:(CUIPresentationMode)inPresentationMode { if (_currentController==nil || _currentController!=_contentsViewController) return; _contentsViewController.presentationMode=inPresentationMode; _navigationViewController.presentationViewController=_contentsViewController.presentationViewController; } - (BOOL)isEmptySelection { return (_selection.crashLogs.count==0); } - (void)setSelection:(CUICrashLogsSelection *)inSelection { if ([_selection isEqual:inSelection]==YES) return; _selection=[inSelection copy]; NSViewController * tNewController=nil; if (_selection.crashLogs.count==0) { tNewController=_emptySelectionViewController; _navigationViewController.presentationViewController=nil; } else { tNewController=_contentsViewController; } if (_currentController!=tNewController) { [_currentController.view removeFromSuperview]; tNewController.view.frame=_contentsView.bounds; [_contentsView addSubview:tNewController.view]; } _currentController=tNewController; if (_selection.crashLogs.count!=0) { _contentsViewController.crashLog=_selection.crashLogs.firstObject; _navigationViewController.presentationViewController=_contentsViewController.presentationViewController; } } - (IBAction)showHideBottomView:(id)sender { if (_contentsViewController.presentationMode!=CUIPresentationModeOutline) return; [_contentsViewController showHideBottomView:sender]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (_currentController!=_contentsViewController) return NO; if ([super respondsToSelector:tAction]==NO) { NSString * tSelectorName=NSStringFromSelector(tAction); if ([tSelectorName hasPrefix:@"CUI_MENUACTION_"]==NO && [tSelectorName isEqualToString:@"performTextFinderAction:"]==NO) return NO; if ([_contentsViewController respondsToSelector:tAction]==YES) return [_contentsViewController validateMenuItem:inMenuItem]; return NO; } return YES; } #pragma mark - CUIKeyViews - (NSView *)firstKeyView { if (_currentController==nil || _currentController==_emptySelectionViewController) return nil; return _contentsViewController.firstKeyView; } - (NSView *)lastKeyView { if (_currentController==nil || _currentController==_emptySelectionViewController) return nil; return _contentsViewController.lastKeyView; } #pragma mark - Notifications - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification { CUICrashLogsSelection * tSelection=inNotification.object; if (tSelection==nil) return; self.selection=tSelection; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIContentsViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashDataTransform.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIReportThemedTransform.h" @interface CUICrashDataTransform : CUIReportThemedTransform @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashDataTransform.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashDataTransform.h" #import "CUIApplicationPreferences.h" #import "CUIApplicationPreferences+Themes.h" #import "CUICrashLogBinaryImages.h" #import "CUIBinaryImageUtility.h" #import "CUIThemesManager.h" #import "CUIThemeItemsGroup+UI.h" #ifndef __DISABLE_SYMBOLICATION_ #import "CUIdSYMBundlesManager.h" #import "CUISymbolicationManager.h" #import "CUISymbolicationDataFormatter.h" #endif #import "CUICrashLogExceptionInformation+QuickHelp.h" @interface CUICrashLog (Private) // Sections ranges @property (readonly) NSRange headerRange; @property (readonly) NSRange exceptionInformationRange; @property (readonly) NSRange diagnosticMessagesRange; @property (readonly) NSRange backtracesRange; @property (readonly) NSRange threadStateRange; @property (readonly) NSRange binaryImagesRange; @end @interface CUIDataTransform (Private) - (void)setOutput:(NSAttributedString *)inOutput; @end @implementation CUICrashDataTransform - (CUICrashLog *)crashlog { return self.input; } #pragma mark - - (BOOL)transform { if ([super transform]==NO) return NO; CUICrashLog * tCrashLog=self.input; if ([tCrashLog isKindOfClass:CUIRawCrashLog.class]==NO) { // A COMPLETER return NO; } [self updatesCachedAttributes]; if ([tCrashLog isMemberOfClass:CUIRawCrashLog.class]==YES) { NSAttributedString * tAttributedString=[[NSAttributedString alloc] initWithString:tCrashLog.rawText attributes:self.plainTextAttributes]; self.output=tAttributedString; return YES; } if ([tCrashLog isMemberOfClass:CUICrashLog.class]==NO) { // A COMPLETER return NO; } self.processPath=tCrashLog.header.executablePath; NSMutableArray * tLines=[NSMutableArray array]; [tCrashLog.rawText enumerateLinesUsingBlock:^(NSString * bLine, BOOL * bOutStop) { [tLines addObject:bLine]; }]; NSMutableArray * tMutableArray=[tLines mutableCopy]; if (tCrashLog.binaryImagesRange.location!=NSNotFound) { if ((self.displaySettings.visibleSections & CUIDocumentBinaryImagesSection)==0) { [tMutableArray removeObjectsInRange:tCrashLog.binaryImagesRange]; } else { NSArray * tBacktracesLines=[tLines subarrayWithRange:tCrashLog.binaryImagesRange]; NSArray * tFilteredLines=[self processedBinaryImagesSectionLines:tBacktracesLines reportVersion:tCrashLog.reportVersion error:NULL]; [tMutableArray removeObjectsInRange:tCrashLog.binaryImagesRange]; [tMutableArray insertObjects:tFilteredLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tCrashLog.binaryImagesRange.location,tFilteredLines.count)]]; } } if (tCrashLog.threadStateRange.location!=NSNotFound) { if ((self.displaySettings.visibleSections & CUIDocumentThreadStateSection)==0) { [tMutableArray removeObjectsInRange:tCrashLog.threadStateRange]; } else { NSArray * tThreadStateLines=[tLines subarrayWithRange:tCrashLog.threadStateRange]; NSArray * tFilteredLines=[self processedThreadStateSectionLines:tThreadStateLines error:NULL]; [tMutableArray removeObjectsInRange:tCrashLog.threadStateRange]; [tMutableArray insertObjects:tFilteredLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tCrashLog.threadStateRange.location,tFilteredLines.count)]]; } } if (tCrashLog.backtracesRange.location!=NSNotFound) { if ((self.displaySettings.visibleSections & CUIDocumentBacktracesSection)==0) { [tMutableArray removeObjectsInRange:tCrashLog.backtracesRange]; } else { NSArray * tBacktracesLines=[tLines subarrayWithRange:tCrashLog.backtracesRange]; NSArray * tFilteredLines=[self processedBacktracesSectionLines:tBacktracesLines error:NULL]; [tMutableArray removeObjectsInRange:tCrashLog.backtracesRange]; [tMutableArray insertObjects:tFilteredLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tCrashLog.backtracesRange.location,tFilteredLines.count)]]; } } if (tCrashLog.diagnosticMessagesRange.location!=NSNotFound) { if ((self.displaySettings.visibleSections & CUIDocumentDiagnosticMessagesSection)==0) { [tMutableArray removeObjectsInRange:tCrashLog.diagnosticMessagesRange]; } else { NSArray * tDiagnosticMessagesLines=[tLines subarrayWithRange:tCrashLog.diagnosticMessagesRange]; NSArray * tFilteredLines=[self processedDiagnosticMessagesSectionLines:tDiagnosticMessagesLines error:NULL]; [tMutableArray removeObjectsInRange:tCrashLog.diagnosticMessagesRange]; [tMutableArray insertObjects:tFilteredLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tCrashLog.diagnosticMessagesRange.location,tFilteredLines.count)]]; } } if (tCrashLog.exceptionInformationRange.location!=NSNotFound) { if ((self.displaySettings.visibleSections & CUIDocumentExceptionInformationSection)==0) { [tMutableArray removeObjectsInRange:tCrashLog.exceptionInformationRange]; } else { NSArray * tExceptionInformationLines=[tLines subarrayWithRange:tCrashLog.exceptionInformationRange]; NSArray * tFilteredLines=[self processedExceptionInformationSectionLines:tExceptionInformationLines error:NULL]; [tMutableArray removeObjectsInRange:tCrashLog.exceptionInformationRange]; [tMutableArray insertObjects:tFilteredLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tCrashLog.exceptionInformationRange.location,tFilteredLines.count)]]; } } if (tCrashLog.isHeaderAvailable==YES) { if ((self.displaySettings.visibleSections & CUIDocumentHeaderSection)==0) { [tMutableArray removeObjectsInRange:tCrashLog.headerRange]; } else { NSArray * HeaderLines=[tLines subarrayWithRange:tCrashLog.headerRange]; NSArray * tFilteredLines=[self processedHeaderSectionLines:HeaderLines error:NULL]; [tMutableArray removeObjectsInRange:tCrashLog.headerRange]; [tMutableArray insertObjects:tFilteredLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tCrashLog.headerRange.location,tFilteredLines.count)]]; } } self.output=[self joinLines:tMutableArray withString:@"\n"]; return YES; } #pragma mark - Header - (NSArray *)processedHeaderSectionLines:(NSArray *)inLines error:(NSError **)outError { if (inLines.count==0) return inLines; NSMutableArray * tProcessedLines=[NSMutableArray array]; [inLines enumerateObjectsUsingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { NSUInteger tLineLength=bLine.length; // Skip Blank lines if (tLineLength==0) { [tProcessedLines addObject:bLine]; return; } // Find Key and Value NSScanner * tScanner=[NSScanner scannerWithString:bLine]; NSString * tKey; if ([tScanner scanUpToString:@":" intoString:&tKey]==NO) { [tProcessedLines addObject:bLine]; *bOutStop=YES; return; } NSRange tKeyRange=NSMakeRange(0,tScanner.scanLocation+1); tScanner.scanLocation=tScanner.scanLocation+1; tScanner.charactersToBeSkipped=nil; [tScanner scanCharactersFromSet:self.whitespaceCharacterSet intoString:NULL]; NSRange tValueRange=NSMakeRange(tScanner.scanLocation,bLine.length-1-tScanner.scanLocation+1); NSMutableAttributedString * tProcessedLine=[[NSMutableAttributedString alloc] initWithString:bLine attributes:self.plainTextAttributes]; if (bLineNumber==0) { NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Header" }; [tProcessedLine addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,bLine.length)]; } [tProcessedLine addAttributes:self.keyAttributes range:tKeyRange]; if ([tKey isEqualToString:@"Path"]==YES) { [tProcessedLine addAttributes:self.pathAttributes range:tValueRange]; } else if ([tKey isEqualToString:@"Version"]==YES || [tKey isEqualToString:@"OS Version"]==YES) { [tProcessedLine addAttributes:self.versionAttributes range:tValueRange]; } else if ([tKey isEqualToString:@"Anonymous UUID"]==YES || [tKey isEqualToString:@"Sleep/Wake UUID"]==YES) { [tProcessedLine addAttributes:self.UUIDAttributes range:tValueRange]; } [tProcessedLines addObject:tProcessedLine]; }]; return [tProcessedLines copy]; } #pragma mark - Exception Information - (NSArray *)processedExceptionInformationSectionLines:(NSArray *)inLines error:(NSError **)outError { if (inLines.count==0) return inLines; NSMutableArray * tProcessedLines=[NSMutableArray array]; [inLines enumerateObjectsUsingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { NSUInteger tLineLength=bLine.length; // Skip Blank lines if (tLineLength==0) { [tProcessedLines addObject:bLine]; return; } // Find Key and Value NSScanner * tScanner=[NSScanner scannerWithString:bLine]; NSString * tKey; if ([tScanner scanUpToString:@":" intoString:&tKey]==NO || tScanner.scanLocation==tLineLength) { [tProcessedLines addObject:bLine]; return; } NSRange tKeyRange=NSMakeRange(0,tScanner.scanLocation+1); tScanner.scanLocation=tScanner.scanLocation+1; tScanner.charactersToBeSkipped=nil; [tScanner scanCharactersFromSet:self.whitespaceCharacterSet intoString:NULL]; NSRange tValueRange=NSMakeRange(tScanner.scanLocation,bLine.length-1-tScanner.scanLocation+1); NSMutableAttributedString * tProcessedLine=[[NSMutableAttributedString alloc] initWithString:bLine attributes:self.plainTextAttributes]; [tProcessedLine addAttributes:self.keyAttributes range:tKeyRange]; if (bLineNumber==0) { NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Exception Information" }; [tProcessedLine addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,bLine.length)]; } if ([tKey isEqualToString:@"Exception Type"]==YES) { switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: [tProcessedLine addAttributes:@{ NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle|NSUnderlineStylePatternDash) } range:tValueRange]; [tProcessedLine addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"a://exception_type"] } range:tValueRange]; break; default: break; } } if ([tKey isEqualToString:@"Termination Reason"]==YES) { switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: if (self.crashlog.exceptionInformation.isQuickHelpAvailableForTerminationReason==YES) { [tProcessedLine addAttributes:@{ NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle|NSUnderlineStylePatternDash) } range:tValueRange]; [tProcessedLine addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"a://termination_reason"] } range:tValueRange]; } break; default: break; } } if ([tKey isEqualToString:@"Crashed Thread"]==YES) { if ((self.displaySettings.visibleSections & CUIDocumentBacktracesSection)==CUIDocumentBacktracesSection && ((CUICrashLog *)self.input).backtraces.threads.count>0) { switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: [tProcessedLine addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"a://crashed_thread"] } range:tKeyRange]; break; case CUIHyperlinksHTML: [tProcessedLine addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"sharp://crashed_thread"] } range:tKeyRange]; break; default: break; } } [tProcessedLine addAttributes:self.crashedThreadLabelAttributes range:tValueRange]; } [tProcessedLines addObject:tProcessedLine]; }]; return tProcessedLines; } #pragma mark - Diagnostic Messages - (NSArray *)processedDiagnosticMessagesSectionLines:(NSArray *)inLines error:(NSError **)outError { if (inLines.count==0) return inLines; NSMutableArray * tProcessedLines=[NSMutableArray array]; // First line NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Diagnostic Messages" }; NSMutableAttributedString * tAttributedString=[[NSMutableAttributedString alloc] initWithString:inLines.firstObject attributes:tJumpAnchorAttributes]; NSDictionary * tFirstLineAttributes=self.keyAttributes; [tAttributedString addAttributes:tFirstLineAttributes range:NSMakeRange(0,tAttributedString.length)]; [tProcessedLines addObject:tAttributedString]; // Other Lines NSRange tOtherLinesRange=NSMakeRange(1,inLines.count-1); [inLines enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:tOtherLinesRange] options:0 usingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { id tObject=bLine; NSUInteger tLineLength=bLine.length; if (tLineLength==0) { [tProcessedLines addObject:bLine]; return; } if ([bLine characterAtIndex:tLineLength-1]==':') { if ([bLine isEqualToString:@"Application Specific Information:"]==YES || [bLine isEqualToString:@"Dyld Error Message:"]==YES || [bLine isEqualToString:@"Application Specific Signatures:"]==YES || [bLine isEqualToString:@"CreationBacktrace:"]==YES || [bLine isEqualToString:@" Ordered grouping begin/end backtraces:"]==YES) { NSAttributedString * tLineAttributedString=[[NSAttributedString alloc] initWithString:bLine attributes:self.keyAttributes]; tObject=tLineAttributedString; } } [tProcessedLines addObject:tObject]; }]; return tProcessedLines; } #pragma mark - Backtraces - (NSArray *)processedBacktracesSectionLines:(NSArray *)inLines error:(NSError **)outError { if (inLines.count==0) return inLines; NSMutableArray * tProcessedLines=[NSMutableArray array]; __block NSInteger tThreadEntityLineStart=0; __block NSInteger tThreadEntityLineEnd=0; [inLines enumerateObjectsUsingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL *bOutStop) { // Retrieve thread number, crashed status and dispatch queue name if (bLine.length!=0) return; tThreadEntityLineEnd=bLineNumber; // Keep the blank line NSRange tThreadRange=NSMakeRange(tThreadEntityLineStart, tThreadEntityLineEnd-tThreadEntityLineStart+1); NSError * tError; NSArray * tFilteredThreadLines=[self processedThreadBacktraceLines:[inLines subarrayWithRange:tThreadRange] error:&tError]; [tProcessedLines addObjectsFromArray:tFilteredThreadLines]; tThreadEntityLineStart=bLineNumber+1; }]; NSMutableAttributedString * tMutableAttributedString=tProcessedLines.firstObject; NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Backtraces" }; [tMutableAttributedString addAttributes:tJumpAnchorAttributes range:NSMakeRange(0, tMutableAttributedString.length)]; return tProcessedLines; } - (NSArray *)processedThreadBacktraceLines:(NSArray *)inLines error:(NSError **)outError { if (inLines.count==0) return inLines; NSString * tHeaderLine=inLines.firstObject; BOOL tCrashedThread=NO; NSString * tName=nil; if ([tHeaderLine isEqualToString:@"Backtrace not available"]==YES) { NSMutableAttributedString * tMutableAttributedString=[[NSMutableAttributedString alloc] initWithString:tHeaderLine attributes:self.plainTextAttributes]; NSMutableArray * tProcessedLines=[NSMutableArray arrayWithObject:tMutableAttributedString]; NSRange tOtherLinesRange=NSMakeRange(1,inLines.count-1); [inLines enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:tOtherLinesRange] options:0 usingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { [tProcessedLines addObject:bLine]; }]; return [tProcessedLines copy]; } CUICrashLogBacktraces * tBacktraces=((CUICrashLog *)self.input).backtraces; CUIThread * tThread=nil; if ([tHeaderLine hasPrefix:@"Application Specific Backtrace"]==YES) { tName=@"Application Specific Backtrace"; tThread=[tBacktraces threadNamed:tName]; } else { NSArray * tComponents=[tHeaderLine componentsSeparatedByString:@"::"]; NSString * tLeftPart; if (tComponents.count==0) { // Uh oh // A COMPLETER } tLeftPart=tComponents.firstObject; if (tComponents.count!=2) tLeftPart=[tLeftPart stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]; NSArray * tThreadNumberComponents=[tLeftPart componentsSeparatedByString:@" "]; if (tThreadNumberComponents.count<2) { // Uh oh if (outError!=NULL) *outError=[NSError errorWithDomain:CUIDataTransformErrorDomain code:CUIDataTransformUnknownError userInfo:@{}]; return nil; } tName=tThreadNumberComponents[1]; // <- it's actually the number if (tThreadNumberComponents.count==3) { if ([tThreadNumberComponents[2] caseInsensitiveCompare:@"Crashed"]==NSOrderedSame) tCrashedThread=YES; } if ((self.displaySettings.visibleSections & CUIDocumentBacktraceCrashedThreadSubSection)!=0) { if (tCrashedThread==NO) return @[]; } tThread=[tBacktraces threadWithNumber:[tName integerValue]]; } NSMutableAttributedString * tMutableAttributedString=[[NSMutableAttributedString alloc] initWithString:inLines.firstObject attributes:self.plainTextAttributes]; NSRange tStringRange=NSMakeRange(0, tMutableAttributedString.length); [tMutableAttributedString addAttributes:@{ CUIThreadAnchorAttributeName:[NSString stringWithFormat:@"thread:%@",tName] } range:tStringRange]; if (tCrashedThread==YES) { switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: [tMutableAttributedString addAttributes:@{ CUIGenericAnchorAttributeName:@"a:crashed_thread" } range:tStringRange]; break; case CUIHyperlinksHTML: { NSURL * tURL=[NSURL URLWithString:@"anchor://crashed_thread"]; if (tURL!=nil) [tMutableAttributedString addAttributes:@{NSLinkAttributeName:tURL} range:tStringRange]; break; } default: break; } } NSDictionary * tAttributes=(tCrashedThread==YES) ? self.crashedThreadLabelAttributes : self.threadLabelAttributes; [tMutableAttributedString addAttributes:tAttributes range:tStringRange]; NSMutableArray * tProcessedLines=[NSMutableArray arrayWithObject:tMutableAttributedString]; NSRange tOtherLinesRange=NSMakeRange(1,inLines.count-1); __block NSUInteger tStackFrameIndex=0; [inLines enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:tOtherLinesRange] options:0 usingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { if (bLine.length==0) { [tProcessedLines addObject:bLine]; return; } NSString * tProcessedStackFrameLine=[self processedStackFrameLine:bLine stackFrame:tThread.callStackBacktrace.stackFrames[tStackFrameIndex]]; if (tProcessedStackFrameLine!=nil) { [tProcessedLines addObject:tProcessedStackFrameLine]; } else { NSLog(@"Error transforming line: %@",bLine); [tProcessedLines addObject:bLine]; } tStackFrameIndex+=1; }]; return tProcessedLines; } #pragma mark - Thread State - (NSArray *)processedThreadStateSectionLines:(NSArray *)inLines error:(NSError **)outError { if (inLines.count==0) return inLines; NSMutableArray * tProcessedLines=[NSMutableArray array]; // First line NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Thread State" }; NSMutableAttributedString * tAttributedString=[[NSMutableAttributedString alloc] initWithString:inLines.firstObject attributes:tJumpAnchorAttributes]; NSDictionary * tFirstLineAttributes=self.keyAttributes; [tAttributedString addAttributes:tFirstLineAttributes range:NSMakeRange(0,tAttributedString.length)]; [tProcessedLines addObject:tAttributedString]; // Other Lines NSRange tOtherLinesRange=NSMakeRange(1,inLines.count-1); __block NSUInteger tLastLine=0; [inLines enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:tOtherLinesRange] options:0 usingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { NSMutableAttributedString * tMutableAttributedString=[[NSMutableAttributedString alloc] initWithString:bLine attributes:self.keyAttributes]; if (bLine.length<4) { tLastLine=bLineNumber+1; [tProcessedLines addObject:tMutableAttributedString]; *bOutStop=YES; return; } NSScanner * tRegistersScanner=[NSScanner scannerWithString:bLine]; tRegistersScanner.charactersToBeSkipped=self.whitespaceCharacterSet; while (tRegistersScanner.isAtEnd==NO) { tRegistersScanner.charactersToBeSkipped=nil; [tRegistersScanner scanCharactersFromSet:self.whitespaceCharacterSet intoString:nil]; NSString * tRegisterName; tRegistersScanner.charactersToBeSkipped=self.whitespaceCharacterSet; if ([tRegistersScanner scanUpToString:@":" intoString:&tRegisterName]==NO) return; if ([tRegistersScanner scanString:@": " intoString:NULL]==NO) return; NSRange tValueRange=NSMakeRange(tRegistersScanner.scanLocation, 0); if ([tRegistersScanner scanHexLongLong:NULL]==NO) return; tValueRange.length=tRegistersScanner.scanLocation-1-tValueRange.location+1; tRegistersScanner.charactersToBeSkipped=nil; [tRegistersScanner scanCharactersFromSet:self.whitespaceCharacterSet intoString:nil]; [tMutableAttributedString addAttributes:self.registerValueAttributes range:tValueRange]; } [tProcessedLines addObject:tMutableAttributedString]; }]; // Remaining lines [inLines enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tLastLine,inLines.count-1-tLastLine+1)] options:0 usingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { NSUInteger tLineLength=bLine.length; // Skip Blank lines if (tLineLength==0) { [tProcessedLines addObject:[[NSAttributedString alloc] initWithString:bLine attributes:self.plainTextAttributes]]; return; } // Find Key and Value NSScanner * tScanner=[NSScanner scannerWithString:bLine]; NSString * tKey; if ([tScanner scanUpToString:@":" intoString:&tKey]==NO) { // A COMPLETER [tProcessedLines addObject:[[NSAttributedString alloc] initWithString:bLine attributes:self.plainTextAttributes]]; return; } NSRange tKeyRange=NSMakeRange(0,tScanner.scanLocation+1); NSMutableAttributedString * tMutableAttributedString=nil; if (tScanner.scanLocation1) { // User Code tIsUserCode=YES; } NSMutableAttributedString * tNewLine=[[NSMutableAttributedString alloc] initWithString:inLine attributes:self.plainTextAttributes]; tScanner.scanLocation=tIdentifierStart+tIdentifierRealLength; NSRange tIdentifierRange=NSMakeRange(tIdentifierStart, tIdentifierRealLength); if (inReportVersion==6) { tScanner.scanLocation+=1; } else { if (tIsMissingVersion==NO) { if ([tScanner scanUpToString:@"(" intoString:NULL]==NO) return nil; } else { if ([tScanner scanUpToString:@"<" intoString:NULL]==NO) return nil; } } // Version NSUInteger tVersionStart=NSNotFound; NSUInteger tVersionEnd=NSNotFound; if (tIsMissingVersion==NO) { tVersionStart=tScanner.scanLocation; if ([tScanner scanUpToString:@")" intoString:NULL]==NO) return nil; tVersionEnd=tScanner.scanLocation; } // UUID can be missing // A COMPLETER if (tIsMissingVersion==NO) { tScanner.scanLocation+=2; } NSUInteger tUUIDStart=NSNotFound; NSUInteger tUUIDEnd=NSNotFound; if ([inLine characterAtIndex:tScanner.scanLocation]=='<') { tUUIDStart=tScanner.scanLocation; if ([tScanner scanUpToString:@">" intoString:NULL]==NO) return nil; tUUIDEnd=tScanner.scanLocation; } else { tScanner.scanLocation-=2; } if ([tScanner scanUpToString:@"/" intoString:NULL]==NO) return nil; if (tUUIDEnd!=NSNotFound) { NSString * tBinaryImageUUID=[inLine substringWithRange:NSMakeRange(tUUIDStart+1, tUUIDEnd-tUUIDStart-1)]; switch(self.hyperlinksStyle) { case CUIHyperlinksHTML: { NSURL * tURL=[NSURL URLWithString:[NSString stringWithFormat:@"anchor://%@",tBinaryImageUUID]]; if (tURL!=nil) [tNewLine addAttributes:@{NSLinkAttributeName:tURL} range:NSMakeRange(0, tNewLine.length)]; break; } default: [tNewLine addAttributes:@{ CUIBinaryAnchorAttributeName:[NSString stringWithFormat:@"bin:%@",tBinaryImageUUID] } range:NSMakeRange(0, tNewLine.length)]; break; } } NSRange tPathRange=NSMakeRange(tScanner.scanLocation,inLine.length-1-tScanner.scanLocation+1); NSDictionary * tIdentifierAttributes=self.plainTextAttributes; if (self.themesProvider.currentTheme.isMonochrome==NO) { tIdentifierAttributes=@{ NSForegroundColorAttributeName:(tIsUserCode==YES) ? [CUIBinaryImageUtility colorForUserCode]: [CUIBinaryImageUtility colorForIdentifier:tIdentifier] }; } [tNewLine addAttributes:tIdentifierAttributes range:tIdentifierRange]; [tNewLine addAttributes:self.memoryAddressAttributes range:NSMakeRange(tMinAddressStart, tMinAddressEnd-tMinAddressStart+1)]; [tNewLine addAttributes:self.memoryAddressAttributes range:NSMakeRange(tMaxAddressStart, tMaxAddressEnd-tMaxAddressStart+1)]; if (tUUIDStart!=NSNotFound) { [tNewLine addAttributes:self.UUIDAttributes range:NSMakeRange(tUUIDStart,tUUIDEnd-tUUIDStart+1)]; } if (tVersionEnd!=NSNotFound && tVersionStart!=NSNotFound) { [tNewLine addAttributes:self.versionAttributes range:NSMakeRange(tVersionStart,tVersionEnd-tVersionStart+1)]; } [tNewLine addAttributes:self.pathAttributes range:tPathRange]; return tNewLine; } #pragma mark - - (NSAttributedString *)joinLines:(NSArray *)inLines withString:(NSString *)inNewLineFeed { NSMutableAttributedString * tMutableAttributedString=[NSMutableAttributedString new]; [inLines enumerateObjectsUsingBlock:^(id bLine, NSUInteger bLineNumber, BOOL * bOutStop) { if ([bLine isKindOfClass:NSString.class]==YES) { NSAttributedString * tAttributedString=[[NSAttributedString alloc] initWithString:bLine attributes:self.plainTextAttributes]; [tMutableAttributedString appendAttributedString:tAttributedString]; if (bLineNumber @interface CUICrashLog (UI) - (NSImage *)processIcon; - (NSString *)operatingSystemDisplayName; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLog+UI.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLog+UI.h" #import "CUIRawCrashLog+Path.h" @implementation CUICrashLog (UI) - (NSImage *)processIcon { static NSImage * sExecutableBinaryIcon=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sExecutableBinaryIcon=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ExecutableBinaryIcon.icns"]; }); NSString * tPath=[self stringByResolvingUSERInPath:self.header.executablePath]; NSString * tMacOSDirectoryPath=tPath.stringByDeletingLastPathComponent; if ([tMacOSDirectoryPath.lastPathComponent isEqualToString:@"MacOS"]==NO) return [[NSWorkspace sharedWorkspace] iconForFile:tPath]; NSString * tContentsDirectoryPath=tMacOSDirectoryPath.stringByDeletingLastPathComponent; if ([tContentsDirectoryPath.lastPathComponent isEqualToString:@"Contents"]==NO) return sExecutableBinaryIcon; NSDictionary * tDictionary=[NSDictionary dictionaryWithContentsOfFile:[tContentsDirectoryPath stringByAppendingPathComponent:@"Info.plist"]]; if (tDictionary==nil) return sExecutableBinaryIcon; NSString * tExecutableName=tDictionary[@"CFBundleExecutable"]; if ([tExecutableName isEqualToString:tPath.lastPathComponent]==NO) return sExecutableBinaryIcon; NSString * tApplicationIconName=tDictionary[@"CFBundleIconFile"]; if (tApplicationIconName.pathExtension.length==0) tApplicationIconName=[tApplicationIconName stringByAppendingPathExtension:@"icns"]; NSString * tIconPath=[[tContentsDirectoryPath stringByAppendingPathComponent:@"Resources"] stringByAppendingPathComponent:tApplicationIconName]; NSImage * tImage=[[NSImage alloc] initWithContentsOfFile:tIconPath]; if (tImage!=nil) return tImage; return [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericApplicationIcon)]; } - (NSString *)operatingSystemDisplayName { CUIOperatingSystemVersion * tVersion=self.header.operatingSystemVersion; switch(tVersion.majorVersion) { case 11: return @"macOS Big Sur"; case 12: return @"macOS Monterey"; case 13: return @"macOS Ventura"; case 14: return @"macOS Sonoma"; default: break; } NSUInteger tMinorVersion=self.header.operatingSystemVersion.minorVersion; switch(tMinorVersion) { case 6: return @"Mac OS X Snow Leopard"; case 10: return @"OS X Yosemite"; case 11: return @"macOS Mavericks"; case 12: return @"macOS Sierra"; case 13: return @"macOS High Sierra"; case 14: return @"macOS Mojave"; case 15: return @"macOS Catalina"; } return @"macOS"; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLog.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRawCrashLog.h" #import "CUICrashLogHeader.h" #import "CUICrashLogExceptionInformation.h" #import "CUICrashLogDianosticMessages.h" #import "CUICrashLogBacktraces.h" #import "CUICrashLogThreadState.h" #import "CUICrashLogBinaryImages.h" #import "NSFileManager+ExtendedAttributes.h" @interface CUICrashLog : CUIRawCrashLog @property (readonly) CUICrashLogHeader * header; @property (readonly) CUICrashLogExceptionInformation * exceptionInformation; @property (readonly) CUICrashLogDianosticMessages * diagnosticMessages; @property (readonly) CUICrashLogBacktraces * backtraces; @property (readonly) CUICrashLogThreadState * threadState; @property (readonly) CUICrashLogBinaryImages * binaryImages; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLog.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLog.h" #import "CUIParsingErrors.h" #import "CUICrashLogSectionsDetector.h" @interface CUICrashLog () @property NSError * parsingError; // Sections ranges @property NSRange headerRange; @property NSRange exceptionInformationRange; @property NSRange diagnosticMessagesRange; @property NSRange backtracesRange; @property NSRange threadStateRange; @property NSRange binaryImagesRange; @property BOOL fullyParsed; @property CUICrashLogHeader * header; @property CUICrashLogExceptionInformation * exceptionInformation; @property CUICrashLogDianosticMessages * diagnosticMessages; @property CUICrashLogBacktraces * backtraces; @property CUICrashLogThreadState * threadState; @property CUICrashLogBinaryImages * binaryImages; @end @implementation CUICrashLog - (instancetype)initWithString:(NSString *)inString error:(NSError **)outError { if ([inString isKindOfClass:NSString.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super initWithString:inString error:outError]; if (self!=nil) { _headerRange.location=NSNotFound; _exceptionInformationRange.location=NSNotFound; _diagnosticMessagesRange.location=NSNotFound; _backtracesRange.location=NSNotFound; _threadStateRange.location=NSNotFound; _binaryImagesRange.location=NSNotFound; NSError * tError=nil; if (self.ipsReport!=nil) { IPSIncident * tIncident=self.ipsReport.incident; _header=[[CUICrashLogHeader alloc] initWithIPSIncident:tIncident error:&tError]; if (_header==nil) { // A COMPLETER return nil; } _exceptionInformation=[[CUICrashLogExceptionInformation alloc] initWithIPSIncident:tIncident error:&tError]; if (_exceptionInformation==nil) { // A COMPLETER return nil; } _diagnosticMessages=[[CUICrashLogDianosticMessages alloc] initWithIPSIncident:tIncident error:&tError]; if (_diagnosticMessages==nil) { // A COMPLETER return nil; } } else { NSMutableArray * tLines=[NSMutableArray array]; [self.rawText enumerateLinesUsingBlock:^(NSString * bLine, BOOL * bOutStop) { [tLines addObject:bLine]; }]; @try { BOOL tResult=[self detectSectionsOfTextualRepresentation:tLines error:&tError]; if (tResult==NO) { NSLog(@"Error detecting section : %@",tError.userInfo[CUIParsingErrorSectionNameKey]); _parsingError=tError; // Raw Text Mode only // A COMPLETER return nil; } _header=[[CUICrashLogHeader alloc] initWithTextualRepresentation:[tLines subarrayWithRange:_headerRange] error:&tError]; if (_header==nil) { if (tError!=nil) { NSUInteger tAbsoluteLineNumber=[tError.userInfo[CUIParsingErrorLineKey] unsignedIntegerValue]+_headerRange.location; NSLog(@"Error parsing line : %lu",tAbsoluteLineNumber); _parsingError=[NSError errorWithDomain:CUIParsingErrorDomain code:tError.code userInfo:@{CUIParsingErrorLineKey:@(tAbsoluteLineNumber)}]; } // A COMPLETER return nil; } _exceptionInformation=[[CUICrashLogExceptionInformation alloc] initWithTextualRepresentation:[tLines subarrayWithRange:_exceptionInformationRange] reportVersion:_header.reportVersion error:&tError]; if (_exceptionInformation==nil) { if (tError!=nil) { NSUInteger tAbsoluteLineNumber=[tError.userInfo[CUIParsingErrorLineKey] unsignedIntegerValue]+_headerRange.location; NSLog(@"Error parsing line : %lu",tAbsoluteLineNumber); _parsingError=[NSError errorWithDomain:CUIParsingErrorDomain code:tError.code userInfo:@{CUIParsingErrorLineKey:@(tAbsoluteLineNumber)}]; } // A COMPLETER return nil; } if (_diagnosticMessagesRange.location!=NSNotFound) { _diagnosticMessages=[[CUICrashLogDianosticMessages alloc] initWithTextualRepresentation:[tLines subarrayWithRange:_diagnosticMessagesRange] reportVersion:_header.reportVersion error:&tError]; if (_diagnosticMessages==nil) { if (tError!=nil) { NSUInteger tAbsoluteLineNumber=[tError.userInfo[CUIParsingErrorLineKey] unsignedIntegerValue]+_headerRange.location; NSLog(@"Error parsing line : %lu",tAbsoluteLineNumber); _parsingError=[NSError errorWithDomain:CUIParsingErrorDomain code:tError.code userInfo:@{CUIParsingErrorLineKey:@(tAbsoluteLineNumber)}]; } // A COMPLETER return nil; } } // The other sections will be parsed when the log is displayed for real } @catch (NSException *exception) { NSLog(@"Exception raised while parsing \"%@\"",self.rawText); return nil; } @finally { } } } return self; } #pragma mark - - (BOOL)isHeaderAvailable { if ([super isHeaderAvailable]==YES) return YES; return (self.headerRange.location!=NSNotFound); } - (BOOL)isExceptionInformationAvailable { if ([super isExceptionInformationAvailable]==YES) return YES; return (self.exceptionInformationRange.location!=NSNotFound); } - (BOOL)isDiagnosticMessageAvailable { if ([super isDiagnosticMessageAvailable]==YES) return YES; return (self.diagnosticMessagesRange.location!=NSNotFound); } - (BOOL)isBacktracesAvailable { if ([super isBacktracesAvailable]==YES) return YES; return (self.backtracesRange.location!=NSNotFound); } - (BOOL)isThreadStateAvailable { if ([super isThreadStateAvailable]==YES) return YES; return (self.threadStateRange.location!=NSNotFound); } - (BOOL)isBinaryImagesAvailable { if ([super isBinaryImagesAvailable]==YES) return YES; return (self.binaryImagesRange.location!=NSNotFound); } - (id)valueForKeyPath:(NSString *)inKeyPath { if ([inKeyPath isEqualToString:@"header.bundleIdentifier"]==YES) return self.header.bundleIdentifier; if ([inKeyPath isEqualToString:@"header.executablePath"]==YES) return self.header.executablePath; if ([inKeyPath isEqualToString:@"header.executableVersion"]==YES) return self.header.executableVersion; if ([inKeyPath isEqualToString:@"header.operatingSystemVersion.stringValue"]==YES) return self.header.operatingSystemVersion.stringValue; if ([inKeyPath isEqualToString:@"exceptionInformation.crashedThreadName"]==YES) return self.exceptionInformation.crashedThreadName; return [super valueForKeyPath:inKeyPath]; } - (NSString *)processName { return self.header.processName; } - (NSDate *)dateTime { return self.header.dateTime; } - (NSUInteger)reportVersion { return self.header.reportVersion; } - (NSNumber *)numberOfHoursSinceCrash { NSDate * tDate=[NSDate date]; NSTimeInterval tTimeInterval=[tDate timeIntervalSinceDate:self.dateTime]; NSInteger tNumberOfHours=round(tTimeInterval/3600); return @(tNumberOfHours); } #pragma mark - - (BOOL)detectSectionsOfTextualRepresentation:(NSArray *)inLines error:(NSError **)outError { NSRange tRange; NSUInteger tFirstLine=0; // Header Section (Required) tRange=[CUICrashLogSectionsDetector detectHeaderSectionRangeInTextualRepresentation:inLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tFirstLine,inLines.count-tFirstLine)]]; if (tRange.location==NSNotFound) { if (outError!=NULL) *outError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingSectionDetectionFailedError userInfo:@{CUIParsingErrorSectionNameKey:@"Header"}]; return NO; } self.headerRange=tRange; // Exception Information Section (Required) tFirstLine=NSMaxRange(tRange); tRange=[CUICrashLogSectionsDetector detectExceptionInformationSectionRangeInTextualRepresentation:inLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tFirstLine,inLines.count-tFirstLine)]]; if (tRange.location==NSNotFound) { if (outError!=NULL) *outError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingSectionDetectionFailedError userInfo:@{CUIParsingErrorSectionNameKey:@"Exception Information"}]; return NO; } self.exceptionInformationRange=tRange; // Diagnostic Messages (Optional) tFirstLine=NSMaxRange(tRange); NSString * tString=inLines[tFirstLine]; if ([tString hasPrefix:@"Application Specific Information:"]==YES || [tString hasPrefix:@"VM Regions Near"]==YES || [tString hasPrefix:@"VM Region Info:"]==YES) { tRange=[CUICrashLogSectionsDetector detectDiagnosticMessageSectionRangeInTextualRepresentation:inLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tFirstLine,inLines.count-tFirstLine)]]; if (tRange.location==NSNotFound) { if (outError!=NULL) *outError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingSectionDetectionFailedError userInfo:@{CUIParsingErrorSectionNameKey:@"Diagnostic Messages"}]; return NO; } self.diagnosticMessagesRange=tRange; tFirstLine=NSMaxRange(tRange); tString=inLines[tFirstLine]; } // Backtraces if ([tString isEqualToString:@"Backtrace not available"]==YES || [tString hasPrefix:@"Application Specific Backtrace"]==YES || [tString hasPrefix:@"Thread 0"]==YES) { tRange=[CUICrashLogSectionsDetector detectBacktracesSectionRangeInTextualRepresentation:inLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tFirstLine,inLines.count-tFirstLine)]]; if (tRange.location==NSNotFound) { if (outError!=NULL) *outError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingSectionDetectionFailedError userInfo:@{CUIParsingErrorSectionNameKey:@"Backtraces"}]; return NO; } self.backtracesRange=tRange; tFirstLine=NSMaxRange(tRange); tString=inLines[tFirstLine]; } // Thread State if ((([tString hasPrefix:@"Thread"]==YES || [tString hasPrefix:@"Unknown thread"]==YES) && [tString rangeOfString:@"crashed with"].location!=NSNotFound) || ([tString rangeOfString:@"Thread State" options:NSCaseInsensitiveSearch].location==0)) { tRange=[CUICrashLogSectionsDetector detectThreadStateSectionRangeInTextualRepresentation:inLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tFirstLine,inLines.count-tFirstLine)]]; if (tRange.location==NSNotFound) { if (outError!=NULL) *outError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingSectionDetectionFailedError userInfo:@{CUIParsingErrorSectionNameKey:@"Thread State"}]; return NO; } self.threadStateRange=tRange; tFirstLine=NSMaxRange(tRange); tString=inLines[tFirstLine]; } // Binary Images if ([tString rangeOfString:@"Binary Images" options:NSCaseInsensitiveSearch].location==0) { tRange=[CUICrashLogSectionsDetector detectBinaryImagesSectionRangeInTextualRepresentation:inLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tFirstLine,inLines.count-tFirstLine)]]; if (tRange.location==NSNotFound) { if (outError!=NULL) *outError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingSectionDetectionFailedError userInfo:@{CUIParsingErrorSectionNameKey:@"Binary Images"}]; return NO; } self.binaryImagesRange=tRange; } return YES; } #pragma mark - - (BOOL)isFullyParsed { return self.fullyParsed; } - (BOOL)finalizeParsing { NSError * tError=nil; IPSReport * tIPSReport=self.ipsReport; if (tIPSReport!=nil) { if (tIPSReport.incident.threads!=nil) { _backtraces=[[CUICrashLogBacktraces alloc] initWithIPSIncident:tIPSReport.incident error:&tError]; if (_backtraces==nil) { // A COMPLETER return NO; } } { _threadState=[[CUICrashLogThreadState alloc] initWithIPSIncident:tIPSReport.incident error:&tError]; if (_threadState==nil && tError!=nil) { // A COMPLETER return NO; } } if (tIPSReport.incident.binaryImages!=nil) { _binaryImages=[[CUICrashLogBinaryImages alloc] initWithIPSIncident:tIPSReport.incident error:&tError]; if (_binaryImages==nil) { // A COMPLETER return NO; } } self.fullyParsed=YES; return YES; } NSMutableArray * tLines=[NSMutableArray array]; [self.rawText enumerateLinesUsingBlock:^(NSString * bLine, BOOL * bOutStop) { [tLines addObject:bLine]; }]; if (self.backtracesRange.location!=NSNotFound) { _backtraces=[[CUICrashLogBacktraces alloc] initWithTextualRepresentation:[tLines subarrayWithRange:self.backtracesRange] reportVersion:_header.reportVersion error:&tError]; if (_backtraces==nil) { if (tError!=nil) { NSUInteger tAbsoluteLineNumber=[tError.userInfo[CUIParsingErrorLineKey] unsignedIntegerValue]+_headerRange.location; NSLog(@"Error parsing line : %lu",tAbsoluteLineNumber); _parsingError=[NSError errorWithDomain:CUIParsingErrorDomain code:tError.code userInfo:@{CUIParsingErrorLineKey:@(tAbsoluteLineNumber)}]; } // A COMPLETER return NO; } } if (self.threadStateRange.location!=NSNotFound) { _threadState=[[CUICrashLogThreadState alloc] initWithTextualRepresentation:[tLines subarrayWithRange:self.threadStateRange] reportVersion:_header.reportVersion error:&tError]; if (_threadState==nil) { if (tError!=nil) { NSUInteger tAbsoluteLineNumber=[tError.userInfo[CUIParsingErrorLineKey] unsignedIntegerValue]+_headerRange.location; NSLog(@"Error parsing line : %lu",tAbsoluteLineNumber); _parsingError=[NSError errorWithDomain:CUIParsingErrorDomain code:tError.code userInfo:@{CUIParsingErrorLineKey:@(tAbsoluteLineNumber)}]; } // A COMPLETER return NO; } } if (self.binaryImagesRange.location!=NSNotFound) { _binaryImages=[[CUICrashLogBinaryImages alloc] initWithTextualRepresentation:[tLines subarrayWithRange:self.binaryImagesRange] reportVersion:self.reportVersion error:&tError]; if (_binaryImages==nil) { if (tError!=nil) { NSUInteger tAbsoluteLineNumber=[tError.userInfo[CUIParsingErrorLineKey] unsignedIntegerValue]+_headerRange.location; NSLog(@"Error parsing line : %lu",tAbsoluteLineNumber); _parsingError=[NSError errorWithDomain:CUIParsingErrorDomain code:tError.code userInfo:@{CUIParsingErrorLineKey:@(tAbsoluteLineNumber)}]; } // A COMPLETER return NO; } } self.fullyParsed=YES; return YES; } #pragma mark - - (NSString *)description { return [NSString stringWithFormat:@"%@ %@",self.processName,self.dateTime.description]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBacktraces+Utilities.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogBacktraces.h" @interface CUICrashLogBacktraces (Utilities) - (NSArray *)allBinaryImagesIdentifiers; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBacktraces+Utilities.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogBacktraces+Utilities.h" @implementation CUICrashLogBacktraces (Utilities) - (NSArray *)allBinaryImagesIdentifiers { NSMutableSet * tMutableSet=[NSMutableSet set]; [self.threads enumerateObjectsUsingBlock:^(CUIThread * bThread, NSUInteger bIndex, BOOL * bOutStop) { [bThread.callStackBacktrace.stackFrames enumerateObjectsUsingBlock:^(CUIStackFrame * bCall, NSUInteger bOtherIndex, BOOL * bOutOtherStop) { if (bCall.binaryImageIdentifier!=nil) [tMutableSet addObject:bCall.binaryImageIdentifier]; }]; }]; return [tMutableSet allObjects]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBacktraces.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIThread.h" #import "IPSIncident.h" @interface CUICrashLogBacktraces : NSObject @property (readonly) BOOL hasApplicationSpecificBacktrace; @property (nonatomic,readonly) NSArray * threads; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError; - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError; - (CUIThread *)threadNamed:(NSString *)inName; - (CUIThread *)threadWithNumber:(NSUInteger)inThreadNumber; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBacktraces.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogBacktraces.h" #import "CUIParsingErrors.h" #import "NSArray+WBExtensions.h" @interface CUICrashLogBacktraces () { NSMutableArray * _threads; } @property (readwrite) BOOL hasApplicationSpecificBacktrace; - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError; @end @implementation CUICrashLogBacktraces - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError { if ([inLines isKindOfClass:NSArray.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _threads=[NSMutableArray array]; if ([self parseTextualRepresentation:inLines outError:outError]==NO) { return nil; } } return self; } - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError { if ([inIncident isKindOfClass:IPSIncident.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { NSMutableArray * tApplicationBacktracesThreads=[NSMutableArray array]; _hasApplicationSpecificBacktrace=NO; IPSIncidentExceptionInformation * tExceptionInformation=inIncident.exceptionInformation; if (tExceptionInformation!=nil) { NSArray * tLastExceptionBacktrace=tExceptionInformation.lastExceptionBacktrace; if (tLastExceptionBacktrace.count>0) { NSError * tError; CUIThread * tThread=[[CUIThread alloc] initApplicationSpecificBacktraceWithThreadFrames:tLastExceptionBacktrace binaryImages:inIncident.binaryImages error:&tError]; if (tThread==nil) { return nil; } [tApplicationBacktracesThreads addObject:tThread]; _hasApplicationSpecificBacktrace=YES; } } if (_hasApplicationSpecificBacktrace==NO) { IPSIncidentDiagnosticMessage * tDiagnosticMessage=inIncident.diagnosticMessage; if (tDiagnosticMessage!=nil) { IPSApplicationSpecificInformation * tApplicationSpecificInformation=tDiagnosticMessage.asi; if (tApplicationSpecificInformation.backtraces.count>0) { NSArray * tApplicationSpecificBacktraces=tApplicationSpecificInformation.backtraces; [tApplicationSpecificBacktraces enumerateObjectsUsingBlock:^(NSString * bString, NSUInteger bIndex, BOOL * bOutStop) { NSMutableArray * tLines=[NSMutableArray arrayWithObject:@"Application Specific Backtrace 1"]; [bString enumerateLinesUsingBlock:^(NSString * bLine, BOOL * bOutStop) { [tLines addObject:bLine]; }]; NSError * tError; CUIThread * tThread=[[CUIThread alloc] initApplicationSpecificBacktraceWithTextualRepresentation:tLines error:&tError]; if (tThread==nil) { *bOutStop=YES; return; } [tApplicationBacktracesThreads addObject:tThread]; }]; // A COMPLETER _hasApplicationSpecificBacktrace=YES; } } } NSArray * tThreads=inIncident.threads; if (tThreads==nil) { // A COMPLETER return nil; } _threads=[[tThreads WB_arrayByMappingObjectsUsingBlock:^CUIThread *(IPSThread * bThread, NSUInteger bIndex) { CUIThread * tThread=[[CUIThread alloc] initWithIPSThread:bThread atIndex:bIndex binaryImages:inIncident.binaryImages error:NULL]; if (tThread==nil) { // A COMPLETER } return tThread; }] mutableCopy]; if (tApplicationBacktracesThreads.count>0) { [_threads insertObjects:tApplicationBacktracesThreads atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,tApplicationBacktracesThreads.count)]]; } } return self; } #pragma mark - - (CUIThread *)threadNamed:(NSString *)inName { if (inName==nil) return nil; for(CUIThread * tThread in _threads) { if ([tThread.name isEqualToString:inName]==YES) return tThread; } return nil; } - (CUIThread *)threadWithNumber:(NSUInteger)inThreadNumber { for(CUIThread * tThread in _threads) { if (tThread.isApplicationSpecificBacktrace==NO && tThread.number==inThreadNumber) return tThread; } return nil; } #pragma mark - - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError { if ([inLines.firstObject isEqualToString:@"Backtrace not available"]==YES) return YES; __block NSError * tError=nil; // Probably not as fast as block enumeration but the code is easier to follow. NSUInteger tLinesCount=inLines.count; NSUInteger tIndex=0; while (tIndex #import "CUIBinaryImage.h" #import "IPSIncident.h" @interface CUICrashLogBinaryImages : NSObject @property (readonly) NSArray * binaryImages; @property (nonatomic,readonly) NSArray * allUUIDs; @property (nonatomic,readonly) NSArray * userCodeBinaryImages; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError; - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError; - (CUIBinaryImage *)binaryImageWithIdentifier:(NSString *)inIdentifier; - (CUIBinaryImage *)binaryImageForMemoryAddress:(NSUInteger)inMemoryAddress; - (BOOL)isUserCodeAtMemoryAddress:(NSUInteger)inMemoryAddress inBinaryImage:(NSString *)inIdentifier; - (BOOL)isUserCodeAtMemoryAddress:(NSUInteger)inMemoryAddress inBinaryName:(NSString *)inName; - (NSString *)binaryImageIdentifierForName:(NSString *)inBinaryName; - (CUIBinaryImage *)binaryImageWithIdentifierOrName:(NSString *)inString identifier:(NSString **)outIdentifier; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBinaryImages.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogBinaryImages.h" #import "CUIParsingErrors.h" #import "NSArray+WBExtensions.h" @interface CUICrashLogBinaryImages () { NSMutableDictionary * _binaryImagesRegistry; NSMutableDictionary * _binaryNamesRegistry; NSMutableDictionary * _binaryNameToIdentifierRosettaStone; } @property (readwrite) NSArray * binaryImages; - (BOOL)parseTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion outError:(NSError **)outError; @end @implementation CUICrashLogBinaryImages - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError { if ([inLines isKindOfClass:NSArray.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _binaryImages=[NSArray array]; _binaryImagesRegistry=[NSMutableDictionary dictionary]; _binaryNamesRegistry=[NSMutableDictionary dictionary]; _binaryNameToIdentifierRosettaStone=[NSMutableDictionary dictionary]; if ([self parseTextualRepresentation:inLines reportVersion:inReportVersion outError:outError]==NO) { return nil; } } return self; } - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError { if ([inIncident isKindOfClass:IPSIncident.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { NSMutableDictionary * tBinaryImagesRegistry=[NSMutableDictionary dictionary]; NSMutableDictionary * tBinaryNamesRegistry=[NSMutableDictionary dictionary]; NSMutableDictionary * tBinaryNameToIdentifierRosettaStone=[NSMutableDictionary dictionary]; _binaryImages=(NSArray *)[inIncident.binaryImages WB_arrayByMappingObjectsLenientlyUsingBlock:^CUIBinaryImage *(IPSImage * bImage, NSUInteger bIndex) { if ([bImage.source isEqualToString:@"A"]==YES) return nil; CUIBinaryImage * tBinaryImage=[[CUIBinaryImage alloc] initWithImage:bImage error:NULL]; if (tBinaryImage==nil) { // A COMPLETER } else { tBinaryImagesRegistry[tBinaryImage.identifier]=tBinaryImage; NSString * tBinartName=tBinaryImage.path.lastPathComponent; tBinaryNamesRegistry[tBinartName]=tBinaryImage; tBinaryNameToIdentifierRosettaStone[tBinartName]=tBinaryImage.identifier; } return tBinaryImage; }]; _binaryImagesRegistry=tBinaryImagesRegistry; _binaryNamesRegistry=tBinaryNamesRegistry; _binaryNameToIdentifierRosettaStone=tBinaryNameToIdentifierRosettaStone; } return self; } #pragma mark - - (BOOL)parseTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion outError:(NSError **)outError { if ([inLines.firstObject isEqualToString:@"Binary images description not available"]==YES) return YES; __block NSError * tError=nil; NSArray * tImagesLines=[inLines subarrayWithRange:NSMakeRange(1, inLines.count-1)]; NSMutableArray * tBinaryImages=[NSMutableArray array]; [tImagesLines enumerateObjectsUsingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL *bOutStop) { NSUInteger tLineLength=bLine.length; if (tLineLength==0) { *bOutStop=YES; return; } CUIBinaryImage * tBinaryImage=[[CUIBinaryImage alloc] initWithString:bLine reportVersion:inReportVersion error:&tError]; if (tBinaryImage==nil) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } [tBinaryImages addObject:tBinaryImage]; self->_binaryImagesRegistry[tBinaryImage.identifier]=tBinaryImage; NSString * tBinartName=tBinaryImage.path.lastPathComponent; self->_binaryNamesRegistry[tBinartName]=tBinaryImage; self->_binaryNameToIdentifierRosettaStone[tBinartName]=tBinaryImage.identifier; }]; _binaryImages=[tBinaryImages copy]; if (outError!=NULL && tError!=nil) *outError=tError; return YES; } #pragma mark - - (NSArray *)allUUIDs { return [_binaryImages WB_arrayByMappingObjectsLenientlyUsingBlock:^id(CUIBinaryImage * bBinaryImage, NSUInteger bIndex) { return bBinaryImage.UUID; // can be nil }]; } - (NSArray *)userCodeBinaryImages { return [_binaryImages WB_filteredArrayUsingBlock:^BOOL(CUIBinaryImage * bBinaryImage, NSUInteger bIndex) { if (bBinaryImage.isUserCode==YES) return YES; NSString * tPath=bBinaryImage.path; return ([tPath hasPrefix:@"/System/"]==NO && [tPath hasPrefix:@"/usr/lib"]==NO); }]; } - (NSString *)binaryImageIdentifierForName:(NSString *)inBinaryName { if (inBinaryName==nil) return nil; return _binaryNameToIdentifierRosettaStone[inBinaryName]; } - (CUIBinaryImage *)binaryImageWithIdentifier:(NSString *)inIdentifier { if (inIdentifier==nil) return nil; return _binaryImagesRegistry[inIdentifier]; } - (CUIBinaryImage *)binaryImageForMemoryAddress:(NSUInteger)inMemoryAddress { static CUIBinaryImage * sLastFoundBinaryImage=nil; if (sLastFoundBinaryImage!=nil) { CUIAddressesRange * tRange=sLastFoundBinaryImage.addressesRange; if (inMemoryAddress>=tRange.loadAddress && inMemoryAddress<(tRange.loadAddress+tRange.length)) return sLastFoundBinaryImage; } for(CUIBinaryImage * tBinaryImage in _binaryImages) { CUIAddressesRange * tRange=tBinaryImage.addressesRange; if (inMemoryAddress>=tRange.loadAddress && inMemoryAddress<(tRange.loadAddress+tRange.length)) { sLastFoundBinaryImage=tBinaryImage; return tBinaryImage; } } return nil; } - (BOOL)isUserCodeAtMemoryAddress:(NSUInteger)inMemoryAddress inBinaryImage:(NSString *)inIdentifier { CUIBinaryImage * tBinaryImage=_binaryImagesRegistry[inIdentifier]; if (tBinaryImage==nil) return NO; if (tBinaryImage.isUserCode==NO) return NO; CUIAddressesRange * tRange=tBinaryImage.addressesRange; return (inMemoryAddress>=tRange.loadAddress && inMemoryAddress<(tRange.loadAddress+tRange.length)); } - (BOOL)isUserCodeAtMemoryAddress:(NSUInteger)inMemoryAddress inBinaryName:(NSString *)inName { CUIBinaryImage * tBinaryImage=_binaryNamesRegistry[inName]; if (tBinaryImage==nil) return NO; if (tBinaryImage.isUserCode==NO) return NO; CUIAddressesRange * tRange=tBinaryImage.addressesRange; return (inMemoryAddress>=tRange.loadAddress && inMemoryAddress<(tRange.loadAddress+tRange.length)); } - (CUIBinaryImage *)binaryImageWithIdentifierOrName:(NSString *)inString identifier:(NSString **)outIdentifier { CUIBinaryImage * tBinaryImage=[self binaryImageWithIdentifier:inString]; if (tBinaryImage==nil) { NSString * tUUID=[self binaryImageIdentifierForName:inString]; if (tUUID!=nil) { tBinaryImage=[self binaryImageWithIdentifier:tUUID]; if (tBinaryImage!=nil) { if (outIdentifier!=NULL) *outIdentifier=tUUID; } } } else { if (outIdentifier!=NULL) *outIdentifier=inString; } return tBinaryImage; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBrowsingState.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUITextModeDisplaySettings.h" #import "CUIOutlineModeDisplaySettings.h" @interface CUICrashLogBrowsingState : NSObject @property CUITextModeDisplaySettings * textModeDisplaySettings; @property NSUInteger firstVisibleLineNumber; @property CGFloat firstVisibleLineVerticalOffset; @property CUIOutlineModeDisplaySettings * outlineModeDisplaySettings; @property NSMutableDictionary * listDisclosedThreads; @property (copy) NSString * listSelectedStackFrame; @property NSUInteger columnSelectedThread; @property NSUInteger columnSelectedStackFrame; @property (readonly) NSMutableDictionary * registersViewValues; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBrowsingState.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogBrowsingState.h" @interface CUICrashLogBrowsingState () @property NSMutableDictionary * registersViewValues; @end @implementation CUICrashLogBrowsingState - (instancetype)init { self=[super init]; if (self!=nil) { _firstVisibleLineNumber=NSNotFound; _firstVisibleLineVerticalOffset=0; _registersViewValues=[NSMutableDictionary dictionary]; _listDisclosedThreads=nil; _listSelectedStackFrame=nil; _columnSelectedThread=NSNotFound; _columnSelectedStackFrame=NSNotFound; } return self; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBrowsingStateRegistry.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogBrowsingState.h" #import "CUICrashLog.h" @interface CUICrashLogBrowsingStateRegistry : NSObject + (CUICrashLogBrowsingStateRegistry *)sharedRegistry; - (CUICrashLogBrowsingState *)browsingStateForCrashLog:(CUICrashLog *)inCrashLog windowNumber:(NSInteger)inWindowNumber; - (void)setBrowsingState:(CUICrashLogBrowsingState *)inBrowsingState forCrashLog:(CUICrashLog *)inCrashLog windowNumber:(NSInteger)inWindowNumber; - (void)removeBrowsingStateForCrashLog:(CUICrashLog *)inCrashLog windowNumber:(NSInteger)inWindowNumber; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogBrowsingStateRegistry.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogBrowsingStateRegistry.h" @interface CUICrashLogBrowsingStateRegistry () { NSMutableDictionary * _registry; } @end @implementation CUICrashLogBrowsingStateRegistry + (CUICrashLogBrowsingStateRegistry *)sharedRegistry { static CUICrashLogBrowsingStateRegistry * sRegistry=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sRegistry=[CUICrashLogBrowsingStateRegistry new]; }); return sRegistry; } #pragma mark - - (instancetype)init { self=[super init]; if (self!=nil) { _registry=[NSMutableDictionary dictionary]; } return self; } #pragma mark - - (CUICrashLogBrowsingState *)browsingStateForCrashLog:(CUICrashLog *)inCrashLog windowNumber:(NSInteger)inWindowNumber { NSString * tPath=inCrashLog.crashLogFilePath; if (tPath==nil) return nil; NSMutableDictionary * tMutableDictionary=_registry[@(inWindowNumber)]; if (tMutableDictionary==nil) { tMutableDictionary=[NSMutableDictionary dictionary]; _registry[@(inWindowNumber)]=tMutableDictionary; } CUICrashLogBrowsingState * tBrowsingState=tMutableDictionary[tPath]; if (tBrowsingState==nil) { tBrowsingState=[CUICrashLogBrowsingState new]; tMutableDictionary[tPath]=tBrowsingState; } return tBrowsingState; } - (void)setBrowsingState:(CUICrashLogBrowsingState *)inBrowsingState forCrashLog:(CUICrashLog *)inCrashLog windowNumber:(NSInteger)inWindowNumber { NSString * tPath=inCrashLog.crashLogFilePath; if (inBrowsingState==nil || tPath==nil) return; NSMutableDictionary * tMutableDictionary=_registry[@(inWindowNumber)]; if (tMutableDictionary==nil) { tMutableDictionary=[NSMutableDictionary dictionary]; if (tMutableDictionary==nil) { NSLog(@"Uh oh"); return; } _registry[@(inWindowNumber)]=tMutableDictionary; } tMutableDictionary[tPath]=inBrowsingState; } - (void)removeBrowsingStateForCrashLog:(CUICrashLog *)inCrashLog windowNumber:(NSInteger)inWindowNumber { NSString * tPath=inCrashLog.crashLogFilePath; if (tPath==nil) return; NSMutableDictionary * tMutableDictionary=_registry[@(inWindowNumber)]; if (tMutableDictionary==nil) return; [tMutableDictionary removeObjectForKey:tPath]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogContentsViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" #import "CUIApplicationPreferences.h" #import "CUICrashLogPresentationViewController.h" #import "CUIKeyViews.h" @interface CUICrashLogContentsViewController : NSViewController @property (nonatomic) CUIPresentationMode presentationMode; @property (nonatomic) CUICrashLog * crashLog; @property (nonatomic,getter=isBottomViewCollapsed) BOOL bottomViewCollapsed; @property (nonatomic,readonly) CUICrashLogPresentationViewController * presentationViewController; - (IBAction)showHideBottomView:(id)sender; @end extern NSString * const CUICrashLogContentsViewPresentationModeDidChangeNotification; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogContentsViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogContentsViewController.h" #import "CUICrashLogPresentationTextViewController.h" #import "CUICrashLogPresentationOutlineViewController.h" #import "CUIdSYMDropView.h" #import "CUIdSYMBundlesManager.h" #import "CUIdSYMHunter.h" NSString * const CUIDefaultsPresentationModeKey=@"ui.presentationMode"; NSString * const CUICrashLogContentsViewPresentationModeDidChangeNotification=@"CUICrashLogContentsViewPresentationModeDidChangeNotification"; @interface CUICrashLogContentsViewController () { CUICrashLogPresentationTextViewController * _textViewController; CUICrashLogPresentationOutlineViewController * _outlineViewController; CUICrashLogPresentationViewController * _currentPresentationViewController; CUIdSYMHunter * _shareddSYMHunter; } - (void)setPresentationMode:(CUIPresentationMode)inPresentationMode transferCrashLog:(BOOL)inTransferCrashLog; - (void)symbolicate; // Notifications - (void)huntDidFinish:(NSNotification *)inNotification; @end @implementation CUICrashLogContentsViewController - (instancetype)init { self=[super init]; if (self!=nil) { _presentationMode=CUIPresentationModeUnknown; _textViewController=[CUICrashLogPresentationTextViewController new]; _outlineViewController=[CUICrashLogPresentationOutlineViewController new]; _shareddSYMHunter=[CUIdSYMHunter sharedHunter]; } return self; } - (NSString *)nibName { return @"CUICrashLogContentsViewController"; } - (void)viewDidLoad { [super viewDidLoad]; NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; [tUserDefaults registerDefaults:@{ CUIDefaultsPresentationModeKey:@(CUIPresentationModeText) }]; [self setPresentationMode:[tUserDefaults integerForKey:CUIDefaultsPresentationModeKey] transferCrashLog:NO]; ((CUIdSYMDropView *)self.view).delegate=self; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(huntDidFinish:) name:CUIdSYMHunterHuntDidFinishNotification object:nil]; } #pragma mark - - (CUICrashLogPresentationViewController *)presentationViewController { return _currentPresentationViewController; } #pragma mark - NSObject - (id)forwardingTargetForSelector:(SEL)aSelector { return _currentPresentationViewController; } - (BOOL)respondsToSelector:(SEL)aSelector { BOOL tResponds=[super respondsToSelector:aSelector]; if (tResponds==YES) return YES; if (_currentPresentationViewController==nil) return NO; NSString * tSelectorName=NSStringFromSelector(aSelector); if ([tSelectorName hasPrefix:@"CUI_MENUACTION_"]==NO && [tSelectorName isEqualToString:@"performTextFinderAction:"]==NO) return NO; return [_currentPresentationViewController respondsToSelector:aSelector]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if ([super respondsToSelector:tAction]==NO) { NSString * tSelectorName=NSStringFromSelector(tAction); if ([tSelectorName hasPrefix:@"CUI_MENUACTION_"]==NO && [tSelectorName isEqualToString:@"performTextFinderAction:"]==NO) return NO; if ([_currentPresentationViewController respondsToSelector:tAction]==YES) return [_currentPresentationViewController validateMenuItem:inMenuItem]; return NO; } if (tAction==@selector(CUI_MENUACTION_switchPresentationMode:)) { inMenuItem.state=(inMenuItem.tag==self.presentationMode) ? NSControlStateValueOn : NSControlStateValueOff; return YES; } if (tAction==@selector(CUI_MENUACTION_champollion:)) { NSArray * tUserCodeBinaryUUIDs=[self.crashLog.binaryImages.userCodeBinaryImages WB_arrayByMappingObjectsUsingBlock:^NSString *(CUIBinaryImage * bImage, NSUInteger bIndex) { return bImage.UUID; }]; NSMutableSet * tUUIDsSet=[NSMutableSet setWithArray:tUserCodeBinaryUUIDs]; // Remove the UUIDs that are already known to the dSYMBundleManager [[CUIdSYMBundlesManager sharedManager].bundlesSet enumerateObjectsUsingBlock:^(CUIdSYMBundle * bBundle, BOOL * bOutStop) { NSArray * tUUIDs=bBundle.binaryUUIDs; if (tUUIDs.count==0) return; [tUUIDsSet minusSet:[NSSet setWithArray:tUUIDs]]; }]; [tUUIDsSet minusSet:_shareddSYMHunter.huntingBundleUUIDs]; return (tUUIDsSet.count>0); } return NO; } - (IBAction)CUI_MENUACTION_switchPresentationMode:(id)sender { CUIPresentationMode tPresentationMode=CUIPresentationModeUnknown; if ([sender isKindOfClass:[NSMenuItem class]]==YES) { NSMenuItem * tMenuItem=(NSMenuItem *)sender; tPresentationMode=tMenuItem.tag; } else if ([sender isKindOfClass:[NSSegmentedControl class]]==YES) { NSSegmentedControl * tSegmentedControl=(NSSegmentedControl *)sender; tPresentationMode=[tSegmentedControl tagForSegment:tSegmentedControl.selectedSegment]; } else { return; } self.presentationMode=tPresentationMode; } - (IBAction)CUI_MENUACTION_champollion:(id)sender { [self symbolicate]; } #pragma mark - - (void)setCrashLog:(CUICrashLog *)inCrashLog { if (_crashLog==inCrashLog) return; _crashLog=inCrashLog; CUIApplicationPreferences * tApplicationPreferences=[CUIApplicationPreferences sharedPreferences]; if (inCrashLog==nil) return; _currentPresentationViewController.crashLog=inCrashLog; if ([inCrashLog isKindOfClass:[CUICrashLog class]]==NO) return; if (tApplicationPreferences.searchForSymbolsFilesAutomatically==YES) [self symbolicate]; } - (BOOL)isBottomViewCollapsed { switch(self.presentationMode) { case CUIPresentationModeOutline: return _outlineViewController.isBinaryImagesViewCollapsed; case CUIPresentationModeText: default: break; } return NO; } #pragma mark - - (void)symbolicate { NSArray * tUserCodeBinaryUUIDs=[self.crashLog.binaryImages.userCodeBinaryImages WB_arrayByMappingObjectsUsingBlock:^NSString *(CUIBinaryImage * bImage, NSUInteger bIndex) { return bImage.UUID; }]; NSMutableSet * tUUIDsSet=[NSMutableSet setWithArray:tUserCodeBinaryUUIDs]; // Remove the UUIDs that are already known to the dSYMBundleManager [[CUIdSYMBundlesManager sharedManager].bundlesSet enumerateObjectsUsingBlock:^(CUIdSYMBundle * bBundle, BOOL * bOutStop) { NSArray * tUUIDs=bBundle.binaryUUIDs; if (tUUIDs.count==0) return; [tUUIDsSet minusSet:[NSSet setWithArray:tUUIDs]]; }]; if (tUUIDsSet.count==0) return; [_shareddSYMHunter huntBundleWithUUIDs:tUUIDsSet]; } - (void)setPresentationMode:(CUIPresentationMode)inPresentationMode { [self setPresentationMode:inPresentationMode transferCrashLog:YES]; } - (void)setPresentationMode:(CUIPresentationMode)inPresentationMode transferCrashLog:(BOOL)inTransferCrashLog { if (inPresentationMode==CUIPresentationModeUnknown) return; if (_presentationMode==inPresentationMode) return; _presentationMode=inPresentationMode; NSWindow * tWindow=self.view.window; BOOL tShouldRestoreFirstController=NO; CUICrashLog * tCurrentCrashLog=nil; if (inTransferCrashLog==YES) { tCurrentCrashLog=_currentPresentationViewController.crashLog; } if (_currentPresentationViewController!=nil) { NSResponder * tResponder=tWindow.firstResponder; while (tResponder!=nil) { if (tResponder==_currentPresentationViewController) { tShouldRestoreFirstController=YES; break; } tResponder=tResponder.nextResponder; } } [_currentPresentationViewController.view removeFromSuperview]; switch(_presentationMode) { case CUIPresentationModeText: _textViewController.view.frame=self.view.bounds; _currentPresentationViewController=_textViewController; break; case CUIPresentationModeOutline: _outlineViewController.view.frame=self.view.bounds; _currentPresentationViewController=_outlineViewController; break; default: return; } if (inTransferCrashLog==YES) { _currentPresentationViewController.crashLog=tCurrentCrashLog; } [self.view addSubview:_currentPresentationViewController.view]; if (tShouldRestoreFirstController==YES) [tWindow makeFirstResponder:_currentPresentationViewController]; // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogContentsViewPresentationModeDidChangeNotification object:self userInfo:@{@"mode":@(_presentationMode)}]; // Save presentation mode in defaults NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; [tUserDefaults setInteger:_presentationMode forKey:CUIDefaultsPresentationModeKey]; } #pragma mark - - (IBAction)showHideBottomView:(id)sender { if ([_currentPresentationViewController isKindOfClass:[CUICrashLogPresentationOutlineViewController class]]==NO) return; [_outlineViewController showHideBottomView:sender]; } #pragma mark - CUIFileDeadDropViewDelegate - (BOOL)fileDeadDropView:(CUIFileDeadDropView *)inView validateDropFileURLs:(NSArray *)inURLArray { if (inURLArray==nil) return NO; if ([self.crashLog isMemberOfClass:[CUICrashLog class]]==NO) return NO; CUIdSYMBundlesManager * tBundlesManager=[CUIdSYMBundlesManager sharedManager]; NSArray * tAllUUIDs=self.crashLog.binaryImages.allUUIDs; NSArray * tFilteredArray=[inURLArray WB_filteredArrayUsingBlock:^BOOL(NSURL * bURL, NSUInteger bIndex) { NSNumber *tIsDirectoryNumber; if ([bURL getResourceValue:&tIsDirectoryNumber forKey:NSURLIsDirectoryKey error:NULL]==NO) return NO; if (tIsDirectoryNumber.boolValue==NO) return NO; // Should have .crash extension if ([bURL.pathExtension caseInsensitiveCompare:@"dSYM"]!=NSOrderedSame) return NO; // Check that these are dSYM bundles and that the UUIDs are not already listed CUIdSYMBundle * tBundle=[[CUIdSYMBundle alloc] initWithURL:bURL]; if (tBundle.isDSYMBundle==NO) return NO; if ([tBundlesManager containsBundle:tBundle]==YES) return NO; // Check that one of the UUIDs is the one of a binary of the crash log NSUInteger tIndex=[tBundle.binaryUUIDs indexOfObjectPassingTest:^BOOL(NSString * bUUID, NSUInteger bIndex, BOOL * bOutStop) { return [tAllUUIDs containsObject:bUUID]; }]; return (tIndex!=NSNotFound); }]; return (tFilteredArray.count>0); } - (BOOL)fileDeadDropView:(CUIFileDeadDropView *)inView acceptDropFileURLs:(NSArray *)inURLArray { if (inURLArray==nil) return NO; CUIdSYMBundlesManager * tBundlesManager=[CUIdSYMBundlesManager sharedManager]; NSArray * tAllUUIDs=self.crashLog.binaryImages.allUUIDs; NSArray * tMappedArray=[inURLArray WB_arrayByMappingObjectsLenientlyUsingBlock:^CUIdSYMBundle *(NSURL * bURL, NSUInteger bIndex) { NSNumber *tIsDirectoryNumber; if ([bURL getResourceValue:&tIsDirectoryNumber forKey:NSURLIsDirectoryKey error:NULL]==NO) return nil; if (tIsDirectoryNumber.boolValue==NO) return nil; // Should have .crash extension if ([bURL.pathExtension caseInsensitiveCompare:@"dSYM"]!=NSOrderedSame) return nil; // Check that these are dSYM bundles and that the UUIDs are not already listed CUIdSYMBundle * tBundle=[[CUIdSYMBundle alloc] initWithURL:bURL]; if (tBundle.isDSYMBundle==NO) return nil; if ([tBundlesManager containsBundle:tBundle]==YES) return nil; // Check that one the UUIDs is the one of a binary of the crash log NSUInteger tIndex=[tBundle.binaryUUIDs indexOfObjectPassingTest:^BOOL(NSString * bUUID, NSUInteger bIndex, BOOL * bOutStop) { return [tAllUUIDs containsObject:bUUID]; }]; return (tIndex!=NSNotFound) ? tBundle : nil; }]; [tBundlesManager addBundles:tMappedArray]; return (tMappedArray.count>0); } #pragma mark - CUIKeyViews - (NSView *)firstKeyView { return _currentPresentationViewController.firstKeyView; } - (NSView *)lastKeyView { return _currentPresentationViewController.lastKeyView; } #pragma mark - Notifications - (void)huntDidFinish:(NSNotification *)inNotification { // A COMPLETER } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogContentsViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogDianosticMessages.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "IPSIncident.h" @interface CUICrashLogDianosticMessages : NSObject @property (readonly,copy) NSString * messages; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError; - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogDianosticMessages.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogDianosticMessages.h" #import "IPSIncident+ApplicationSpecificInformation.h" #import "CUIParsingErrors.h" @interface CUICrashLogDianosticMessages () @property (copy) NSString * messages; @end @implementation CUICrashLogDianosticMessages - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError { if ([inLines isKindOfClass:NSArray.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; _messages=@""; if ([self parseTextualRepresentation:inLines outError:outError]==NO) { return nil; } return self; } - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError { if ([inIncident isKindOfClass:IPSIncident.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { IPSIncidentDiagnosticMessage * tDiagnosticMessage=inIncident.diagnosticMessage; if (tDiagnosticMessage!=nil) { NSMutableString * tMessages=[NSMutableString string]; // VM Region Info if (tDiagnosticMessage.vmregioninfo!=nil) { [tMessages appendFormat:@"VM Region Info: %@\n",tDiagnosticMessage.vmregioninfo]; [tMessages appendString:@"\n"]; } // Application Specific Information NSArray * tApplicationSpecificInformationMessage = [inIncident applicationSpecificInformationMessage]; if (tApplicationSpecificInformationMessage.count>0) { [tMessages appendString:@"Application Specific Information:\n"]; [tMessages appendString:[tApplicationSpecificInformationMessage componentsJoinedByString:@"\n"]]; [tMessages appendString:@"\n"]; } // Application Specific Signatures NSArray * tSignatures = tDiagnosticMessage.asi.signatures; if (tSignatures) { [tMessages appendString:@"Application Specific Signatures:\n"]; for(NSString * tSignature in tSignatures) [tMessages appendFormat:@"%@\n",tSignature]; } _messages=[tMessages copy]; } } return self; } #pragma mark - - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError { __block NSError * tError=nil; NSString * tFirstLine=inLines.firstObject; NSMutableIndexSet * tMutableIndexSet=[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0,inLines.count)]; if ([tFirstLine hasPrefix:@"Application Specific Information:"]==YES) { [tMutableIndexSet removeIndex:0]; } _messages=[[inLines objectsAtIndexes:tMutableIndexSet] componentsJoinedByString:@"\n"]; if (outError!=NULL && tError!=nil) *outError=tError; return YES; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogErrors.h ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUICrashLogDomain; NS_ERROR_ENUM(CUICrashLogDomain) { CUICrashLogEmptyFileError = 1, // Empty file CUICrashLogInvalidFormatFileError = 2, // File with contents that do not match the supported formats }; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogErrors.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogErrors.h" NSString * const CUICrashLogDomain=@"fr.whitebox.crashlog"; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+QuickHelp.h ================================================ /* Copyright (c) 2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogExceptionInformation.h" @interface CUICrashLogExceptionInformation (QuickHelp) @property (nonatomic,readonly,getter=isQuickHelpAvailableForTerminationReason) BOOL quickHelpAvailableForTerminationReason; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+QuickHelp.m ================================================ /* Copyright (c) 2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogExceptionInformation+QuickHelp.h" NSString * const CUITerminationReasonSignalNamespace=@"SIGNAL"; // OS_REASON_SIGNAL NSString * const CUITerminationReasonCodesigningNamespace=@"CODESIGNING"; // OS_REASON_CODESIGNING NSString * const CUITerminationReasonDyldNamespace=@"DYLD"; // OS_REASON_DYLD NSString * const CUITerminationReasonLibXPCNamespace=@"LIBXPC"; // OS_REASON_LIBXPC NSString * const CUITerminationReasonLibSystemNamespace=@"LIBSYSTEM"; // OS_REASON_LIBSYSTEM NSString * const CUITerminationReasonWatchdogNamespace=@"WATCHDOG"; // OS_REASON_WATCHDOG NSString * const CUITerminationReasonEndpointSecurityNamespace=@"ENDPOINTSECURITY"; // OS_REASON_ENDPOINTSECURITY typedef NS_ENUM(NSUInteger, CUITerminationReasonEndpointSecurityCode) { CUITerminationReasonEndpointSecurityProcessBlockedByESClient = 1, CUITerminationReasonEndpointSecurityESClientRequestTimedOut = 2 }; @implementation CUICrashLogExceptionInformation (QuickHelp) - (BOOL)isQuickHelpAvailableForTerminationReason { if ([self.terminationNamespace isEqualToString:CUITerminationReasonEndpointSecurityNamespace]==YES) { switch(self.terminationCode) { case 2: return YES; default: break; } return NO; } if ([self.terminationNamespace isEqualToString:CUITerminationReasonLibSystemNamespace]==YES) // libkern/os/reason_private.h { switch(self.terminationCode) { case 2: // OS_REASON_LIBSYSTEM_CODE_FAULT return NO; // A COMPLETER default: break; } return NO; } if ([self.terminationNamespace isEqualToString:CUITerminationReasonWatchdogNamespace]==YES) { switch(self.terminationCode) { case 1: return NO; // A COMPLETER default: break; } return NO; } if ([self.terminationNamespace isEqualToString:CUITerminationReasonCodesigningNamespace]==YES) // bsd/sys/reason.h { switch(self.terminationCode) { case 1: // CODESIGNING_EXIT_REASON_TASKGATED_INVALID_SIG return NO; // A COMPLETER case 2: // CODESIGNING_EXIT_REASON_INVALID_PAGE return NO; // A COMPLETER default: break; } return NO; } if ([self.terminationNamespace isEqualToString:CUITerminationReasonDyldNamespace]==YES) // dyld/include/mach-o/dyld_priv.h { switch(self.terminationCode) { case 1: // DYLD_EXIT_REASON_DYLIB_MISSING return NO; // A COMPLETER case 2: // DYLD_EXIT_REASON_DYLIB_WRONG_ARCH return NO; // A COMPLETER default: break; } return NO; } if ([self.terminationNamespace isEqualToString:CUITerminationReasonLibXPCNamespace]==YES) // dyld/include/mach-o/dyld_priv.h { switch(self.terminationCode) { case 4: return NO; // A COMPLETER default: break; } return NO; } return NO; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogExceptionInformation.h" @interface CUICrashLogExceptionInformation (UI) - (NSString *)humanFriendlyExceptionType; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogExceptionInformation+UI.h" @implementation CUICrashLogExceptionInformation (UI) - (NSString *)humanFriendlyExceptionType { NSString * tExceptionType=self.exceptionType; if (tExceptionType==nil) return @"Unknown"; static NSDictionary * sHumanFriendlyStrings=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sHumanFriendlyStrings=@{ @"EXC_BAD_ACCESS":@"Bad Access", @"EXC_BAD_INSTRUCTION":@"Bad Insruction", @"EXC_BREAKPOINT":@"Breakpoint", @"EXC_CRASH":@"Crash", // A COMPLETER }; }); NSString * tString=sHumanFriendlyStrings[tExceptionType]; if (tString!=nil) return tString; return tExceptionType; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "IPSIncident.h" @interface CUICrashLogExceptionInformation : NSObject @property (readonly) NSInteger crashedThreadIndex; // -1 -> Unknown @property (readonly,copy) NSString * crashedThreadName; // Can be nil @property (readonly,copy) NSString * exceptionType; @property (readonly,copy) NSString * exceptionSignal; @property (readonly,copy) NSString * exceptionSubtype; // Can be nil // On macOS, exception subtype is in exceptionCodes. @property (readonly) NSArray * exceptionCodes; @property (readonly,copy) NSString * exceptionNote; // Can be nil @property (readonly,copy) NSString * terminationNamespace; // Can be nil @property (readonly) NSUInteger terminationCode; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError; - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError; - (NSString *)displayedExceptionType; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogExceptionInformation.h" #import "CUIParsingErrors.h" #import "NSArray+WBExtensions.h" @interface CUICrashLogExceptionInformation () @property NSInteger crashedThreadIndex; // -1 -> Unknown @property (copy) NSString * crashedThreadName; @property (copy) NSString * exceptionType; @property (copy) NSString * exceptionSignal; @property (copy) NSString * exceptionSubtype; @property NSArray * exceptionCodes; @property (copy) NSString * exceptionNote; @property (copy) NSString * terminationNamespace; @property NSUInteger terminationCode; + (BOOL)parseString:(NSString *)inString threadIndex:(NSInteger *)outThreadIndex threadName:(NSString **)outThreadName; + (BOOL)parseString:(NSString *)inString exceptionType:(NSString **)outExceptionType signal:(NSString **)outExceptionSignal; + (BOOL)parseString:(NSString *)inString exceptionCodes:(NSArray **)outExceptionCodes; - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError; @end @implementation CUICrashLogExceptionInformation + (BOOL)parseString:(NSString *)inString threadIndex:(NSInteger *)outThreadIndex threadName:(NSString **)outThreadName { if ([inString isEqualToString:@"Unknown"]==YES) { if (outThreadIndex!=NULL) *outThreadIndex=-1; if (outThreadName!=NULL) *outThreadName=nil; return YES; } NSScanner * tScanner=[NSScanner scannerWithString:inString]; NSInteger tInteger; if ([tScanner scanInteger:&tInteger]==NO) { // A COMPLETER return NO; } if (outThreadIndex!=NULL) *outThreadIndex=tInteger; NSString * tString=[[inString substringFromIndex:tScanner.scanLocation] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; if (outThreadName!=NULL) *outThreadName=tString; return YES; } + (BOOL)parseString:(NSString *)inString exceptionType:(NSString **)outExceptionType signal:(NSString **)outExceptionSignal { NSScanner * tScanner=[NSScanner scannerWithString:inString]; NSString * tString; if ([tScanner scanUpToString:@" (" intoString:&tString]==NO || tString.length==inString.length) { if (outExceptionType!=NULL) *outExceptionType=[inString copy]; return YES; } if (outExceptionType!=NULL) *outExceptionType=[tString copy]; NSString * tSubString=[inString substringWithRange:NSMakeRange(tScanner.scanLocation+2,inString.length-2-(tScanner.scanLocation+2)+1)]; if (outExceptionSignal!=NULL) *outExceptionSignal=tSubString; return YES; } + (BOOL)parseString:(NSString *)inString exceptionCodes:(NSArray **)outExceptionCodes { NSArray * tComponents=[inString componentsSeparatedByString:@","]; NSMutableArray * tMutableArray=[NSMutableArray array]; for(NSString * tCodeString in tComponents) { NSScanner * tScanner=[NSScanner scannerWithString:tCodeString]; unsigned long long tHexaValue; if ([tScanner scanHexLongLong:&tHexaValue]==NO) { return NO; } [tMutableArray addObject:@(tHexaValue)]; } if (outExceptionCodes!=NULL) *outExceptionCodes=[tMutableArray copy]; return YES; } + (BOOL)parseString:(NSString *)inString terminationReasonNamespace:(NSString **)outNamespace code:(NSUInteger *)outCode { NSScanner * tScanner=[NSScanner scannerWithString:inString]; BOOL tSimpleFormat=YES; if ([inString hasPrefix:@"Namespace "]==YES) { tSimpleFormat=NO; tScanner.scanLocation+=@"Namespace ".length; } NSString * tNamespace=nil; if (tSimpleFormat==YES) { if ([tScanner scanUpToString:@", [" intoString:&tNamespace]==NO) { return NO; } tScanner.scanLocation+=@", [".length; } else { if ([tScanner scanUpToString:@", Code " intoString:&tNamespace]==NO) { return NO; } tScanner.scanLocation+=@", Code ".length; } if (outNamespace!=NULL) *outNamespace=tNamespace; unsigned long long tHexValue; if ([tScanner scanHexLongLong:&tHexValue]==NO) return NO; if (outCode!=NULL) *outCode=tHexValue; return YES; } #pragma mark - - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError { if ([inLines isKindOfClass:NSArray.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _crashedThreadIndex=-1; if ([self parseTextualRepresentation:inLines outError:outError]==NO) { return nil; } } return self; } - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError { if ([inIncident isKindOfClass:IPSIncident.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { IPSIncidentExceptionInformation * tExceptionInformation=inIncident.exceptionInformation; _crashedThreadIndex=tExceptionInformation.faultingThread; if (tExceptionInformation.legacyInfo.threadTriggered.queue!=nil) _crashedThreadName=[NSString stringWithFormat:@"Dispatch queue: %@",tExceptionInformation.legacyInfo.threadTriggered.queue]; _exceptionType=tExceptionInformation.exception.type; _exceptionSignal=tExceptionInformation.exception.signal; _exceptionSubtype=tExceptionInformation.exception.codes; _exceptionCodes=[tExceptionInformation.exception.rawCodes WB_arrayByMappingObjectsUsingBlock:^NSString *(NSNumber * bNumber, NSUInteger bIndex) { return @"A COMPLETER"; }]; _exceptionNote=(tExceptionInformation.isCorpse==YES) ? @"EXC_CORPSE_NOTIFY" : nil; _terminationNamespace=[tExceptionInformation.termination.namespace copy]; _terminationCode=tExceptionInformation.termination.code; } return self; } #pragma mark - - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError { __block NSError * tError=nil; [inLines enumerateObjectsUsingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL *bOutStop) { NSUInteger tLineLength=bLine.length; // Skip Blank lines if (tLineLength==0) return; // Find Key and Value NSScanner * tScanner=[NSScanner scannerWithString:bLine]; NSString * tKey; if ([tScanner scanUpToString:@":" intoString:&tKey]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } NSUInteger tIndex=tScanner.scanLocation+1; if (tIndex>=(tLineLength-1)) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } NSString * tValue=[[bLine substringFromIndex:tIndex] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; if (tValue.length==0) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } // Retrieve values if ([tKey isEqualToString:@"Crashed Thread"]==YES) { NSInteger tInteger; NSString * tString; if ([CUICrashLogExceptionInformation parseString:tValue threadIndex:&tInteger threadName:&tString]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.crashedThreadIndex=tInteger; self.crashedThreadName=tString; return; } if ([tKey isEqualToString:@"Exception Type"]==YES) { NSString * tExceptionType=nil; NSString * tExceptionSignal=nil; if ([CUICrashLogExceptionInformation parseString:tValue exceptionType:&tExceptionType signal:&tExceptionSignal]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.exceptionType=tExceptionType; self.exceptionSignal=tExceptionSignal; return; } if ([tKey isEqualToString:@"Exception Subtype"]==YES) { self.exceptionSubtype=tValue; return; } if ([tKey isEqualToString:@"Exception Codes"]==YES) { NSArray * tExceptionCodes=nil; if ([CUICrashLogExceptionInformation parseString:tValue exceptionCodes:&tExceptionCodes]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.exceptionCodes=tExceptionCodes; return; } if ([tKey isEqualToString:@"Exception Note"]==YES) { self.exceptionNote=tValue; return; } if ([tKey isEqualToString:@"Termination Reason"]==YES) { NSString * tNamespace=nil; NSUInteger tCode=0; if ([CUICrashLogExceptionInformation parseString:tValue terminationReasonNamespace:&tNamespace code:&tCode]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.terminationNamespace=tNamespace; self.terminationCode=tCode; return; } }]; if (outError!=NULL && tError!=nil) *outError=tError; return YES; } //Exception Type: EXC_CRASH (Code Signature Invalid) //Exception Codes: 0x0000000000000000, 0x0000000000000000 //Exception Note: EXC_CORPSE_NOTIFY #pragma mark - - (NSString *)displayedExceptionType { if (self.exceptionSignal==nil) return self.exceptionType; return [NSString stringWithFormat:@"%@ (%@)",self.exceptionType,self.exceptionSignal]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogHeader.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "IPSIncident.h" #import "CUIOperatingSystemVersion.h" #include "CUICodeType.h" @interface CUICrashLogHeader : NSObject @property (readonly) NSUInteger reportVersion; @property (readonly) NSDate * dateTime; @property (readonly) CUIOperatingSystemVersion * operatingSystemVersion; @property (readonly) BOOL systemIntegrityProtectionEnabled; @property (readonly,copy) NSString * bridgeOSVersion; // T2 Embedded OS Version (can be nil) @property (readonly,copy) NSString * anonymousUUID; @property (readonly) CUICodeType codeType; @property (readonly) BOOL native; @property (readonly,copy) NSString * executablePath; @property (readonly,copy) NSString * bundleIdentifier; @property (readonly,copy) NSString * executableVersion; @property (readonly,copy) NSString * responsibleProcessName; @property (readonly) pid_t responsibleProcessIdentifier; @property (readonly,copy) NSString * processName; @property (readonly) pid_t processIdentifier; @property (readonly,copy) NSString * parentProcessName; @property (readonly) pid_t parentProcessIdentifier; @property (readonly) uid_t userIdentifier; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError; - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogHeader.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogHeader.h" #import "CUIParsingErrors.h" @interface CUICrashLogHeader () { NSDateFormatter * _dateFormatter; } @property NSUInteger reportVersion; @property NSDate * dateTime; @property CUIOperatingSystemVersion * operatingSystemVersion; @property BOOL systemIntegrityProtectionEnabled; @property (copy) NSString * bridgeOSVersion; @property (copy) NSString * anonymousUUID; @property CUICodeType codeType; @property BOOL native; @property (copy) NSString * executablePath; @property (copy) NSString * bundleIdentifier; @property (copy) NSString * executableVersion; @property (copy) NSString * responsibleProcessName; @property pid_t responsibleProcessIdentifier; @property (copy) NSString * processName; @property pid_t processIdentifier; @property (copy) NSString * parentProcessName; @property pid_t parentProcessIdentifier; @property uid_t userIdentifier; + (NSDateFormatter *)crashDateFormatter; + (BOOL)parseString:(NSString *)inString processName:(NSString **)outProcessName identifier:(pid_t *)outProcessIdentifier; + (BOOL)parseString:(NSString *)inString integerValue:(NSInteger *)outIntegerValue; + (BOOL)parseString:(NSString *)inString codeType:(CUICodeType *)outCodeType native:(BOOL *)outNative; - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError; @end @implementation CUICrashLogHeader + (NSDateFormatter *)crashDateFormatter { static NSDateFormatter * sCrashDateFormatter=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sCrashDateFormatter = [NSDateFormatter new]; sCrashDateFormatter.locale=[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; // Technical Q&A QA1480 sCrashDateFormatter.dateFormat=@"yyyy-MM-dd HH:mm:ss.SSS z"; }); return sCrashDateFormatter; } + (BOOL)parseString:(NSString *)inString processName:(NSString **)outProcessName identifier:(pid_t *)outProcessIdentifier { NSScanner * tScanner=[NSScanner scannerWithString:inString]; NSString * tString; if ([tScanner scanUpToString:@" [" intoString:&tString]==NO) { // A COMPLETER return NO; } if (outProcessName!=NULL) *outProcessName=[tString copy]; NSString * tSubString=[inString substringWithRange:NSMakeRange(tScanner.scanLocation+2,inString.length-2-(tScanner.scanLocation+2)+1)]; if (outProcessIdentifier!=NULL) *outProcessIdentifier=(pid_t)[tSubString integerValue]; return YES; } + (BOOL)parseString:(NSString *)inString integerValue:(NSInteger *)outIntegerValue { if (outIntegerValue!=NULL) *outIntegerValue=[inString integerValue]; return YES; } + (BOOL)parseString:(NSString *)inString codeType:(CUICodeType *)outCodeType native:(BOOL *)outNative { NSArray * tComponents=[inString componentsSeparatedByString:@" "]; switch(tComponents.count) { case 2: if (outNative!=NULL) *outNative=([tComponents[1] caseInsensitiveCompare:@"(Native)"]==NSOrderedSame); case 1: if (outCodeType!=NULL) { *outCodeType=CUICodeTypeUnknown; NSString * tString=tComponents.firstObject; if ([tString isEqualToString:@"X86"]==YES) { *outCodeType=CUICodeTypeX86; } else if ([tString isEqualToString:@"X86-64"]==YES) { *outCodeType=CUICodeTypeX86_64; } else if ([tString isEqualToString:@"ARM-64"]==YES) { *outCodeType=CUICodeTypeARM_64; } } break; } return YES; } #pragma mark - - (instancetype)initWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError { if ([inLines isKindOfClass:NSArray.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _systemIntegrityProtectionEnabled=YES; if ([self parseTextualRepresentation:inLines outError:outError]==NO) { return nil; } } return self; } - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError { if ([inIncident isKindOfClass:IPSIncident.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { IPSIncidentHeader * tIPSHeader=inIncident.header; _reportVersion=12; _dateTime=tIPSHeader.captureTime; NSString * tSystemVersionTrain=tIPSHeader.operatingSystemVersion.train; NSString * tPrefix=@"Mac OS X "; // A COMPLETER (Think iOS) if ([tSystemVersionTrain hasPrefix:tPrefix]==NO) { tPrefix=@"macOS "; if ([tSystemVersionTrain hasPrefix:tPrefix]==NO) { tPrefix=@""; } } _operatingSystemVersion=[[CUIOperatingSystemVersion alloc] initWithString:[tSystemVersionTrain substringFromIndex:tPrefix.length]]; _systemIntegrityProtectionEnabled=tIPSHeader.systemIntegrityProtectionEnable; _bridgeOSVersion=nil; if ([tIPSHeader.crashReporterKey isKindOfClass:NSUUID.class]==YES) _anonymousUUID=[tIPSHeader.crashReporterKey UUIDString]; else _anonymousUUID=tIPSHeader.crashReporterKey; _codeType=CUICodeTypeARM_64; if ([tIPSHeader.cpuType isEqualToString:@"X86-64"]==YES) { _codeType=CUICodeTypeX86_64; } else if ([tIPSHeader.cpuType isEqualToString:@"ARM-64"]==YES) { _codeType=CUICodeTypeARM_64; } _native=(tIPSHeader.translated==NO); _executablePath=tIPSHeader.processPath; IPSBundleInfo * tBundleInfo=tIPSHeader.bundleInfo; _bundleIdentifier=tBundleInfo.bundleIdentifier; if (tBundleInfo.bundleVersion!=nil) { _executableVersion=[NSString stringWithFormat:@"%@ (%@)",tBundleInfo.bundleShortVersionString,tBundleInfo.bundleVersion]; } else { _executableVersion=tIPSHeader.bundleInfo.bundleShortVersionString; } _responsibleProcessName=tIPSHeader.responsibleProcessName; _responsibleProcessIdentifier=tIPSHeader.responsibleProcessID; _processName=tIPSHeader.processName; _processIdentifier=tIPSHeader.processID; _parentProcessName=tIPSHeader.parentProcessName; _parentProcessIdentifier=tIPSHeader.parentProcessID; _userIdentifier=tIPSHeader.userID; } return self; } #pragma mark - - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError { __block NSError * tError=nil; [inLines enumerateObjectsUsingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL *bOutStop) { NSUInteger tLineLength=bLine.length; // Skip Blank lines if (tLineLength==0) return; // Find Key and Value NSScanner * tScanner=[NSScanner scannerWithString:bLine]; NSString * tKey; if ([tScanner scanUpToString:@":" intoString:&tKey]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } NSUInteger tIndex=tScanner.scanLocation+1; if (tIndex>=(tLineLength-1)) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } NSString * tValue=[[bLine substringFromIndex:tIndex] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; if (tValue.length==0) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } // Retrieve values NSString * tString; pid_t tProcessIdentifier; if ([tKey isEqualToString:@"Process"]==YES) { if ([CUICrashLogHeader parseString:tValue processName:&tString identifier:&tProcessIdentifier]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.processName=tString; self.processIdentifier=tProcessIdentifier; return; } if ([tKey isEqualToString:@"Parent Process"]==YES) { if ([CUICrashLogHeader parseString:tValue processName:&tString identifier:&tProcessIdentifier]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.parentProcessName=tString; self.parentProcessIdentifier=tProcessIdentifier; return; } if ([tKey isEqualToString:@"Responsible"]==YES) { if ([CUICrashLogHeader parseString:tValue processName:&tString identifier:&tProcessIdentifier]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.responsibleProcessName=tString; self.responsibleProcessIdentifier=tProcessIdentifier; return; } if ([tKey isEqualToString:@"Date/Time"]==YES) { NSDate * tDate = [[CUICrashLogHeader crashDateFormatter] dateFromString:tValue]; if (tDate==nil) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingDateTimeParsingError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.dateTime=tDate; return; } NSInteger tInteger=0; if ([tKey isEqualToString:@"Report Version"]==YES) { if ([CUICrashLogHeader parseString:tValue integerValue:&tInteger]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.reportVersion=tInteger; return; } if ([tKey isEqualToString:@"User ID"]==YES) { if ([CUICrashLogHeader parseString:tValue integerValue:&tInteger]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.userIdentifier=(uid_t)tInteger; return; } if ([tKey isEqualToString:@"Path"]==YES) { self.executablePath=tValue; return; } if ([tKey isEqualToString:@"Identifier"]==YES) { self.bundleIdentifier=tValue; return; } if ([tKey isEqualToString:@"Version"]==YES) { self.executableVersion=tValue; return; } if ([tKey isEqualToString:@"Bridge OS Version"]==YES) { self.bridgeOSVersion=tValue; return; } if ([tKey isEqualToString:@"Anonymous UUID"]==YES) { self.anonymousUUID=tValue; return; } if ([tKey isEqualToString:@"OS Version"]==YES) { NSString * tPrefix=@"Mac OS X "; // A COMPLETER (Think iOS) if ([tValue hasPrefix:tPrefix]==NO) { tPrefix=@"macOS "; if ([tValue hasPrefix:tPrefix]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } } NSString * tVersion=[tValue substringFromIndex:tPrefix.length]; CUIOperatingSystemVersion * tOperatingSystemVersion=[[CUIOperatingSystemVersion alloc] initWithString:tVersion]; if (tOperatingSystemVersion==nil) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.operatingSystemVersion=tOperatingSystemVersion; return; } if ([tKey isEqualToString:@"Code Type"]==YES) { CUICodeType tCodeType=CUICodeTypeUnknown; BOOL tNative=NO; // X86-64 (Native) // X86 (Native) if ([CUICrashLogHeader parseString:tValue codeType:&tCodeType native:&tNative]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.codeType=tCodeType; self.native=tNative; return; } if ([tKey isEqualToString:@"System Integrity Protection"]==YES) { // A COMPLETER if ([tValue caseInsensitiveCompare:@"enabled"]==YES) { self.systemIntegrityProtectionEnabled=NO; } else if ([tValue caseInsensitiveCompare:@"disabled"]==YES) { self.systemIntegrityProtectionEnabled=NO; } return; } }]; if (outError!=NULL && tError!=nil) *outError=tError; return YES; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogPresentationOutlineViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogPresentationViewController.h" #import "CUIOutlineModeDisplaySettings.h" @interface CUICrashLogPresentationOutlineViewController : CUICrashLogPresentationViewController @property (readonly) CUIOutlineModeDisplaySettings * displaySettings; @property (nonatomic,readonly,getter=isBinaryImagesViewCollapsed) BOOL binaryImagesViewCollapsed; - (IBAction)showHideBottomView:(id)sender; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogPresentationOutlineViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogPresentationOutlineViewController.h" #import "CUIThreadNamedTableCellView.h" #import "CUICrashLog+UI.h" #import "CUIStackFrame+UI.h" #import "CUIThreadsListViewController.h" #import "CUIThreadsColumnViewController.h" #import "CUICenteredLabelViewController.h" #import "CUIBinaryImagesViewController.h" #import "CUIExceptionTypePopUpViewController.h" #import "CUICrashLogBrowsingStateRegistry.h" #import "CUIApplicationPreferences.h" NSString * const CUIDefaultsThreadsModeViewKey=@"ui.threadView"; NSString * const CUIDefaultsTopViewHeightKey=@"topView.height"; NSString * const CUIDefaultsTopViewCollapsedKey=@"topView.collapsed"; NSString * const CUIDefaultsBottomViewHeightKey=@"bottomView.height"; NSString * const CUIDefaultsBottomViewCollapsedKey=@"bottomView.collapsed"; NSString * const CUIBottomViewCollapseStateDidChangeNotification=@"CUIBottomViewCollapseStateDidChangeNotification"; typedef NS_ENUM(NSUInteger, CUIThreadsModeView) { CUIThreadsModeViewUnknown=0, CUIThreadsModeViewList=1, CUIThreadsModeViewColumn=2, CUIThreadsModeViewLightTable=3 }; #define CUIThreadsBottomBarHeight 16.0 #define CUIDiagnosticsViewMinimumHeight 60.0 #define CUIThreadsViewMinimumHeight 200.0 #define CUIBinaryImagesViewMinimumHeight 190.0 @interface CUICrashLogPresentationOutlineViewController () { IBOutlet NSTextField * _exceptionTypeValue; IBOutlet NSButton * _exceptionTypeMoreInfoButton; IBOutlet NSSplitView * _splitView; IBOutlet NSView * _topView; IBOutlet NSTextView * _diagnosticMessageTextView; IBOutlet NSView * _middleView; IBOutlet NSView * _threadsContainerView; // Bottom bar IBOutlet NSButton * _showBinaryImagesButton; IBOutlet NSButton * _listModeButton; IBOutlet NSButton * _columnModeButton; IBOutlet NSButton * _lightTableModeButton; IBOutlet NSButton * _showOnlyCrashedThreadButton; IBOutlet NSView * _bottomView; CUIThreadsModeView _threadsViewMode; CUICenteredLabelViewController * _noThreadsViewController; CUIThreadsViewController * _threadsViewController; CUIBinaryImagesViewController * _binaryImagesViewController; NSAttributedString * _diagnosticHeader; } @property CUIOutlineModeDisplaySettings * displaySettings; - (void)refresh; - (IBAction)showMoreExceptionInfo:(id)sender; - (IBAction)showInFinder:(id)sender; - (IBAction)switchViewMode:(id)sender; - (void)showThreadsViewForMode:(CUIThreadsModeView)inMode; @end @implementation CUICrashLogPresentationOutlineViewController + (void)initialize { [[NSUserDefaults standardUserDefaults] registerDefaults:@{ CUIDefaultsThreadsModeViewKey:@(CUIThreadsModeViewList), CUIDefaultsTopViewCollapsedKey:@(NO), CUIDefaultsTopViewHeightKey:@(92.0), CUIDefaultsBottomViewCollapsedKey:@(YES), CUIDefaultsBottomViewHeightKey:@(CUIBinaryImagesViewMinimumHeight) }]; } - (instancetype)init { self=[super init]; if (self!=nil) { _diagnosticHeader=[[NSAttributedString alloc] initWithString:NSLocalizedString(@"Diagnostics\n\n",@"") attributes:@{ NSForegroundColorAttributeName:[NSColor secondaryLabelColor], NSFontAttributeName:[NSFont systemFontOfSize:13.0 weight:NSFontWeightBold] }]; self.visibleStackFrameComponents=CUIStackFrameByteOffsetComponent; _threadsViewMode=[[NSUserDefaults standardUserDefaults] integerForKey:CUIDefaultsThreadsModeViewKey]; } return self; } #pragma mark - - (NSString *)nibName { return @"CUICrashLogPresentationOutlineViewController"; } - (void)viewDidLoad { [super viewDidLoad]; _diagnosticMessageTextView.textContainerInset=NSMakeSize(8.0, 8.0); _listModeButton.state=NSControlStateValueOff; _columnModeButton.state=NSControlStateValueOff; _lightTableModeButton.state=NSControlStateValueOff; switch(_threadsViewMode) { case CUIThreadsModeViewList: _listModeButton.state=NSControlStateValueOn; break; case CUIThreadsModeViewColumn: _columnModeButton.state=NSControlStateValueOn; break; case CUIThreadsModeViewLightTable: _lightTableModeButton.state=NSControlStateValueOn; break; default: break; } _showOnlyCrashedThreadButton.state=(self.showOnlyCrashedThread==YES) ? NSControlStateValueOn : NSControlStateValueOff; _showByteOffsetButton.state=((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showMachineInstructionAddressButton.state=((self.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showBinaryNameButton.state=((self.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; [self showThreadsViewForMode:_threadsViewMode]; _binaryImagesViewController=[CUIBinaryImagesViewController new]; _binaryImagesViewController.view.frame=_bottomView.bounds; [_bottomView addSubview:_binaryImagesViewController.view]; } - (void)viewDidAppear { [super viewDidAppear]; // Restore SplitView divider position NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; CGFloat tTopViewHeight=CUIDiagnosticsViewMinimumHeight; NSNumber * tNumber=[tUserDefaults objectForKey:CUIDefaultsTopViewCollapsedKey]; if (tNumber==nil || [tNumber boolValue]==YES) [_splitView setPosition:[_splitView maxPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0]; tNumber=[tUserDefaults objectForKey:CUIDefaultsTopViewHeightKey]; if (tNumber!=nil) tTopViewHeight=[tNumber doubleValue]; BOOL tIsCollapsed=NO; tNumber=[tUserDefaults objectForKey:CUIDefaultsBottomViewCollapsedKey]; if (tNumber==nil || [tNumber boolValue]==YES) tIsCollapsed=YES; if (tIsCollapsed==YES) [_splitView setPosition:[_splitView maxPossiblePositionOfDividerAtIndex:1] ofDividerAtIndex:1]; CGFloat tBottomViewWHeight=CUIBinaryImagesViewMinimumHeight; tNumber=[tUserDefaults objectForKey:CUIDefaultsBottomViewHeightKey]; if (tNumber!=nil) tBottomViewWHeight=[tNumber doubleValue]; [self _splitView:_splitView resizeSubviewsWithTopViewHeight:tTopViewHeight bottomViewHeight:tBottomViewWHeight]; [NSNotificationCenter.defaultCenter postNotificationName:CUIBottomViewCollapseStateDidChangeNotification object:self.view.window userInfo:@{@"Collapsed":@(tIsCollapsed)}]; } - (void)viewWillDisappear { [super viewWillDisappear]; // Save browsing state [self saveBrowsingState]; // Save SplitView divider position NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; NSArray * tSubviews=_splitView.subviews; NSView * tTopView=tSubviews[0]; [tUserDefaults setObject:@(NSHeight(tTopView.frame)) forKey:CUIDefaultsTopViewHeightKey]; [tUserDefaults setBool:[_splitView isSubviewCollapsed:tTopView] forKey:CUIDefaultsTopViewCollapsedKey]; NSView * tBottomView=tSubviews[2]; [tUserDefaults setObject:@(NSHeight(tBottomView.frame)) forKey:CUIDefaultsBottomViewHeightKey]; [tUserDefaults setBool:[_splitView isSubviewCollapsed:tBottomView] forKey:CUIDefaultsBottomViewCollapsedKey]; } - (void)saveBrowsingState { CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; if (self.crashLog!=nil) { CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; tBrowsingState.outlineModeDisplaySettings=[self.displaySettings copy]; } } #pragma mark - - (void)setCrashLog:(CUICrashLog *)inCrashLog { [self saveBrowsingState]; [super setCrashLog:inCrashLog]; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:inCrashLog windowNumber:self.view.window.windowNumber]; _displaySettings=[tBrowsingState.outlineModeDisplaySettings copy]; if (self.displaySettings==nil) { // A COMPLETER self.displaySettings=[[CUIApplicationPreferences sharedPreferences].defaultOutlineModeDisplaySettings copy]; } BOOL tIsRawCrashLog=[self.crashLog isMemberOfClass:[CUIRawCrashLog class]]; _exceptionTypeMoreInfoButton.enabled=(tIsRawCrashLog==NO); NSUInteger tThreadsCount=0; if (tIsRawCrashLog==NO) { tThreadsCount=self.crashLog.backtraces.threads.count; } BOOL tAreBacktracesAvailable=(tThreadsCount>0); if (_noThreadsViewController!=nil) { if (tThreadsCount>0) { [self showThreadsViewForMode:_threadsViewMode]; } } else { if (tThreadsCount==0) { [self showThreadsViewForMode:_threadsViewMode]; } } _threadsViewController.crashLog=inCrashLog; _threadsViewController.showOnlyCrashedThread=self.displaySettings.showOnlyCrashedThread; _threadsViewController.visibleStackFrameComponents=self.displaySettings.visibleStackFrameComponents; _showOnlyCrashedThreadButton.enabled=(tIsRawCrashLog==NO && tAreBacktracesAvailable==YES); _showByteOffsetButton.enabled=(tIsRawCrashLog==NO && tAreBacktracesAvailable==YES); _showMachineInstructionAddressButton.enabled=(tIsRawCrashLog==NO && tAreBacktracesAvailable==YES); _showBinaryNameButton.enabled=(tIsRawCrashLog==NO && tAreBacktracesAvailable==YES); if (tIsRawCrashLog==NO && tAreBacktracesAvailable==YES) { _showOnlyCrashedThreadButton.state=(self.displaySettings.showOnlyCrashedThread==YES) ? NSControlStateValueOn : NSControlStateValueOff; _showByteOffsetButton.state=((self.displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)==CUIStackFrameByteOffsetComponent) ? NSControlStateValueOn : NSControlStateValueOff; _showMachineInstructionAddressButton.state=((self.displaySettings.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)==CUIStackFrameMachineInstructionAddressComponent) ? NSControlStateValueOn : NSControlStateValueOff; _showBinaryNameButton.state=(((self.displaySettings.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)==CUIStackFrameBinaryNameComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; } else { _showOnlyCrashedThreadButton.state=NSControlStateValueOff; _showByteOffsetButton.state=NSControlStateValueOff; _showMachineInstructionAddressButton.state=NSControlStateValueOff; _showBinaryNameButton.state=NSControlStateValueOff; } _binaryImagesViewController.crashLog=(tIsRawCrashLog==NO) ? inCrashLog : nil; [self refresh]; } - (void)showThreadsViewForMode:(CUIThreadsModeView)inMode { if ([self.crashLog isMemberOfClass:[CUIRawCrashLog class]]==YES || self.crashLog.backtraces.threads.count==0) { if (_noThreadsViewController!=nil) return; [_threadsViewController.view removeFromSuperview]; _threadsViewController=nil; _noThreadsViewController=[CUICenteredLabelViewController new]; _noThreadsViewController.label=NSLocalizedString(@"No backtraces available", @""); _noThreadsViewController.labelSize=CUILabelSizeBig; NSRect tBounds=_threadsContainerView.bounds; _noThreadsViewController.view.frame=tBounds; [_threadsContainerView addSubview:_noThreadsViewController.view]; NSWindow * tWindow=self.view.window; if (tWindow.firstResponder==tWindow) [tWindow makeFirstResponder:self]; return; } [_noThreadsViewController.view removeFromSuperview]; _noThreadsViewController=nil; [_threadsViewController.view removeFromSuperview]; switch(inMode) { case CUIThreadsModeViewList: _threadsViewController=[[CUIThreadsListViewController alloc] initWithUserInterfaceLayoutDirection:self.view.userInterfaceLayoutDirection]; break; case CUIThreadsModeViewColumn: _threadsViewController=[[CUIThreadsColumnViewController alloc] initWithUserInterfaceLayoutDirection:self.view.userInterfaceLayoutDirection]; break; default: break; } NSRect tBounds=_threadsContainerView.bounds; _threadsViewController.view.frame=tBounds; [_threadsContainerView addSubview:_threadsViewController.view]; _threadsViewController.crashLog=self.crashLog; _threadsViewController.showOnlyCrashedThread=self.showOnlyCrashedThread; _threadsViewController.visibleStackFrameComponents=self.visibleStackFrameComponents; } - (BOOL)isBinaryImagesViewCollapsed { return ([_splitView isSubviewCollapsed:_bottomView]==YES); } - (BOOL)showOnlyCrashedThread { return self.displaySettings.showOnlyCrashedThread; } - (void)setShowOnlyCrashedThread:(BOOL)inShowOnlyCrashedThread { self.displaySettings.showOnlyCrashedThread=inShowOnlyCrashedThread; _threadsViewController.showOnlyCrashedThread=inShowOnlyCrashedThread; } - (void)setVisibleStackFrameComponents:(CUIStackFrameComponents)inVisibleStackFrameComponents { [super setVisibleStackFrameComponents:inVisibleStackFrameComponents]; self.displaySettings.visibleStackFrameComponents=inVisibleStackFrameComponents; _threadsViewController.visibleStackFrameComponents=inVisibleStackFrameComponents; } #pragma mark - - (void)refresh { CUICrashLog * tCrashLog=self.crashLog; NSMutableParagraphStyle * tMutableParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; tMutableParagraphStyle.tabStops=@[]; tMutableParagraphStyle.lineSpacing=2.0; NSMutableAttributedString * tMutableAttributedString=[_diagnosticHeader mutableCopy]; if ([tCrashLog isKindOfClass:[CUICrashLog class]]==NO) { _exceptionTypeValue.stringValue=@""; [tMutableAttributedString appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedString(@"N/A", @"") attributes:@{NSParagraphStyleAttributeName:tMutableParagraphStyle, NSForegroundColorAttributeName:[NSColor textColor] }]]; _diagnosticMessageTextView.textStorage.attributedString=tMutableAttributedString; return; } NSString * tString=[tCrashLog.exceptionInformation displayedExceptionType]; _exceptionTypeValue.stringValue=(tString!=nil) ? tString : @""; tString=tCrashLog.diagnosticMessages.messages; if (tString.length==0) tString=NSLocalizedString(@"N/A", @""); [tMutableAttributedString appendAttributedString:[[NSAttributedString alloc] initWithString:tString attributes:@{NSParagraphStyleAttributeName:tMutableParagraphStyle, NSForegroundColorAttributeName:[NSColor textColor] }]]; _diagnosticMessageTextView.textStorage.attributedString=tMutableAttributedString; [_diagnosticMessageTextView scrollPoint:NSZeroPoint]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { return [super validateMenuItem:inMenuItem]; } - (IBAction)showMoreExceptionInfo:(id)sender { if ([self.crashLog isMemberOfClass:[CUIRawCrashLog class]]==YES) return; NSPopover * tExceptionTypeLookUpPopOver = [NSPopover new]; tExceptionTypeLookUpPopOver.contentSize=NSMakeSize(500.0, 20.0); tExceptionTypeLookUpPopOver.behavior=NSPopoverBehaviorTransient; tExceptionTypeLookUpPopOver.animates=NO; tExceptionTypeLookUpPopOver.delegate=self; CUIExceptionTypePopUpViewController * tPopUpViewController=[CUIExceptionTypePopUpViewController new]; tPopUpViewController.popover=tExceptionTypeLookUpPopOver; tPopUpViewController.delegate=self; [tPopUpViewController setExceptionType:self.crashLog.exceptionType signal:self.crashLog.exceptionSignal]; tExceptionTypeLookUpPopOver.contentViewController=tPopUpViewController; NSView * tTrick=tPopUpViewController.view; // This is used to trigger the viewDidLoad method of the contentViewController. (void)tTrick; } - (IBAction)showInFinder:(id)sender { [[NSWorkspace sharedWorkspace] selectFile:self.crashLog.header.executablePath inFileViewerRootedAtPath:@""]; } - (IBAction)showHideBottomView:(id)sender { if ([_splitView isSubviewCollapsed:_bottomView]==YES) { CGFloat tPosition=NSHeight(_splitView.frame)-_splitView.dividerThickness-NSHeight(_bottomView.frame); [_splitView setPosition:tPosition ofDividerAtIndex:1]; } else { [_splitView setPosition:[_splitView maxPossiblePositionOfDividerAtIndex:1] ofDividerAtIndex:1]; } } - (IBAction)switchViewMode:(NSButton *)sender { if (sender.tag==_threadsViewMode) { switch(_threadsViewMode) { case CUIThreadsModeViewList: _listModeButton.state=WBControlStateValueOn; break; case CUIThreadsModeViewColumn: _columnModeButton.state=WBControlStateValueOn; break; case CUIThreadsModeViewLightTable: _lightTableModeButton.state=WBControlStateValueOn; break; default: break; } return; } switch(_threadsViewMode) { case CUIThreadsModeViewList: _listModeButton.state=NSControlStateValueOff; break; case CUIThreadsModeViewColumn: _columnModeButton.state=NSControlStateValueOff; break; case CUIThreadsModeViewLightTable: _lightTableModeButton.state=NSControlStateValueOff; break; default: break; } _threadsViewMode=sender.tag; [self showThreadsViewForMode:_threadsViewMode]; [[NSUserDefaults standardUserDefaults] setInteger:_threadsViewMode forKey:CUIDefaultsThreadsModeViewKey]; } - (IBAction)CUI_MENUACTION_switchShowOnlyCrashedThread:(NSButton *)sender { BOOL tShow=(sender.state==NSControlStateValueOn); self.showOnlyCrashedThread=tShow; _threadsViewController.showOnlyCrashedThread=tShow; } #pragma mark - CUIQuickHelpPopUpViewControllerDelegate - (void)quickHelpPopUpViewController:(CUIQuickHelpPopUpViewController *)inController didComputeSizeOfPopover:(NSPopover *)inPopover { // Compute the coordinates for the popover NSRect tRect=_exceptionTypeMoreInfoButton.bounds; [inPopover showRelativeToRect:tRect ofView:_exceptionTypeMoreInfoButton preferredEdge:NSMaxYEdge]; } #pragma mark - NSPopoverDelegate - (void)popoverDidClose:(NSNotification *)inNotification { NSWindow * tWindow=self.view.window; if (tWindow.firstResponder==tWindow.contentView) [tWindow makeFirstResponder:self]; } #pragma mark - NSSplitViewDelegate - (BOOL)splitView:(NSSplitView *)inSplitView canCollapseSubview:(NSView *)subview { if (subview==_bottomView /*|| subview==_topView*/) return YES; return NO; } - (void)_splitView:(NSSplitView *)inSplitView resizeSubviewsWithTopViewHeight:(CGFloat)inTopViewHeight bottomViewHeight:(CGFloat)inBottomViewHeight { NSRect tSplitViewFrame=inSplitView.frame; NSRect tTopFrame=_topView.frame; tTopFrame.size.height=inTopViewHeight; NSRect tMiddleFrame=_middleView.frame; NSRect tBottomFrame=_bottomView.frame; tBottomFrame.size.height=inBottomViewHeight; CGFloat tTopHeight=([inSplitView isSubviewCollapsed:_topView]==NO) ? NSHeight(tTopFrame) : 0.0; CGFloat tBottomHeight=([inSplitView isSubviewCollapsed:_bottomView]==NO) ? NSHeight(tBottomFrame) : 0.0; tMiddleFrame.size.height=NSHeight(tSplitViewFrame)-tTopHeight-tBottomHeight-2*inSplitView.dividerThickness; if (tMiddleFrame.size.height { IBOutlet CUICrashLogTextView * _textView; NoodleLineNumberView * _lineNumberView; IBOutlet NSPopUpButton * _sectionsVisibilityPopUpButton; IBOutlet NSButton * _colorsSyntaxButton; BOOL _wrapText; CGFloat _fontSizeDelta; //NSFont * _monospacedFont; CUIThemeItemsGroup * _textThemeItemsGroup; NSArray * _sectionsList; NSDictionary * _sectionsRanges; } @property CUITextModeDisplaySettings * displaySettings; - (void)saveBrowsingState; - (void)refreshText; - (IBAction)CUI_MENUACTION_exportCrashLog:(id)sender; - (IBAction)CUI_MENUACTION_jumpToCrashedThread:(id)sender; - (IBAction)CUI_MENUACTION_increaseFontSize:(id)sender; - (IBAction)CUI_MENUACTION_decreaseFontSize:(id)sender; - (IBAction)CUI_MENUACTION_resetFontSize:(id)sender; - (IBAction)CUI_MENUACTION_jumpToLine:(id)sender; // Notifications - (void)itemAttributesDidChange:(NSNotification *)inNotification; - (void)currentThemeDidChange:(NSNotification *)inNotification; - (void)jumpToSection:(NSNotification *)inNotification; - (void)boundsDidChange:(NSNotification *)inNotification; - (void)symbolicateAutomaticallyDidChange:(NSNotification *)inNotification; - (void)showsLineNumbersDidChange:(NSNotification *)inNotification; - (void)lineWrappingDidChange:(NSNotification *)inNotification; - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification; - (void)stackFrameSymbolicationDidSucceed:(NSNotification *)inNotification; @end @implementation CUICrashLogPresentationTextViewController + (void)initialize { [[NSUserDefaults standardUserDefaults] registerDefaults:@{CUICrashLogPresentationTextViewFontSizeDelta:@(0.0)}]; } - (instancetype)init { self=[super init]; if (self!=nil) { _wrapText=YES; _fontSizeDelta=[[NSUserDefaults standardUserDefaults] doubleForKey:CUICrashLogPresentationTextViewFontSizeDelta]; _textThemeItemsGroup=[[CUIThemesManager sharedManager].currentTheme itemsGroupWithIdentifier:[CUIApplicationPreferences groupIdentifierForPresentationMode:CUIPresentationModeText]]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSString *)nibName { return @"CUICrashLogPresentationTextViewController"; } - (void)viewDidLoad { [super viewDidLoad]; NSScrollView * tScrollView=_textView.enclosingScrollView; _lineNumberView = [[NoodleLineNumberView alloc] initWithScrollView:tScrollView]; tScrollView.verticalRulerView=_lineNumberView; tScrollView.hasHorizontalRuler=NO; tScrollView.hasVerticalRuler=YES; _textView.textContainerInset=NSMakeSize(8,300); _textView.delegate=self; _textView.textStorage.font=[[_textThemeItemsGroup attributesForItem:CUIThemeItemPlainText] font]; _textView.displaysLinkToolTips=NO; _textView.linkTextAttributes = @{ NSCursorAttributeName:[NSCursor pointingHandCursor] }; [_textView setPostsBoundsChangedNotifications:YES]; _textView.wrapLines=YES; CUIThemeItemAttributes * tAttributes=[_textThemeItemsGroup attributesForItem:CUIThemeItemSelectionBackground]; if (tAttributes!=nil) _textView.selectedTextAttributes=@{NSBackgroundColorAttributeName:tAttributes.color, NSForegroundColorAttributeName:[[_textThemeItemsGroup attributesForItem:CUIThemeItemSelectionText] color] }; //NSBackgroundColorAttributeName:[NSColor unemphasizedSelectedTextBackgroundColor], //NSForegroundColorAttributeName:[NSColor unemphasizedSelectedTextColor], //NSBackgroundColorAttributeName:[NSColor greenColor] [self showsLineNumbers:[CUIApplicationPreferences sharedPreferences].showsLineNumbers]; if ([_textView.identifier isEqualToString:@"CUIAlwaysWrap"]==YES) [self setWrapText:YES]; else [self setWrapText:[CUIApplicationPreferences sharedPreferences].lineWrapping]; // Register for notifications NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(currentThemeDidChange:) name:CUIThemesManagerCurrentThemeDidChangeNotification object:nil]; } - (void)viewDidAppear { [super viewDidAppear]; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter removeObserver:self name:CUIThemeItemAttributesDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(itemAttributesDidChange:) name:CUIThemeItemAttributesDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:@"jumpToSectionNotification" object:nil]; [tNotificationCenter addObserver:self selector:@selector(jumpToSection:) name:@"jumpToSectionNotification" object:nil]; [tNotificationCenter removeObserver:self name:NSViewBoundsDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(boundsDidChange:) name:NSViewBoundsDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(symbolicateAutomaticallyDidChange:) name:CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIPreferencesTextModeShowsLineNumbersDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(showsLineNumbersDidChange:) name:CUIPreferencesTextModeShowsLineNumbersDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIPreferencesTextModeLineWrappingDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(lineWrappingDidChange:) name:CUIPreferencesTextModeLineWrappingDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIdSYMBundlesManagerDidAddBundlesNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(dSYMBundlesManagerDidAddBundles:) name:CUIdSYMBundlesManagerDidAddBundlesNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIStackFrameSymbolicationDidSucceedNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(stackFrameSymbolicationDidSucceed:) name:CUIStackFrameSymbolicationDidSucceedNotification object:nil]; [tNotificationCenter removeObserver:self name:@"windowDidNotHandleKeyEventNotification" object:nil]; [tNotificationCenter addObserver:self selector:@selector(handleKeyDown:) name:@"windowDidNotHandleKeyEventNotification" object:self.view.window]; } - (void)viewWillDisappear { [super viewWillDisappear]; // Save browsing state [self saveBrowsingState]; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter removeObserver:self name:CUIThemeItemAttributesDidChangeNotification object:nil]; //[tNotificationCenter removeObserver:self name:CUIThemesManagerCurrentThemeDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:@"jumpToSectionNotification" object:nil]; [tNotificationCenter removeObserver:self name:NSViewBoundsDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIPreferencesTextModeShowsLineNumbersDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIPreferencesTextModeLineWrappingDidChangeNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIdSYMBundlesManagerDidAddBundlesNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIStackFrameSymbolicationDidSucceedNotification object:nil]; [tNotificationCenter removeObserver:self name:@"windowDidNotHandleKeyEventNotification" object:nil]; } #pragma mark - - (void)saveBrowsingState { CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; if (self.crashLog!=nil) { CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; tBrowsingState.textModeDisplaySettings=[self.displaySettings copy]; NSRect tVisibleRect = _textView.visibleRect; NSLayoutManager * tLayoutManager = _textView.layoutManager; NSUInteger tNumberOfGlyphs = tLayoutManager.numberOfGlyphs; NSUInteger tGlyphIndex = 0; for (NSUInteger tLineNumber = 1; tGlyphIndex < tNumberOfGlyphs; tLineNumber++) { NSRange tLineRange; NSRect tLineRect=[tLayoutManager lineFragmentRectForGlyphAtIndex:tGlyphIndex effectiveRange:&tLineRange]; if (NSIntersectsRect(tVisibleRect, tLineRect)==YES) { tBrowsingState.firstVisibleLineNumber=tLineNumber; NSRect tBounds=[tLayoutManager boundingRectForGlyphRange:tLineRange inTextContainer:_textView.textContainer]; tBrowsingState.firstVisibleLineVerticalOffset=NSMinY(tVisibleRect)-NSMinY(tBounds); break; } tGlyphIndex = NSMaxRange(tLineRange); } } } - (BOOL)showOnlyCrashedThread { return ((self.displaySettings.visibleSections & CUIDocumentBacktraceCrashedThreadSubSection)==CUIDocumentBacktraceCrashedThreadSubSection); } - (void)setShowOnlyCrashedThread:(BOOL)inShowOnlyCrashedThread { if (inShowOnlyCrashedThread==YES) { self.displaySettings.visibleSections|=CUIDocumentBacktraceCrashedThreadSubSection; } else { self.displaySettings.visibleSections&=~CUIDocumentBacktraceCrashedThreadSubSection; } } - (void)setCrashLog:(CUICrashLog *)inCrashLog { [self saveBrowsingState]; [super setCrashLog:inCrashLog]; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:inCrashLog windowNumber:self.view.window.windowNumber]; self.displaySettings=[tBrowsingState.textModeDisplaySettings copy]; if (self.displaySettings==nil) { self.displaySettings=[[CUIApplicationPreferences sharedPreferences].defaultTextModeDisplaySettings copy]; } BOOL tIsRawCrashLog=[self.crashLog isMemberOfClass:[CUIRawCrashLog class]]; _sectionsVisibilityPopUpButton.enabled=(tIsRawCrashLog==NO); _showOnlyCrashedThreadButton.enabled=(tIsRawCrashLog==NO); _showByteOffsetButton.enabled=(tIsRawCrashLog==NO); _showMachineInstructionAddressButton.enabled=(tIsRawCrashLog==NO); _showBinaryNameButton.enabled=(tIsRawCrashLog==NO); if (tIsRawCrashLog==NO) { _showOnlyCrashedThreadButton.state=((self.displaySettings.visibleSections & CUIDocumentBacktraceCrashedThreadSubSection)==CUIDocumentBacktraceCrashedThreadSubSection) ? NSControlStateValueOn : NSControlStateValueOff; _showByteOffsetButton.state=((self.displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)==CUIStackFrameByteOffsetComponent) ? NSControlStateValueOn : NSControlStateValueOff; _showMachineInstructionAddressButton.state=((self.displaySettings.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)==CUIStackFrameMachineInstructionAddressComponent) ? NSControlStateValueOn : NSControlStateValueOff; _showBinaryNameButton.state=(((self.displaySettings.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)==CUIStackFrameBinaryNameComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; } if (tIsRawCrashLog==NO) { self.visibleStackFrameComponents=self.displaySettings.visibleStackFrameComponents; } else { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshText) object:nil]; [self refreshText]; } // Restore (vertical) scrolling position? if (tBrowsingState.firstVisibleLineNumber==NSNotFound || (tBrowsingState.firstVisibleLineNumber==0 && tBrowsingState.firstVisibleLineNumber<0.01)) { [_textView CUI_scrollPoint:NSZeroPoint]; //[_textView scrollToBeginningOfDocument:self]; [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogPresentationDisplayedSectionsDidChangeNotification object:nil]; return; } NSLayoutManager * tLayoutManager = _textView.layoutManager; NSUInteger tNumberOfGlyphs = tLayoutManager.numberOfGlyphs; NSUInteger tGlyphIndex = 0; for (NSUInteger tLineNumber = 1; tGlyphIndex < tNumberOfGlyphs; tLineNumber++) { NSRange tLineRange; [tLayoutManager lineFragmentRectForGlyphAtIndex:tGlyphIndex effectiveRange:&tLineRange]; if (tLineNumber == tBrowsingState.firstVisibleLineNumber) { // Scroll to line NSRect tBounds=[_textView.layoutManager boundingRectForGlyphRange:tLineRange inTextContainer:_textView.textContainer]; tBounds.origin.x=0; tBounds.origin.y+=tBrowsingState.firstVisibleLineVerticalOffset; [_textView CUI_scrollPoint:tBounds.origin]; break; } tGlyphIndex = NSMaxRange(tLineRange); } dispatch_async(dispatch_get_main_queue(), ^{ [self boundsDidChange:[NSNotification notificationWithName:NSViewBoundsDidChangeNotification object:self->_textView]]; }); //_textView.textStorage.font=[NSFont monospacedDigitSystemFontOfSize:11.0 weight:NSFontWeightRegular]; } - (void)setVisibleStackFrameComponents:(CUIStackFrameComponents)inVisibleStackFrameComponents { [super setVisibleStackFrameComponents:inVisibleStackFrameComponents]; self.displaySettings.visibleStackFrameComponents=inVisibleStackFrameComponents; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshText) object:nil]; [self refreshText]; } - (NSRange)crashedThreadRange { __block NSRange tRange=NSMakeRange(NSNotFound,0); [_textView.textStorage enumerateAttribute:CUIGenericAnchorAttributeName inRange:NSMakeRange(0,_textView.textStorage.length) options:0 usingBlock:^(NSString * bValue, NSRange bRange, BOOL * bOutStop) { if (bValue==nil) return; if ([bValue isEqualToString:@"a:crashed_thread"]) { tRange=bRange; *bOutStop=YES; } }]; return tRange; } - (void)showsLineNumbers:(BOOL)inShowsLineNumbers { NSScrollView * tScrollView=_textView.enclosingScrollView; BOOL tIsChange=(_textView.enclosingScrollView.rulersVisible!=inShowsLineNumbers); _textView.enclosingScrollView.rulersVisible=inShowsLineNumbers; [_textView.enclosingScrollView tile]; if (tIsChange==YES && inShowsLineNumbers==YES) { // Offset to the right NSRect tVisibleRect=[_textView visibleRect]; tVisibleRect.origin.x-=NSWidth(tScrollView.verticalRulerView.frame); [_textView scrollRectToVisible:tVisibleRect]; } [self refreshLinesGutter]; } - (void)setWrapText:(BOOL)inWrap { if (_wrapText==inWrap) return; _wrapText=inWrap; NSScrollView * tScrollView=_textView.enclosingScrollView; if (_wrapText==NO) { tScrollView.hasHorizontalScroller=YES; tScrollView.hasVerticalScroller=YES; _textView.autoresizingMask=(NSViewWidthSizable | NSViewHeightSizable); NSClipView * tClipView=(NSClipView *)_textView.superview; NSRect tClipViewFrame=tClipView.frame; NSTextContainer * tTextContainer=[[NSTextContainer alloc] initWithContainerSize:NSMakeSize(10000000, 10000000)]; [tTextContainer setWidthTracksTextView:NO]; [tTextContainer setHeightTracksTextView:NO]; [_textView replaceTextContainer:tTextContainer]; _textView.minSize=tClipViewFrame.size; _textView.maxSize=NSMakeSize(10000000, 10000000); _textView.horizontallyResizable=YES; _textView.verticallyResizable=YES; } else { tScrollView.hasHorizontalScroller=NO; tScrollView.hasVerticalScroller=YES; _textView.autoresizingMask=(NSViewWidthSizable | NSViewHeightSizable); NSClipView * tClipView=(NSClipView *)_textView.superview; NSRect tClipViewFrame=tClipView.frame; CGFloat tWidth=NSWidth(tClipViewFrame); NSTextContainer * tTextContainer=[[NSTextContainer alloc] initWithContainerSize:NSMakeSize(tWidth, 10000000)]; [tTextContainer setWidthTracksTextView:YES]; [tTextContainer setHeightTracksTextView:NO]; [_textView replaceTextContainer:tTextContainer]; _textView.minSize=tClipViewFrame.size; _textView.maxSize=NSMakeSize(tWidth, 10000000); _textView.horizontallyResizable=NO; _textView.verticallyResizable=YES; } _textView.wrapLines=inWrap; _textView.autoresizingMask=NSViewNotSizable; tScrollView.rulersVisible=[CUIApplicationPreferences sharedPreferences].showsLineNumbers; } #pragma mark - - (void)refreshLinesGutter { // Update Line Numbers color CUIThemeItemAttributes * tAttributes=[_textThemeItemsGroup attributesForItem:CUIThemeItemLineNumber]; _lineNumberView.textColor=tAttributes.color; } - (void)refreshText { CUICrashLog * tCrashLog=self.crashLog; if (tCrashLog==nil) return; _lineNumberView.fontSizeDelta=_fontSizeDelta; CUIDataTransform * tDataTransform=nil; if (tCrashLog.ipsReport!=nil) { tDataTransform=[[CUIIPSTransform alloc] initWithThemesProvider:[CUIThemesManager sharedManager]]; tDataTransform.input=tCrashLog.ipsReport; ((CUIIPSTransform *)tDataTransform).crashlog=tCrashLog; } else { tDataTransform=[[CUICrashDataTransform alloc] initWithThemesProvider:[CUIThemesManager sharedManager]]; tDataTransform.input=tCrashLog; } tDataTransform.displaySettings=self.displaySettings; tDataTransform.fontSizeDelta=_fontSizeDelta; if ([tDataTransform transform]==NO) { // A COMPLETER } NSAttributedString * tAttributedString=tDataTransform.output; _textView.backgroundColor=[[_textThemeItemsGroup attributesForItem:CUIThemeItemBackground] color]; _lineNumberView.backgroundColor=[[_textThemeItemsGroup attributesForItem:CUIThemeItemBackground] color]; _textView.selectedTextAttributes=@{ NSBackgroundColorAttributeName:[[_textThemeItemsGroup attributesForItem:CUIThemeItemSelectionBackground] color], NSForegroundColorAttributeName:[[_textThemeItemsGroup attributesForItem:CUIThemeItemSelectionText] color] }; _textView.textStorage.attributedString=tAttributedString; //[_textView.layoutManager ensureLayoutForTextContainer:_textView.textContainer]; // Compute sections ranges __block NSString * tPreviousSection=nil; __block NSString * tCurrentSection=nil; NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; NSMutableArray * tMutableArray=[NSMutableArray array]; [tAttributedString enumerateAttributesInRange:NSMakeRange(0,tAttributedString.length) options:0 usingBlock:^(NSDictionary * bAttributes, NSRange bRange, BOOL * bOutStop) { NSString * bValue=bAttributes[CUIThreadAnchorAttributeName]; if (bValue==nil) { bValue=bAttributes[CUISectionAnchorAttributeName]; if (bValue==nil) return; } if (tMutableDictionary[bValue]!=nil) return; [tMutableArray addObject:bValue]; tCurrentSection=bValue; tMutableDictionary[tCurrentSection]=[NSValue valueWithRange:bRange]; if (tPreviousSection!=nil) { NSRange tPreviousRange=[tMutableDictionary[tPreviousSection] rangeValue]; tPreviousRange.length=bRange.location-tPreviousRange.location; tMutableDictionary[tPreviousSection]=[NSValue valueWithRange:tPreviousRange]; } tPreviousSection=tCurrentSection; }]; if (tPreviousSection!=nil) { NSRange tPreviousRange=[tMutableDictionary[tPreviousSection] rangeValue]; tPreviousRange.length=tAttributedString.length-tPreviousRange.location; tMutableDictionary[tPreviousSection]=[NSValue valueWithRange:tPreviousRange]; } _sectionsList=[tMutableArray copy]; _sectionsRanges=[tMutableDictionary copy]; } #pragma mark - CUIEQuickHelpPopUpViewControllerDelegate - (void)quickHelpPopUpViewController:(CUIQuickHelpPopUpViewController *)inController didComputeSizeOfPopover:(NSPopover *)inPopover { // Compute the coordinates for the popover NSRect tRect=[_textView.layoutManager boundingRectForGlyphRange:inController.textRange inTextContainer:_textView.textContainer]; NSPoint containerOrigin = [_textView textContainerOrigin]; tRect=NSOffsetRect(tRect, containerOrigin.x, containerOrigin.y); [inPopover showRelativeToRect:tRect ofView:_textView preferredEdge:NSMaxYEdge]; } #pragma mark - NSTextViewDelegate - (BOOL)textView:(NSTextView *)inTextView clickedOnLink:(id)inLink atIndex:(NSUInteger)inCharIndex { if ([inLink isKindOfClass:[NSURL class]]==YES) { NSURL * tURL=(NSURL *)inLink; if ([tURL.scheme isEqualToString:@"a"]==YES) { NSString * tHost=tURL.host; if ([tHost isEqualToString:@"crashed_thread"]==YES) { // Jump to crash thread line NSRange tCrashedThreadRange=[self crashedThreadRange]; [_textView setSelectedRange:tCrashedThreadRange]; [_textView scrollRangeToVisible:tCrashedThreadRange]; return YES; } else if ([tHost isEqualToString:@"exception_type"]==YES) { __block NSRange tRange=NSMakeRange(NSNotFound,0); //:[NSURL URLWithString:@"a://exception_type"] [_textView.textStorage enumerateAttribute:NSLinkAttributeName inRange:NSMakeRange(0,_textView.textStorage.length) options:0 usingBlock:^(NSURL * bValue, NSRange bRange, BOOL * bOutStop) { if ([bValue isKindOfClass:[NSURL class]]==NO) return; if ([bValue.absoluteString isEqualToString:@"a://exception_type"]==YES) { tRange=bRange; *bOutStop=YES; } }]; if (tRange.location==NSNotFound) return NO; NSPopover * tExceptionTypeLookUpPopOver = [NSPopover new]; tExceptionTypeLookUpPopOver.contentSize=NSMakeSize(500.0, 20.0); tExceptionTypeLookUpPopOver.behavior=NSPopoverBehaviorTransient; tExceptionTypeLookUpPopOver.animates=NO; CUIExceptionTypePopUpViewController * tPopUpViewController=[CUIExceptionTypePopUpViewController new]; tPopUpViewController.popover=tExceptionTypeLookUpPopOver; tPopUpViewController.delegate=self; tPopUpViewController.textRange=tRange; [tPopUpViewController setExceptionType:self.crashLog.exceptionType signal:self.crashLog.exceptionSignal]; tExceptionTypeLookUpPopOver.contentViewController=tPopUpViewController; NSView * tTrick=tPopUpViewController.view; // This is used to trigger the viewDidLoad method of the contentViewController. (void)tTrick; return YES; } else if ([tHost isEqualToString:@"termination_reason"]==YES) { __block NSRange tRange=NSMakeRange(NSNotFound,0); //:[NSURL URLWithString:@"a://termination_reason"] [_textView.textStorage enumerateAttribute:NSLinkAttributeName inRange:NSMakeRange(0,_textView.textStorage.length) options:0 usingBlock:^(NSURL * bValue, NSRange bRange, BOOL * bOutStop) { if ([bValue isKindOfClass:[NSURL class]]==NO) return; if ([bValue.absoluteString isEqualToString:@"a://termination_reason"]==YES) { tRange=bRange; *bOutStop=YES; } }]; if (tRange.location==NSNotFound) return NO; NSPopover * tExceptionTypeLookUpPopOver = [NSPopover new]; tExceptionTypeLookUpPopOver.contentSize=NSMakeSize(500.0, 20.0); tExceptionTypeLookUpPopOver.behavior=NSPopoverBehaviorTransient; tExceptionTypeLookUpPopOver.animates=NO; CUITerminationReasonPopUpViewController * tPopUpViewController=[CUITerminationReasonPopUpViewController new]; tPopUpViewController.popover=tExceptionTypeLookUpPopOver; tPopUpViewController.delegate=self; tPopUpViewController.textRange=tRange; CUICrashLogExceptionInformation * tExceptionInformation=self.crashLog.exceptionInformation; [tPopUpViewController setNamespace:tExceptionInformation.terminationNamespace code:tExceptionInformation.terminationCode]; tExceptionTypeLookUpPopOver.contentViewController=tPopUpViewController; NSView * tTrick=tPopUpViewController.view; // This is used to trigger the viewDidLoad method of the contentViewController. (void)tTrick; return YES; } } else if ([tURL.scheme isEqualToString:@"bin"]==YES) { __block NSRange tRange=NSMakeRange(NSNotFound,0); NSString * tAnchorValue=[NSString stringWithFormat:@"bin:%@",tURL.host]; [_textView.textStorage enumerateAttribute:CUIBinaryAnchorAttributeName inRange:NSMakeRange(0,_textView.textStorage.length) options:0 usingBlock:^(NSString * bValue, NSRange bRange, BOOL * bOutStop) { if (bValue==nil) return; if ([bValue isEqualToString:tAnchorValue]) { tRange=bRange; *bOutStop=YES; } }]; if (tRange.location!=NSNotFound) { [_textView setSelectedRange:tRange]; [_textView scrollRangeToVisible:tRange]; } return YES; } else if ([tURL.scheme hasPrefix:@"sourcecode-"]==YES) { //NSUInteger tLineNumber=[[tURL.scheme substringFromIndex:[@"sourcecode-" length]] integerValue]; // BBEdit -> bbedit_tool file_path +line // Open the file in the appropriate source editor NSURL * tFileURL=[NSURL fileURLWithPath:tURL.path]; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101600 if (@available(*, macOS 11.0)) { [[NSWorkspace sharedWorkspace] openURLs:@[tFileURL] withApplicationAtURL:[CUIApplicationPreferences sharedPreferences].preferedSourceCodeEditorURL configuration:[NSWorkspaceOpenConfiguration configuration] completionHandler:^(NSRunningApplication * _Nullable app, NSError * _Nullable error) { }]; } else #endif { [[NSWorkspace sharedWorkspace] openURLs:@[tFileURL] withApplicationAtURL:[CUIApplicationPreferences sharedPreferences].preferedSourceCodeEditorURL options:NSWorkspaceLaunchDefault configuration:@{} error:NULL]; } return YES; } } return NO; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; CUICrashLog * tCrashLog=self.crashLog; // Text Viewer /*if (tAction==@selector(CUI_MENUACTION_switchSyntaxHighlighting:)) { inMenuItem.state=(self.displaySettings.highlightSyntax==YES) ? NSControlStateValueOn : NSControlStateValueOff; }*/ if (tAction==@selector(performTextFinderAction:)) { return [_textView validateMenuItem:inMenuItem]; } if (tAction==@selector(CUI_MENUACTION_resetFontSize:)) { return (fabs(_fontSizeDelta)>=1); } if (tAction==@selector(CUI_MENUACTION_switchTheme:)) { return [super validateMenuItem:inMenuItem]; } // File Menu if (tAction==@selector(CUI_MENUACTION_print:)) { return YES; } // Navigate Menu BOOL tIsRawCrashLog=[tCrashLog isMemberOfClass:[CUIRawCrashLog class]]; if (tAction==@selector(CUI_MENUACTION_jumpToHeader:)) { if (tIsRawCrashLog==YES) return NO; return ((self.displaySettings.visibleSections & CUIDocumentHeaderSection)==CUIDocumentHeaderSection); } if (tAction==@selector(CUI_MENUACTION_jumpToExceptionInformation:)) { if (tIsRawCrashLog==YES) return NO; return ((self.displaySettings.visibleSections & CUIDocumentExceptionInformationSection)==CUIDocumentExceptionInformationSection); } if (tAction==@selector(CUI_MENUACTION_jumpToDiagnosticMessages:)) { if (tIsRawCrashLog==YES) return NO; return ((self.displaySettings.visibleSections & CUIDocumentDiagnosticMessagesSection)==CUIDocumentDiagnosticMessagesSection); } if (tAction==@selector(CUI_MENUACTION_jumpToBacktraces:)) { if (tIsRawCrashLog==YES) return NO; return ((self.displaySettings.visibleSections & CUIDocumentBacktracesSection)==CUIDocumentBacktracesSection); } if (tAction==@selector(CUI_MENUACTION_jumpToThreadState:)) { if (tIsRawCrashLog==YES) return NO; return ((self.displaySettings.visibleSections & CUIDocumentThreadStateSection)==CUIDocumentThreadStateSection); } if (tAction==@selector(CUI_MENUACTION_jumpToBinaryImages:)) { if (tIsRawCrashLog==YES) return NO; return ((self.displaySettings.visibleSections & CUIDocumentBinaryImagesSection)==CUIDocumentBinaryImagesSection); } if (tAction==@selector(CUI_MENUACTION_jumpToCrashedThread:)) { if (tIsRawCrashLog==YES) return NO; return ((self.displaySettings.visibleSections & CUIDocumentBacktracesSection)==CUIDocumentBacktracesSection) && ((self.displaySettings.visibleSections & CUIDocumentBacktraceCrashedThreadSubSection)==0); } if (tAction==@selector(CUI_MENUACTION_switchHeaderVisibility:)) { if (tIsRawCrashLog==YES) return NO; BOOL tEnabled=tCrashLog.isHeaderAvailable; inMenuItem.state=(tEnabled==YES) ? ((self.displaySettings.visibleSections & CUIDocumentHeaderSection)==CUIDocumentHeaderSection) : NSControlStateValueOff; return tEnabled; } if (tAction==@selector(CUI_MENUACTION_switchExceptionInformationVisibility:)) { if (tIsRawCrashLog==YES) return NO; BOOL tEnabled=tCrashLog.isExceptionInformationAvailable; inMenuItem.state=(tEnabled==YES) ? ((self.displaySettings.visibleSections & CUIDocumentExceptionInformationSection)==CUIDocumentExceptionInformationSection) : NSControlStateValueOff; return tEnabled; } if (tAction==@selector(CUI_MENUACTION_switchDiagnosticMessagesVisibility:)) { if (tIsRawCrashLog==YES) return NO; BOOL tEnabled=tCrashLog.isDiagnosticMessageAvailable; inMenuItem.state=(tEnabled==YES) ? ((self.displaySettings.visibleSections & CUIDocumentDiagnosticMessagesSection)==CUIDocumentDiagnosticMessagesSection) : NSControlStateValueOff; return tEnabled; } if (tAction==@selector(CUI_MENUACTION_switchBacktracesVisibility:)) { if (tIsRawCrashLog==YES) return NO; BOOL tEnabled=tCrashLog.isBacktracesAvailable; inMenuItem.state=(tEnabled==YES) ? ((self.displaySettings.visibleSections & CUIDocumentBacktracesSection)==CUIDocumentBacktracesSection) : NSControlStateValueOff; return tEnabled; } if (tAction==@selector(CUI_MENUACTION_switchThreadStateVisibility:)) { if (tIsRawCrashLog==YES) return NO; BOOL tEnabled=tCrashLog.isThreadStateAvailable; inMenuItem.state=(tEnabled==YES) ? ((self.displaySettings.visibleSections & CUIDocumentThreadStateSection)==CUIDocumentThreadStateSection) : NSControlStateValueOff; return tEnabled; } if (tAction==@selector(CUI_MENUACTION_switchBinaryImagesVisibility:)) { if (tIsRawCrashLog==YES) return NO; BOOL tEnabled=tCrashLog.isBinaryImagesAvailable; inMenuItem.state=(tEnabled==YES) ? ((self.displaySettings.visibleSections & CUIDocumentBinaryImagesSection)==CUIDocumentBinaryImagesSection) : NSControlStateValueOff; return tEnabled; } return [super validateMenuItem:inMenuItem]; } #pragma mark - - (void)handleKeyDown:(NSNotification *)inNotification { NSEvent * tEvent=inNotification.userInfo[@"Event"]; NSString * tTypedText=tEvent.characters; NSUInteger tLength=tTypedText.length; for(NSUInteger tIndex=0;tIndex0); // A COMPLETER (minimum length?) IPSReport * tIPSReport=self.crashLog.ipsReport; tAccessoryViewController.canObfuscateContents=(tIPSReport!=nil); tExportPanel.accessoryView=tAccessoryViewController.view; [tExportPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger bResult){ if (bResult!=NSModalResponseOK) return; CUICrashLogExportFormat tSelectedExportFormat=tAccessoryViewController.exportFormat; CUIDataTransform * tDataTransform=nil; if (tIPSReport!=nil) { IPSReport * tFinalIPSReport=tIPSReport; tDataTransform=[[CUIIPSTransform alloc] initWithThemesProvider:[CUIThemesManager sharedManager]]; if (tAccessoryViewController.obfuscateContents==YES) { IPSObfuscator * tObfuscator=[IPSObfuscator new]; tFinalIPSReport=[tIPSReport obfuscateWithObfuscator:tObfuscator]; tDataTransform.symbolicationMode=CUISymbolicationModeNone; } tDataTransform.input=tFinalIPSReport; ((CUIReportThemedTransform *)tDataTransform).crashlog=self.crashLog; } else { tDataTransform=[[CUICrashDataTransform alloc] initWithThemesProvider:[CUIThemesManager sharedManager]]; tDataTransform.input=self.crashLog; } tDataTransform.displaySettings=[tAccessoryViewController.displaySettings copy]; tDataTransform.fontSizeDelta=0; switch(tSelectedExportFormat) { case CUICrashLogExportFormatHTML: tDataTransform.hyperlinksStyle=CUIHyperlinksHTML; break; default: tDataTransform.hyperlinksStyle=CUIHyperlinksNone; break; } if ([tDataTransform transform]==NO) { NSBeep(); return; } NSAttributedString * tAttributedString=tDataTransform.output; // Extract the selection if needed if (tAccessoryViewController.exportedContents==CUICrashLogExportedContentsSelection) { tAttributedString=[tAttributedString attributedSubstringFromRange:tSelectionRange]; } //NSRTFTextDocumentType //NSHTMLTextDocumentType // NSAttributedStringDocumentType tDocumenType=NSPlainTextDocumentType; switch(tSelectedExportFormat) { case CUICrashLogExportFormatRTF: tDocumenType=NSRTFTextDocumentType; break; case CUICrashLogExportFormatHTML: tDocumenType=NSHTMLTextDocumentType; break; default: break; } NSData * tData=nil; NSError * tError=nil; if (tSelectedExportFormat==CUICrashLogExportFormatPDF) { NSPrintInfo * tPrintInfo=[NSPrintInfo sharedPrintInfo]; NSRect tBounds=self->_textView.bounds; if (tAccessoryViewController.exportedContents==CUICrashLogExportedContentsSelection) { NSRange tGlyphRange=[self->_textView.layoutManager glyphRangeForCharacterRange:tSelectionRange actualCharacterRange:NULL]; NSRect tBoundingRect=[self->_textView.layoutManager boundingRectForGlyphRange:tGlyphRange inTextContainer:self->_textView.textContainer]; tBounds.size.height=NSHeight(tBoundingRect); } else { tBounds=self->_textView.bounds; tBounds.size.height-=300; } tPrintInfo.paperSize=tBounds.size; tPrintInfo.topMargin=0; tPrintInfo.bottomMargin=0; tPrintInfo.leftMargin=0; tPrintInfo.rightMargin=0; tPrintInfo.verticallyCentered=NO; NSTextView * tPrintableTextView=[[NSTextView alloc] initWithFrame:tBounds]; tPrintableTextView.backgroundColor=[[self->_textThemeItemsGroup attributesForItem:CUIThemeItemBackground] color]; [tPrintableTextView.textStorage appendAttributedString:tAttributedString]; tPrintableTextView.textStorage.font=[[self->_textThemeItemsGroup attributesForItem:CUIThemeItemPlainText] font]; NSMutableData * tMutableData=[NSMutableData data]; NSPrintOperation * tPrintOperation=[NSPrintOperation PDFOperationWithView:tPrintableTextView insideRect:tBounds toData:tMutableData printInfo:tPrintInfo]; [tPrintOperation runOperation]; tData=[tMutableData copy]; } else { if (tSelectedExportFormat==CUICrashLogExportFormatText) { tData=[tAttributedString.string dataUsingEncoding:NSUTF8StringEncoding]; } else { NSDictionary * tDocumentAttributes=@{ NSDocumentTypeDocumentAttribute:tDocumenType, NSBackgroundColorDocumentAttribute:self->_textView.backgroundColor }; tData=[tAttributedString dataFromRange:NSMakeRange(0,tAttributedString.length) documentAttributes:tDocumentAttributes error:&tError]; } } if (tData==nil) { NSBeep(); // A COMPLETER (Alert dialog?) return; } switch(tSelectedExportFormat) { case CUICrashLogExportFormatRTF: break; case CUICrashLogExportFormatHTML: { NSString * tString=[[NSString alloc] initWithData:tData encoding:NSUTF8StringEncoding]; NSString * tOtherString=[tString stringByReplacingOccurrencesOfString:@"href=\"sharp://" withString:@"style=\"color:inherit;text-decoration: none\" href=\"#" options:NSCaseInsensitiveSearch range:NSMakeRange(0,tString.length)]; tOtherString=[tOtherString stringByReplacingOccurrencesOfString:@"href=\"anchor://" withString:@"name=\"" options:NSCaseInsensitiveSearch range:NSMakeRange(0,tOtherString.length)]; tData=[tOtherString dataUsingEncoding:NSUTF8StringEncoding]; break; } default: break; } tError=nil; if ([tData writeToURL:tExportPanel.URL options:(NSDataWritingAtomic) error:&tError]==YES) { //[[NSWorkspace sharedWorkspace] selectFile:tExportPanel.URL.path inFileViewerRootedAtPath:@""]; return; } // Export failed NSString * tInformativeText=nil; if (tError!=nil) tInformativeText=tError.localizedDescription; dispatch_async(dispatch_get_main_queue(), ^{ NSBeep(); NSAlert * tAlert=[NSAlert new]; tAlert.messageText=NSLocalizedString(@"The export operation failed.", @""); tAlert.informativeText=tInformativeText; [tAlert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse returnCode) { // Do nothing }]; }); }]; } #pragma Reader Menu - (IBAction)CUI_MENUACTION_increaseFontSize:(id)sender { _fontSizeDelta+=1.0; [self refreshText]; [[NSUserDefaults standardUserDefaults] setDouble:_fontSizeDelta forKey:CUICrashLogPresentationTextViewFontSizeDelta]; } - (IBAction)CUI_MENUACTION_decreaseFontSize:(id)sender { NSFont * tPlainTextFont=[[_textThemeItemsGroup attributesForItem:CUIThemeItemPlainText] font]; CGFloat tNewDeltaSize=_fontSizeDelta-1.0; if (tPlainTextFont.pointSize + tNewDeltaSize>6.0) { _fontSizeDelta=tNewDeltaSize; [self refreshText]; [[NSUserDefaults standardUserDefaults] setDouble:_fontSizeDelta forKey:CUICrashLogPresentationTextViewFontSizeDelta]; } } - (IBAction)CUI_MENUACTION_resetFontSize:(id)sender { _fontSizeDelta=0; [self refreshText]; [[NSUserDefaults standardUserDefaults] setDouble:_fontSizeDelta forKey:CUICrashLogPresentationTextViewFontSizeDelta]; } #pragma mark - - (IBAction)performTextFinderAction:(id)sender { [_textView performTextFinderAction:sender]; } #pragma mark - Navigate Menu - (IBAction)CUI_MENUACTION_jumpToLine:(id)sender { CUILineJumperWindowController * tController=[CUILineJumperWindowController sharedLineJumperWindowController]; if (tController.window.isVisible==NO) [tController popUpForTextView:_textView]; } - (IBAction)CUI_MENUACTION_jumpToCrashedThread:(id)sender { [self _jumpToAnchor:@"a:crashed_thread"]; } - (void)_jumpToAnchor:(NSString *)inAnchor { if (inAnchor.length==0) return; __block NSRange tRange=NSMakeRange(NSNotFound,0); NSArray * tAnchorsAttributesNames=@[ CUIGenericAnchorAttributeName, CUISectionAnchorAttributeName, CUIThreadAnchorAttributeName, CUIBinaryAnchorAttributeName ]; for(NSString * tAnchorAttributeName in tAnchorsAttributesNames) { [_textView.textStorage enumerateAttribute:tAnchorAttributeName inRange:NSMakeRange(0,_textView.textStorage.length) options:0 usingBlock:^(NSString * bValue, NSRange bRange, BOOL * bOutStop) { if (bValue==nil) return; if ([bValue isEqualToString:inAnchor]) { tRange=bRange; *bOutStop=YES; } }]; if (tRange.location!=NSNotFound) break; } if (tRange.location!=NSNotFound) { NSRect tBounds=[_textView.layoutManager boundingRectForGlyphRange:tRange inTextContainer:_textView.textContainer]; tBounds.origin.x=0; [_textView CUI_scrollPoint:tBounds.origin]; } } - (IBAction)CUI_MENUACTION_jumpToHeader:(id)sender { [self _jumpToAnchor:@"section:Header"]; } - (IBAction)CUI_MENUACTION_jumpToExceptionInformation:(id)sender { [self _jumpToAnchor:@"section:Exception Information"]; } - (IBAction)CUI_MENUACTION_jumpToDiagnosticMessages:(id)sender { [self _jumpToAnchor:@"section:Diagnostic Messages"]; } - (IBAction)CUI_MENUACTION_jumpToBacktraces:(id)sender { [self _jumpToAnchor:@"section:Backtraces"]; } - (IBAction)CUI_MENUACTION_jumpToThreadState:(id)sender { [self _jumpToAnchor:@"section:Thread State"]; } - (IBAction)CUI_MENUACTION_jumpToBinaryImages:(id)sender { [self _jumpToAnchor:@"section:Binary Images"]; } #pragma mark - - (void)_CUI_MENUACTION_switchVisibilityCommon { [self refreshText]; // Update the Sections menu in the navigation bar [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogPresentationDisplayedSectionsDidChangeNotification object:nil]; // Update the selected item in the Sections menu if needed [self boundsDidChange:nil]; } - (IBAction)CUI_MENUACTION_switchHeaderVisibility:(id)sender { self.displaySettings.visibleSections^=CUIDocumentHeaderSection; [self _CUI_MENUACTION_switchVisibilityCommon]; } - (IBAction)CUI_MENUACTION_switchExceptionInformationVisibility:(id)sender { self.displaySettings.visibleSections^=CUIDocumentExceptionInformationSection; [self _CUI_MENUACTION_switchVisibilityCommon]; } - (IBAction)CUI_MENUACTION_switchDiagnosticMessagesVisibility:(id)sender { self.displaySettings.visibleSections^=CUIDocumentDiagnosticMessagesSection; [self _CUI_MENUACTION_switchVisibilityCommon]; } - (IBAction)CUI_MENUACTION_switchBacktracesVisibility:(id)sender { self.displaySettings.visibleSections^=CUIDocumentBacktracesSection; [self _CUI_MENUACTION_switchVisibilityCommon]; } - (IBAction)CUI_MENUACTION_switchThreadStateVisibility:(id)sender { self.displaySettings.visibleSections^=CUIDocumentThreadStateSection; [self _CUI_MENUACTION_switchVisibilityCommon]; } - (IBAction)CUI_MENUACTION_switchBinaryImagesVisibility:(id)sender { self.displaySettings.visibleSections^=CUIDocumentBinaryImagesSection; [self _CUI_MENUACTION_switchVisibilityCommon]; } #pragma mark - - (IBAction)CUI_MENUACTION_switchShowOnlyCrashedThread:(id)sender { self.displaySettings.visibleSections^=CUIDocumentBacktraceCrashedThreadSubSection; [self refreshText]; } - (IBAction)CUI_MENUACTION_switchShowOffset:(id)sender { self.displaySettings.visibleStackFrameComponents^=CUIStackFrameByteOffsetComponent; [self refreshText]; } - (IBAction)CUI_MENUACTION_switchShowMemoryAddress:(id)sender { self.displaySettings.visibleStackFrameComponents^=CUIStackFrameMachineInstructionAddressComponent; [self refreshText]; } - (IBAction)CUI_MENUACTION_switchShowBinaryImageIdentifier:(id)sender { self.displaySettings.visibleStackFrameComponents^=CUIStackFrameBinaryNameComponent; [self refreshText]; } - (NSView *)firstKeyView { return _textView; } - (NSView *)lastKeyView { return _textView; } #pragma mark - Notifications - (void)itemAttributesDidChange:(NSNotification *)inNotification { // Save selection NSRange tSelectionRange=_textView.selectedRange; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshText) object:nil]; [self refreshText]; [self refreshLinesGutter]; // Restore selection if (tSelectionRange.location!=NSNotFound) _textView.selectedRange=tSelectionRange; } - (void)currentThemeDidChange:(NSNotification *)inNotification { _textThemeItemsGroup=[[CUIThemesManager sharedManager].currentTheme itemsGroupWithIdentifier:[CUIApplicationPreferences groupIdentifierForPresentationMode:CUIPresentationModeText]]; // Save selection NSRange tSelectionRange=_textView.selectedRange; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshText) object:nil]; [self refreshText]; [self refreshLinesGutter]; // Restore selection if (tSelectionRange.location!=NSNotFound) _textView.selectedRange=tSelectionRange; } - (void)jumpToSection:(NSNotification *)inNotification { [self _jumpToAnchor:inNotification.object]; } - (void)boundsDidChange:(NSNotification *)inNotification { if ([self.crashLog isMemberOfClass:[CUIRawCrashLog class]]==YES) return; NSRect tBoundingRect=[_textView.superview bounds]; NSRange tVisibleRange=[_textView.layoutManager glyphRangeForBoundingRect:tBoundingRect inTextContainer:_textView.textContainer]; NSMutableArray * tVisibleSections=[_sectionsList mutableCopy]; NSMutableIndexSet * tMutableIndexSet=[NSMutableIndexSet indexSet]; [_sectionsList enumerateObjectsUsingBlock:^(NSString * bSection, NSUInteger bIndex, BOOL * bOutStop) { NSValue * tValue=self->_sectionsRanges[bSection]; if (tValue==nil) return; NSRange tSectionRange=[tValue rangeValue]; if (NSIntersectionRange(tSectionRange,tVisibleRange).length!=0) return; [tMutableIndexSet addIndex:bIndex]; }]; [tVisibleSections removeObjectsAtIndexes:tMutableIndexSet]; [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogPresentationVisibleSectionsDidChangeNotification object:tVisibleSections]; //NSLog(@"%@",NSStringFromRange(tVisibleRange)); //NSLog(@"%@",NSStringFromRect([_textView.superview bounds])); } - (void)symbolicateAutomaticallyDidChange:(NSNotification *)inNotification { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshText) object:nil]; [self performSelector:@selector(refreshText) withObject:nil afterDelay:0.1]; } - (void)showsLineNumbersDidChange:(NSNotification *)inNotification { [self showsLineNumbers:[CUIApplicationPreferences sharedPreferences].showsLineNumbers]; } - (void)lineWrappingDidChange:(NSNotification *)inNotification { [self setWrapText:[CUIApplicationPreferences sharedPreferences].lineWrapping]; } - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification { if ([self.crashLog isMemberOfClass:[CUIRawCrashLog class]]==YES) return; // Ideally we should just request to symbolicate the machineInstructionAddresses that can be [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshText) object:nil]; [self performSelector:@selector(refreshText) withObject:nil afterDelay:0.1]; } - (void)stackFrameSymbolicationDidSucceed:(NSNotification *)inNotification { if (inNotification.object!=self.crashLog) return; if ([self.crashLog isMemberOfClass:[CUIRawCrashLog class]]==YES) return; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshText) object:nil]; [self performSelector:@selector(refreshText) withObject:nil afterDelay:0.1]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogPresentationViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" #import "CUICrashLog+Transform.h" #import "CUIStackFrame+UI.h" #import "CUITextModeDisplaySettings.h" #import "CUIKeyViews.h" extern NSString * const CUICrashLogPresentationDisplayedSectionsDidChangeNotification; extern NSString * const CUICrashLogPresentationVisibleSectionsDidChangeNotification; @interface CUICrashLogPresentationViewController : NSViewController { IBOutlet NSButton * _showOnlyCrashedThreadButton; IBOutlet NSButton * _showByteOffsetButton; IBOutlet NSButton * _showMachineInstructionAddressButton; IBOutlet NSButton * _showBinaryNameButton; } @property (nonatomic) CUICrashLog * crashLog; @property (nonatomic) CUIStackFrameComponents visibleStackFrameComponents; - (IBAction)CUI_MENUACTION_switchTheme:(NSMenuItem *)sender; - (IBAction)CUI_MENUACTION_switchShowOffset:(id)sender; - (IBAction)CUI_MENUACTION_switchShowMemoryAddress:(id)sender; - (IBAction)CUI_MENUACTION_switchShowBinaryImageIdentifier:(id)sender; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogPresentationViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogPresentationViewController.h" #import "CUIThemesManager.h" #import "CUIPreferencesWindowController.h" NSString * const CUICrashLogPresentationDisplayedSectionsDidChangeNotification=@"CUICrashLogPresentationDisplayedSectionsDidChangeNotification"; NSString * const CUICrashLogPresentationVisibleSectionsDidChangeNotification=@"CUICrashLogPresentationVisibleSectionsDidChangeNotification"; @interface CUICrashLogPresentationViewController () @end @implementation CUICrashLogPresentationViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - - (void)setCrashLog:(CUICrashLog *)inCrashLog { _crashLog=inCrashLog; if (_crashLog.isFullyParsed==NO) { [_crashLog finalizeParsing]; } } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(CUI_MENUACTION_switchTheme:)) { if ([inMenuItem.title isEqualToString:[CUIThemesManager sharedManager].currentTheme.name]==YES) { inMenuItem.state=NSControlStateValueOn; } else { inMenuItem.state=NSControlStateValueOff; } return YES; } if (tAction==@selector(CUI_MENUACTION_switchShowOffset:)) { inMenuItem.state=((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; } else if (tAction==@selector(CUI_MENUACTION_switchShowMemoryAddress:)) { inMenuItem.state=((self.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; } else if (tAction==@selector(CUI_MENUACTION_switchShowBinaryImageIdentifier:)) { inMenuItem.state=((self.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; } return YES; } - (IBAction)CUI_MENUACTION_switchTheme:(NSMenuItem *)sender { CUIThemesManager * tThemesManager=[CUIThemesManager sharedManager]; tThemesManager.currentTheme=[tThemesManager themeWithUUID:sender.representedObject]; } - (IBAction)CUI_MENUACTION_switchShowOffset:(id)sender { self.visibleStackFrameComponents^=CUIStackFrameByteOffsetComponent; } - (IBAction)CUI_MENUACTION_switchShowMemoryAddress:(id)sender { self.visibleStackFrameComponents^=CUIStackFrameMachineInstructionAddressComponent; } - (IBAction)CUI_MENUACTION_switchShowBinaryImageIdentifier:(id)sender { self.visibleStackFrameComponents^=CUIStackFrameBinaryNameComponent; } #pragma mark - CUIKeyViews - (NSView *)firstKeyView { return nil; } - (NSView *)lastKeyView { return nil; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogSectionsDetector.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICrashLogSectionsDetector : NSObject + (NSRange)detectHeaderSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes; + (NSRange)detectExceptionInformationSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes; + (NSRange)detectDiagnosticMessageSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes; + (NSRange)detectBacktracesSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes; + (NSRange)detectThreadStateSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes; + (NSRange)detectBinaryImagesSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogSectionsDetector.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogSectionsDetector.h" @implementation CUICrashLogSectionsDetector + (NSRange)detectHeaderSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes { __block NSRange tRange={.location=NSNotFound,.length=0}; // Find the "Exception Information" section start [inLines enumerateObjectsAtIndexes:inIndexes options:0 usingBlock:^(NSString * bLine , NSUInteger bLineNumber, BOOL * bOutStop) { if ([bLine hasPrefix:@"Crashed Thread:"]==YES || [bLine hasPrefix:@"Exception Type:"]==YES) { NSUInteger tFirstLine=inIndexes.firstIndex; NSUInteger tLastLine=bLineNumber-1; tRange=NSMakeRange(tFirstLine, tLastLine-tFirstLine+1); *bOutStop=YES; return; } }]; return tRange; } + (NSRange)detectExceptionInformationSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes { __block NSRange tRange={.location=NSNotFound,.length=0}; // Find the "Diagnostic Message" or "Backtrace" section start [inLines enumerateObjectsAtIndexes:inIndexes options:0 usingBlock:^(NSString * bLine , NSUInteger bLineNumber, BOOL * bOutStop) { if ([bLine hasPrefix:@"Application Specific Information:"]==YES || [bLine hasPrefix:@"VM Regions Near"]==YES || [bLine hasPrefix:@"VM Region Info:"]==YES || [bLine isEqualToString:@"Backtrace not available"]==YES || [bLine hasPrefix:@"Application Specific Backtrace"]==YES || [bLine hasPrefix:@"Thread 0"]==YES) { NSUInteger tFirstLine=inIndexes.firstIndex; NSUInteger tLastLine=bLineNumber-1; tRange=NSMakeRange(tFirstLine, tLastLine-tFirstLine+1); *bOutStop=YES; return; } }]; return tRange; } + (NSRange)detectDiagnosticMessageSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes { __block NSRange tRange={.location=NSNotFound,.length=0}; // Find the "Backtrace" or "Thread State" or "Binary Images" section start [inLines enumerateObjectsAtIndexes:inIndexes options:0 usingBlock:^(NSString * bLine , NSUInteger bLineNumber, BOOL * bOutStop) { if ([bLine hasPrefix:@"Application Specific Backtrace"]==YES || [bLine hasPrefix:@"Thread 0"]==YES || ([bLine hasPrefix:@"Thread"]==YES && [bLine rangeOfString:@"crashed with"].location !=NSNotFound) || [bLine rangeOfString:@"Binary Images" options:NSCaseInsensitiveSearch].location==0 ) { NSUInteger tFirstLine=inIndexes.firstIndex; NSUInteger tLastLine=bLineNumber-1; tRange=NSMakeRange(tFirstLine, tLastLine-tFirstLine+1); *bOutStop=YES; return; } }]; return tRange; } + (NSRange)detectBacktracesSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes { __block NSRange tRange={.location=NSNotFound,.length=0}; // Find the "Thread State" or "Binary Images" section start [inLines enumerateObjectsAtIndexes:inIndexes options:0 usingBlock:^(NSString * bLine , NSUInteger bLineNumber, BOOL * bOutStop) { if ((([bLine hasPrefix:@"Thread"]==YES || [bLine hasPrefix:@"Unknown"]==YES) && [bLine rangeOfString:@"crashed with"].location!=NSNotFound) || [bLine rangeOfString:@"Thread State" options:NSCaseInsensitiveSearch].location==0 || [bLine rangeOfString:@"Binary Images" options:NSCaseInsensitiveSearch].location==0 ) { NSUInteger tFirstLine=inIndexes.firstIndex; NSUInteger tLastLine=bLineNumber-1; tRange=NSMakeRange(tFirstLine, tLastLine-tFirstLine+1); *bOutStop=YES; return; } }]; return tRange; } + (NSRange)detectThreadStateSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes { __block NSRange tRange={.location=NSNotFound,.length=0}; // Find the "Thread State" or "Binary Images" section start [inLines enumerateObjectsAtIndexes:inIndexes options:0 usingBlock:^(NSString * bLine , NSUInteger bLineNumber, BOOL * bOutStop) { if ([bLine rangeOfString:@"Binary Images" options:NSCaseInsensitiveSearch].location==0) { NSUInteger tFirstLine=inIndexes.firstIndex; NSUInteger tLastLine=bLineNumber-1; tRange=NSMakeRange(tFirstLine, tLastLine-tFirstLine+1); *bOutStop=YES; return; } }]; return tRange; } + (NSRange)detectBinaryImagesSectionRangeInTextualRepresentation:(NSArray *)inLines atIndexes:(NSIndexSet *)inIndexes { NSUInteger tFirstLine=inIndexes.firstIndex; NSUInteger tLastLine=inIndexes.lastIndex; NSRange tRange=NSMakeRange(tFirstLine, tLastLine-tFirstLine+1); return tRange; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogTableCellView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICrashLogTableCellView : NSTableCellView @property (assign) IBOutlet NSTextField * dateLabel; @property (assign) IBOutlet NSTextField * exceptionTypeLabel; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogTableCellView.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogTableCellView.h" #define RESIZING_BORDER 400 #define INTERSPACE_H 8 #define SMALL_WIDTH 71 #define LARGE_WIDTH 100 @implementation CUICrashLogTableCellView - (void)layout { NSRect tBounds=self.bounds; NSRect tFrame=self.exceptionTypeLabel.frame; if (self.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft) { if (tBounds.size.width>RESIZING_BORDER) { if (tFrame.size.width<(LARGE_WIDTH+1)) { tFrame.size.width=LARGE_WIDTH; self.exceptionTypeLabel.frame=tFrame; NSRect tOtherFrame=self.dateLabel.frame; tOtherFrame.size.width=NSMaxX(tOtherFrame)-(NSMaxX(tFrame)+INTERSPACE_H); tOtherFrame.origin.x=NSMaxX(tFrame)+INTERSPACE_H; self.dateLabel.frame=tOtherFrame; tOtherFrame=self.textField.frame; tOtherFrame.size.width=NSMaxX(tOtherFrame)-(NSMaxX(tFrame)+INTERSPACE_H); tOtherFrame.origin.x=NSMaxX(tFrame)+INTERSPACE_H; self.textField.frame=tOtherFrame; } } else { if (tFrame.size.width>(SMALL_WIDTH+1)) { tFrame.size.width=SMALL_WIDTH; self.exceptionTypeLabel.frame=tFrame; NSRect tOtherFrame=self.dateLabel.frame; tOtherFrame.size.width=NSMaxX(tOtherFrame)-(NSMaxX(tFrame)+INTERSPACE_H); tOtherFrame.origin.x=NSMaxX(tFrame)+INTERSPACE_H; self.dateLabel.frame=tOtherFrame; tOtherFrame=self.textField.frame; tOtherFrame.size.width=NSMaxX(tOtherFrame)-(NSMaxX(tFrame)+INTERSPACE_H); tOtherFrame.origin.x=NSMaxX(tFrame)+INTERSPACE_H; self.textField.frame=tOtherFrame; } } } else { if (tBounds.size.width>RESIZING_BORDER) { if (tFrame.size.width<(LARGE_WIDTH+1)) { tFrame.origin.x=NSMaxX(tFrame)-LARGE_WIDTH; tFrame.size.width=LARGE_WIDTH; self.exceptionTypeLabel.frame=tFrame; NSRect tOtherFrame=self.dateLabel.frame; tOtherFrame.size.width=NSMinX(tFrame)-INTERSPACE_H-NSMinX(tOtherFrame); self.dateLabel.frame=tOtherFrame; tOtherFrame=self.textField.frame; tOtherFrame.size.width=NSMinX(tFrame)-INTERSPACE_H-NSMinX(tOtherFrame); self.textField.frame=tOtherFrame; } } else { if (tFrame.size.width>(SMALL_WIDTH+1)) { tFrame.origin.x=NSMaxX(tFrame)-SMALL_WIDTH; tFrame.size.width=SMALL_WIDTH; self.exceptionTypeLabel.frame=tFrame; NSRect tOtherFrame=self.dateLabel.frame; tOtherFrame.size.width=NSMinX(tFrame)-INTERSPACE_H-NSMinX(tOtherFrame); self.dateLabel.frame=tOtherFrame; tOtherFrame=self.textField.frame; tOtherFrame.size.width=NSMinX(tFrame)-INTERSPACE_H-NSMinX(tOtherFrame); self.textField.frame=tOtherFrame; } } } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogTextView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICrashLogTextView : NSTextView @property BOOL wrapLines; - (void) CUI_scrollPoint:(NSPoint)inPoint; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogTextView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogTextView.h" @interface NSView (Private) - (void)_scrollPoint:(NSPoint *)point fromView:(NSView *)inView; - (void)_scrollDown:(CGFloat)inOffset; - (void)_scrollUp:(CGFloat)inOffset; @end @implementation CUICrashLogTextView - (void)_scrollUp:(CGFloat)inOffset { if (self.wrapLines==YES) { [super _scrollUp:inOffset]; return; } NSScrollView * tScrollView=self.enclosingScrollView; NSView * tDocumentView=tScrollView.documentView; NSRulerView * tVerticalRulerView=tScrollView.verticalRulerView; if (self!=tDocumentView || tVerticalRulerView==nil || tScrollView.horizontalScroller.isHidden==YES) { [super _scrollUp:inOffset]; return; } NSRect tOldFrame=tDocumentView.frame; // Offset the text view frame to take into account the vertical ruler width NSRect tNewFrame=tOldFrame; tNewFrame.origin.x-=NSWidth(tVerticalRulerView.frame); self.frame=tNewFrame; [super _scrollUp:inOffset]; // Restore the text view frame self.frame=tOldFrame; } - (void)_scrollDown:(CGFloat)inOffset { if (self.wrapLines==YES) { [super _scrollDown:inOffset]; return; } NSScrollView * tScrollView=self.enclosingScrollView; NSView * tDocumentView=tScrollView.documentView; NSRulerView * tVerticalRulerView=tScrollView.verticalRulerView; if (self!=tDocumentView || tVerticalRulerView==nil || tScrollView.horizontalScroller.isHidden==YES) { [super _scrollDown:inOffset]; return; } NSRect tOldFrame=tDocumentView.frame; NSRect tNewFrame=tOldFrame; tNewFrame.origin.x-=NSWidth(tVerticalRulerView.frame); self.frame=tNewFrame; [super _scrollDown:inOffset]; // Restore the text view frame self.frame=tOldFrame; } - (void)CUI_scrollPoint:(NSPoint)inPoint { if (self.wrapLines==YES) { [super scrollPoint:inPoint]; return; } NSScrollView * tScrollView=self.enclosingScrollView; NSView * tDocumentView=tScrollView.documentView; NSRulerView * tVerticalRulerView=tScrollView.verticalRulerView; if (self!=tDocumentView || tVerticalRulerView==nil || tScrollView.horizontalScroller.isHidden==YES) { [self scrollPoint:inPoint]; return; } // Offset the text view frame to take into account the vertical ruler width inPoint.x-=NSWidth(tVerticalRulerView.frame); [self scrollPoint:inPoint]; } - (NSPoint)textContainerOrigin { return NSMakePoint(8,8); } #pragma mark - - (void)keyDown:(NSEvent *)inEvent { NSString * tTypedText=inEvent.characters; NSUInteger tLength=tTypedText.length; for(NSUInteger tIndex=0;tIndex #import "CUIRegister.h" #import "IPSIncident.h" @interface CUICrashLogThreadState : NSObject @property (readonly) NSUInteger threadIndex; @property (readonly) cpu_type_t CPUType; @property (readonly) NSArray * registers; @property (readonly) NSUInteger logicalCPU; @property (readonly) NSUInteger errorCode; @property (readonly) NSUInteger trapNumber; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError; - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogThreadState.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogThreadState.h" #import "CUIParsingErrors.h" #import "IPSThreadState+RegisterDisplayName.h" #import "NSArray+WBExtensions.h" #import "NSString+CPU.h" @interface CUICrashLogThreadState () @property NSUInteger threadIndex; @property cpu_type_t CPUType; @property NSArray * registers; @property NSUInteger logicalCPU; @property NSUInteger errorCode; @property NSUInteger trapNumber; - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError; @end @implementation CUICrashLogThreadState - (instancetype)initWithTextualRepresentation:(NSArray *)inLines reportVersion:(NSUInteger)inReportVersion error:(NSError **)outError { if ([inLines isKindOfClass:NSArray.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _registers=@[]; if ([self parseTextualRepresentation:inLines outError:outError]==NO) { return nil; } } return self; } - (instancetype)initWithIPSIncident:(IPSIncident *)inIncident error:(NSError **)outError { if ([inIncident isKindOfClass:IPSIncident.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { IPSThreadState * tThreadState=inIncident.threadState; if (tThreadState==nil) { if (outError!=NULL) *outError=nil; return nil; } _threadIndex=inIncident.exceptionInformation.faultingThread; IPSIncidentHeader * tHeader=inIncident.header; _CPUType=[tHeader.cpuType CUI_CPUType]; NSArray * tRegistersOrder; if ([tThreadState.flavor isEqualToString:@"x86_THREAD_STATE"]==YES) { tRegistersOrder=@[@"rax",@"rbx",@"rcx",@"rdx", @"rdi",@"rsi",@"rbp",@"rsp", @"r8",@"r9",@"r10",@"r11", @"r12",@"r13",@"r14",@"r15", @"rip",@"rflags",@"cr2" ]; } else { tRegistersOrder=@[@"x0",@"x1",@"x2",@"x3", @"x4",@"x5",@"x6",@"x7", @"x8",@"x9",@"x10",@"x11", @"x12",@"x13",@"x14",@"x15", @"x16",@"x17",@"x18",@"x19", @"x20",@"x21",@"x22",@"x23", @"x24",@"x25",@"x26",@"x27", @"x28",@"fp",@"lr", @"sp",@"pc",@"cpsr", @"far",@"esr" ]; } _registers=[tRegistersOrder WB_arrayByMappingObjectsUsingBlock:^id(NSString * bRegisterName, NSUInteger bIndex) { IPSRegisterState * tRegisterState=tThreadState.registersStates[bRegisterName]; if (tRegisterState!=nil) { CUIRegister * tRegister=[CUIRegister new]; tRegister.name=[IPSThreadState displayNameForRegisterName:bRegisterName]; tRegister.value=tRegisterState.value; return tRegister; } return nil; }]; // A COMPLETER /*_logicalCPU=; _errorCode=; _trapNumber=;*/ } return self; } - (BOOL)parseTextualRepresentation:(NSArray *)inLines outError:(NSError **)outError { __block NSError * tError=nil; // Scan the first line NSCharacterSet * tWhitespaceCharacterSet=[NSCharacterSet whitespaceCharacterSet]; NSScanner * tScanner=[NSScanner scannerWithString:inLines.firstObject]; tScanner.charactersToBeSkipped=tWhitespaceCharacterSet; if ([tScanner scanString:@"Thread " intoString:NULL]==NO) return NO; // Thread Index NSInteger tInteger=-1; if ([tScanner scanInteger:&tInteger]==YES) { self.threadIndex=tInteger; if ([tScanner scanString:@"crashed with " intoString:NULL]==NO) return NO; // Architecture NSString * tString; if ([tScanner scanUpToString:@"Thread State" intoString:&tString]==NO) return NO; tString=[tString stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; if ([tString isEqualToString:@"ARM"]==YES) { self.CPUType=CPU_TYPE_ARM; } else if ([tString isEqualToString:@"X86"]==YES) { self.CPUType=CPU_TYPE_X86; } tScanner.scanLocation+=[@"Thread State" length]; if ([tScanner scanUpToString:@":" intoString:&tString]==NO) return NO; tString=[tString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"()"]]; if ([tString isEqualToString:@"64-bit"]==YES) self.CPUType|=CPU_ARCH_ABI64; } else { if ([inLines.firstObject hasPrefix:@"Thread State"]==NO) return NO; self.threadIndex=NSNotFound; self.CPUType=CPU_TYPE_ANY; } // Registers values NSMutableArray * tMutableArray=[NSMutableArray array]; __block NSUInteger tEndOfRegisterValues=NSNotFound; [inLines enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1,inLines.count-1)] options:0 usingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { if (bLine.length<4) { tEndOfRegisterValues=bLineNumber+1; *bOutStop=YES; return; } NSScanner * tRegistersScanner=[NSScanner scannerWithString:bLine]; tRegistersScanner.charactersToBeSkipped=tWhitespaceCharacterSet; while (tRegistersScanner.isAtEnd==NO) { NSString * tRegisterName; if ([tRegistersScanner scanUpToString:@":" intoString:&tRegisterName]==NO) return; if ([tRegistersScanner scanString:@": " intoString:NULL]==NO) return; unsigned long long tRegisterValue; if ([tRegistersScanner scanHexLongLong:&tRegisterValue]==NO) return; CUIRegister * tRegister=[CUIRegister new]; tRegister.name=tRegisterName; tRegister.value=tRegisterValue; [tMutableArray addObject:tRegister]; } }]; self.registers=[tMutableArray copy]; if (tEndOfRegisterValues==NSNotFound || (tEndOfRegisterValues==(inLines.count-1))) return YES; // Other keys-values [inLines enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tEndOfRegisterValues+1,inLines.count-1-(tEndOfRegisterValues+1)+1)] options:0 usingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { NSUInteger tLineLength=bLine.length; // Skip Blank lines if (tLineLength==0) return; // Find Key and Value NSScanner * tScanner=[NSScanner scannerWithString:bLine]; NSString * tKey; if ([tScanner scanUpToString:@":" intoString:&tKey]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } NSUInteger tIndex=tScanner.scanLocation+1; if (tIndex>=(tLineLength-1)) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } NSString * tValue=[[bLine substringFromIndex:tIndex] stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; if (tValue.length==0) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } if ([tKey isEqualToString:@"Logical CPU"]==YES) { NSScanner * tScanner=[NSScanner scannerWithString:tValue]; unsigned long long tValue; if ([tScanner scanUnsignedLongLong:&tValue]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.logicalCPU=tValue; return; } else if ([tKey isEqualToString:@"Error Code"]==YES) { NSScanner * tScanner=[NSScanner scannerWithString:tValue]; unsigned long long tHexaValue; if ([tScanner scanHexLongLong:&tHexaValue]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.errorCode=tHexaValue; return; } else if ([tKey isEqualToString:@"Trap Number"]==YES) { NSScanner * tScanner=[NSScanner scannerWithString:tValue]; unsigned long long tValue; if ([tScanner scanUnsignedLongLong:&tValue]==NO) { tError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingUnknownError userInfo:@{CUIParsingErrorLineKey:@(bLineNumber)}]; *bOutStop=YES; return; } self.trapNumber=tValue; return; } }]; if (outError!=NULL && tError!=nil) *outError=tError; return YES; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsListViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIKeyViews.h" @interface CUICrashLogsListViewController : NSViewController @property (readonly) NSTableView * tableView; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsListViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsListViewController.h" #import "CUICrashLogsSourcesSelection.h" #import "CUICrashLogsSelection.h" #import "CUICrashLogTableCellView.h" #import "CUICrashLog+UI.h" #import "NSArray+WBExtensions.h" #import "NSTableView+Selection.h" #import "CUIApplicationPreferences.h" #import "CUICrashLogsSourcesManager.h" #import "CUICrashLogExceptionInformation+UI.h" @interface CUICrashLogsListViewController () { IBOutlet NSTableView * _tableView; IBOutlet NSMenu * _shareMenu; IBOutlet NSSearchField * _filterField; IBOutlet NSPopUpButton * _sortPopUpButton; CUICrashLogsSource * _source; NSMutableArray * _filteredAndSortedCrashLogsArray; NSString * _filterPattern; CUICrashLogsSortType _sortType; NSDateFormatter * _crashLogDateFormatter; BOOL _showsFileNames; } - (IBAction)share:(id)sender; - (IBAction)showInFinder:(id)sender; - (IBAction)CUI_MENUACTION_moveToTrash:(id)sender; - (IBAction)CUI_MENUACTION_moveAllToTrash:(id)sender; - (IBAction)takeFilterPatternFrom:(id)sender; - (IBAction)switchDisplayedName:(id)sender; - (IBAction)switchSortType:(id)sender; // Notification - (void)crashLogsSourcesSelectionDidChange:(NSNotification *)inNotification; - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification; - (void)crashLogsSortTypeDidChange:(NSNotification *)inNotification; - (void)showFileNamesDidChange:(NSNotification *)inNotification; @end @implementation CUICrashLogsListViewController - (instancetype)init { self=[super init]; if (self!=nil) { _filterPattern=@""; _crashLogDateFormatter=[NSDateFormatter new]; _crashLogDateFormatter.formatterBehavior=NSDateFormatterBehavior10_4; _crashLogDateFormatter.dateStyle=NSDateFormatterMediumStyle; _crashLogDateFormatter.timeStyle=NSDateFormatterShortStyle; CUIApplicationPreferences * tApplicationPreferences=[CUIApplicationPreferences sharedPreferences]; _sortType=tApplicationPreferences.crashLogsSortType; _showsFileNames=(tApplicationPreferences.crashLogsShowFileNames==YES); } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSString *)nibName { return @"CUICrashLogsListViewController"; } - (void)viewDidLoad { [super viewDidLoad]; [_shareMenu removeAllItems]; [[NSSharingService sharingServicesForItems:@[[[NSBundle mainBundle] URLForResource:@"Localizable" withExtension:@"strings"]]] enumerateObjectsUsingBlock:^(NSSharingService * bSharingService, NSUInteger bIndex, BOOL * bOutStop) { NSMenuItem * tMenuItem=[[NSMenuItem alloc] initWithTitle:bSharingService.menuItemTitle action:@selector(share:) keyEquivalent:@""]; tMenuItem.target=self; tMenuItem.image=bSharingService.image; tMenuItem.representedObject=bSharingService; [self->_shareMenu addItem:tMenuItem]; }]; _filterField.centersPlaceholder=NO; NSSearchFieldCell * tSearchFieldCell=_filterField.cell; NSButtonCell * tButtonCell=tSearchFieldCell.searchButtonCell; tButtonCell.image=[NSImage imageNamed:@"filter_Template"]; tButtonCell.alternateImage=tButtonCell.image; // Register for notifications NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(crashLogsSourcesSelectionDidChange:) name:CUICrashLogsSourcesSelectionDidChangeNotification object:[CUICrashLogsSourcesSelection sharedSourcesSelection]]; [tNotificationCenter addObserver:self selector:@selector(crashLogsSelectionDidChange:) name:CUICrashLogsSelectionDidChangeNotification object:[CUICrashLogsSelection sharedSelection]]; [tNotificationCenter addObserver:self selector:@selector(crashLogsSortTypeDidChange:) name:CUIPreferencesCrashLogsSortTypeDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(showFileNamesDidChange:) name:CUIPreferencesCrashLogsShowFileNamesDidChangeNotification object:nil]; } #pragma mark - - (void)refreshList { NSIndexSet * tIndexSet=_tableView.selectedRowIndexes; NSArray * tSelectedItems=[_filteredAndSortedCrashLogsArray objectsAtIndexes:tIndexSet]; NSArray * tSelectedResourceIdentifiers=[tSelectedItems WB_arrayByMappingObjectsUsingBlock:^id(CUIRawCrashLog * bCrashLog, NSUInteger bIndex) { return bCrashLog.resourceIdentifier; }]; NSArray * tArray=_source.crashLogs; if (_filterPattern.length>0) { _filteredAndSortedCrashLogsArray=[NSMutableArray array]; [tArray enumerateObjectsUsingBlock:^(CUICrashLog * bCrashLog, NSUInteger bIndex, BOOL * bOutStop) { if ([bCrashLog isKindOfClass:CUICrashLog.class]==NO) return; if (self->_showsFileNames==NO) { NSString * tProcessName=bCrashLog.header.processName; if (tProcessName!=nil && [tProcessName rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound) { [self->_filteredAndSortedCrashLogsArray addObject:bCrashLog]; return; } NSString * tResponsibleProcessName=bCrashLog.header.responsibleProcessName; if (tResponsibleProcessName!=nil && [tResponsibleProcessName rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound) { [self->_filteredAndSortedCrashLogsArray addObject:bCrashLog]; return; } } else { NSString * tCrashLogFileName=bCrashLog.crashLogFilePath.lastPathComponent.stringByDeletingPathExtension; if (tCrashLogFileName!=nil && [tCrashLogFileName rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound) { [self->_filteredAndSortedCrashLogsArray addObject:bCrashLog]; return; } } if ([bCrashLog.exceptionInformation.exceptionType rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound || [bCrashLog.exceptionInformation.exceptionSignal rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound) { [self->_filteredAndSortedCrashLogsArray addObject:bCrashLog]; return; } }]; } else { _filteredAndSortedCrashLogsArray=[tArray mutableCopy]; } switch(_sortType) { case CUICrashLogsSortDateDescending: [_filteredAndSortedCrashLogsArray sortUsingSelector:@selector(compareDateReverse:)]; break; case CUICrashLogsSortProcessNameAscending: if (_showsFileNames==NO) [_filteredAndSortedCrashLogsArray sortUsingSelector:@selector(compareProcessName:)]; else [_filteredAndSortedCrashLogsArray sortUsingSelector:@selector(compareCrashLogFileName:)]; break; } NSArray * tSaveSelectionCrashLogs=nil; CUICrashLogsSelection * tSelection=[CUICrashLogsSelection sharedSelection]; if (tSelection.source==_source) { tSaveSelectionCrashLogs=[tSelection.crashLogs copy]; } [_tableView reloadData]; NSMutableIndexSet * tNewSelectionIndexSet=[NSMutableIndexSet indexSet]; [_filteredAndSortedCrashLogsArray enumerateObjectsUsingBlock:^(CUIRawCrashLog * bCrashLog, NSUInteger bIndex,BOOL * bOutStop) { if ([tSelectedResourceIdentifiers containsObject:bCrashLog.resourceIdentifier]==YES) [tNewSelectionIndexSet addIndex:bIndex]; }]; if (tNewSelectionIndexSet.count>0) { [_tableView selectRowIndexes:tNewSelectionIndexSet byExtendingSelection:NO]; } else { if (tSaveSelectionCrashLogs!=nil) { [_filteredAndSortedCrashLogsArray enumerateObjectsUsingBlock:^(id bCrashLog, NSUInteger bIndex,BOOL * bOutStop) { if ([tSaveSelectionCrashLogs containsObject:bCrashLog]==YES) [tNewSelectionIndexSet addIndex:bIndex]; }]; } if (tNewSelectionIndexSet.count>0) { [_tableView selectRowIndexes:tNewSelectionIndexSet byExtendingSelection:NO]; } else { [self tableViewSelectionDidChange:[NSNotification notificationWithName:NSTableViewSelectionDidChangeNotification object:_tableView]]; } } } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { if (inMenuItem.tag==-1) return NO; SEL tAction=inMenuItem.action; if (tAction==@selector(showInFinder:) || tAction==@selector(CUI_MENUACTION_moveToTrash:)) { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; if (tSelectionIndexSet.count==0) return NO; NSArray * tCrashLogs=_filteredAndSortedCrashLogsArray; __block BOOL tResult=YES; [tSelectionIndexSet enumerateIndexesUsingBlock:^(NSUInteger bIndex,BOOL * bOutStop){ CUIRawCrashLog * tCrashLog=tCrashLogs[bIndex]; NSString * tPath=tCrashLog.crashLogFilePath; if (tPath.length==0 || [[NSFileManager defaultManager] fileExistsAtPath:tPath]==NO) { tResult=NO; *bOutStop=NO; return; } }]; return tResult; } if (tAction==@selector(CUI_MENUACTION_moveAllToTrash:)) { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; if (tSelectionIndexSet.count!=1) return NO; NSArray * tCrashLogs=_filteredAndSortedCrashLogsArray; CUIRawCrashLog * tCrashLog=tCrashLogs[tSelectionIndexSet.firstIndex]; if (tCrashLog==nil) return NO; NSString * tPath=tCrashLog.crashLogFilePath; if (tPath.length==0 || [[NSFileManager defaultManager] fileExistsAtPath:tPath]==NO) return NO; inMenuItem.title=[NSString stringWithFormat:NSLocalizedString(@"Move All \"%@\" Reports to Trash",@""),tCrashLog.processName]; return YES; } if (tAction==@selector(switchDisplayedName:)) { inMenuItem.state=(inMenuItem.tag==_showsFileNames) ? NSControlStateValueOn : NSControlStateValueOff; return YES; } if (tAction==@selector(switchSortType:)) { inMenuItem.state=(inMenuItem.tag==_sortType) ? NSControlStateValueOn : NSControlStateValueOff; return YES; } return YES; } - (IBAction)share:(NSMenuItem *)sender { NSSharingService * tSharingService=sender.representedObject; NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; NSArray * tArray=[_filteredAndSortedCrashLogsArray objectsAtIndexes:tSelectionIndexSet]; NSArray * tURLs=[tArray WB_arrayByMappingObjectsUsingBlock:^id(CUIRawCrashLog * bCrashLog, NSUInteger bIndex) { return [NSURL fileURLWithPath:bCrashLog.crashLogFilePath]; }]; tSharingService.delegate = self; [tSharingService performWithItems:tURLs]; } - (void)_shareSelectionWithService:(NSString *)inServiceID { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; NSArray * tArray=[_filteredAndSortedCrashLogsArray objectsAtIndexes:tSelectionIndexSet]; NSArray * tURLs=[tArray WB_arrayByMappingObjectsUsingBlock:^id(CUIRawCrashLog * bCrashLog, NSUInteger bIndex) { return [NSURL fileURLWithPath:bCrashLog.crashLogFilePath]; }]; NSSharingService * tService = [NSSharingService sharingServiceNamed:inServiceID]; tService.delegate = self; [tService performWithItems:tURLs]; } - (IBAction)showInFinder:(id)sender { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; NSWorkspace * tSharedWorkspace=[NSWorkspace sharedWorkspace]; [_filteredAndSortedCrashLogsArray enumerateObjectsAtIndexes:tSelectionIndexSet options:0 usingBlock:^(CUIRawCrashLog * bCrashLog, NSUInteger bIndex, BOOL * bOutStop) { NSString * tPath=bCrashLog.crashLogFilePath; if (tPath.length>0) [tSharedWorkspace selectFile:tPath inFileViewerRootedAtPath:@""]; }]; } - (IBAction)CUI_MENUACTION_moveToTrash:(id)sender { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; if (tSelectionIndexSet.count==0) return; NSFileManager * tFileManager=[NSFileManager defaultManager]; NSMutableIndexSet * tMutableIndexSet=[tSelectionIndexSet mutableCopy]; [_filteredAndSortedCrashLogsArray enumerateObjectsAtIndexes:tSelectionIndexSet options:0 usingBlock:^(CUIRawCrashLog * bCrashLog, NSUInteger bIndex, BOOL * bOutStop) { NSError * tError=nil; if ([tFileManager trashItemAtURL:[NSURL fileURLWithPath:bCrashLog.crashLogFilePath] resultingItemURL:NULL error:&tError]==NO) { [tMutableIndexSet removeIndex:bIndex]; NSLog(@"%@",tError); } }]; if (tMutableIndexSet.counttPrefix.length) { tLabelValue=[tExceptionType substringFromIndex:tPrefix.length]; } else { tLabelValue=tExceptionType; } tTableCellView.exceptionTypeLabel.stringValue=tLabelValue; tTableCellView.exceptionTypeLabel.toolTip=[tExceptionInformation displayedExceptionType]; } // Voice Over NSString * tDateString=[_crashLogDateFormatter stringFromDate:tCrashLog.dateTime]; if (tExceptionType==nil) { NSString * tFormat=NSLocalizedString(@"Crash Report for process %@, date: %@", @""); tTableCellView.accessibilityLabel=[NSString stringWithFormat:tFormat,tCrashLog.processName,tDateString]; } else { NSString * tFormat=NSLocalizedString(@"Crash Report for process %@, date: %@, exception type: %@", @""); tTableCellView.accessibilityLabel=[NSString stringWithFormat:tFormat,tCrashLog.processName,tDateString,[tExceptionInformation humanFriendlyExceptionType]]; } return tTableCellView; } - (void)tableViewSelectionDidChange:(NSNotification *)inNotification { NSInteger tSelectedRow=_tableView.selectedRow; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; // Stop observing CUICrashLogsSelection * tCrashLogsSelection=[CUICrashLogsSelection sharedSelection]; [tNotificationCenter removeObserver:self name:CUICrashLogsSelectionDidChangeNotification object:tCrashLogsSelection]; [tCrashLogsSelection setSource:_source crashLogs:(tSelectedRow==-1) ? @[] : @[_filteredAndSortedCrashLogsArray[tSelectedRow]]]; // Restore observation [tNotificationCenter addObserver:self selector:@selector(crashLogsSelectionDidChange:) name:CUICrashLogsSelectionDidChangeNotification object:tCrashLogsSelection]; } #pragma mark - NSSharingServiceDelegate - (void)sharingService:(NSSharingService *)sharingService didFailToShareItems:(NSArray *)items error:(NSError *)error { // A COMPLETER NSBeep(); } #pragma mark - CUIKeyViews - (NSView *)firstKeyView { return _tableView; } - (NSView *)lastKeyView { return _filterField; } #pragma mark - Notifications - (void)crashLogsSourcesSelectionDidChange:(NSNotification *)inNotification { CUICrashLogsSourcesSelection * tSelection=inNotification.object; if ([tSelection isKindOfClass:CUICrashLogsSourcesSelection.class]==NO) return; CUICrashLogsSource * tFirstSource=tSelection.sources.allObjects.firstObject; if (tFirstSource==_source) return; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter removeObserver:self name:CUICrashLogsSourceDidUpdateSourceNotification object:_source]; _source=tFirstSource; [self refreshList]; // Register for notification [tNotificationCenter addObserver:self selector:@selector(sourceDidUpdateSource:) name:CUICrashLogsSourceDidUpdateSourceNotification object:_source]; } - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification { CUICrashLogsSelection * tSelection=inNotification.object; // Refresh Selection NSMutableIndexSet * tIndexSet=[NSMutableIndexSet indexSet]; [_filteredAndSortedCrashLogsArray enumerateObjectsUsingBlock:^(id bCrashLog, NSUInteger bIndex, BOOL * bOutStop) { if ([tSelection.crashLogs containsObject:bCrashLog]==YES) [tIndexSet addIndex:bIndex]; }]; if (tIndexSet.count==0) { [_source.crashLogs enumerateObjectsUsingBlock:^(id bCrashLog, NSUInteger bIndex, BOOL * bOutStop) { if ([tSelection.crashLogs containsObject:bCrashLog]==YES) [tIndexSet addIndex:bIndex]; }]; if (tIndexSet.count==0) { [tIndexSet addIndex:0]; } else { NSArray * tSelectedCrashLogs=[tSelection.crashLogs copy]; _filterField.stringValue=@""; _filterPattern=@""; [self refreshList]; tIndexSet=[NSMutableIndexSet indexSet]; [_filteredAndSortedCrashLogsArray enumerateObjectsUsingBlock:^(id bCrashLog, NSUInteger bIndex, BOOL * bOutStop) { if ([tSelectedCrashLogs containsObject:bCrashLog]==YES) [tIndexSet addIndex:bIndex]; }]; } } [_tableView selectRowIndexes:tIndexSet byExtendingSelection:NO]; [_tableView scrollRowToVisible:tIndexSet.firstIndex]; } - (void)sourceDidUpdateSource:(NSNotification *)inNotification { [self refreshList]; } - (void)crashLogsSortTypeDidChange:(NSNotification *)inNotification { _sortType=[CUIApplicationPreferences sharedPreferences].crashLogsSortType; [self refreshList]; } - (void)showFileNamesDidChange:(NSNotification *)inNotification { _showsFileNames=[CUIApplicationPreferences sharedPreferences].crashLogsShowFileNames; [self refreshList]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsMainViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICrashLogsMainViewController : NSViewController @property (readonly) NSSplitView * splitView; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsMainViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsMainViewController.h" #import "CUISidebarViewController.h" #import "CUIContentsViewController.h" #import "CUIRightViewController.h" #import "CUICrashLogsSelection.h" #define CUISidebarMinimumWidth 250 #define CUIContentsMinimumWidth 700 #define CUIInspectorMinimumWidth 250 typedef NS_ENUM(NSUInteger, CUISplitViewSubViewTag) { CUISplitViewSidebarViewTag=0, CUISplitViewMiddleViewTag=1, CUISplitViewInspectorViewTag=2, }; NSString * const CUIDefaultsSidebarWidthKey=@"sidebar.width"; NSString * const CUIDefaultsSidebarCollapsedKey=@"sidebar.collapsed"; NSString * const CUIDefaultsInspectorViewWidthKey=@"rightView.width"; NSString * const CUIDefaultsInspectorViewCollapsedKey=@"rightView.collapsed"; @interface CUICrashLogsMainViewController () { IBOutlet NSSplitView * _splitView; IBOutlet NSView * _leftView; IBOutlet NSView * _middleView; IBOutlet NSView * _rightView; CUISidebarViewController * _sidebarViewController; CUIContentsViewController * _contentsViewController; CUIRightViewController * _inspectorViewController; } - (void)updateNextKeyViews; - (IBAction)showHideViews:(id)sender; //- (IBAction)switchPresentationMode:(NSMenuItem *)sender; - (void)_splitView:(NSSplitView *)inSplitView resizeSubviewsWithSidebarWidth:(CGFloat)inSidebarWidth inspectorViewWidth:(CGFloat)inInspectorViewWidth; @end @implementation CUICrashLogsMainViewController - (instancetype)init { self=[super init]; if (self!=nil) { _sidebarViewController=[CUISidebarViewController new]; _contentsViewController=[CUIContentsViewController new]; _inspectorViewController=[CUIRightViewController new]; [self addChildViewController:_sidebarViewController]; [self addChildViewController:_contentsViewController]; [self addChildViewController:_inspectorViewController]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - NSObject - (id)forwardingTargetForSelector:(SEL)aSelector { if ([_contentsViewController respondsToSelector:aSelector]==YES) { return _contentsViewController; } if ([_sidebarViewController respondsToSelector:aSelector]==YES) { return _sidebarViewController; } return nil; } - (BOOL)respondsToSelector:(SEL)aSelector { BOOL tResponds=[super respondsToSelector:aSelector]; if (tResponds==YES) return YES; NSString * tSelectorName=NSStringFromSelector(aSelector); if ([tSelectorName hasPrefix:@"CUI_MENUACTION_"]==NO && [tSelectorName isEqualToString:@"performTextFinderAction:"]==NO) return NO; tResponds=[_contentsViewController respondsToSelector:aSelector]; if (tResponds==YES) return YES; return [_sidebarViewController respondsToSelector:aSelector]; } #pragma mark - - (NSString *)nibName { return @"CUICrashLogsMainViewController"; } - (void)viewDidLoad { [super viewDidLoad]; BOOL tIsLeftToRightLayout=(_splitView.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight); NSView *tSidebarView; NSView *tInspectorView; if (tIsLeftToRightLayout==YES) { tSidebarView=_leftView; tInspectorView=_rightView; } else { tSidebarView=_rightView; tInspectorView=_leftView; } _inspectorViewController.view.frame=tInspectorView.bounds; [tInspectorView addSubview:_inspectorViewController.view]; _contentsViewController.view.frame=_middleView.bounds; [_middleView addSubview:_contentsViewController.view]; _sidebarViewController.view.frame=tSidebarView.bounds; [tSidebarView addSubview:_sidebarViewController.view]; [self updateNextKeyViews]; } - (void)viewDidAppear { [super viewDidAppear]; // Restore SplitView divider position BOOL tIsLeftToRightLayout=(_splitView.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight); NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; NSNumber * tNumber=[tUserDefaults objectForKey:CUIDefaultsSidebarCollapsedKey]; if ([tNumber boolValue]==YES) { if (tIsLeftToRightLayout==YES) [_splitView setPosition:[_splitView minPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0]; else [_splitView setPosition:[_splitView maxPossiblePositionOfDividerAtIndex:1] ofDividerAtIndex:1]; } tNumber=[tUserDefaults objectForKey:CUIDefaultsInspectorViewCollapsedKey]; if ([tNumber boolValue]==YES) { if (tIsLeftToRightLayout==NO) [_splitView setPosition:[_splitView minPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0]; else [_splitView setPosition:[_splitView maxPossiblePositionOfDividerAtIndex:1] ofDividerAtIndex:1]; } CGFloat tSidebarWidth=CUISidebarMinimumWidth; tNumber=[tUserDefaults objectForKey:CUIDefaultsSidebarWidthKey]; if (tNumber!=nil) tSidebarWidth=[tNumber doubleValue]; CGFloat tInspectorViewWidth=CUIInspectorMinimumWidth; tNumber=[tUserDefaults objectForKey:CUIDefaultsInspectorViewWidthKey]; if (tNumber!=nil) tInspectorViewWidth=[tNumber doubleValue]; [self _splitView:_splitView resizeSubviewsWithSidebarWidth:tSidebarWidth inspectorViewWidth:tInspectorViewWidth]; } - (void)viewWillDisappear { // Save SplitView divider position NSView * tSidebarView=nil; NSView * tInspectorView=nil; if (_splitView.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tSidebarView=_leftView; tInspectorView=_rightView; } else { tSidebarView=_rightView; tInspectorView=_leftView; } NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; [tUserDefaults setObject:@(NSWidth(tSidebarView.frame)) forKey:CUIDefaultsSidebarWidthKey]; [tUserDefaults setBool:[_splitView isSubviewCollapsed:tSidebarView] forKey:CUIDefaultsSidebarCollapsedKey]; [tUserDefaults setObject:@(NSWidth(tInspectorView.frame)) forKey:CUIDefaultsInspectorViewWidthKey]; [tUserDefaults setBool:[_splitView isSubviewCollapsed:tInspectorView] forKey:CUIDefaultsInspectorViewCollapsedKey]; } #pragma mark - - (void)updateNextKeyViews { NSView * tContentsFirstKeyView=_contentsViewController.firstKeyView; if (tContentsFirstKeyView==nil) { [_sidebarViewController.lastKeyView setNextKeyView:_sidebarViewController.firstKeyView]; } else { [_sidebarViewController.lastKeyView setNextKeyView:_contentsViewController.firstKeyView]; [_contentsViewController.lastKeyView setNextKeyView:_sidebarViewController.firstKeyView]; } } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if ([super respondsToSelector:tAction]==NO) { NSString * tSelectorName=NSStringFromSelector(tAction); if ([tSelectorName hasPrefix:@"CUI_MENUACTION_"]==NO && [tSelectorName isEqualToString:@"performTextFinderAction:"]==NO) return NO; if ([_contentsViewController respondsToSelector:tAction]==YES) return [_contentsViewController validateMenuItem:inMenuItem]; if ([_sidebarViewController respondsToSelector:tAction]==YES) return [_sidebarViewController validateMenuItem:inMenuItem]; return NO; } if (tAction==@selector(showHideViews:)==YES) { NSView * sidebarView=nil; NSView * inspectorView=nil; if (_splitView.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { sidebarView=_leftView; inspectorView=_rightView; } else { sidebarView=_rightView; inspectorView=_leftView; } switch(inMenuItem.tag) { case CUISplitViewSidebarViewTag: inMenuItem.title=([_splitView isSubviewCollapsed:sidebarView]==YES) ? NSLocalizedString(@"Show Sidebar", @"") : NSLocalizedString(@"Hide Sidebar", @""); break; case CUISplitViewMiddleViewTag: inMenuItem.title=(_contentsViewController.isBottomViewCollapsed==YES) ? NSLocalizedString(@"Show Binary Images", @"") : NSLocalizedString(@"Hide Binary Images", @""); if ([CUICrashLogsSelection sharedSelection].crashLogs.count==0) return NO; if (_contentsViewController.presentationMode!=CUIPresentationModeOutline) return NO; break; case CUISplitViewInspectorViewTag: inMenuItem.title=([_splitView isSubviewCollapsed:inspectorView]==YES) ? NSLocalizedString(@"Show Inspector", @"") : NSLocalizedString(@"Hide Inspector", @""); break; } } return YES; } - (IBAction)showHideViews:(id)sender { BOOL tIsLeftViewCollapsed=[_splitView isSubviewCollapsed:_leftView]; BOOL tIsRightViewCollapsed=[_splitView isSubviewCollapsed:_rightView]; CUISplitViewSubViewTag tSwitchTag=-1; if ([sender isKindOfClass:[NSSegmentedControl class]]==YES) { tSwitchTag=1; NSSegmentedControl * tSegmentedControl=(NSSegmentedControl *)sender; if ([tSegmentedControl isSelectedForSegment:0]==tIsLeftViewCollapsed) tSwitchTag=0; if ([tSegmentedControl isSelectedForSegment:2]==tIsRightViewCollapsed) tSwitchTag=2; } else if ([sender isKindOfClass:[NSMenuItem class]]==YES) { tSwitchTag=((NSMenuItem *) sender).tag; } NSWindow * tWindow=self.view.window; switch(tSwitchTag) { case 0: if (tIsLeftViewCollapsed==NO) { [_splitView setPosition:[_splitView minPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0]; if (tWindow.firstResponder==tWindow) [tWindow makeFirstResponder:self]; } else { CGFloat tPosition=NSWidth(_leftView.frame); [_splitView setPosition:tPosition ofDividerAtIndex:0]; [self splitView:_splitView resizeSubviewsWithOldSize:_splitView.frame.size]; } break; case 1: [_contentsViewController showHideBottomView:self]; break; case 2: if (tIsRightViewCollapsed==NO) { [_splitView setPosition:[_splitView maxPossiblePositionOfDividerAtIndex:1] ofDividerAtIndex:1]; if (tWindow.firstResponder==tWindow) { [tWindow makeFirstResponder:self]; } } else { CGFloat tPosition=NSWidth(_splitView.frame)-_splitView.dividerThickness-NSWidth(_rightView.frame); [_splitView setPosition:tPosition ofDividerAtIndex:1]; [self splitView:_splitView resizeSubviewsWithOldSize:_splitView.frame.size]; } break; } if (self.view.window.firstResponder==nil) { [self.view.window makeFirstResponder:_middleView]; } } #pragma mark - NSSplitViewDelegate - (void)_splitView:(NSSplitView *)inSplitView resizeSubviewsWithSidebarWidth:(CGFloat)inSidebarWidth inspectorViewWidth:(CGFloat)inInspectorViewWidth { BOOL tIsLeftToRightLayout=(_splitView.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight); NSView * tSidebarView=nil; NSView * tInspectorView=nil; if (tIsLeftToRightLayout==YES) { tSidebarView=_leftView; tInspectorView=_rightView; } else { tSidebarView=_rightView; tInspectorView=_leftView; } NSRect tSplitViewFrame=inSplitView.frame; NSRect tSidebarFrame=tSidebarView.frame; tSidebarFrame.size.width=inSidebarWidth; NSRect tContentsFrame=_middleView.frame; NSRect tInspectorFrame=tInspectorView.frame; tInspectorFrame.size.width=inInspectorViewWidth; CGFloat tSidebarWidth=([inSplitView isSubviewCollapsed:tSidebarView]==NO) ? NSWidth(tSidebarFrame) : 0.0; CGFloat tInspectorWidth=([inSplitView isSubviewCollapsed:tInspectorView]==NO) ? NSWidth(tInspectorFrame) : 0.0; tContentsFrame.size.width=NSWidth(tSplitViewFrame)-tSidebarWidth-tInspectorWidth-2*inSplitView.dividerThickness; if (tContentsFrame.size.width ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorPanel.h ================================================ /* Copyright (c) 2021-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogsOpenErrorRecord.h" @interface CUICrashLogsOpenErrorPanel : NSPanel @property NSArray * errors; + (CUICrashLogsOpenErrorPanel *)crashLogsOpenErrorPanel; - (void)beginSheetModalForWindow:(NSWindow *)inWindow completionHandler:(void (^)(NSModalResponse response))handler; - (NSModalResponse)runModal; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorPanel.m ================================================ /* Copyright (c) 2021-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsOpenErrorPanel.h" #import "CUICrashLogsOpenErrorRecord+UI.h" #import "NSTableView+Selection.h" @interface CUICrashLogsOpenErrorWindowController : NSWindowController { IBOutlet NSTextField * _messageLabel; IBOutlet NSTextField * _informativeLabel; IBOutlet NSTableView * _tableView; IBOutlet NSButton * _defaultButton; } @property (nonatomic) NSArray * errors; - (void)updateUI; - (IBAction)showInFinder:(id)sender; - (IBAction)endDialog:(id)sender; @end @implementation CUICrashLogsOpenErrorWindowController - (NSString *)windowNibName { return @"CUICrashLogsOpenErrorWindowController"; } - (void)windowDidLoad { [super windowDidLoad]; NSTableColumn * tTableColumn=[_tableView tableColumnWithIdentifier:@"file"]; tTableColumn.headerCell.title=NSLocalizedString(@"Name",@""); tTableColumn=[_tableView tableColumnWithIdentifier:@"reason"]; tTableColumn.headerCell.title=NSLocalizedString(@"Reason",@""); NSRect tButtonFrame=_defaultButton.frame; _defaultButton.title=NSLocalizedString(@"OK",@""); [_defaultButton sizeToFit]; CGFloat tWidth=NSWidth(_defaultButton.frame); if (tWidth *)inErrors { if (_errors==inErrors) return; _errors=inErrors; if (_tableView!=nil) [self updateUI]; } #pragma mark - - (void)updateUI { NSString * tMessageString=@""; NSString * tInformativeString=@""; switch (_errors.count) { case 0: break; case 1: tMessageString=NSLocalizedString(@"An error occurred while opening the file.", @""); tInformativeString=NSLocalizedString(@"The file can't be opened for the following reason:", @""); break; default: tMessageString=NSLocalizedString(@"An error occurred while opening some files.", @""); tInformativeString=NSLocalizedString(@"These files can't be opened for the following reasons:", @""); break; } _messageLabel.stringValue=tMessageString; _informativeLabel.stringValue=tInformativeString; [_tableView reloadData]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(showInFinder:)) { return YES; } return YES; } - (IBAction)showInFinder:(id)sender { NSIndexSet * tSelectedRows=[_tableView WB_selectedOrClickedRowIndexes]; [self.errors enumerateObjectsAtIndexes:tSelectedRows options:0 usingBlock:^(CUICrashLogsOpenErrorRecord * bRecord, NSUInteger bIndex, BOOL * bOutStop) { [[NSWorkspace sharedWorkspace] selectFile:bRecord.sourceURL.path inFileViewerRootedAtPath:@""]; }]; } - (IBAction)endDialog:(NSButton *)sender { [NSApp stopModalWithCode:NSModalResponseOK]; } #pragma mark - NSTableViewDataSource - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return _errors.count; } #pragma mark - NSTableViewDelegate - (NSView *)tableView:(NSTableView *)inTableView viewForTableColumn:(NSTableColumn *)inTableColumn row:(NSInteger)inRow { CUICrashLogsOpenErrorRecord * tRecord=_errors[inRow]; NSString * tTableColumnIdentifier=inTableColumn.identifier; NSTableCellView * tTableCellView=[inTableView makeViewWithIdentifier:tTableColumnIdentifier owner:self]; if ([tTableColumnIdentifier isEqualToString:@"file"]==YES) { NSImage * tIcon=[[NSWorkspace sharedWorkspace] iconForFile:tRecord.sourceURL.path]; tTableCellView.imageView.image=tIcon; tTableCellView.textField.stringValue=tRecord.sourceURL.path.lastPathComponent; } else if ([tTableColumnIdentifier isEqualToString:@"reason"]==YES) { tTableCellView.textField.stringValue=tRecord.localizedDescription; } return tTableCellView; } @end @interface CUICrashLogsOpenErrorPanel () { CUICrashLogsOpenErrorWindowController * retainedWindowController; } - (void)_sheetDidEndSelector:(NSWindow *)inWindow returnCode:(NSInteger)inReturnCode contextInfo:(void *)contextInfo; @end @implementation CUICrashLogsOpenErrorPanel + (CUICrashLogsOpenErrorPanel *)crashLogsOpenErrorPanel { CUICrashLogsOpenErrorWindowController * tWindowController=[CUICrashLogsOpenErrorWindowController new]; CUICrashLogsOpenErrorPanel * tPanel=(CUICrashLogsOpenErrorPanel *)tWindowController.window; tPanel->retainedWindowController=tWindowController; return tPanel; } #pragma mark - - (NSArray *)errors { return retainedWindowController.errors; } - (void)setErrors:(NSArray *)inErrors { retainedWindowController.errors=inErrors; } #pragma mark - - (void)_sheetDidEndSelector:(CUICrashLogsOpenErrorPanel *)inPanel returnCode:(NSInteger)inReturnCode contextInfo:(void *)contextInfo { void(^handler)(NSInteger) = (__bridge_transfer void(^)(NSInteger)) contextInfo; if (handler!=nil) handler(inReturnCode); inPanel->retainedWindowController=nil; [inPanel orderOut:self]; } - (void)beginSheetModalForWindow:(NSWindow *)inWindow completionHandler:(void (^)(NSModalResponse))handler { [inWindow beginSheet:self completionHandler:^(NSModalResponse bResponse) { if (handler!=nil) handler(bResponse); self->retainedWindowController=nil; }]; } - (NSModalResponse)runModal { NSModalResponse tModalResponse=[NSApp runModalForWindow:self]; retainedWindowController=nil; [self orderOut:self]; return tModalResponse; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorRecord+UI.h ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsOpenErrorRecord.h" @interface CUICrashLogsOpenErrorRecord (UI) - (NSString *)localizedDescription; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorRecord+UI.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsOpenErrorRecord+UI.h" @implementation CUICrashLogsOpenErrorRecord (UI) - (NSString *)localizedDescription { NSString * tString=self.description; if (tString==nil) return @"-"; return NSLocalizedString(tString, @""); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorRecord.h ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogErrors.h" @interface CUICrashLogsOpenErrorRecord : NSObject @property NSURL * sourceURL; @property (copy) NSError * openError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorRecord.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsOpenErrorRecord.h" #import "IPSError.h" @implementation CUICrashLogsOpenErrorRecord - (NSString *)description { NSError * tError=self.openError; if (tError==nil) return @"-"; if ([tError.domain isEqualToString:IPSErrorDomain]==YES) { switch(tError.code) { case IPSUnsupportedBugTypeError: return @"The format of this file is invalid or unsupported."; default: break; } } else if ([tError.domain isEqualToString:CUICrashLogDomain]==YES) { switch(tError.code) { case CUICrashLogEmptyFileError: return @"This file is empty."; case CUICrashLogInvalidFormatFileError: return @"The format of this file is invalid or unsupported."; default: break; } } else if ([tError.domain isEqualToString:NSCocoaErrorDomain]==YES) { switch (tError.code) { case NSFileReadNoPermissionError: return @"You don't have permission to view this file."; default: return [NSString stringWithFormat:@"Error code: %ld",tError.code]; } } return @"-"; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsProvider.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" extern NSString * const CUIRetiredPathComponent; typedef NS_ENUM(NSUInteger, CUICrashLogsProviderCollectOptions) { CUICrashLogsProviderCollectRetired = 1 }; @interface CUICrashLogsProvider : NSObject + (CUICrashLogsProvider *)defaultProvider; - (NSArray *)currentUserCrashLogs; - (NSArray *)systemCrashLogs; - (id)crashLogWithContentsOfFile:(NSString *)inPath error:(NSError **)outError; - (NSArray *)crashLogsForDirectory:(NSString *)inDirectoryPath error:(NSError **)outError; - (NSArray *)crashLogsForDirectory:(NSString *)inDirectoryPath options:(CUICrashLogsProviderCollectOptions)inOptions error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsProvider.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsProvider.h" #import "NSArray+WBExtensions.h" NSString * const CUIRetiredPathComponent=@"Retired"; @interface CUICrashLogsProvider () - (NSArray *)crashLogsForDirectory:(NSString *)inDirectoryPath options:(CUICrashLogsProviderCollectOptions)options error:(NSError **)outError; @end @implementation CUICrashLogsProvider + (CUICrashLogsProvider *)defaultProvider { static CUICrashLogsProvider * sDefaultProvider=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sDefaultProvider=[CUICrashLogsProvider new]; }); return sDefaultProvider; } #pragma mark - - (NSArray *)currentUserCrashLogs { NSString * tDirectoryPath=[@"~/Library/Logs/DiagnosticReports/" stringByExpandingTildeInPath]; return [self crashLogsForDirectory:tDirectoryPath options:CUICrashLogsProviderCollectRetired error:NULL]; } - (NSArray *)systemCrashLogs { NSString * tDirectoryPath=@"/Library/Logs/DiagnosticReports/"; return [self crashLogsForDirectory:tDirectoryPath options:CUICrashLogsProviderCollectRetired error:NULL]; } - (id)crashLogWithContentsOfFile:(NSString *)inPath error:(NSError **)outError { if ([inPath isKindOfClass:NSString.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } NSString * tExtension=inPath.pathExtension; if ([tExtension caseInsensitiveCompare:@"crash"]!=NSOrderedSame && [tExtension caseInsensitiveCompare:@"ips"]!=NSOrderedSame) return nil; NSError * tError=nil; id tCrashLog=[[CUICrashLog alloc] initWithContentsOfFile:inPath error:&tError]; if (tCrashLog==nil) { BOOL tryAgainIfRawSucceed=NO; if ([tError.domain isEqualToString:NSCocoaErrorDomain]==YES) { switch(tError.code) { case NSFileReadNoSuchFileError: // File is missing, no point in trying to read it case NSFileReadNoPermissionError: // Not enough privileges to read file, no point in trying to read it if (outError!=nil) *outError=tError; return nil; case NSFileReadUnknownError: { NSError * tUnderlyingError=tError.userInfo[NSUnderlyingErrorKey]; if ([tUnderlyingError.domain isEqualToString:NSPOSIXErrorDomain]==YES && tUnderlyingError.code==EINTR) { tryAgainIfRawSucceed=YES; } } case NSPropertyListReadCorruptError: // Invalid json file. if (outError!=nil) *outError=tError; return nil; default: break; } } else if ([tError.domain isEqualToString:CUICrashLogDomain]==YES) { switch(tError.code) { case CUICrashLogEmptyFileError: case CUICrashLogInvalidFormatFileError: // Not worth retrying as a raw file if (outError!=nil) *outError=tError; NSLog(@"Error when parsing report file \"%@\": Empty file or not a crash log report.",inPath); return nil; } } NSLog(@"Error when parsing report file \"%@\", will try to parse it as raw report: %@",inPath,tError.description); tCrashLog=[[CUIRawCrashLog alloc] initWithContentsOfFile:inPath error:&tError]; if (tCrashLog!=nil) { id newCrashLogAttempt=[[CUICrashLog alloc] initWithContentsOfFile:inPath error:&tError]; if (newCrashLogAttempt!=nil) tCrashLog=newCrashLogAttempt; } } return tCrashLog; } - (NSArray *)crashLogsForDirectory:(NSString *)inDirectoryPath error:(NSError **)outError { return [self crashLogsForDirectory:inDirectoryPath options:0 error:outError]; } - (NSArray *)crashLogsForDirectory:(NSString *)inDirectoryPath options:(CUICrashLogsProviderCollectOptions)inOptions error:(NSError **)outError { if ([inDirectoryPath isKindOfClass:NSString.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } NSArray * tArray=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:inDirectoryPath error:outError]; if ((inOptions & CUICrashLogsProviderCollectRetired) == CUICrashLogsProviderCollectRetired && [tArray containsObject:CUIRetiredPathComponent]==YES) { NSArray * tRetiredArray=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[inDirectoryPath stringByAppendingPathComponent:CUIRetiredPathComponent] error:NULL]; if (tRetiredArray.count>0) tArray = [tArray arrayByAddingObjectsFromArray:tRetiredArray]; } NSArray * tCrashLogsArray=[tArray WB_arrayByMappingObjectsLenientlyUsingBlock:^id(NSString * bComponent, NSUInteger bIndex) { NSString * tComponentExtension=bComponent.pathExtension; if ([tComponentExtension caseInsensitiveCompare:@"crash"]!=NSOrderedSame && [tComponentExtension caseInsensitiveCompare:@"ips"]!=NSOrderedSame) return nil; NSString * tFilePath=[inDirectoryPath stringByAppendingPathComponent:bComponent]; NSError * tError=nil; id tCrashLog=[[CUICrashLog alloc] initWithContentsOfFile:tFilePath error:&tError]; if (tCrashLog==nil) { if ([tError.domain isEqualToString:NSCocoaErrorDomain]==YES) { switch(tError.code) { case NSFileReadNoSuchFileError: // File is missing, no point in trying to read it case NSFileReadNoPermissionError: // Not enough privileges to read file, no point in trying to read it return nil; default: break; } } else if ([tError.domain isEqualToString:CUICrashLogDomain]==YES) { switch(tError.code) { case CUICrashLogEmptyFileError: case CUICrashLogInvalidFormatFileError: // Not worth retrying as a raw file return nil; } } tCrashLog=[[CUIRawCrashLog alloc] initWithContentsOfFile:tFilePath error:&tError]; } return tCrashLog; }]; return tCrashLogsArray; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSelection.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogsSource.h" extern NSString * const CUICrashLogsSelectionDidChangeNotification; @interface CUICrashLogsSelection : NSObject @property (readonly) CUICrashLogsSource * source; @property (readonly) NSArray * crashLogs; + (CUICrashLogsSelection *)sharedSelection; - (void)setSource:(CUICrashLogsSource *)inSource crashLogs:(NSArray *)inCrashLogs; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSelection.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSelection.h" NSString * const CUICrashLogsSelectionDidChangeNotification=@"CUICrashLogsSelectionDidChangeNotification"; @interface CUICrashLogsSelection () @property CUICrashLogsSource * source; @property NSArray * crashLogs; @end @implementation CUICrashLogsSelection + (CUICrashLogsSelection *)sharedSelection { static CUICrashLogsSelection * sSharedSelection=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSharedSelection=[CUICrashLogsSelection new]; }); return sSharedSelection; } - (instancetype)init { self=[super init]; if (self!=nil) { _crashLogs=@[]; } return self; } #pragma mark - NSObject - (NSUInteger)hash { return self.source.name.hash; } - (BOOL)isEqual:(CUICrashLogsSelection *)inOtherSelection { return (self.source==inOtherSelection.source && [self.crashLogs isEqualToArray:inOtherSelection.crashLogs]==YES); } #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { CUICrashLogsSelection * nSelection=[CUICrashLogsSelection new]; nSelection.source=self.source; nSelection.crashLogs=[self.crashLogs copy]; return nSelection; } #pragma mark - - (void)setSource:(CUICrashLogsSource *)inSource crashLogs:(NSArray *)inCrashLogs { if (_source==inSource && _crashLogs==inCrashLogs) return; _source=inSource; _crashLogs=inCrashLogs; [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogsSelectionDidChangeNotification object:self]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSource+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSource.h" #import @interface CUICrashLogsSource (UI) - (NSImage *)icon; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSource+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSource+UI.h" @implementation CUICrashLogsSource (UI) - (NSImage *)icon { NSImage * tImage=nil; switch(self.type) { case CUICrashLogsSourceTypeDirectory: tImage=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SidebarGenericFolder.icns"]; break; case CUICrashLogsSourceTypeFile: tImage=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SidebarGenericFile.icns"]; break; case CUICrashLogsSourceTypeSmart: tImage=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SidebarSmartFolder.icns"]; break; default: break; } [tImage setTemplate:YES]; return tImage; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSource.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" extern NSString * const CUICrashLogsSourceTypeKey; extern NSString * const CUICrashLogsSourceDidAddSourcesNotification; extern NSString * const CUICrashLogsSourceDidUpdateSourceNotification; extern NSString * const CUICrashLogsSourceDidRemoveSourcesNotification; typedef NS_ENUM(NSUInteger, CUICrashLogsSourceType) { CUICrashLogsSourceTypeUnknown, CUICrashLogsSourceTypeAll, CUICrashLogsSourceTypeStandardDirectory, CUICrashLogsSourceTypeToday, CUICrashLogsSourceTypeDirectory, CUICrashLogsSourceTypeFile, CUICrashLogsSourceTypeSmart, CUICrashLogsSourceTypeSeparator }; @interface CUICrashLogsSource : NSObject @property (nonatomic,readonly) CUICrashLogsSourceType type; @property (nonatomic,copy) NSString * name; @property (nonatomic,copy) NSString * sourceDescription; @property (nonatomic,readonly) NSArray * crashLogs; - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation; - (NSDictionary *)representation; - (BOOL)containsCrashLogForFileAtPath:(NSString *)inPath; - (id)crashLogForFileAtPath:(NSString *)inPath; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSource.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSource.h" NSString * const CUICrashLogsSourceTypeKey=@"type"; NSString * const CUICrashLogsSourceNameKey=@"name"; NSString * const CUICrashLogsSourceDescription=@"description"; NSString * const CUICrashLogsSourceDidAddSourcesNotification=@"CUICrashLogsSourcesDidAddSourcesNotification"; NSString * const CUICrashLogsSourceDidUpdateSourceNotification=@"CUICrashLogsSourceDidUpdateSourceNotification"; NSString * const CUICrashLogsSourceDidRemoveSourcesNotification=@"CUICrashLogsSourceDidRemoveSourcesNotification"; @implementation CUICrashLogsSource - (instancetype)init { self=[super init]; if (self!=nil) { _name=@""; _sourceDescription=@""; } return self; } - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { if ([inRepresentation isKindOfClass:NSDictionary.class]==NO) return nil; self=[super init]; if (self!=nil) { NSString * tString=inRepresentation[CUICrashLogsSourceNameKey]; if (tString!=nil && [tString isKindOfClass:NSString.class]==NO) return nil; _name=(tString!=nil) ? [tString copy] : @""; tString=inRepresentation[CUICrashLogsSourceDescription]; if (tString!=nil && [tString isKindOfClass:NSString.class]==NO) return nil; _sourceDescription=(tString!=nil) ? [tString copy] : @""; } return self; } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeUnknown; } - (NSArray *)crashLogs { return nil; } - (NSDictionary *)representation { return @{ CUICrashLogsSourceTypeKey:@(self.type), CUICrashLogsSourceNameKey:self.name, CUICrashLogsSourceDescription:self.sourceDescription }; } #pragma mark - - (BOOL)containsCrashLogForFileAtPath:(NSString *)inPath { return ([self crashLogForFileAtPath:inPath]!=nil); } - (id)crashLogForFileAtPath:(NSString *)inPath { for(CUIRawCrashLog * tCrashLog in self.crashLogs) { NSString * tCrashLogFilePath=tCrashLog.crashLogFilePath; if (tCrashLogFilePath==nil) continue; if ([tCrashLogFilePath isEqualToString:inPath]==YES) return tCrashLog; } return nil; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceAll+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceAll.h" #import @interface CUICrashLogsSourceAll (UI) - (NSImage *)icon; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceAll+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceAll+UI.h" @implementation CUICrashLogsSourceAll (UI) - (NSImage *)icon { static NSImage * sIcon=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sIcon=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SidebarAllMyFiles.icns"]; sIcon.template=YES; }); return sIcon; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceAll.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSource.h" @interface CUICrashLogsSourceAll : CUICrashLogsSource + (CUICrashLogsSourceAll *)crashLogsSourceAll; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceAll.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceAll.h" @interface CUICrashLogsSourceAll () { NSMutableSet * _allSources; NSArray * _crashLogs; } // Notifications - (void)crashLogsSourceDidAddSources:(NSNotification *)inNotification; - (void)crashLogsSourceDidUpdateSource:(NSNotification *)inNotification; - (void)crashLogsSourceDidRemoveSources:(NSNotification *)inNotification; @end @implementation CUICrashLogsSourceAll + (CUICrashLogsSourceAll *)crashLogsSourceAll { static CUICrashLogsSourceAll * sCrashLogsSourceAll=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sCrashLogsSourceAll=[CUICrashLogsSourceAll new]; }); return sCrashLogsSourceAll; } - (instancetype)init { self=[super init]; if (self!=nil) { _allSources=[NSMutableSet set]; _crashLogs=@[]; // Register for notifications NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(crashLogsSourceDidAddSources:) name:CUICrashLogsSourceDidAddSourcesNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(crashLogsSourceDidUpdateSource:) name:CUICrashLogsSourceDidUpdateSourceNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(crashLogsSourceDidRemoveSources:) name:CUICrashLogsSourceDidRemoveSourcesNotification object:nil]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeAll; } - (NSString *)name { return NSLocalizedString(@"All",@""); } - (NSString *)sourceDescription { return NSLocalizedString(@"All reports from all sources", @""); } - (NSArray *)crashLogs { if (_crashLogs==nil) { NSMutableArray * tMutableArray=[NSMutableArray array]; [_allSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, BOOL * bOutStop) { NSArray * tLogs=bSource.crashLogs; [tMutableArray addObjectsFromArray:tLogs]; }]; _crashLogs=[tMutableArray copy]; } return _crashLogs; } #pragma mark - - (void)refresh { _crashLogs=nil; [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogsSourceDidUpdateSourceNotification object:self]; } #pragma mark - Notifications - (void)crashLogsSourceDidAddSources:(NSNotification *)inNotification { NSArray * tSources=inNotification.object; if ([tSources isKindOfClass:[NSArray class]]==NO) return; __block NSUInteger tNewCrashLogs=0; [tSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { if ([bSource isKindOfClass:[CUICrashLogsSource class]]==NO) return; if (bSource.type==CUICrashLogsSourceTypeSmart) return; [self->_allSources addObject:bSource]; tNewCrashLogs+=bSource.crashLogs.count; }]; if (tNewCrashLogs>0) [self refresh]; } - (void)crashLogsSourceDidUpdateSource:(NSNotification *)inNotification { CUICrashLogsSource * tSource=(CUICrashLogsSource *)inNotification.object; switch(tSource.type) { case CUICrashLogsSourceTypeAll: case CUICrashLogsSourceTypeSmart: return; default: break; } if ([tSource isKindOfClass:[CUICrashLogsSource class]]==NO) return; if (tSource.type==CUICrashLogsSourceTypeSmart) return; if ([_allSources containsObject:tSource]==NO) return; [self refresh]; } - (void)crashLogsSourceDidRemoveSources:(NSNotification *)inNotification { NSArray * tSources=inNotification.object; if ([tSources isKindOfClass:[NSArray class]]==NO) return; __block NSUInteger tRemovedCrashLogs=0; [tSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { if ([bSource isKindOfClass:[CUICrashLogsSource class]]==NO) return; if (bSource.type==CUICrashLogsSourceTypeSmart) return; [self->_allSources removeObject:bSource]; tRemovedCrashLogs+=bSource.crashLogs.count; }]; if (tRemovedCrashLogs>0) [self refresh]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceDirectory.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceFileSystemItem.h" @interface CUICrashLogsSourceDirectory : CUICrashLogsSourceFileSystemItem - (instancetype)initWithContentsOfFileSystemItemAtPath:(NSString *)inPath collectRetired:(BOOL)inCollectRetired error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceDirectory.m ================================================ /* Copyright (c) 2020-2025 Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceDirectory.h" #import "CUICrashLogsProvider.h" void mycallback( ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]); @interface CUICrashLogsSourceDirectory () { NSArray * _crashLogs; FSEventStreamRef _eventStreamRef; BOOL _collectRetired; } - (void)handleFileSystemEventIDs:(const FSEventStreamEventId[])inEventIDs paths:(NSArray *)inEventsPaths flags:(const FSEventStreamEventFlags[])inFlags; @end @implementation CUICrashLogsSourceDirectory - (BOOL)initCommonWithError:(NSError **)outError { NSArray * tCrashLogs=[[CUICrashLogsProvider defaultProvider] crashLogsForDirectory:self.path options:(_collectRetired==YES) ? CUICrashLogsProviderCollectRetired : 0 error:outError]; if (tCrashLogs==nil) return NO; _crashLogs=tCrashLogs; NSArray * tMonitoredPaths=nil; if (_collectRetired == YES) { tMonitoredPaths=@[self.path, [self.path stringByAppendingPathComponent:CUIRetiredPathComponent]]; } else { tMonitoredPaths=@[self.path]; } FSEventStreamContext context; context.info = (__bridge void *)self; // !!! context.version = 0; context.retain = NULL; context.release = NULL; context.copyDescription = NULL; CFAbsoluteTime latency = 3.0; /* Latency in seconds */ /* Create the stream, passing in a callback */ _eventStreamRef = FSEventStreamCreate(kCFAllocatorDefault,&mycallback,&context,(__bridge CFArrayRef)tMonitoredPaths,kFSEventStreamEventIdSinceNow,latency,kFSEventStreamCreateFlagWatchRoot+kFSEventStreamCreateFlagUseCFTypes); FSEventStreamScheduleWithRunLoop(_eventStreamRef, CFRunLoopGetCurrent(),kCFRunLoopDefaultMode); FSEventStreamStart(_eventStreamRef); return YES; } - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { self=[super initWithRepresentation:inRepresentation]; if (self!=nil) { if ([self initCommonWithError:NULL]==NO) return nil; } return self; } - (instancetype)initWithContentsOfFileSystemItemAtPath:(NSString *)inPath error:(NSError **)outError { self = [super initWithContentsOfFileSystemItemAtPath:inPath error:outError]; if (self!=nil) { if ([self initCommonWithError:NULL]==NO) return nil; } return self; } - (instancetype)initWithContentsOfFileSystemItemAtPath:(NSString *)inPath collectRetired:(BOOL)inCollectRetired error:(NSError **)outError { self=[super initWithContentsOfFileSystemItemAtPath:inPath error:outError]; if (self!=nil) { _collectRetired=inCollectRetired; if ([self initCommonWithError:outError]==NO) return nil; } return self; } - (void)dealloc { if (_eventStreamRef!=NULL) { FSEventStreamStop(_eventStreamRef); FSEventStreamInvalidate(_eventStreamRef); FSEventStreamRelease(_eventStreamRef); } } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeDirectory; } - (NSString *)name { return self.path.lastPathComponent; } - (NSArray *)crashLogs { return _crashLogs; } #pragma mark - - (BOOL)containsCrashLogsFileAtPath:(NSString *)inPath { if ([inPath rangeOfString:self.path options:NSCaseInsensitiveSearch].location!=0) return NO; for(CUIRawCrashLog * tCrashLog in self.crashLogs) { NSString * tCrashLogFilePath=tCrashLog.crashLogFilePath; if (tCrashLogFilePath==nil) continue; if ([tCrashLogFilePath isEqualToString:inPath]==YES) return YES; } return NO; } #pragma mark - - (void)handleFileSystemEventIDs:(const FSEventStreamEventId[])inEventIDs paths:(NSArray *)inEventsPaths flags:(const FSEventStreamEventFlags[])inFlags { // Check if the directory stil exists if ((inFlags[0] & kFSEventStreamEventFlagRootChanged)==kFSEventStreamEventFlagRootChanged) { // A COMPLETER /*BOOL tIsDirectory; if ([[NSFileManager defaultManager] fileExistsAtPath:_directoryPath isDirectory:&tIsDirectory]==NO || tIsDirectory==NO) { // A COMPLETER return; }*/ _crashLogs=[[CUICrashLogsProvider defaultProvider] crashLogsForDirectory:self.path options:(_collectRetired==YES) ? CUICrashLogsProviderCollectRetired : 0 error:NULL]; } else { // Refresh the list of crash logs NSArray * tCrashLogs=[[CUICrashLogsProvider defaultProvider] crashLogsForDirectory:self.path options:(_collectRetired==YES) ? CUICrashLogsProviderCollectRetired : 0 error:NULL]; if (tCrashLogs==nil) return; _crashLogs=tCrashLogs; } [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogsSourceDidUpdateSourceNotification object:self]; } @end void mycallback(ConstFSEventStreamRef streamRef,void * inInfo,size_t inNumEvent,void * inEventPaths,const FSEventStreamEventFlags inEventFlags[],const FSEventStreamEventId inEventIDs[]) { NSArray * tEventPaths=(__bridge NSArray *)inEventPaths; CUICrashLogsSourceDirectory * tSourceDirectory=(__bridge CUICrashLogsSourceDirectory *)inInfo; [tSourceDirectory handleFileSystemEventIDs:inEventIDs paths:tEventPaths flags:inEventFlags]; } ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceFile.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceFileSystemItem.h" @interface CUICrashLogsSourceFile : CUICrashLogsSourceFileSystemItem @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceFile.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceFile.h" #import "CUICrashLogsProvider.h" @interface CUICrashLogsSourceFile () { NSArray * _crashLogs; } @end @implementation CUICrashLogsSourceFile - (BOOL)initCommonWithError:(NSError **)outError { id tCrashLog=[[CUICrashLogsProvider defaultProvider] crashLogWithContentsOfFile:self.path error:outError]; if (tCrashLog==nil) return NO; _crashLogs=@[tCrashLog]; return YES; } - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { self=[super initWithRepresentation:inRepresentation]; if (self!=nil) { if ([self initCommonWithError:NULL]==NO) return nil; } return self; } - (instancetype)initWithContentsOfFileSystemItemAtPath:(NSString *)inPath error:(NSError **)outError { self=[super initWithContentsOfFileSystemItemAtPath:inPath error:outError]; if (self!=nil) { if ([self initCommonWithError:outError]==NO) return nil; } return self; } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeFile; } - (NSString *)name { return self.path.lastPathComponent.stringByDeletingPathExtension; } - (NSArray *)crashLogs { return _crashLogs; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceFileSystemItem.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSource.h" @interface CUICrashLogsSourceFileSystemItem : CUICrashLogsSource @property (readonly,copy) NSString * path; - (instancetype)initWithContentsOfFileSystemItemAtPath:(NSString *)inPath error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceFileSystemItem.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceFileSystemItem.h" NSString * const CUICrashLogSourcePathKey=@"path"; @interface CUICrashLogsSourceFileSystemItem () @property (copy) NSString * path; @end @implementation CUICrashLogsSourceFileSystemItem - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { self=[super initWithRepresentation:inRepresentation]; if (self!=nil) { NSString * tString=inRepresentation[CUICrashLogSourcePathKey]; if ([tString isKindOfClass:NSString.class]==NO) return nil; if (tString.length==0) return nil; _path=[tString copy]; } return self; } - (instancetype)initWithContentsOfFileSystemItemAtPath:(NSString *)inPath error:(NSError **)outError { if ([inPath isKindOfClass:NSString.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _path=[inPath copy]; } return self; } #pragma mark - - (NSString *)sourceDescription { return (self.path!=nil) ? self.path : @""; } - (NSDictionary *)representation { NSMutableDictionary * tMutableDictionary=[[super representation] mutableCopy]; tMutableDictionary[CUICrashLogSourcePathKey]=self.path; return [tMutableDictionary copy]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceSeparator.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSource.h" @interface CUICrashLogsSourceSeparator : CUICrashLogsSource + (CUICrashLogsSourceSeparator *)separator; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceSeparator.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceSeparator.h" @implementation CUICrashLogsSourceSeparator + (CUICrashLogsSourceSeparator *)separator { static CUICrashLogsSourceSeparator * sSeparator=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSeparator=[CUICrashLogsSourceSeparator new]; }); return sSeparator; } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeSeparator; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceSmart.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSource.h" @interface CUICrashLogsSourceSmart : CUICrashLogsSource @property (readonly) NSUInteger version; @property (nonatomic) NSPredicate * predicate; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceSmart.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceSmart.h" #import "CUICrashLogsSourceAll.h" #define SMARTSOURCE_VERSION_1 1 #define SMARTSOURCE_VERSION_2 2 #define SMARTSOURCE_CURRENTVERSION SMARTSOURCE_VERSION_2 #define SMARTSOURCE_MAXIMUMSUPPORTEDVERSION SMARTSOURCE_VERSION_2 NSString * const CUICrashLogsSourcesSmartVersionKey=@"version"; NSString * const CUICrashLogsSourcesSmartPredicateKey=@"predicate"; @interface CUICrashLogsSourceSmart () { NSArray * _filteredCrashLogs; } @property NSUInteger version; - (void)sourceAllDidUpdateSource:(NSNotification *)inNotification; @end @implementation CUICrashLogsSourceSmart - (instancetype)init { self=[super init]; if (self!=nil) { [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(sourceAllDidUpdateSource:) name:CUICrashLogsSourceDidUpdateSourceNotification object:[CUICrashLogsSourceAll crashLogsSourceAll]]; self.name=NSLocalizedString(@"Untitled source", @""); _version=SMARTSOURCE_CURRENTVERSION; _predicate=[NSPredicate predicateWithFormat:@"processName = \"MyApplication\""]; } return self; } - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { self=[super initWithRepresentation:inRepresentation]; if (self!=nil) { [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(sourceAllDidUpdateSource:) name:CUICrashLogsSourceDidUpdateSourceNotification object:[CUICrashLogsSourceAll crashLogsSourceAll]]; NSNumber * tNumber=inRepresentation[CUICrashLogsSourcesSmartVersionKey]; if (tNumber!=nil) { if ([tNumber isKindOfClass:NSNumber.class]==NO) return nil; _version=tNumber.unsignedIntegerValue; } else { _version=SMARTSOURCE_VERSION_1; } if (_version>SMARTSOURCE_MAXIMUMSUPPORTEDVERSION) { NSLog(@"Smart Source object version (%lu) is not supported by this version of Unexpectedly",(unsigned long)_version); return nil; } NSString * tString=inRepresentation[CUICrashLogsSourcesSmartPredicateKey]; if ([tString isKindOfClass:NSString.class]==NO) return nil; self.predicate=[NSPredicate predicateWithFormat:tString]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeSmart; } - (NSArray *)crashLogs { return _filteredCrashLogs; } - (void)setPredicate:(NSPredicate *)inPredicate { if (_predicate==inPredicate) return; _predicate=inPredicate; [self sourceAllDidUpdateSource:[NSNotification notificationWithName:CUICrashLogsSourceDidUpdateSourceNotification object:[CUICrashLogsSourceAll crashLogsSourceAll]]]; } - (NSDictionary *)representation { NSMutableDictionary * tMutableDictionary=[[super representation] mutableCopy]; tMutableDictionary[CUICrashLogsSourcesSmartVersionKey]=@(self.version); tMutableDictionary[CUICrashLogsSourcesSmartPredicateKey]=self.predicate.predicateFormat; return [tMutableDictionary copy]; } #pragma mark - Notifications - (void)sourceAllDidUpdateSource:(NSNotification *)inNotification { _filteredCrashLogs=[[CUICrashLogsSourceAll crashLogsSourceAll].crashLogs filteredArrayUsingPredicate:self.predicate]; [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogsSourceDidUpdateSourceNotification object:self]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceSmartEditorPanel.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogsSourceSmart.h" @interface CUICrashLogsSourceSmartEditorPanel : NSPanel @property (nonatomic) CUICrashLogsSourceSmart * source; @property (nonatomic) NSString * prompt; + (CUICrashLogsSourceSmartEditorPanel *)crashLogsSourceSmartEditorPanel; - (void)beginSheetModalForWindow:(NSWindow *)inWindow completionHandler:(void (^)(NSModalResponse response))handler; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceSmartEditorPanel.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceSmartEditorPanel.h" #import "CUICrashLogsSourcesManager.h" #include @interface CUICrashLogsSourceSmartEditorWindowController : NSWindowController { IBOutlet NSTextField * _nameTextField; IBOutlet NSTextField * _descriptionTextField; IBOutlet NSPredicateEditor * _predicatorEditor; IBOutlet NSButton * _defaultButton; } @property (nonatomic) CUICrashLogsSourceSmart * source; @property (nonatomic,copy) NSString * prompt; - (IBAction)endDialog:(id)sender; @end @implementation CUICrashLogsSourceSmartEditorWindowController - (NSString *)windowNibName { return @"CUICrashLogsSourceSmartEditorWindowController"; } - (void)windowDidLoad { [super windowDidLoad]; // Row Template 1 NSArray *keyPaths = @[[NSExpression expressionForKeyPath:@"processName"], [NSExpression expressionForKeyPath:@"header.bundleIdentifier"], [NSExpression expressionForKeyPath:@"header.executablePath"], [NSExpression expressionForKeyPath:@"header.executableVersion"], [NSExpression expressionForKeyPath:@"exceptionInformation.crashedThreadName"], [NSExpression expressionForKeyPath:@"header.operatingSystemVersion.stringValue"]]; NSPredicateEditorRowTemplate * tRowTemplate1 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:keyPaths rightExpressionAttributeType:NSStringAttributeType modifier:NSDirectPredicateModifier operators:@[@(NSEqualToPredicateOperatorType), @(NSNotEqualToPredicateOperatorType), @(NSBeginsWithPredicateOperatorType), @(NSEndsWithPredicateOperatorType), @(NSContainsPredicateOperatorType)] options:(NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption)]; // Row Template 2 NSPredicateEditorRowTemplate * tRowTemplate2 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:@[[NSExpression expressionForKeyPath:@"dateTime"]] rightExpressionAttributeType:NSDateAttributeType modifier:NSDirectPredicateModifier operators:@[@(NSLessThanOrEqualToPredicateOperatorType), @(NSGreaterThanOrEqualToPredicateOperatorType), ] options:(NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption)]; // Row Template 3 NSPredicateEditorRowTemplate * tRowTemplate3 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:@[[NSExpression expressionForKeyPath:@"exceptionType"]] rightExpressions:@[[NSExpression expressionForConstantValue:@"EXC_ARITHMETIC"], [NSExpression expressionForConstantValue:@"EXC_BAD_ACCESS"], [NSExpression expressionForConstantValue:@"EXC_BAD_INSTRUCTION"], [NSExpression expressionForConstantValue:@"EXC_BREAKPOINT"], [NSExpression expressionForConstantValue:@"EXC_CORPSE_NOTIFY"], [NSExpression expressionForConstantValue:@"EXC_CRASH"], [NSExpression expressionForConstantValue:@"EXC_EMULATION"], [NSExpression expressionForConstantValue:@"EXC_GUARD"], [NSExpression expressionForConstantValue:@"EXC_MACH_SYSCALL"], [NSExpression expressionForConstantValue:@"EXC_RESOURCE"], [NSExpression expressionForConstantValue:@"EXC_RPC_ALERT"], [NSExpression expressionForConstantValue:@"EXC_SOFTWARE"], [NSExpression expressionForConstantValue:@"EXC_SYSCALL"]] modifier:NSDirectPredicateModifier operators:@[@(NSEqualToPredicateOperatorType)] options:(NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption)]; // Row Template 4 NSPredicateEditorRowTemplate * tRowTemplate4 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:@[[NSExpression expressionForKeyPath:@"exceptionSignal"]] rightExpressions:@[[NSExpression expressionForConstantValue:@"SIGABRT"], [NSExpression expressionForConstantValue:@"SIGBUS"], [NSExpression expressionForConstantValue:@"SIGILL"], [NSExpression expressionForConstantValue:@"SIGKILL"], [NSExpression expressionForConstantValue:@"SIGQUIT"], [NSExpression expressionForConstantValue:@"SIGSEGV"], [NSExpression expressionForConstantValue:@"SIGTRAP"], [NSExpression expressionForConstantValue:@"Code Signature Invalid"], ] modifier:NSDirectPredicateModifier operators:@[@(NSEqualToPredicateOperatorType)] options:(NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption)]; // Row Template 5 keyPaths = @[[NSExpression expressionForKeyPath:@"crashLogFileName"]]; NSPredicateEditorRowTemplate * tRowTemplate5 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:keyPaths rightExpressionAttributeType:NSStringAttributeType modifier:NSDirectPredicateModifier operators:@[@(NSEqualToPredicateOperatorType), @(NSNotEqualToPredicateOperatorType), @(NSBeginsWithPredicateOperatorType), @(NSEndsWithPredicateOperatorType), @(NSContainsPredicateOperatorType)] options:(NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption)]; // Row Template 6 NSPredicateEditorRowTemplate * tRowTemplate6 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:@[[NSExpression expressionForKeyPath:@"reportSourceTypeNumber"]] rightExpressions:@[[NSExpression expressionForConstantValue:@(CUICrashLogReportSourceTypeUser)], [NSExpression expressionForConstantValue:@(CUICrashLogReportSourceTypeSystem)], [NSExpression expressionForConstantValue:@(CUICrashLogReportSourceTypeOther)]] modifier:NSDirectPredicateModifier operators:@[@(NSEqualToPredicateOperatorType)] options:(NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption)]; NSArray *compoundTypes = @[@(NSAndPredicateType), @(NSOrPredicateType)]; NSPredicateEditorRowTemplate * tRowTemplateCompound = [[NSPredicateEditorRowTemplate alloc] initWithCompoundTypes:compoundTypes]; _predicatorEditor.rowTemplates=@[tRowTemplate1, tRowTemplate2,tRowTemplate3,tRowTemplate4,tRowTemplate5,tRowTemplate6,tRowTemplateCompound]; // Default button if (self.prompt!=nil) { NSRect tButtonFrame=_defaultButton.frame; _defaultButton.title=self.prompt; [_defaultButton sizeToFit]; CGFloat tWidth=NSWidth(_defaultButton.frame); if (tWidthretainedWindowController=tWindowController; return tPanel; } #pragma mark - - (CUICrashLogsSourceSmart *)source { return retainedWindowController.source; } - (void)setSource:(CUICrashLogsSourceSmart *)inSource { retainedWindowController.source=inSource; } - (NSString *)prompt { return retainedWindowController.prompt; } - (void)setPrompt:(NSString *)inPrompt { retainedWindowController.prompt=inPrompt; } #pragma mark - - (void)_sheetDidEndSelector:(CUICrashLogsSourceSmartEditorPanel *)inPanel returnCode:(NSInteger)inReturnCode contextInfo:(void *)contextInfo { void(^handler)(NSInteger) = (__bridge_transfer void(^)(NSInteger)) contextInfo; if (handler!=nil) handler(inReturnCode); inPanel->retainedWindowController=nil; [inPanel orderOut:self]; } - (void)beginSheetModalForWindow:(NSWindow *)inWindow completionHandler:(void (^)(NSModalResponse bResponse))handler { [inWindow beginSheet:self completionHandler:^(NSModalResponse bResponse) { if (handler!=nil) handler(bResponse); self->retainedWindowController=nil; }]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceStandardDirectory+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceStandardDirectory.h" #import @interface CUICrashLogsSourceStandardDirectory (UI) - (NSImage *)icon; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceStandardDirectory+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceStandardDirectory+UI.h" @implementation CUICrashLogsSourceStandardDirectory (UI) - (NSImage *)icon { NSImage * tImage=nil; switch(self.domainMask) { case NSUserDomainMask: tImage=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SideBarHomeFolder.icns"]; break; case NSLocalDomainMask: tImage=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SidebarGenericFolder.icns"]; break; default: break; } [tImage setTemplate:YES]; return tImage; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceStandardDirectory.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceDirectory.h" @interface CUICrashLogsSourceStandardDirectory : CUICrashLogsSourceDirectory @property (readonly) NSSearchPathDomainMask domainMask; + (CUICrashLogsSourceStandardDirectory *)sourceDiagnosticReportsInDomain:(NSSearchPathDomainMask)inDomainMask error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceStandardDirectory.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceStandardDirectory.h" #import "CUICrashLogsProvider.h" @interface CUICrashLogsSourceStandardDirectory () @property NSSearchPathDomainMask domainMask; @end @implementation CUICrashLogsSourceStandardDirectory + (CUICrashLogsSourceStandardDirectory *)sourceDiagnosticReportsInDomain:(NSSearchPathDomainMask)inDomainMask error:(NSError **)outError { NSArray * tArray=NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, inDomainMask, YES); NSString * tPath=[tArray.firstObject stringByAppendingPathComponent:@"Logs/DiagnosticReports"]; CUICrashLogsSourceStandardDirectory * tSource=[[CUICrashLogsSourceStandardDirectory alloc] initWithContentsOfFileSystemItemAtPath:tPath collectRetired:YES error:outError]; if (tSource!=nil) { tSource.domainMask=inDomainMask; } return tSource; } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeStandardDirectory; } - (NSString *)name { switch(self.domainMask) { case NSUserDomainMask: return NSLocalizedString(@"User Reports", @""); case NSLocalDomainMask: return NSLocalizedString(@"System Reports", @""); default: break; } return @"Unknown domain"; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceTableCellView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICrashLogsSourceTableCellView : NSTableCellView @property (assign) IBOutlet NSTextField * countTextField; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceTableCellView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceTableCellView.h" @implementation CUICrashLogsSourceTableCellView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceToday+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceToday.h" #import @interface CUICrashLogsSourceToday (UI) @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceToday+UI.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceToday+UI.h" @implementation CUICrashLogsSourceToday (UI) - (NSImage *)icon { static NSImage * sIcon=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sIcon=[NSImage imageNamed:@"sidebar_recents_Template"]; sIcon.template=YES; }); return sIcon; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceToday.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceSmart.h" @interface CUICrashLogsSourceToday : CUICrashLogsSourceSmart @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourceToday.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourceToday.h" #import "CUICrashLogsSourceAll.h" @interface CUICrashLogsSourceSmart () - (void)sourceAllDidUpdateSource:(NSNotification *)inNotification; @end @interface CUICrashLogsSourceToday () { NSTimer * _timer; } @end @implementation CUICrashLogsSourceToday - (instancetype)init { self=[super init]; if (self!=nil) { self.predicate=[NSPredicate predicateWithFormat:@"numberOfHoursSinceCrash <= 24"]; _timer=[NSTimer scheduledTimerWithTimeInterval:60*60 repeats:YES block:^(NSTimer * _Nonnull timer) { NSNotification * tNotification=[NSNotification notificationWithName:CUICrashLogsSourceDidUpdateSourceNotification object:[CUICrashLogsSourceAll crashLogsSourceAll]]; [self sourceAllDidUpdateSource:tNotification]; }]; } return self; } - (void)dealloc { [_timer invalidate]; _timer=nil; } #pragma mark - - (CUICrashLogsSourceType)type { return CUICrashLogsSourceTypeToday; } - (NSString *)name { return NSLocalizedString(@"Recents",@""); } - (NSString *)sourceDescription { return NSLocalizedString(@"Reports from the last 24 hours",@""); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourcesManager.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogsSource.h" extern NSString * const CUICrashLogsSourcesManagerSourcesDidChangeNotification; @interface CUICrashLogsSourcesManager : NSObject @property (readonly) NSArray * allSources; + (CUICrashLogsSourcesManager *)sharedManager; - (NSArray *)sourcesOfType:(CUICrashLogsSourceType)inType; - (NSArray *)sourcesOfTypes:(NSSet *)inTypes; - (void)synchronizeDefaults; - (void)addSources:(NSArray *)inSources; - (void)moveSourcesAtIndexes:(NSIndexSet *)inOldIndexes toIndexes:(NSIndexSet *)inNewIndexes; - (void)removeSources:(NSArray *)inSources; - (void)sortCustomSourcesByName; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourcesManager.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourcesManager.h" #import "NSArray+WBExtensions.h" #import "CUICrashLogsSourceSeparator.h" #import "CUICrashLogsSourceFile.h" #import "CUICrashLogsSourceDirectory.h" #import "CUICrashLogsSourceStandardDirectory.h" #import "CUICrashLogsSourceSmart.h" #import "CUICrashLogsSourceAll.h" #import "CUICrashLogsSourceToday.h" NSString * const CUIDefaultsSourcesManagerCustomSourcesListKey=@"sources.custom"; NSString * const CUICrashLogsSourcesManagerSourcesDidChangeNotification=@"CUICrashLogsSourcesManagerSourcesDidChangeNotification"; @interface CUICrashLogsSourcesManager () { NSMutableArray * _sources; NSUInteger _customSourcesCount; } @end @implementation CUICrashLogsSourcesManager + (CUICrashLogsSourcesManager *)sharedManager { static CUICrashLogsSourcesManager * sSourcesManager=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [[NSUserDefaults standardUserDefaults] registerDefaults:@{CUIDefaultsSourcesManagerCustomSourcesListKey:@[]}]; sSourcesManager=[CUICrashLogsSourcesManager new]; }); return sSourcesManager; } #pragma mark - - (instancetype)init { self=[super init]; if (self!=nil) { _sources=[NSMutableArray array]; CUICrashLogsSourceAll * tSourceAll=[CUICrashLogsSourceAll crashLogsSourceAll]; if (tSourceAll==nil) { } else { [_sources addObject:tSourceAll]; } CUICrashLogsSourceToday * tSourceToday=[CUICrashLogsSourceToday new]; if (tSourceToday==nil) { } else { [_sources addObject:tSourceToday]; } NSError * tError=nil; // Current User Crash Logs CUICrashLogsSourceStandardDirectory * tUserCrashLogsSource=[CUICrashLogsSourceStandardDirectory sourceDiagnosticReportsInDomain:NSUserDomainMask error:&tError]; if (tUserCrashLogsSource==nil) { } else { [_sources addObject:tUserCrashLogsSource]; } // System User Crash Logs CUICrashLogsSourceStandardDirectory * tSystemCrashLogsSource=[CUICrashLogsSourceStandardDirectory sourceDiagnosticReportsInDomain:NSLocalDomainMask error:&tError]; if (tSystemCrashLogsSource==nil) { } else { [_sources addObject:tSystemCrashLogsSource]; } // Custom Sources NSArray * tCustomSourcesRepresentations=[[NSUserDefaults standardUserDefaults] objectForKey:CUIDefaultsSourcesManagerCustomSourcesListKey]; NSArray * tCustomSources=[tCustomSourcesRepresentations WB_arrayByMappingObjectsLenientlyUsingBlock:^id(NSDictionary * bRepresentation, NSUInteger bIndex) { NSNumber * tNumber=bRepresentation[CUICrashLogsSourceTypeKey]; if ([tNumber isKindOfClass:NSNumber.class]==NO) return nil; CUICrashLogsSourceType tType=[tNumber unsignedIntegerValue]; switch(tType) { case CUICrashLogsSourceTypeDirectory: return [[CUICrashLogsSourceDirectory alloc] initWithRepresentation:bRepresentation]; case CUICrashLogsSourceTypeFile: return [[CUICrashLogsSourceFile alloc] initWithRepresentation:bRepresentation]; case CUICrashLogsSourceTypeSmart: return [[CUICrashLogsSourceSmart alloc] initWithRepresentation:bRepresentation]; default: return nil; } }]; _customSourcesCount=tCustomSources.count; NSMutableArray * tMutableArray=[NSMutableArray arrayWithObjects:tUserCrashLogsSource,tSystemCrashLogsSource, nil]; if (_customSourcesCount>0) { [_sources addObject:[CUICrashLogsSourceSeparator separator]]; [_sources addObjectsFromArray:tCustomSources]; [tMutableArray addObjectsFromArray:tCustomSources]; } [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogsSourceDidAddSourcesNotification object:tMutableArray]; } return self; } #pragma mark - - (NSArray *)allSources { return _sources; } #pragma mark - - (NSArray *)sourcesOfType:(CUICrashLogsSourceType)inType { return [_sources WB_filteredArrayUsingBlock:^BOOL(CUICrashLogsSource * bSource, NSUInteger bIndex) { return (bSource.type==inType); }]; } - (NSArray *)sourcesOfTypes:(NSSet *)inTypes { return [_sources WB_filteredArrayUsingBlock:^BOOL(CUICrashLogsSource * bSource, NSUInteger bIndex) { return [inTypes containsObject:@(bSource.type)]; }]; } #pragma mark - - (void)synchronizeDefaults { NSArray * tCustomSourcesRepresentations=@[]; if (_customSourcesCount>0) { NSArray * tCustomSources=[_sources subarrayWithRange:NSMakeRange(_sources.count-_customSourcesCount, _customSourcesCount)]; tCustomSourcesRepresentations=[tCustomSources WB_arrayByMappingObjectsLenientlyUsingBlock:^id(CUICrashLogsSource * bSource, NSUInteger bIndex) { return [bSource representation]; }]; } [[NSUserDefaults standardUserDefaults] setObject:tCustomSourcesRepresentations forKey:CUIDefaultsSourcesManagerCustomSourcesListKey]; } - (void)addSources:(NSArray *)inSources { NSArray * tPossibleSources=[inSources WB_filteredArrayUsingBlock:^BOOL(CUICrashLogsSource * bSource, NSUInteger bIndex) { switch(bSource.type) { case CUICrashLogsSourceTypeDirectory: case CUICrashLogsSourceTypeFile: case CUICrashLogsSourceTypeSmart: return YES; default: return NO; } }]; if (tPossibleSources.count>0) { if (_customSourcesCount==0) [_sources addObject:[CUICrashLogsSourceSeparator separator]]; [_sources addObjectsFromArray:tPossibleSources]; _customSourcesCount+=tPossibleSources.count; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter postNotificationName:CUICrashLogsSourceDidAddSourcesNotification object:tPossibleSources]; [tNotificationCenter postNotificationName:CUICrashLogsSourcesManagerSourcesDidChangeNotification object:self]; [self synchronizeDefaults]; } } - (void)moveSourcesAtIndexes:(NSIndexSet *)inOldIndexes toIndexes:(NSIndexSet *)inNewIndexes { NSArray * tObjects=[_sources objectsAtIndexes:inOldIndexes]; [_sources removeObjectsAtIndexes:inOldIndexes]; [_sources insertObjects:tObjects atIndexes:inNewIndexes]; } - (void)removeSources:(NSArray *)inSources { NSArray * tPossibleSources=[inSources WB_filteredArrayUsingBlock:^BOOL(CUICrashLogsSource * bSource, NSUInteger bIndex) { switch(bSource.type) { case CUICrashLogsSourceTypeDirectory: case CUICrashLogsSourceTypeFile: case CUICrashLogsSourceTypeSmart: return YES; default: return NO; } }]; if (tPossibleSources.count>0) { [_sources removeObjectsInArray:tPossibleSources]; _customSourcesCount-=tPossibleSources.count; if (_customSourcesCount==0) [_sources removeObjectIdenticalTo:[CUICrashLogsSourceSeparator separator]]; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter postNotificationName:CUICrashLogsSourceDidRemoveSourcesNotification object:tPossibleSources]; [tNotificationCenter postNotificationName:CUICrashLogsSourcesManagerSourcesDidChangeNotification object:self]; [self synchronizeDefaults]; } } - (void)sortCustomSourcesByName { NSRange tCustomSourcesRange=NSMakeRange(5, _customSourcesCount); NSMutableArray * tSortableArray=[[_sources objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:tCustomSourcesRange]] mutableCopy]; [tSortableArray sortUsingComparator:^NSComparisonResult(CUICrashLogsSource * bSource1, CUICrashLogsSource * bSource2) { return [bSource1.name caseInsensitiveCompare:bSource2.name]; }]; [_sources removeObjectsInRange:tCustomSourcesRange]; [_sources addObjectsFromArray:tSortableArray]; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter postNotificationName:CUICrashLogsSourcesManagerSourcesDidChangeNotification object:self]; [self synchronizeDefaults]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourcesSelection.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogsSource.h" extern NSString * const CUICrashLogsSourcesSelectionDidChangeNotification; @interface CUICrashLogsSourcesSelection : NSObject @property (nonatomic) NSSet * sources; @property (nonatomic,readonly) NSArray * crashLogs; + (CUICrashLogsSourcesSelection *)sharedSourcesSelection; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourcesSelection.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourcesSelection.h" NSString * const CUICrashLogsSourcesSelectionDidChangeNotification=@"CUICrashLogsSourcesSelectionDidChangeNotification"; @implementation CUICrashLogsSourcesSelection + (CUICrashLogsSourcesSelection *)sharedSourcesSelection { static CUICrashLogsSourcesSelection * sSharedSourcesSelection=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSharedSourcesSelection=[CUICrashLogsSourcesSelection new]; }); return sSharedSourcesSelection; } #pragma mark - - (void)setSources:(NSSet *)inSources { if (_sources==inSources) return; _sources=inSources; [NSNotificationCenter.defaultCenter postNotificationName:CUICrashLogsSourcesSelectionDidChangeNotification object:self]; } - (NSArray *)crashLogs { NSMutableOrderedSet * tMutableOrderedSet=[NSMutableOrderedSet orderedSet]; [self.sources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, BOOL * bOutStop) { NSArray * tCrashLogs=bSource.crashLogs; if (tCrashLogs!=nil) [tMutableOrderedSet addObjectsFromArray:tCrashLogs]; }]; return [tMutableOrderedSet array]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourcesViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIKeyViews.h" @interface CUICrashLogsSourcesViewController : NSViewController @property (readonly) NSTableView * tableView; @property (nonatomic,readonly) NSRect effectiveBottonBarRect; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashLogsSourcesViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashLogsSourcesViewController.h" #import "CUICrashLogsSource.h" #import "CUICrashLogsSourceSeparator.h" #import "CUICrashLogsSourceAll.h" #import "CUICrashLogsSourceFileSystemItem.h" #import "CUICrashLogsSourceFile.h" #import "CUICrashLogsSourceDirectory.h" #import "CUICrashLogsSource+UI.h" #import "CUICrashLogsSourcesManager.h" #import "CUICrashLogsSourcesSelection.h" #import "NSTableView+Selection.h" #import "NSArray+WBExtensions.h" #import "NSIndexSet+Analysis.h" #import "CUICrashLogsSourceTableCellView.h" #import "CUICrashLogsSourceSmartEditorPanel.h" #import "NSArray+UniqueName.h" #import "CUICrashLogsOpenErrorPanel.h" NSString * const CUICrashLogsSourcesInternalPboardType=@"fr.whitebox.unexpectedly.sources.internal.array"; @interface CUICrashLogsSourcesViewController () { IBOutlet NSTableView * _tableView; IBOutlet NSButton * _removeButton; IBOutlet NSPopUpButton * _actionPopUpButton; CUICrashLogsSourcesManager * _sourcesManager; CUICrashLogsSourcesSelection * _sourcesSelection; NSIndexSet * _internalDragData; NSSet * _openPanelExistingSingleFiles; NSSet * _openPanelExistingDirectories; } - (IBAction)tableViewDoubleAction:(id)sender; - (IBAction)takeSourceNameFrom:(id)sender; - (IBAction)CUI_MENUACTION_addSource:(id)sender; - (IBAction)CUI_MENUACTION_addSmartSource:(id)sender; - (IBAction)editSmartSource:(id)sender; - (IBAction)CUI_MENUACTION_importSmartSource:(id)sender; - (IBAction)CUI_MENUACTION_exportSmartSource:(id)sender; - (IBAction)removeSources:(id)sender; - (IBAction)showInFinder:(id)sender; - (IBAction)sortByName:(id)sender; // Notifications - (void)sourcesManagerSourcesDidChange:(NSNotification *)inNotification; - (void)sourceDidUpdateSource:(NSNotification *)inNotification; - (void)sourcesSelectionDidChange:(NSNotification *)inNotification; @end @implementation CUICrashLogsSourcesViewController - (instancetype)init { self=[super init]; if (self!=nil) { _sourcesManager=[CUICrashLogsSourcesManager sharedManager]; _sourcesSelection=[CUICrashLogsSourcesSelection sharedSourcesSelection]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSString *)nibName { return @"CUICrashLogsSourcesViewController"; } - (void)viewDidLoad { [super viewDidLoad]; _tableView.doubleAction=@selector(tableViewDoubleAction:); [_tableView registerForDraggedTypes:@[NSPasteboardTypeFileURL,CUICrashLogsSourcesInternalPboardType]]; _removeButton.enabled=NO; NSUInteger tIndex=0; if (_sourcesSelection.sources.count>0) { tIndex=[_sourcesManager.allSources indexOfObject:_sourcesSelection.sources.allObjects.firstObject]; } [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tIndex] byExtendingSelection:NO]; // Register for notifications NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(sourcesManagerSourcesDidChange:) name:CUICrashLogsSourcesManagerSourcesDidChangeNotification object:_sourcesManager]; [tNotificationCenter addObserver:self selector:@selector(sourceDidUpdateSource:) name:CUICrashLogsSourceDidUpdateSourceNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(sourcesSelectionDidChange:) name:CUICrashLogsSourcesSelectionDidChangeNotification object:_sourcesSelection]; [self tableViewSelectionDidChange:[NSNotification notificationWithName:NSTableViewSelectionDidChangeNotification object:_tableView userInfo:nil]]; } - (void)viewDidAppear { [super viewDidAppear]; } #pragma mark - - (NSRect)effectiveBottonBarRect { NSRect tEffectiveRect; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tEffectiveRect.origin.x=NSMaxX(_removeButton.frame); tEffectiveRect.size.width=NSMinX(_actionPopUpButton.frame)-tEffectiveRect.origin.x; tEffectiveRect.origin.y=NSHeight(_tableView.enclosingScrollView.frame); tEffectiveRect.size.height=NSMinY(_tableView.enclosingScrollView.frame); } else { tEffectiveRect.origin.x=NSMaxX(_actionPopUpButton.frame); tEffectiveRect.size.width=NSMinX(_removeButton.frame)-tEffectiveRect.origin.x; tEffectiveRect.origin.y=NSHeight(_tableView.enclosingScrollView.frame); tEffectiveRect.size.height=NSMinY(_tableView.enclosingScrollView.frame); } return tEffectiveRect; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; NSIndexSet * tSelectedRows=[_tableView WB_selectedOrClickedRowIndexes]; if (tAction==@selector(delete:)) { if (tSelectedRows.count==0) return NO; __block BOOL tSourcesCanBeDeleted=YES; NSArray * tSelectedSources=[_sourcesManager.allSources objectsAtIndexes:tSelectedRows]; [tSelectedSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { switch(bSource.type) { case CUICrashLogsSourceTypeAll: case CUICrashLogsSourceTypeStandardDirectory: case CUICrashLogsSourceTypeToday: tSourcesCanBeDeleted=NO; break; default: break; } }]; return tSourcesCanBeDeleted; } if (tAction==@selector(editSmartSource:)) { __block BOOL tCanEdit=YES; [_sourcesManager.allSources enumerateObjectsAtIndexes:tSelectedRows options:0 usingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { if ([bSource isMemberOfClass:[CUICrashLogsSourceSmart class]]==NO) { tCanEdit=NO; *bOutStop=YES; } }]; return tCanEdit; } if (tAction==@selector(CUI_MENUACTION_exportSmartSource:)) { __block BOOL tCanExport=YES; [_sourcesManager.allSources enumerateObjectsAtIndexes:tSelectedRows options:0 usingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { if ([bSource isMemberOfClass:[CUICrashLogsSourceSmart class]]==NO) { tCanExport=NO; *bOutStop=YES; } }]; return tCanExport; } if (tAction==@selector(showInFinder:)) { __block BOOL tCanShowInFinder=YES; [_sourcesManager.allSources enumerateObjectsAtIndexes:tSelectedRows options:0 usingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { if ([bSource isKindOfClass:[CUICrashLogsSourceFileSystemItem class]]==NO) { tCanShowInFinder=NO; *bOutStop=YES; } }]; return tCanShowInFinder; } if (tAction==@selector(sortByName:)) { if (tSelectedRows.count==0) return NO; NSArray * tSelectedSources=[_sourcesManager.allSources objectsAtIndexes:tSelectedRows]; __block NSUInteger tNumberOfCustomSources=0; [tSelectedSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { switch(bSource.type) { case CUICrashLogsSourceTypeDirectory: case CUICrashLogsSourceTypeFile: case CUICrashLogsSourceTypeSmart: tNumberOfCustomSources++; break; default: break; } }]; return (tNumberOfCustomSources>=1); } return YES; } - (IBAction)delete:(id)sender { [self removeSources:sender]; } - (IBAction)tableViewDoubleAction:(id)sender { NSIndexSet * tSelectedRows=[_tableView WB_selectedOrClickedRowIndexes]; NSArray * tArray=[_sourcesManager.allSources objectsAtIndexes:tSelectedRows]; CUICrashLogsSourceSmart * tSmartSource=tArray.firstObject; if (tSmartSource.type!=CUICrashLogsSourceTypeSmart) return; [self editSmartSource:sender]; } - (IBAction)takeSourceNameFrom:(NSTextField *)sender { NSInteger tEditedRow=[_tableView rowForView:sender]; if (tEditedRow==-1) return; NSString * tNewName=sender.stringValue; CUICrashLogsSourceSmart * tSourceSmart=(CUICrashLogsSourceSmart *)_sourcesManager.allSources[tEditedRow]; // Avoid replacing with the same name if ([tNewName isEqualToString:tSourceSmart.name]==YES) return; // Avoid empty Name if (tNewName.length==0) { [_tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:tEditedRow] columnIndexes:[NSIndexSet indexSetWithIndex:0]]; return; } // Avoid duplicate names NSArray * tAllSmartSourcesNames=[[_sourcesManager sourcesOfType:CUICrashLogsSourceTypeSmart] WB_arrayByMappingObjectsUsingBlock:^NSString *(CUICrashLogsSourceSmart * bSmartSource, NSUInteger bIndex) { return bSmartSource.name; }]; if ([tAllSmartSourcesNames containsObject:tNewName]==YES) { NSAlert * tAlert=[NSAlert new]; tAlert.alertStyle=NSAlertStyleCritical; tAlert.messageText=[NSString stringWithFormat:NSLocalizedString(@"The name \"%@\" is already taken.",@""),tNewName]; tAlert.informativeText=NSLocalizedString(@"Please choose a different name.",@""); [tAlert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse returnCode) { [self->_tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:tEditedRow] columnIndexes:[NSIndexSet indexSetWithIndex:0]]; [self->_tableView editColumn:0 row:tEditedRow withEvent:nil select:YES]; }]; return; } tSourceSmart.name=tNewName; [_sourcesManager synchronizeDefaults]; } - (IBAction)CUI_MENUACTION_addSource:(id)sender { NSOpenPanel * tOpenPanel=[NSOpenPanel openPanel]; tOpenPanel.canChooseFiles=YES; tOpenPanel.canChooseDirectories=YES; tOpenPanel.allowsMultipleSelection=YES; tOpenPanel.prompt=NSLocalizedString(@"Add", @""); //tOpenPanel.allowedFileTypes=@[@".crash"]; tOpenPanel.delegate=self; NSMutableArray * tOpenErrors=[NSMutableArray array]; CUICrashLogsSourceAll * tSourcesAll=[CUICrashLogsSourceAll crashLogsSourceAll]; _openPanelExistingSingleFiles=[NSSet setWithArray:[tSourcesAll.crashLogs WB_arrayByMappingObjectsLenientlyUsingBlock:^id(CUICrashLog *bCrashLog, NSUInteger bIndex) { return bCrashLog.crashLogFilePath; }]]; _openPanelExistingDirectories=[NSSet setWithArray:[self->_sourcesManager.allSources WB_arrayByMappingObjectsLenientlyUsingBlock:^id(CUICrashLogsSourceDirectory *bCrashSource, NSUInteger bIndex) { if ([bCrashSource isKindOfClass:[CUICrashLogsSourceDirectory class]]==NO) return nil; return bCrashSource.path; }]]; [tOpenPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse bReturnCode) { self->_openPanelExistingSingleFiles=nil; self->_openPanelExistingDirectories=nil; if (bReturnCode==NSModalResponseCancel) return; NSMutableArray * tNewSources=[NSMutableArray array]; for(NSURL * tURL in tOpenPanel.URLs) { if (tURL.isFileURL==NO) continue; BOOL tIsDirectory; if ([[NSFileManager defaultManager] fileExistsAtPath:tURL.path isDirectory:&tIsDirectory]==NO) continue; CUICrashLogsSource * tSource=nil; NSError * tError=nil; if (tIsDirectory==NO) { tSource=[[CUICrashLogsSourceFile alloc] initWithContentsOfFileSystemItemAtPath:tURL.path error:&tError]; } else { tSource=[[CUICrashLogsSourceDirectory alloc] initWithContentsOfFileSystemItemAtPath:tURL.path error:NULL]; // Check if the directory is not already a source // A COMPLETER } if (tSource==nil) { if (tIsDirectory==NO && tError!=nil) { CUICrashLogsOpenErrorRecord * tRecord=[CUICrashLogsOpenErrorRecord new]; tRecord.sourceURL=tURL; tRecord.openError=tError; [tOpenErrors addObject:tRecord]; } continue; } if (tSource!=nil) [tNewSources addObject:tSource]; } [self->_sourcesManager addSources:tNewSources]; [self->_tableView reloadData]; [self->_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:self->_sourcesManager.allSources.count-1] byExtendingSelection:NO]; if (tOpenErrors.count>0) { NSBeep(); dispatch_async(dispatch_get_main_queue(), ^{ CUICrashLogsOpenErrorPanel * tErrorPanel=[CUICrashLogsOpenErrorPanel crashLogsOpenErrorPanel]; tErrorPanel.errors=tOpenErrors; [tErrorPanel runModal]; }); } }]; } - (IBAction)CUI_MENUACTION_addSmartSource:(id)sender { CUICrashLogsSourceSmartEditorPanel * tEditorPanel=[CUICrashLogsSourceSmartEditorPanel crashLogsSourceSmartEditorPanel]; tEditorPanel.source=[CUICrashLogsSourceSmart new]; tEditorPanel.prompt=NSLocalizedString(@"Add",@""); [tEditorPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse bResponse) { if (bResponse==NSModalResponseCancel) return; [self->_sourcesManager addSources:@[tEditorPanel.source]]; [self->_tableView reloadData]; [self->_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:self->_sourcesManager.allSources.count-1] byExtendingSelection:NO]; }]; } - (IBAction)editSmartSource:(id)sender { CUICrashLogsSourceSmartEditorPanel * tEditorPanel=[CUICrashLogsSourceSmartEditorPanel crashLogsSourceSmartEditorPanel]; NSIndexSet * tSelectedRows=[_tableView WB_selectedOrClickedRowIndexes]; NSArray * tArray=[_sourcesManager.allSources objectsAtIndexes:tSelectedRows]; tEditorPanel.source=tArray.firstObject; tEditorPanel.prompt=NSLocalizedString(@"OK",@""); [tEditorPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse bResponse) { if (bResponse==NSModalResponseCancel) return; [self->_tableView reloadDataForRowIndexes:tSelectedRows columnIndexes:[NSIndexSet indexSetWithIndex:0]]; [self->_sourcesManager synchronizeDefaults]; }]; } - (IBAction)CUI_MENUACTION_importSmartSource:(id)sender { NSOpenPanel * tImportPanel=[NSOpenPanel openPanel]; tImportPanel.resolvesAliases=YES; tImportPanel.canChooseFiles=YES; //tImportPanel.allowsMultipleSelection=YES; tImportPanel.canCreateDirectories=NO; tImportPanel.prompt=NSLocalizedString(@"Import", @""); //tImportPanel.delegate=self; [tImportPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger bResult){ if (bResult!=NSModalResponseOK) return; NSArray * tExistingSmartSources=[self->_sourcesManager sourcesOfType:CUICrashLogsSourceTypeSmart]; NSArray * tSmartSources=[tImportPanel.URLs WB_arrayByMappingObjectsLenientlyUsingBlock:^CUICrashLogsSourceSmart *(NSURL * bURL, NSUInteger bIndex) { NSDictionary * tDictionary=[NSDictionary dictionaryWithContentsOfURL:tImportPanel.URL]; if (tDictionary==nil) { NSLog(@"Import Smart Source failure: the selected file is not a property list file."); return nil; } CUICrashLogsSourceSmart * tSmartSource=[[CUICrashLogsSourceSmart alloc] initWithRepresentation:tDictionary]; if (tSmartSource==nil) { NSLog(@"Import Smart Source failure: the selected property list file is not a smart source file."); return nil; } NSString * tUniqueSourceName=[tExistingSmartSources uniqueNameWithBaseName:tSmartSource.name usingNameExtractor:^NSString *(CUICrashLogsSourceSmart * bSmartSource, NSUInteger bIndex) { return bSmartSource.name; }]; if (tUniqueSourceName==nil) { NSLog(@"Import Smart Source failure: a smart source with this name already exists."); // A COMPLETER return nil; } tSmartSource.name=tUniqueSourceName; return tSmartSource; }]; [self->_sourcesManager addSources:tSmartSources]; [self->_tableView reloadData]; [self->_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:self->_sourcesManager.allSources.count-1] byExtendingSelection:NO]; }]; } - (IBAction)CUI_MENUACTION_exportSmartSource:(id)sender { NSIndexSet * tIndexSet=[_tableView WB_selectedOrClickedRowIndexes]; if (tIndexSet.count!=1) return; CUICrashLogsSourceSmart * tSource=_sourcesManager.allSources[tIndexSet.firstIndex]; NSDictionary * tRepresentation=[tSource representation]; if (tRepresentation==nil) return; NSSavePanel * tExportPanel=[NSSavePanel savePanel]; tExportPanel.canSelectHiddenExtension=YES; tExportPanel.allowedFileTypes=@[@"fr.whitebox.unexpectedly.smartSource"]; tExportPanel.nameFieldLabel=NSLocalizedString(@"Export As:", @""); tExportPanel.nameFieldStringValue=tSource.name; tExportPanel.prompt=NSLocalizedString(@"Export", @""); [tExportPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger bResult){ if (bResult!=NSModalResponseOK) return; NSError * tError=nil; if ([tRepresentation writeToURL:tExportPanel.URL error:&tError]==NO) { NSBeep(); NSLog(@"%@",tError.description); // A COMPLETER } }]; } - (IBAction)removeSources:(id)sender { NSIndexSet * tSelectedRows=[_tableView WB_selectedOrClickedRowIndexes]; NSUInteger tSelectionLastIndex=tSelectedRows.lastIndex; CUICrashLogsSource * tNextSelectedSource=nil; if ((tSelectionLastIndex+1)!=_sourcesManager.allSources.count) tNextSelectedSource=_sourcesManager.allSources[tSelectionLastIndex+1]; NSArray * tArray=[_sourcesManager.allSources objectsAtIndexes:tSelectedRows]; [_sourcesManager removeSources:tArray]; [_tableView reloadData]; // Select the row before the last selected one or select the last row NSUInteger tNewSelectedIndex=NSNotFound; if (tNextSelectedSource!=nil) tNewSelectedIndex=[_sourcesManager.allSources indexOfObject:tNextSelectedSource]; if (tNewSelectedIndex==NSNotFound) tNewSelectedIndex=_sourcesManager.allSources.count-1; [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tNewSelectedIndex] byExtendingSelection:NO]; } - (IBAction)showInFinder:(id)sender { NSIndexSet * tSelectedRows=[_tableView WB_selectedOrClickedRowIndexes]; [_sourcesManager.allSources enumerateObjectsAtIndexes:tSelectedRows options:0 usingBlock:^(CUICrashLogsSourceFileSystemItem * bSource, NSUInteger bIndex, BOOL * bOutStop) { [[NSWorkspace sharedWorkspace] selectFile:bSource.path inFileViewerRootedAtPath:@""]; }]; } - (IBAction)sortByName:(id)sender { [_sourcesManager sortCustomSourcesByName]; } #pragma mark - NSTableViewDataSource - (NSInteger)numberOfRowsInTableView:(NSTableView *)inTableView { return _sourcesManager.allSources.count; } #pragma mark - NSTableViewDelegate - (NSView *)tableView:(NSTableView *)inTableView viewForTableColumn:(NSTableColumn *)inTableColumn row:(NSInteger)inRow { CUICrashLogsSource * tSource=_sourcesManager.allSources[inRow]; if (tSource.type==CUICrashLogsSourceTypeSeparator) { return [inTableView makeViewWithIdentifier:@"separator" owner:self]; } CUICrashLogsSourceTableCellView * tTableCellView=(CUICrashLogsSourceTableCellView *)[inTableView makeViewWithIdentifier:@"regular" owner:self]; tTableCellView.imageView.image=tSource.icon; tTableCellView.textField.editable=(tSource.type==CUICrashLogsSourceTypeSmart); tTableCellView.textField.stringValue=tSource.name; tTableCellView.toolTip=tSource.sourceDescription; tTableCellView.countTextField.stringValue=[NSString stringWithFormat:@"%lu",tSource.crashLogs.count]; return tTableCellView; } - (CGFloat)tableView:(NSTableView *)inTableView heightOfRow:(NSInteger)inRow { CUICrashLogsSource * tSource=_sourcesManager.allSources[inRow]; if (tSource.type==CUICrashLogsSourceTypeSeparator) return 12.0; return 24.0; } - (BOOL)tableView:(NSTableView *)inTableView shouldSelectRow:(NSInteger)inRow { CUICrashLogsSource * tSource=_sourcesManager.allSources[inRow]; return (tSource.type!=CUICrashLogsSourceTypeSeparator); } #pragma mark - Drag and Drop support - (BOOL)tableView:(NSTableView *)inTableView writeRowsWithIndexes:(NSIndexSet *)inRowIndexes toPasteboard:(NSPasteboard *)inPasteboard { for(CUICrashLogsSource * tSource in [_sourcesManager.allSources objectsAtIndexes:inRowIndexes]) { switch(tSource.type) { case CUICrashLogsSourceTypeUnknown: case CUICrashLogsSourceTypeAll: case CUICrashLogsSourceTypeStandardDirectory: case CUICrashLogsSourceTypeToday: case CUICrashLogsSourceTypeSeparator: return NO; default: break; } } _internalDragData=inRowIndexes; [inPasteboard declareTypes:@[CUICrashLogsSourcesInternalPboardType] owner:self]; [inPasteboard setData:[NSData data] forType:CUICrashLogsSourcesInternalPboardType]; return YES; } - (NSDragOperation)tableView:(NSTableView *)inTableView validateDrop:(id )info proposedRow:(NSInteger)inRow proposedDropOperation:(NSTableViewDropOperation)inDropOperation { if (inDropOperation==NSTableViewDropOn) return NSDragOperationNone; NSPasteboard * tPasteBoard=[info draggingPasteboard]; // Internal Drag if ([tPasteBoard availableTypeFromArray:@[CUICrashLogsSourcesInternalPboardType]]!=nil && [info draggingSource]==inTableView) { NSUInteger tSeparatorRow=[_sourcesManager.allSources indexOfObject:[CUICrashLogsSourceSeparator separator]]; if (tSeparatorRow==NSNotFound) return NSDragOperationNone; if (inRow<=tSeparatorRow) return NSDragOperationNone; if ([_internalDragData WB_containsOnlyOneRange]==YES) { NSUInteger tFirstIndex=_internalDragData.firstIndex; NSUInteger tLastIndex=_internalDragData.lastIndex; if (inRow>=tFirstIndex && inRow<=(tLastIndex+1)) return NSDragOperationNone; } else { if ([_internalDragData containsIndex:(inRow-1)]==YES) return NSDragOperationNone; } return NSDragOperationMove; } if ([tPasteBoard availableTypeFromArray:@[NSPasteboardTypeFileURL]]!=nil) { NSArray *tClasses = @[NSURL.class]; NSArray *tURLArray = [tPasteBoard readObjectsForClasses:tClasses options:@{NSPasteboardURLReadingFileURLsOnlyKey:@(YES)}]; CUICrashLogsSourceAll * tSourcesAll=[CUICrashLogsSourceAll crashLogsSourceAll]; for (NSURL *tURL in tURLArray) { NSNumber *tIsDirectoryNumber; if ([tURL getResourceValue:&tIsDirectoryNumber forKey:NSURLIsDirectoryKey error:NULL]==NO) continue; NSString *tPath=tURL.path; if (tIsDirectoryNumber.boolValue==YES) { // Do not have the same directory twice for(CUICrashLogsSource * tSource in _sourcesManager.allSources) { switch(tSource.type) { case CUICrashLogsSourceTypeStandardDirectory: case CUICrashLogsSourceTypeDirectory: { CUICrashLogsSourceDirectory * tSourceFile=(CUICrashLogsSourceDirectory *)tSource; if ([tSourceFile.path isEqualToString:tPath]==YES) return NSDragOperationNone; break; } default: break; } } } else { // Should have .crash or .smartsource extension NSString *tExtension=tPath.pathExtension; if ([tExtension caseInsensitiveCompare:@"crash"]==NSOrderedSame || [tExtension caseInsensitiveCompare:@"ips"]==NSOrderedSame) { // Do not have the same file twice (as a single file source) for(CUIRawCrashLog * tCrashLog in tSourcesAll.crashLogs) { if ([tCrashLog.crashLogFilePath isEqualToString:tPath]==YES) return NSDragOperationNone; } } else { if ([tExtension caseInsensitiveCompare:@"smartsource"]!=NSOrderedSame) return NSDragOperationNone; } } } [inTableView setDropRow:-1 dropOperation:NSTableViewDropOn]; return NSDragOperationCopy; } return NSDragOperationNone; } - (BOOL)tableView:(NSTableView *)inTableView acceptDrop:(id )info row:(NSInteger)inRow dropOperation:(NSTableViewDropOperation)inDropOperation { if (inTableView!=_tableView) return NO; // Internal drag and drop NSPasteboard * tPasteBoard=[info draggingPasteboard]; if ([tPasteBoard availableTypeFromArray:@[CUICrashLogsSourcesInternalPboardType]]!=nil && [info draggingSource]==inTableView) { //NSArray * tObjects=[_sourcesManager.allSources objectsAtIndexes:_internalDragData]; NSUInteger tIndex=[_internalDragData firstIndex]; while (tIndex!=NSNotFound) { if (tIndex *tClasses = @[NSURL.class]; NSArray *tURLArray = [tPasteBoard readObjectsForClasses:tClasses options:@{NSPasteboardURLReadingFileURLsOnlyKey:@(YES)}]; NSMutableArray * tDelayedSmartSources=[NSMutableArray array]; NSMutableArray * tOpenErrors=[NSMutableArray array]; NSArray * tNewSources=[tURLArray WB_arrayByMappingObjectsLenientlyUsingBlock:^id(NSURL * bURL, NSUInteger bIndex) { CUICrashLogsSource * tSource=nil; NSNumber *tIsDirectoryNumber; if ([bURL getResourceValue:&tIsDirectoryNumber forKey:NSURLIsDirectoryKey error:NULL]==NO) return nil; NSError * tError; if (tIsDirectoryNumber.boolValue==NO) { NSString * tPathExtension=bURL.pathExtension; if ([tPathExtension caseInsensitiveCompare:@"crash"]==NSOrderedSame || [tPathExtension caseInsensitiveCompare:@"ips"]==NSOrderedSame) { tSource=[[CUICrashLogsSourceFile alloc] initWithContentsOfFileSystemItemAtPath:bURL.path error:&tError]; if (tSource==nil) { CUICrashLogsOpenErrorRecord * tRecord=[CUICrashLogsOpenErrorRecord new]; tRecord.sourceURL=bURL; tRecord.openError=tError; [tOpenErrors addObject:tRecord]; } } else if ([tPathExtension caseInsensitiveCompare:@"smartsource"]==NSOrderedSame) { NSDictionary * tRepresentation=[NSDictionary dictionaryWithContentsOfURL:bURL error:NULL]; if (tRepresentation==nil) { // A COMPLETER return nil; } tSource=[[CUICrashLogsSourceSmart alloc] initWithRepresentation:tRepresentation]; if (tSource==nil) { // A COMLETER return nil; } // Check that the name is not already used and offer to use a unique name NSString * tName=tSource.name; if (tName.length==0) { // A COMPLETER return nil; } NSArray * tExistingSmartSources=[[CUICrashLogsSourcesManager sharedManager] sourcesOfType:CUICrashLogsSourceTypeSmart]; for(CUICrashLogsSourceSmart * tSmartSource in tExistingSmartSources) { if ([tSmartSource.name isEqualToString:tName]==YES) { [tDelayedSmartSources addObject:tSource]; return nil; } } } } else { tSource=[[CUICrashLogsSourceDirectory alloc] initWithContentsOfFileSystemItemAtPath:bURL.path error:&tError]; } return tSource; }]; if (tOpenErrors.count>0) { NSBeep(); dispatch_async(dispatch_get_main_queue(), ^{ CUICrashLogsOpenErrorPanel * tErrorPanel=[CUICrashLogsOpenErrorPanel crashLogsOpenErrorPanel]; tErrorPanel.errors=tOpenErrors; [tErrorPanel runModal]; }); } if (tNewSources.count==0 && tDelayedSmartSources.count==0) return NO; if (tNewSources.count>0) { [_tableView deselectAll:nil]; [_sourcesManager addSources:tNewSources]; [_tableView reloadData]; [_tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_sourcesManager.allSources.count-1] byExtendingSelection:NO]; } if (tDelayedSmartSources.count==0) { // Handle collisions // A COMPLETER } return YES; } return NO; } - (void)tableView:(NSTableView *)inTableView draggingSession:(NSDraggingSession *)inDraggingSession endedAtPoint:(NSPoint)inScreenPoint operation:(NSDragOperation)inOperation { _internalDragData=nil; } #pragma mark - NSOpenSavePanelDelegate - (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)inURL { if (inURL==nil) return NO; if (inURL.isFileURL==NO) return NO; if (inURL.hasDirectoryPath==NO) { NSString * tPathExtension=inURL.pathExtension; if ([tPathExtension caseInsensitiveCompare:@"crash"]!=NSOrderedSame && [tPathExtension caseInsensitiveCompare:@"ips"]!=NSOrderedSame) return NO; if ([_openPanelExistingSingleFiles containsObject:inURL.path]==YES) return NO; } else { if ([_openPanelExistingDirectories containsObject:inURL.path]==YES) return NO; } return YES; } #pragma mark - CUIKeyViews - (NSView *)firstKeyView { return _tableView; } - (NSView *)lastKeyView { return _tableView; } #pragma mark - - (void)tableViewSelectionDidChange:(NSNotification *)inNotification { NSIndexSet * tIndexSet=[_tableView selectedRowIndexes]; if (tIndexSet.count==0) { _removeButton.enabled=NO; _sourcesSelection.sources=[NSSet set]; } else { __block BOOL tSourcesCanBeDeleted=YES; NSArray * tSelectedSources=[_sourcesManager.allSources objectsAtIndexes:tIndexSet]; [tSelectedSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { switch(bSource.type) { case CUICrashLogsSourceTypeAll: case CUICrashLogsSourceTypeStandardDirectory: case CUICrashLogsSourceTypeToday: tSourcesCanBeDeleted=NO; break; default: break; } }]; _removeButton.enabled=tSourcesCanBeDeleted; _sourcesSelection.sources=[[NSSet alloc] initWithArray:tSelectedSources]; } } - (void)sourcesManagerSourcesDidChange:(NSNotification *)inNotification { NSSet * tOldSources=_sourcesSelection.sources; [_tableView reloadData]; // Refresh Selection NSMutableIndexSet * tIndexSet=[NSMutableIndexSet indexSet]; [_sourcesManager.allSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { if ([tOldSources containsObject:bSource]==YES) [tIndexSet addIndex:bIndex]; }]; if (tIndexSet.count==0) { [tIndexSet addIndex:0]; } _sourcesSelection.sources=[[NSSet alloc] initWithArray:[_sourcesManager.allSources objectsAtIndexes:tIndexSet]]; [_tableView selectRowIndexes:tIndexSet byExtendingSelection:NO]; } - (void)sourceDidUpdateSource:(NSNotification *)inNotification { CUICrashLogsSource * tSource=(CUICrashLogsSource *)inNotification.object; if ([tSource isKindOfClass:[CUICrashLogsSource class]]==NO) return; NSUInteger tIndex=[_sourcesManager.allSources indexOfObject:tSource]; if (tIndex==NSNotFound) return; [_tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:tIndex] columnIndexes:[NSIndexSet indexSetWithIndex:0]]; } - (void)sourcesSelectionDidChange:(NSNotification *)inNotification { NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; // Stop observing [tNotificationCenter removeObserver:self name:CUICrashLogsSourcesSelectionDidChangeNotification object:_sourcesSelection]; // Refresh Selection NSMutableIndexSet * tIndexSet=[NSMutableIndexSet indexSet]; [_sourcesManager.allSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { if ([self->_sourcesSelection.sources containsObject:bSource]==YES) [tIndexSet addIndex:bIndex]; }]; if (tIndexSet.count!=_sourcesManager.allSources.count) { if (tIndexSet.count==0) [tIndexSet addIndex:0]; _sourcesSelection.sources=[[NSSet alloc] initWithArray:[_sourcesManager.allSources objectsAtIndexes:tIndexSet]]; } [_tableView selectRowIndexes:tIndexSet byExtendingSelection:NO]; // Restore observation [tNotificationCenter addObserver:self selector:@selector(sourcesSelectionDidChange:) name:CUICrashLogsSourcesSelectionDidChangeNotification object:_sourcesSelection]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashReporterDefaults.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_ENUM(NSUInteger, CUICrashReporterDialogType) { CUICrashReporterDialogTypeBasic, CUICrashReporterDialogTypeDeveloper, CUICrashReporterDialogTypeServer, }; typedef NS_ENUM(NSUInteger, CUICrashReporterNotificationMode) { CUICrashReporterNotificationModeDialog, CUICrashReporterNotificationModeUserNotification, }; @interface CUICrashReporterDefaults : NSObject @property (nonatomic) CUICrashReporterDialogType dialogType; @property (nonatomic) CUICrashReporterNotificationMode notificationMode; @property (nonatomic) BOOL reportUncaughtExceptions; + (CUICrashReporterDefaults *)standardCrashReporterDefaults; - (void)refresh; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashReporterDefaults.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashReporterDefaults.h" NSString * const CUICrashReporterBundleIdentifier=@"com.apple.CrashReporter"; NSString * const CUICrashReporterDefaultsDialogTypeKey=@"DialogType"; NSString * const CUICrashReporterDefaultsNotificationModeKey=@"UseUNC"; NSString * const CUICrashReporterDefaultsReportUncaughtExceptionKey=@"NSApplicationShowExceptions"; @interface CUICrashReporterDefaults () + (CUICrashReporterDialogType)dialogTypeFromString:(NSString *)inString; + (NSString *)stringFromDialogType:(CUICrashReporterDialogType)inDialogType; - (void)refresh; // Notifications - (void)applicationDidBecomeActive:(NSNotification *)inNotification; @end @implementation CUICrashReporterDefaults + (CUICrashReporterDefaults *)standardCrashReporterDefaults { static CUICrashReporterDefaults * sCrashReporterDefaults=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sCrashReporterDefaults=[CUICrashReporterDefaults new]; }); return sCrashReporterDefaults; } + (CUICrashReporterDialogType)dialogTypeFromString:(NSString *)inString { if ([inString isKindOfClass:NSString.class]==NO) return CUICrashReporterDialogTypeBasic; static NSDictionary * sStringToEnumDictionary=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sStringToEnumDictionary=@{ @"basic":@(CUICrashReporterDialogTypeBasic), @"developer":@(CUICrashReporterDialogTypeDeveloper), @"crashreport":@(CUICrashReporterDialogTypeBasic), @"server":@(CUICrashReporterDialogTypeServer) }; }); NSNumber * tNumber=sStringToEnumDictionary[inString]; if (tNumber==nil) return CUICrashReporterDialogTypeBasic; return [tNumber unsignedIntegerValue]; } + (NSString *)stringFromDialogType:(CUICrashReporterDialogType)inDialogType { static NSDictionary * sEnumToStringDictionary=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sEnumToStringDictionary=@{ @(CUICrashReporterDialogTypeBasic):@"basic", @(CUICrashReporterDialogTypeDeveloper):@"developer", @(CUICrashReporterDialogTypeServer):@"server" }; }); return sEnumToStringDictionary[@(inDialogType)]; } #pragma mark - - (instancetype)init { self=[super init]; if (self!=nil) { [self refresh]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:NSApplicationDidBecomeActiveNotification object:nil]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (void)refresh { NSDictionary * tDictionary=(__bridge_transfer NSDictionary *)CFPreferencesCopyMultiple(NULL,(__bridge CFStringRef) CUICrashReporterBundleIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if (tDictionary==nil) tDictionary=[NSDictionary dictionary]; Boolean tBoolean=FALSE; if (CFPreferencesGetAppBooleanValue((__bridge CFStringRef)CUICrashReporterDefaultsReportUncaughtExceptionKey,kCFPreferencesAnyApplication,&tBoolean)==FALSE) { tBoolean=FALSE; } NSMutableDictionary * tRepresentation=[tDictionary mutableCopy]; tRepresentation[CUICrashReporterDefaultsReportUncaughtExceptionKey]=@(tBoolean); // Dialog Type NSString * tDialogTypeValue=tRepresentation[CUICrashReporterDefaultsDialogTypeKey]; if ([tDialogTypeValue isKindOfClass:NSString.class]==NO) { if (tDialogTypeValue!=nil) NSLog(@"Unexpected value type for key: %@",CUICrashReporterDefaultsDialogTypeKey); self.dialogType=CUICrashReporterDialogTypeBasic; } else { self.dialogType=[CUICrashReporterDefaults dialogTypeFromString:tDialogTypeValue]; } // Notification Mode NSNumber * tNumber=tRepresentation[CUICrashReporterDefaultsNotificationModeKey]; if ([tDialogTypeValue isKindOfClass:NSString.class]==NO) { self.notificationMode=CUICrashReporterNotificationModeDialog; } else { if ([tNumber boolValue]==YES) { self.notificationMode=CUICrashReporterNotificationModeUserNotification; } else { self.notificationMode=CUICrashReporterNotificationModeDialog; } } // Report UncaughtException self.reportUncaughtExceptions=[tRepresentation[CUICrashReporterDefaultsReportUncaughtExceptionKey] boolValue]; } #pragma mark - - (void)setDialogType:(CUICrashReporterDialogType)inDialogType { if (_dialogType==inDialogType) return; _dialogType=inDialogType; NSString * tString=[CUICrashReporterDefaults stringFromDialogType:_dialogType]; CFPreferencesSetValue((__bridge CFStringRef)CUICrashReporterDefaultsDialogTypeKey, (__bridge CFStringRef)tString, (__bridge CFStringRef)CUICrashReporterBundleIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); CFPreferencesSynchronize((__bridge CFStringRef)CUICrashReporterBundleIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } - (void)setNotificationMode:(CUICrashReporterNotificationMode)inNotificationMode { if (_notificationMode==inNotificationMode) return; _notificationMode=inNotificationMode; NSNumber * tNumber=@(_notificationMode==CUICrashReporterNotificationModeUserNotification); CFPreferencesSetValue((__bridge CFStringRef)CUICrashReporterDefaultsNotificationModeKey, (__bridge CFNumberRef)tNumber, (__bridge CFStringRef)CUICrashReporterBundleIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); CFPreferencesSynchronize((__bridge CFStringRef)CUICrashReporterBundleIdentifier, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } - (void)setReportUncaughtExceptions:(BOOL)inReportUncaughtExceptions { if (_reportUncaughtExceptions==inReportUncaughtExceptions) return; _reportUncaughtExceptions=inReportUncaughtExceptions; CFPreferencesSetValue((__bridge CFStringRef)CUICrashReporterDefaultsReportUncaughtExceptionKey, (__bridge CFNumberRef)@(_reportUncaughtExceptions), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); CFPreferencesSynchronize(kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } #pragma mark - - (void)applicationDidBecomeActive:(NSNotification *)inNotification { [self refresh]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashedThreadCallRowView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUICrashedThreadCallRowViewIdentifier; @interface CUICrashedThreadCallRowView : NSTableRowView @property (getter=isRootCall) BOOL rootCall; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashedThreadCallRowView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashedThreadCallRowView.h" NSString * const CUICrashedThreadCallRowViewIdentifier=@"CUICrashedThreadCallRowViewIdentifier"; @implementation CUICrashedThreadCallRowView - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; NSRect tBounds=self.bounds; // Draw Background BOOL tIsDark=[self WB_isEffectiveAppearanceDarkAqua]; if (tIsDark==NO) [[NSColor colorWithCalibratedRed:1.0f green:250.0/255.0 blue:250.0/255.0 alpha:1.0f] set]; else [[NSColor colorWithCalibratedRed:0.04f green:0/255.0 blue:0/255.0 alpha:1.0f] set]; NSRectFill(tBounds); if (self.isRootCall==YES) { // Draw bottom line if (tIsDark==NO) [[NSColor colorWithCalibratedRed:0.7882f green:0.1647f blue:0.0902f alpha:1.0] set]; else [[NSColor colorWithCalibratedRed:0.2 green:0 blue:0 alpha:1.0] set]; [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMaxY(tBounds)-0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMaxY(tBounds)-0.5)]; } if (self.isSelected==YES) [self drawSelectionInRect:dirtyRect]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashedThreadRowView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUICrashedThreadRowViewIdentifier; @interface CUICrashedThreadRowView : NSTableRowView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUICrashedThreadRowView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICrashedThreadRowView.h" NSString * const CUICrashedThreadRowViewIdentifier=@"CUICrashedThreadRowViewIdentifier"; @implementation CUICrashedThreadRowView - (void)drawRect:(NSRect)inRect { if (self.isSelected==YES) { [super drawRect:inRect]; return; } NSRect tBounds=self.bounds; BOOL tIsDark=[self WB_isEffectiveAppearanceDarkAqua]; if (tIsDark==NO) { [[NSColor colorWithCalibratedRed:0.9647f green:0.8471f blue:0.8510f alpha:1.0] set]; } else { [[NSColor colorWithCalibratedRed:145/255.0 green:60/255.0 blue:46.0/255.0 alpha:1.0] set]; } NSRectFill(tBounds); if (tIsDark==NO) { [[NSColor colorWithCalibratedRed:0.7882f green:0.1647f blue:0.0902f alpha:1.0] set]; } else { [[NSColor colorWithCalibratedRed:0.2f green:0.1f blue:0.1f alpha:1.0] set]; } [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMinY(tBounds)+0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMinY(tBounds)+0.5)]; [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMaxY(tBounds)-0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMaxY(tBounds)-0.5)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIDataTransform.h ================================================ /* Copyright (c) 2021-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUITextModeDisplaySettings.h" extern NSString * const CUIDataTransformErrorDomain; typedef NS_ENUM(NSUInteger, CUIDataTransformError) { CUIDataTransformUnknownError=1 }; extern NSString * const CUIGenericAnchorAttributeName; extern NSString * const CUISectionAnchorAttributeName; extern NSString * const CUIThreadAnchorAttributeName; extern NSString * const CUIBinaryAnchorAttributeName; typedef NS_ENUM(NSUInteger, CUIHyperlinksStyle) { CUIHyperlinksNone, CUIHyperlinksInternal, CUIHyperlinksHTML }; typedef NS_ENUM(NSUInteger, CUISymbolicationMode) { CUISymbolicationModeNone, CUISymbolicationModeSymbolicate }; @interface CUIDataTransform : NSObject @property CUISymbolicationMode symbolicationMode; @property (nonatomic) CUIHyperlinksStyle hyperlinksStyle; @property (nonatomic) CUITextModeDisplaySettings * displaySettings; @property (nonatomic) CGFloat fontSizeDelta; @property (nonatomic) id input; @property (readonly) NSAttributedString * output; @property (readonly) NSError * error; - (BOOL)transform; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIDataTransform.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIDataTransform.h" NSString * const CUIDataTransformErrorDomain=@"fr.whitebox.data-tranform.error"; NSString * const CUIGenericAnchorAttributeName=@"CUIGenericAnchorAttributeName"; NSString * const CUISectionAnchorAttributeName=@"CUISectionAnchorAttributeName"; NSString * const CUIThreadAnchorAttributeName=@"CUIThreadAnchorAttributeName"; NSString * const CUIBinaryAnchorAttributeName=@"CUIBinaryAnchorAttributeName"; @interface CUIDataTransform () @property (nonatomic,readwrite) NSAttributedString * output; @property (readwrite) NSError * error; - (void)setOutput:(NSAttributedString *)inOutput; @end @implementation CUIDataTransform - (instancetype)init { self=[super init]; if (self!=nil) { _symbolicationMode=CUISymbolicationModeSymbolicate; _hyperlinksStyle=CUIHyperlinksInternal; } return self; } #pragma mark - - (void)setHyperlinksStyle:(CUIHyperlinksStyle)inHyperlinksStyle { _output=nil; _hyperlinksStyle=inHyperlinksStyle; } - (void)setDisplaySettings:(CUITextModeDisplaySettings *)inDisplaySettings { _output=nil; _displaySettings=inDisplaySettings; } - (void)setFontSizeDelta:(CGFloat)inFontSizeDelta { _output=nil; _fontSizeDelta=inFontSizeDelta; } - (void)setInput:(id)inInput { _output=nil; _input=inInput; } - (void)setOutput:(NSAttributedString *)inOutput { _output=inOutput; } #pragma mark - - (BOOL)transform { self.output=nil; return YES; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIExceptionTypePopUpViewController.h ================================================ /* Copyright (c) 2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIQuickHelpPopUpViewController.h" @interface CUIExceptionTypePopUpViewController : CUIQuickHelpPopUpViewController @property (readonly,copy) NSString * exceptionType; @property (readonly,copy) NSString * exceptionSignal; - (void)setExceptionType:(NSString *)inType signal:(NSString *)inSignal; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIExceptionTypePopUpViewController.m ================================================ /* Copyright (c) 2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIExceptionTypePopUpViewController.h" @interface CUIExceptionTypePopUpViewController () @property (copy) NSString * exceptionType; @property (copy) NSString * exceptionSignal; @end @implementation CUIExceptionTypePopUpViewController - (void)setExceptionType:(NSString *)inType signal:(NSString *)inSignal { NSURL * tURL=nil; if (inType!=nil && inSignal!=nil) { tURL=[self.bundle URLForResource:[NSString stringWithFormat:@"%@_%@",inType,inSignal] withExtension:@"html"]; } if (tURL==nil) { // Use no documentation file tURL=[self.bundle URLForResource:@"unknown_exception_type" withExtension:@"html"]; } self.contentsFileURL=tURL; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIExportAccessoryViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUITextModeDisplaySettings.h" typedef NS_ENUM(NSUInteger, CUICrashLogExportFormat) { CUICrashLogExportFormatHTML=0, CUICrashLogExportFormatRTF, CUICrashLogExportFormatPDF, CUICrashLogExportFormatText }; typedef NS_ENUM(NSUInteger, CUICrashLogExportedContentsType) { CUICrashLogExportedContentsAll, CUICrashLogExportedContentsSelection }; @interface CUIExportAccessoryViewController : NSViewController @property NSSavePanel * savePanel; @property (nonatomic) CUICrashLogExportFormat exportFormat; @property (nonatomic) BOOL canSelectExportedContents; @property (nonatomic,readonly) CUICrashLogExportedContentsType exportedContents; @property (nonatomic) BOOL canObfuscateContents; @property (readonly) BOOL obfuscateContents; @property (nonatomic) CUITextModeDisplaySettings * displaySettings; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIExportAccessoryViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIExportAccessoryViewController.h" @interface CUIExportAccessoryViewController () { // Format IBOutlet NSPopUpButton * _formatPopUpButton; // Exported Contents IBOutlet NSButton * _allContentsRadioButton; IBOutlet NSButton * _selectionOnlyRadioButton; // Obfuscate Contents IBOutlet NSButton * _obfuscateContentsRadioButton; IBOutlet NSTextField * _obfuscateDescriptionLabel; } @property (readwrite) BOOL obfuscateContents; - (IBAction)switchExportFormat:(id)sender; - (IBAction)switchExportedContents:(id)sender; @end @implementation CUIExportAccessoryViewController - (instancetype)init { self=[super init]; if (self!=nil) { _obfuscateContents=NO; } return self; } #pragma mark - - (NSString *)nibName { return @"CUIExportAccessoryViewController"; } - (void)viewDidLoad { [super viewDidLoad]; // Export Format [_formatPopUpButton selectItemWithTag:self.exportFormat]; // Exported Contents BOOL tRadioButtonEnabled=(self.canSelectExportedContents==YES); _selectionOnlyRadioButton.enabled=tRadioButtonEnabled; _allContentsRadioButton.enabled=tRadioButtonEnabled; _allContentsRadioButton.state=NSControlStateValueOn; // Obfuscate Contents tRadioButtonEnabled=(self.canObfuscateContents==YES); _obfuscateContentsRadioButton.enabled=tRadioButtonEnabled; _obfuscateContentsRadioButton.state=NSControlStateValueOff; _obfuscateDescriptionLabel.textColor=(tRadioButtonEnabled==YES) ? [NSColor labelColor] : [NSColor disabledControlTextColor]; } #pragma mark - - (void)setExportFormat:(CUICrashLogExportFormat)inExportFormat { if ([_formatPopUpButton selectItemWithTag:inExportFormat]==NO) return; _exportFormat=inExportFormat; } - (void)setCanSelectExportedContents:(BOOL)inCanSelectExportedContents { _canSelectExportedContents=inCanSelectExportedContents; if (_canSelectExportedContents==YES) { _selectionOnlyRadioButton.enabled=YES; } else { _selectionOnlyRadioButton.enabled=NO; _allContentsRadioButton.state=NSControlStateValueOn; } } - (CUICrashLogExportedContentsType)exportedContents { if (_allContentsRadioButton.state==NSControlStateValueOn) return CUICrashLogExportedContentsAll; return CUICrashLogExportedContentsSelection; } - (void)setCanObfuscateContents:(BOOL)inCanObfuscateContents { _canObfuscateContents=inCanObfuscateContents; if (_canObfuscateContents==YES) { _obfuscateContentsRadioButton.enabled=YES; } else { _obfuscateContentsRadioButton.enabled=NO; _obfuscateContentsRadioButton.state=NSControlStateValueOff; } } #pragma mark - - (IBAction)switchExportFormat:(NSPopUpButton *)sender { _exportFormat=sender.selectedTag; switch(_exportFormat) { case CUICrashLogExportFormatHTML: self.savePanel.allowedFileTypes=@[@"html"]; break; case CUICrashLogExportFormatRTF: self.savePanel.allowedFileTypes=@[@"rtf"]; break; case CUICrashLogExportFormatPDF: self.savePanel.allowedFileTypes=@[@"pdf"]; break; case CUICrashLogExportFormatText: self.savePanel.allowedFileTypes=@[@"crash"]; break; } } - (IBAction)switchExportedContents:(id)sender { // Not used at this time } - (IBAction)switchObfuscateContents:(NSButton *)sender { BOOL tObfuscateContents=(sender.state==NSControlStateValueOn); if (tObfuscateContents==_obfuscateContents) return; _obfuscateContents=tObfuscateContents; if (self.canSelectExportedContents==YES) { _selectionOnlyRadioButton.enabled=(_obfuscateContents==NO); _allContentsRadioButton.enabled=(_obfuscateContents==NO); if (_obfuscateContents==YES) _allContentsRadioButton.state=NSControlStateValueOn; } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIFileDeadDropView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @class CUIFileDeadDropView; @protocol CUIFileDeadDropViewDelegate - (BOOL)fileDeadDropView:(CUIFileDeadDropView *)inView validateDropFileURLs:(NSArray *)inFileURLs; - (BOOL)fileDeadDropView:(CUIFileDeadDropView *)inView acceptDropFileURLs:(NSArray *)inFileURLs; @end @interface CUIFileDeadDropView : NSView @property (weak) id delegate; @property (nonatomic,readonly,getter=isHighlighted) BOOL highlighted; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIFileDeadDropView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIFileDeadDropView.h" @interface CUIFileDeadDropView () @property (nonatomic,readwrite,getter=isHighlighted) BOOL highlighted; @end @implementation CUIFileDeadDropView - (instancetype)initWithFrame:(NSRect)inFrame { self=[super initWithFrame:inFrame]; if (self!=nil) { // Register for Drop [self registerForDraggedTypes:@[NSPasteboardTypeFileURL]]; } return self; } - (instancetype)initWithCoder:(NSCoder *)decoder { self=[super initWithCoder:decoder]; if (self!=nil) { // Register for Drop [self registerForDraggedTypes:@[NSPasteboardTypeFileURL]]; } return self; } #pragma mark - - (void)setHighlighted:(BOOL)inHighlighted { if (_highlighted!=inHighlighted) { _highlighted=inHighlighted; [self setNeedsDisplay:YES]; } } #pragma mark - - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; } #pragma mark - - (NSDragOperation)draggingEntered:(id )sender { if (self.delegate==nil) { #ifdef DEBUG NSLog(@"CUIFileDeadDropView <0x%p>: drag & drop won't work. delegate is not set",self); #endif return NSDragOperationNone; } NSPasteboard * tPasteBoard=[sender draggingPasteboard]; if ([tPasteBoard.types containsObject:NSPasteboardTypeFileURL]==NO) return NSDragOperationNone; NSDragOperation tSourceDragMask = [sender draggingSourceOperationMask]; if ((tSourceDragMask & NSDragOperationCopy)==0) return NSDragOperationNone; NSArray *tClasses = @[NSURL.class]; NSArray *tURLArray = [tPasteBoard readObjectsForClasses:tClasses options:@{NSPasteboardURLReadingFileURLsOnlyKey:@(YES)}]; if (tURLArray!=nil) { if ([self.delegate fileDeadDropView:self validateDropFileURLs:tURLArray]==YES) { self.highlighted=YES; return NSDragOperationCopy; } } return NSDragOperationNone; } - (BOOL)performDragOperation:(id )sender { if (self.delegate==nil) { #ifdef DEBUG NSLog(@"CUIFileDeadDropView <0x%p>: drag & drop won't work. delegate is not set",self); #endif return NO; } NSPasteboard * tPasteBoard=[sender draggingPasteboard]; if ([tPasteBoard.types containsObject:NSPasteboardTypeFileURL]==YES) { NSArray *tClasses = @[NSURL.class]; NSArray *tURLArray = [tPasteBoard readObjectsForClasses:tClasses options:@{NSPasteboardURLReadingFileURLsOnlyKey:@(YES)}]; if (tURLArray!=nil) return [self.delegate fileDeadDropView:self acceptDropFileURLs:tURLArray]; } return NO; } - (BOOL)prepareForDragOperation:(id )sender { self.highlighted=NO; return YES; } - (void)draggingExited:(id )sender { self.highlighted=NO; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIFontAndColorsFramedView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import NS_ASSUME_NONNULL_BEGIN @interface CUIFontAndColorsFramedView : NSView @end NS_ASSUME_NONNULL_END ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIFontAndColorsFramedView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIFontAndColorsFramedView.h" @implementation CUIFontAndColorsFramedView - (void)drawRect:(NSRect)dirtyRect { NSRect tBounds=self.bounds; // Draw Background BOOL tIsDarkMode=[self WB_isEffectiveAppearanceDarkAqua]; NSColor * tBackgroundColor=(tIsDarkMode==NO) ? [NSColor colorWithDeviceWhite:0.95 alpha:1.0] : [NSColor colorWithDeviceWhite:0.0 alpha:0.10]; [tBackgroundColor set]; NSRectFill(dirtyRect); NSColor * tForegroundColor=(tIsDarkMode==NO) ? [NSColor colorWithDeviceWhite:0.0 alpha:0.25] : [NSColor containerBorderColor]; [tForegroundColor set]; [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMinY(tBounds)+0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMinY(tBounds)+0.5)]; [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMaxY(tBounds)-0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMaxY(tBounds)-0.5)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIFontBoxView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIFontBoxView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIFontBoxView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIFontBoxView.h" #import "NSResponder+Appearance.h" @implementation CUIFontBoxView - (void)drawRect:(NSRect)dirtyRect { if ([self WB_isEffectiveAppearanceDarkAqua]==NO) [[NSColor colorWithWhite:1.0 alpha:0.50] set]; else [[NSColor colorWithWhite:1.0 alpha:0.05] set]; NSRectFillUsingOperation(self.bounds, NSCompositingOperationSourceOver); [[NSColor quaternaryLabelColor] set]; NSFrameRectWithWidthUsingOperation(self.bounds, 1, NSCompositingOperationSourceOver); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIHopperDisassemblerManager.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIApplicationItemAttributes.h" #include "CUICodeType.h" @protocol CUIHopperDisassemblerActions - (IBAction)openWithHopperDisassembler:(id)sender; @end @interface CUIHopperDisassemblerManager : NSObject + (CUIHopperDisassemblerManager *)sharedManager; - (NSMenu *)availableApplicationsMenuWithTarget:(id)inTarget; - (void)openBinaryImage:(NSString *)inPath withApplicationAttributes:(CUIApplicationItemAttributes *)inApplicationAttributes codeType:(CUICodeType)inCodeType fileOffSet:(void *)inOffset; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIHopperDisassemblerManager.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIHopperDisassemblerManager.h" NSString * const CUIHopperDisassembler4BundleIdentifier=@"com.cryptic-apps.hopper-web-4"; @implementation CUIHopperDisassemblerManager + ()sharedManager { static CUIHopperDisassemblerManager * sManager=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sManager=[CUIHopperDisassemblerManager new]; }); return sManager; } #pragma mark - - (NSMenu *)availableApplicationsMenuWithTarget:(id)inTarget { NSArray * tArray=(__bridge_transfer NSArray *)LSCopyApplicationURLsForBundleIdentifier((__bridge CFStringRef)CUIHopperDisassembler4BundleIdentifier,NULL); // Remove the demo versions and the versions that do not include the hopper command line tool NSArray * tFilteredVersions=[tArray WB_filteredArrayUsingBlock:^BOOL(NSURL * bURL, NSUInteger bIndex) { NSURL * tHopperToolURL=[bURL URLByAppendingPathComponent:@"/Contents/MacOS/hopper"]; if ([tHopperToolURL checkResourceIsReachableAndReturnError:NULL] == NO) return NO; NSBundle * tBundle=[NSBundle bundleWithURL:bURL]; NSString * tBundleVersionString=[tBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; return ([tBundleVersionString hasSuffix:@"-demo"]==NO); }]; if (tFilteredVersions.count==0) return nil; NSMutableArray * tApplicationsAttributes=[[tFilteredVersions WB_arrayByMappingObjectsUsingBlock:^CUIApplicationItemAttributes *(NSURL * bApplicationURL, NSUInteger bIndex) { return [[CUIApplicationItemAttributes alloc] initWithURL:bApplicationURL]; }] mutableCopy]; // Sort the array [tApplicationsAttributes sortUsingSelector:@selector(compare:)]; // Filter the array tApplicationsAttributes=[tApplicationsAttributes WB_filteredArrayUsingBlock:^BOOL(CUIApplicationItemAttributes * bAttributes, NSUInteger bIndex) { return (bAttributes.duplicate==NO); }]; NSMenu * tMenu=[[NSMenu alloc] initWithTitle:@""]; if (tMenu==nil) return nil; for(CUIApplicationItemAttributes * tAttributes in tApplicationsAttributes) { NSMenuItem * tMenuItem=tAttributes.applicationMenuItem; tMenuItem.action=@selector(openWithHopperDisassembler:); tMenuItem.target=inTarget; [tMenu addItem:tMenuItem]; } return tMenu; } - (void)openBinaryImage:(NSString *)inPath withApplicationAttributes:(CUIApplicationItemAttributes *)inApplicationAttributes codeType:(CUICodeType)inCodeType fileOffSet:(void *)inOffset { if (inPath==nil) { NSLog(@"Binary image path should not be nil"); return; } __auto_type postLaunchActions = ^(NSRunningApplication * runningApplication) { // Convert the codeType NSString * tCPUSelection=nil; switch(inCodeType) { case CUICodeTypeX86: tCPUSelection=@"--intel-32"; break; case CUICodeTypeX86_64: tCPUSelection=@"--intel-64"; break; case CUICodeTypeARM_64: tCPUSelection=@"--aarch64"; break; case CUICodeTypePPC: tCPUSelection=@"--ppc"; break; default: break; } NSURL * tCommandLineToolURL=[inApplicationAttributes.applicationURL URLByAppendingPathComponent:@"/Contents/MacOS/hopper"]; NSTask * tTask=[NSTask new]; tTask.executableURL=tCommandLineToolURL; NSMutableArray * tArguments=[NSMutableArray array]; [tArguments addObjectsFromArray:@[ @"-a", @"-l", @"FAT", @"-l", @"Mach-O", @"-e", inPath]]; if (tCPUSelection!=nil) [tArguments addObject:tCPUSelection]; if (inOffset!=NULL) { [tArguments addObjectsFromArray:@[ @"--python-command", [NSString stringWithFormat:@"doc = Document.getCurrentDocument();doc.setCurrentAddress(0x%lx)",(unsigned long)inOffset] ]]; } tTask.arguments=tArguments; tTask.terminationHandler=^(NSTask * bTask){ dispatch_async(dispatch_get_main_queue(), ^{ if (bTask.terminationStatus!=0) { NSLog(@"hopper tool returned with status %d",bTask.terminationStatus); } }); }; NSError * tError=nil; [tTask launchAndReturnError:&tError]; }; // Launch the Hopper Disassembler application if it's not already running (workaround for a limitation of the hopper command line tool) #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101600 if (@available(*, macOS 11.0)) { [[NSWorkspace sharedWorkspace] openApplicationAtURL:inApplicationAttributes.applicationURL configuration:[NSWorkspaceOpenConfiguration configuration] completionHandler:^(NSRunningApplication * _Nullable bRunningApplication, NSError * _Nullable error) { if (bRunningApplication==nil) { NSLog(@"No running instances of Hopper Disassembler and not able to launch one: %@",error); return; } postLaunchActions(bRunningApplication); }]; } else #endif { NSRunningApplication * tRunningApplication=[[NSWorkspace sharedWorkspace] launchApplicationAtURL:inApplicationAttributes.applicationURL options:0 configuration:@{} error:NULL]; if (tRunningApplication==nil) { NSLog(@"No running instances of Hopper Disassembler and not able to launch one."); return; } postLaunchActions(tRunningApplication); } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIIPSTransform.h ================================================ /* Copyright (c) 2021-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIReportThemedTransform.h" @interface CUIIPSTransform : CUIReportThemedTransform @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIIPSTransform.m ================================================ /* Copyright (c) 2021-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIIPSTransform.h" #import "IPSReport.h" #import "IPSDateFormatter.h" #import "IPSIncident+ApplicationSpecificInformation.h" #import "IPSThreadState+RegisterDisplayName.h" #import "IPSImage+UserCode.h" #import "IPSImage+Offset.h" #import "CUIApplicationPreferences.h" #import "CUIApplicationPreferences+Themes.h" #import "CUICrashLogBinaryImages.h" #import "CUIBinaryImageUtility.h" #import "CUIThemesManager.h" #import "CUIThemeItemsGroup+UI.h" #ifndef __DISABLE_SYMBOLICATION_ #import "CUIdSYMBundlesManager.h" #import "CUISymbolicationManager.h" #endif #import "CUIStackFrame.h" #import "CUICrashLogExceptionInformation+QuickHelp.h" @interface CUIDataTransform (Private) - (void)setOutput:(NSAttributedString *)inOutput; @end @implementation CUIIPSTransform + (NSString *)binaryImageStringForAddress:(NSUInteger)inAddress { NSString * tString=[NSString stringWithFormat:@"0x%lx",inAddress]; NSUInteger tLength=tString.length; NSString * tSpaceString=@" "; return [[tSpaceString substringFromIndex:tLength] stringByAppendingString:tString]; } #pragma mark - - (NSAttributedString *)attributedStringForKey:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.keyAttributes]; } - (NSAttributedString *)attributedStringForKeyWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.keyAttributes]; } - (NSAttributedString *)attributedStringForPlainText:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.plainTextAttributes]; } - (NSAttributedString *)attributedStringForPlainTextWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.plainTextAttributes]; } - (NSAttributedString *)attributedStringForPath:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.pathAttributes]; } - (NSAttributedString *)attributedStringForPathWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.pathAttributes]; } - (NSAttributedString *)attributedStringForVersion:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.versionAttributes]; } - (NSAttributedString *)attributedStringForVersionWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.versionAttributes]; } - (NSAttributedString *)attributedStringForUUID:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.UUIDAttributes]; } - (NSAttributedString *)attributedStringForUUIDWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.UUIDAttributes]; } - (NSAttributedString *)attributedStringForThreadLabel:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.threadLabelAttributes]; } - (NSAttributedString *)attributedStringForThreadLabelWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.threadLabelAttributes]; } - (NSAttributedString *)attributedStringForCrashedThreadLabel:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.crashedThreadLabelAttributes]; } - (NSAttributedString *)attributedStringForCrashedThreadLabelWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.crashedThreadLabelAttributes]; } - (NSAttributedString *)attributedStringForMemoryAddress:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:self.memoryAddressAttributes]; } - (NSAttributedString *)attributedStringForMemoryAddressWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.memoryAddressAttributes]; } - (NSAttributedString *)attributedStringForUser:(BOOL)inUserCode code:(NSString *)inString { if (inString==nil) return nil; return [[NSAttributedString alloc] initWithString:inString attributes:(inUserCode==YES) ? self.executableCodeAttributes : self.OSCodeAttributes]; } - (NSAttributedString *)attributedStringForUser:(BOOL)inUserCode codeWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(2,3) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:(inUserCode==YES) ? self.executableCodeAttributes : self.OSCodeAttributes]; } - (NSAttributedString *)attributedStringForRegisterValueWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { if (format==nil) return nil; va_list args; va_start(args, format); NSString * tString=[[NSString alloc] initWithFormat:format arguments:args]; va_end(args); return [[NSAttributedString alloc] initWithString:tString attributes:self.registerValueAttributes]; } - (NSAttributedString *)attributedStringForUser:(BOOL)inUserCode binaryImageIdentifier:(NSString *)inIdentifier { if (inIdentifier==nil) return nil; NSMutableDictionary * tMutableDictionary=[self.plainTextAttributes mutableCopy]; tMutableDictionary[NSForegroundColorAttributeName]=(inUserCode==YES) ? [CUIBinaryImageUtility colorForUserCode]: [CUIBinaryImageUtility colorForIdentifier:inIdentifier]; return [[NSAttributedString alloc] initWithString:(inUserCode==NO) ? inIdentifier : [NSString stringWithFormat:@"+%@",inIdentifier] attributes:tMutableDictionary]; } #pragma mark - - (NSArray *)attributedLinesForHeaderOfIncident:(IPSIncident *)inIncident { IPSIncidentHeader * tHeader=inIncident.header; NSMutableArray * tMutableArray=[NSMutableArray array]; NSMutableAttributedString * tMutableAttributedString; if ([tHeader.crashReporterKey isKindOfClass:NSString.class]) { tMutableAttributedString=[[self attributedStringForKey:@"CrashReporter Key:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:tHeader.crashReporterKey]]; [tMutableArray addObject:tMutableAttributedString]; } tMutableAttributedString=[[self attributedStringForKey:@"Process:"] mutableCopy]; NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Header" }; [tMutableAttributedString addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,tMutableAttributedString.length)]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@ [%d]",tHeader.processName,tHeader.processID]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@"Path:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPath:tHeader.processPath]]; [tMutableArray addObject:tMutableAttributedString]; IPSBundleInfo * tBundleInfo=tHeader.bundleInfo; tMutableAttributedString=[[self attributedStringForKey:@"Identifier:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@",(tBundleInfo.bundleIdentifier!=nil) ? tBundleInfo.bundleIdentifier : tHeader.processName]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@"Version:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForVersion:(tBundleInfo.bundleShortVersionString!=nil) ? tBundleInfo.bundleShortVersionString : @"???"]]; if (tBundleInfo.bundleVersion!=nil) [tMutableAttributedString appendAttributedString:[self attributedStringForVersionWithFormat:@" (%@)",tBundleInfo.bundleVersion]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@"Code Type:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@ (%@)",tHeader.cpuType,(tHeader.translated==NO) ? @"Native" : @"Translated"]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@"Parent Process:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@ [%d]",tHeader.parentProcessName,tHeader.parentProcessID]]; [tMutableArray addObject:tMutableAttributedString]; if (tHeader.responsibleProcessName!=nil) { tMutableAttributedString=[[self attributedStringForKey:@"Responsible:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@ [%d]",tHeader.responsibleProcessName,tHeader.responsibleProcessID]]; [tMutableArray addObject:tMutableAttributedString]; } tMutableAttributedString=[[self attributedStringForKey:@"User ID:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %d",tHeader.userID]]; [tMutableArray addObject:tMutableAttributedString]; [tMutableArray addObject:@""]; tMutableAttributedString=[[self attributedStringForKey:@"Date/Time:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@",[[IPSDateFormatter sharedFormatter] stringFromDate:tHeader.captureTime]]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@"OS Version:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForVersionWithFormat:@"%@ (%@)",tHeader.operatingSystemVersion.train,tHeader.operatingSystemVersion.build]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@"Report Version:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" 12"]]; [tMutableArray addObject:tMutableAttributedString]; if ([tHeader.crashReporterKey isKindOfClass:NSUUID.class]) { tMutableAttributedString=[[self attributedStringForKey:@"Anonymous UUID:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForUUID:[tHeader.crashReporterKey UUIDString]]]; [tMutableArray addObject:tMutableAttributedString]; } [tMutableArray addObject:@""]; if (tHeader.sleepWakeUUID!=nil) { tMutableAttributedString=[[self attributedStringForKey:@"Sleep/Wake UUID:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForUUID:tHeader.sleepWakeUUID.UUIDString]]; [tMutableArray addObject:tMutableAttributedString]; } tMutableAttributedString=[[self attributedStringForKey:@"Time Awake Since Boot:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %lu seconds",(unsigned long)tHeader.uptime]]; [tMutableArray addObject:tMutableAttributedString]; [tMutableArray addObject:@""]; tMutableAttributedString=[[self attributedStringForKey:@"System Integrity Protection:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@",(tHeader.systemIntegrityProtectionEnable==YES) ? @"enabled" : @"disabled"]]; [tMutableArray addObject:tMutableAttributedString]; [tMutableArray addObject:@""]; return tMutableArray; } - (NSArray *)attributedLinesForExceptionInformationOfIncident:(IPSIncident *)inIncident { IPSIncidentExceptionInformation * tExceptionInformation=inIncident.exceptionInformation; NSMutableArray * tMutableArray=[NSMutableArray array]; NSMutableAttributedString * tMutableAttributedString=[[self attributedStringForKey:@"Crashed Thread:"] mutableCopy]; NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Exception Information" }; [tMutableAttributedString addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,tMutableAttributedString.length)]; if ((self.displaySettings.visibleSections & CUIDocumentBacktracesSection)==CUIDocumentBacktracesSection && inIncident.threads.count>0) { switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: [tMutableAttributedString addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"a://crashed_thread"] } range:NSMakeRange(0,tMutableAttributedString.length)]; break; case CUIHyperlinksHTML: [tMutableAttributedString addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"sharp://crashed_thread"] } range:NSMakeRange(0,tMutableAttributedString.length)]; break; default: break; } } [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForCrashedThreadLabelWithFormat:@"%lu",(unsigned long)tExceptionInformation.faultingThread]]; IPSLegacyInfo * tLegacyInfo=tExceptionInformation.legacyInfo; if (tLegacyInfo.threadTriggered.queue!=nil) [tMutableAttributedString appendAttributedString:[self attributedStringForCrashedThreadLabelWithFormat:@" Dispatch queue: %@",tLegacyInfo.threadTriggered.queue]]; [tMutableArray addObject:tMutableAttributedString]; [tMutableArray addObject:@""]; IPSException * tException=tExceptionInformation.exception; tMutableAttributedString=[[self attributedStringForKey:@"Exception Type:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; NSAttributedString * tAttributedString; if (tException.signal!=nil) tAttributedString=[self attributedStringForPlainTextWithFormat:@"%@ (%@)",tException.type,tException.signal]; else tAttributedString=[self attributedStringForPlainTextWithFormat:@"%@",tException.type]; NSMutableAttributedString * tValueAttributedString=[tAttributedString mutableCopy]; switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: [tValueAttributedString addAttributes:@{ NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle|NSUnderlineStylePatternDash) } range:NSMakeRange(0, tValueAttributedString.length)]; [tValueAttributedString addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"a://exception_type"] } range:NSMakeRange(0, tValueAttributedString.length)]; break; default: break; } [tMutableAttributedString appendAttributedString:tValueAttributedString]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@"Exception Codes:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@",(tException.subtype!=nil) ? tException.subtype : tException.codes]]; [tMutableArray addObject:tMutableAttributedString]; if (tExceptionInformation.isCorpse==YES) { tMutableAttributedString=[[self attributedStringForKey:@"Exception Note:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" EXC_CORPSE_NOTIFY"]]; [tMutableArray addObject:tMutableAttributedString]; } [tMutableArray addObject:@""]; IPSTermination * tTermination=tExceptionInformation.termination; if (tTermination!=nil) { tMutableAttributedString=[[self attributedStringForKey:@"Termination Reason:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; tValueAttributedString=[[self attributedStringForPlainTextWithFormat:@"Namespace %@, Code 0x%lx",tTermination.namespace,(unsigned long)tTermination.code] mutableCopy]; if (self.crashlog.exceptionInformation.isQuickHelpAvailableForTerminationReason==YES) { [tValueAttributedString addAttributes:@{ NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle|NSUnderlineStylePatternDash) } range:NSMakeRange(0, tValueAttributedString.length)]; [tValueAttributedString addAttributes:@{ NSLinkAttributeName:[NSURL URLWithString:@"a://termination_reason"] } range:NSMakeRange(0, tValueAttributedString.length)]; } [tMutableAttributedString appendAttributedString:tValueAttributedString]; [tMutableArray addObject:tMutableAttributedString]; if (tTermination.byProc!=nil) { tMutableAttributedString=[[self attributedStringForKey:@"Terminating Process:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@ [%d]",tTermination.byProc,tTermination.byPid]]; [tMutableArray addObject:tMutableAttributedString]; } [tMutableArray addObject:@""]; } return tMutableArray; } - (NSArray *)attributedLinesForDiagnosticMessageOfIncident:(IPSIncident *)inIncident { IPSIncidentDiagnosticMessage * tDiagnosticMessage=inIncident.diagnosticMessage; NSMutableArray * tMutableArray=[NSMutableArray array]; if (tDiagnosticMessage.vmregioninfo!=nil) { NSMutableAttributedString * tMutableAttributedString=[[self attributedStringForKey:@"VM Region Info:"] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@" %@",tDiagnosticMessage.vmregioninfo]]; [tMutableArray addObject:tMutableAttributedString]; [tMutableArray addObject:@""]; } NSArray * tApplicationSpecificInformation=[inIncident applicationSpecificInformationMessage]; if (tApplicationSpecificInformation.count>0) { NSMutableAttributedString * tMutableAttributedString=[[self attributedStringForKey:@"Application Specific Information:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; for (NSString *tSring in tApplicationSpecificInformation) [tMutableArray addObject:[self attributedStringForPlainText:tSring]]; [tMutableArray addObject:@""]; } NSArray * tSignatures=tDiagnosticMessage.asi.signatures; if (tSignatures!=nil) { NSMutableAttributedString * tMutableAttributedString=[[self attributedStringForKey:@"Application Specific Signatures:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; [tSignatures enumerateObjectsUsingBlock:^(NSString * bSignature, NSUInteger bIndex, BOOL * bOutStop) { [tMutableArray addObject:[self attributedStringForPlainText:bSignature]]; }]; [tMutableArray addObject:@""]; } NSMutableAttributedString * tMutableAttributedString=tMutableArray.firstObject; if ([tMutableAttributedString isKindOfClass:[NSMutableAttributedString class]]==YES) { NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Diagnostic Messages" }; [tMutableAttributedString addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,tMutableAttributedString.length)]; } return tMutableArray; } - (NSArray *)attributedLinesForBacktracesOfIncident:(IPSIncident *)inIncident { #define BINARYIMAGENAME_AND_SPACE_MAXLEN 34 NSMutableArray * tMutableArray=[NSMutableArray array]; CUICrashLogBacktraces * tBacktraces=self.crashlog.backtraces; #ifndef __DISABLE_SYMBOLICATION_ NSInteger tThreadIndexOffset=0; #endif NSString * tProcessPath=inIncident.header.processPath; NSArray * tSortedBinaryImages=[inIncident.binaryImages sortedArrayUsingSelector:@selector(compare:)]; #ifndef __DISABLE_SYMBOLICATION_ NSArray * tBacktracesThreads=tBacktraces.threads; __block CUIThread * tBacktraceThread; __block NSArray * tStackFrames; #endif void (^transformThreadFrame)(IPSThreadFrame*, NSUInteger, BOOL *) = ^(IPSThreadFrame * bFrame, NSUInteger bFrameIndex, BOOL * _Nonnull stop) { IPSImage * tBinaryImage=inIncident.binaryImages[bFrame.imageIndex]; BOOL tIsUserCode=tBinaryImage.isUserCode; if (tIsUserCode==NO) { if ([tSortedBinaryImages indexOfObjectIdenticalTo:tBinaryImage]==0) { tIsUserCode=YES; } else { NSString * tPath=tBinaryImage.path; tIsUserCode=(tPath!=nil && [tProcessPath isEqualToString:tPath]==YES); } } NSString * tFrameIndexString=[NSString stringWithFormat:@"%lu",(unsigned long)bFrameIndex]; NSString * tIndexSpace=[@" " substringFromIndex:tFrameIndexString.length]; NSMutableAttributedString * tMutableAttributedString=[[self attributedStringForUser:tIsUserCode code:tFrameIndexString] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode code:tIndexSpace]]; if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)==CUIStackFrameBinaryNameComponent) { NSString * tBinaryImageIdentifier=(tBinaryImage.bundleIdentifier!=nil) ? tBinaryImage.bundleIdentifier : tBinaryImage.name; if (tBinaryImageIdentifier==nil) tBinaryImageIdentifier=@"???"; NSUInteger tImageNameLength=tBinaryImageIdentifier.length; NSMutableAttributedString * tMutableBinaryImageAttributedString=[[self attributedStringForUser:tIsUserCode code:tBinaryImageIdentifier] mutableCopy]; if (self.hyperlinksStyle!=CUIHyperlinksNone && ((self.displaySettings.visibleSections & CUIDocumentBinaryImagesSection)==CUIDocumentBinaryImagesSection)) { NSURL * tURL=nil; switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: tURL=[NSURL URLWithString:[NSString stringWithFormat:@"bin://%@",tBinaryImage.UUID.UUIDString]]; break; case CUIHyperlinksHTML: tURL=[NSURL URLWithString:[NSString stringWithFormat:@"sharp://%@",tBinaryImage.UUID.UUIDString]]; break; default: break; } if (tURL!=nil) [tMutableBinaryImageAttributedString addAttributes:@{NSLinkAttributeName:tURL} range:NSMakeRange(0,tMutableBinaryImageAttributedString.length)]; } [tMutableAttributedString appendAttributedString:tMutableBinaryImageAttributedString]; if ((tImageNameLength+4)>BINARYIMAGENAME_AND_SPACE_MAXLEN) { [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode code:@" "]]; } else { NSString * tImageSpace=[@" " substringFromIndex:tImageNameLength]; [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode code:tImageSpace]]; } } NSUInteger tMachineInstructionAddress=tBinaryImage.loadAddress+bFrame.imageOffset; if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)==CUIStackFrameMachineInstructionAddressComponent) { [tMutableAttributedString appendAttributedString:[self attributedStringForMemoryAddressWithFormat:@"0x%016lx ",(unsigned long)tMachineInstructionAddress]]; } #ifndef __DISABLE_SYMBOLICATION_ BOOL tSymbolicateAutomatically=[CUIApplicationPreferences sharedPreferences].symbolicateAutomatically; if (self.symbolicationMode==CUISymbolicationModeNone) tSymbolicateAutomatically=NO; CUIStackFrame * tStackFrame=tStackFrames[bFrameIndex]; CUISymbolicationData * tSymbolicationData=nil; if (tSymbolicateAutomatically==YES) { tSymbolicationData=tStackFrame.symbolicationData; } if (tSymbolicationData!=nil) { if (tSymbolicationData.stackFrameSymbol==nil) NSLog(@"Missing stackFrameSymbol"); [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode code:[self.symbolicationDataFormatter stringForObjectValue:tSymbolicationData]]]; } else { if (tSymbolicateAutomatically==YES) { // Default values __block NSAttributedString * tCachedResultedAttributedString=nil; [[CUISymbolicationManager sharedSymbolicationManager] lookUpSymbolicationDataForMachineInstructionAddress:tMachineInstructionAddress-tBinaryImage.binaryImageOffset binaryUUID:tBinaryImage.UUID.UUIDString completionHandler:^(CUISymbolicationDataLookUpResult bLookUpResult, CUISymbolicationData *bSymbolicationData) { switch(bLookUpResult) { case CUISymbolicationDataLookUpResultError: case CUISymbolicationDataLookUpResultNotFound: break; case CUISymbolicationDataLookUpResultFound: { tStackFrame.symbolicationData=bSymbolicationData; [[NSNotificationCenter defaultCenter] postNotificationName:CUIStackFrameSymbolicationDidSucceedNotification object:self.crashlog]; break; } case CUISymbolicationDataLookUpResultFoundInCache: { tStackFrame.symbolicationData=bSymbolicationData; tCachedResultedAttributedString=[self attributedStringForUser:tIsUserCode code:[self.symbolicationDataFormatter stringForObjectValue:bSymbolicationData]]; break; } } }]; if (tCachedResultedAttributedString==nil) { if (bFrame.symbol!=nil) { [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode code:bFrame.symbol]]; if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)==CUIStackFrameByteOffsetComponent) [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@" + %lu",(unsigned long)bFrame.symbolLocation]]; } else { [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@"0x%lx",(unsigned long)tBinaryImage.loadAddress]]; if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)==CUIStackFrameByteOffsetComponent) [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@" + %lu",(unsigned long)bFrame.imageOffset]]; } if (bFrame.sourceFile!=nil) [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@" (%@:%lu)",bFrame.sourceFile,(unsigned long)bFrame.sourceLine]]; } else { [tMutableAttributedString appendAttributedString:tCachedResultedAttributedString]; } } else { if (bFrame.symbol!=nil && (tIsUserCode==NO || self.symbolicationMode==CUISymbolicationModeSymbolicate)) { [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode code:bFrame.symbol]]; if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)==CUIStackFrameByteOffsetComponent) [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@" + %lu",(unsigned long)bFrame.symbolLocation]]; } else { [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@"0x%lx",(unsigned long)tBinaryImage.loadAddress]]; if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)==CUIStackFrameByteOffsetComponent) [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@" + %lu",(unsigned long)bFrame.imageOffset]]; } if (bFrame.sourceFile!=nil) [tMutableAttributedString appendAttributedString:[self attributedStringForUser:tIsUserCode codeWithFormat:@" (%@:%lu)",bFrame.sourceFile,(unsigned long)bFrame.sourceLine]]; } } #endif [tMutableArray addObject:tMutableAttributedString]; }; if (tBacktraces.hasApplicationSpecificBacktrace==YES) { #ifndef __DISABLE_SYMBOLICATION_ tThreadIndexOffset=1; #endif NSMutableAttributedString * tMutableAttributedString=nil; tMutableAttributedString=[[self attributedStringForThreadLabelWithFormat:@"Application Specific Backtrace %lu",(unsigned long)1] mutableCopy]; [tMutableAttributedString addAttributes:@{ CUIThreadAnchorAttributeName:@"thread:Application Specific Backtrace" } range:NSMakeRange(0, tMutableAttributedString.length)]; [tMutableArray addObject:tMutableAttributedString]; NSArray * tFrames=inIncident.exceptionInformation.lastExceptionBacktrace; if (tFrames!=nil) { #ifndef __DISABLE_SYMBOLICATION_ tBacktraceThread=tBacktracesThreads.firstObject; tStackFrames=tBacktraceThread.callStackBacktrace.stackFrames; #endif [tFrames enumerateObjectsUsingBlock:transformThreadFrame]; } else { NSArray * tBacktraces=inIncident.diagnosticMessage.asi.backtraces; if (tBacktraces!=nil) { [tBacktraces enumerateObjectsUsingBlock:^(NSString * bString, NSUInteger bIndex, BOOL * bOutStop) { CUIThread * tThread=self.crashlog.backtraces.threads.firstObject; NSMutableArray * tLines=[NSMutableArray array]; [bString enumerateLinesUsingBlock:^(NSString * bLine, BOOL * _Nonnull stop) { [tLines addObject:bLine]; }]; __block NSUInteger tStackFrameIndex=0; [tLines enumerateObjectsUsingBlock:^(NSString * bLine, NSUInteger bLineNumber, BOOL * bOutStop) { if (bLine.length==0) { [tMutableArray addObject:@""]; return; } NSString * tProcessedStackFrameLine=[self processedStackFrameLine:bLine stackFrame:tThread.callStackBacktrace.stackFrames[tStackFrameIndex]]; if (tProcessedStackFrameLine!=nil) { [tMutableArray addObject:tProcessedStackFrameLine]; } else { NSLog(@"Error transforming line: %@",bLine); [tMutableArray addObject:[[NSAttributedString alloc] initWithString:bLine]]; } tStackFrameIndex+=1; }]; }]; } } [tMutableArray addObject:@""]; } [inIncident.threads enumerateObjectsUsingBlock:^(IPSThread * bThread, NSUInteger bThreadIndex, BOOL * bOutStop) { NSString * tCrashedString=(bThread.triggered==YES) ? @" Crashed":@""; NSMutableString * tThreadLabel=[NSMutableString stringWithFormat:@"Thread %lu%@:",(unsigned long)bThreadIndex,tCrashedString]; if (bThread.name!=nil || bThread.queue!=nil) { [tThreadLabel appendString:@": "]; if (bThread.name!=nil) [tThreadLabel appendString:bThread.name]; if (bThread.queue!=nil) [tThreadLabel appendFormat:@"%@Dispatch queue: %@",(bThread.name!=nil) ? @" ": @"",bThread.queue]; } NSMutableAttributedString * tMutableAttributedString=nil; if (bThread.triggered==YES) { tMutableAttributedString=[[self attributedStringForCrashedThreadLabel:tThreadLabel] mutableCopy]; switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: [tMutableAttributedString addAttributes:@{ CUIGenericAnchorAttributeName:@"a:crashed_thread" } range:NSMakeRange(0, tMutableAttributedString.length)]; break; case CUIHyperlinksHTML: { NSURL * tURL=[NSURL URLWithString:@"anchor://crashed_thread"]; if (tURL!=nil) [tMutableAttributedString addAttributes:@{NSLinkAttributeName:tURL} range:NSMakeRange(0, tMutableAttributedString.length)]; break; } default: break; } } else { if ((self.displaySettings.visibleSections & CUIDocumentBacktraceCrashedThreadSubSection)!=0) return; tMutableAttributedString=[[self attributedStringForThreadLabel:tThreadLabel] mutableCopy]; } [tMutableAttributedString addAttributes:@{ CUIThreadAnchorAttributeName:[NSString stringWithFormat:@"thread:%lu",(unsigned long)bThreadIndex] } range:NSMakeRange(0, tMutableAttributedString.length)]; [tMutableArray addObject:tMutableAttributedString]; #ifndef __DISABLE_SYMBOLICATION_ tBacktraceThread=tBacktracesThreads[bThreadIndex + tThreadIndexOffset]; tStackFrames=tBacktraceThread.callStackBacktrace.stackFrames; #endif [bThread.frames enumerateObjectsUsingBlock:transformThreadFrame]; [tMutableArray addObject:@""]; }]; NSMutableAttributedString * tMutableAttributedString=tMutableArray.firstObject; if ([tMutableAttributedString isKindOfClass:[NSMutableAttributedString class]]==YES) { NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Backtraces" }; [tMutableAttributedString addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,tMutableAttributedString.length)]; } return tMutableArray; } - (NSArray *)attributedLinesForThreadStateOfIncident:(IPSIncident *)inIncident { IPSIncidentHeader * tHeader=inIncident.header; IPSThreadState * tCrashedThreadState=nil; IPSIncidentExceptionInformation * tExceptionInformation=inIncident.exceptionInformation; NSMutableArray * tMutableArray=[NSMutableArray array]; IPSThreadInstructionState * tCrashThreadInstructionState=nil; if (tExceptionInformation.faultingThread=32 && tByteValue<127) tASCIIRepresentation[tASCIIIndex]=tByteValue; } [tMutableString appendFormat:@" %s",tASCIIRepresentation]; if (tByteIndex==tOffset) [tMutableString appendString:@" <=="]; tAttributedString=[self attributedStringForPlainText:tMutableString]; [tMutableArray addObject:tAttributedString]; } [tMutableArray addObject:@""]; } } NSMutableAttributedString * tMutableAttributedString=tMutableArray.firstObject; if ([tMutableAttributedString isKindOfClass:[NSMutableAttributedString class]]==YES) { NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Thread State" }; [tMutableAttributedString addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,tMutableAttributedString.length)]; } return tMutableArray; } - (NSArray *)attributedLinesForBinaryImagesOfIncident:(IPSIncident *)inIncident { NSMutableArray * tMutableArray=[NSMutableArray array]; __block NSMutableAttributedString * tMutableAttributedString=[[self attributedStringForKey:@"Binary Images:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; BOOL tIsMonochromeTheme=self.themesProvider.currentTheme.isMonochrome; [[inIncident.binaryImages sortedArrayUsingSelector:@selector(compare:)] enumerateObjectsUsingBlock:^(IPSImage * bImage, NSUInteger bIndex, BOOL * bOutStop) { NSString * tSpaceString=@" "; NSString * tAddressString=[NSString stringWithFormat:@"0x%lx",bImage.loadAddress]; NSUInteger tLength=tAddressString.length; tMutableAttributedString=[[self attributedStringForPlainText:[tSpaceString substringFromIndex:tLength]] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForMemoryAddress:tAddressString]]; [tMutableAttributedString appendAttributedString:[[self attributedStringForPlainText:@" - "] mutableCopy]]; tAddressString=[NSString stringWithFormat:@"0x%lx",bImage.loadAddress+bImage.size]; tLength=tAddressString.length; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:[tSpaceString substringFromIndex:tLength]]]; [tMutableAttributedString appendAttributedString:[self attributedStringForMemoryAddress:tAddressString]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; NSString * tBinaryImageIdentifier=(bImage.bundleIdentifier!=nil) ? bImage.bundleIdentifier : bImage.name; if (tBinaryImageIdentifier==nil) tBinaryImageIdentifier=@"???"; if (tIsMonochromeTheme==YES) { if (bImage.isUserCode==YES) [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@"+"]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:tBinaryImageIdentifier]]; } else { [tMutableAttributedString appendAttributedString:[self attributedStringForUser:bImage.isUserCode binaryImageIdentifier:tBinaryImageIdentifier]]; } [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; if (bImage.bundleShortVersionString!=nil || bImage.bundleVersion!=nil) { if (bImage.bundleVersion==nil) [tMutableAttributedString appendAttributedString:[self attributedStringForVersionWithFormat:@"(%@)",bImage.bundleShortVersionString]]; else [tMutableAttributedString appendAttributedString:[self attributedStringForVersionWithFormat:@"(%@ - %@)",(bImage.bundleShortVersionString!=nil) ? bImage.bundleShortVersionString : @"???",bImage.bundleVersion]]; } else { [tMutableAttributedString appendAttributedString:[self attributedStringForVersion:@"(???)"]]; } [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; NSString * tUUIDString=bImage.UUID.UUIDString; [tMutableAttributedString appendAttributedString:[self attributedStringForUUIDWithFormat:@"<%@>",tUUIDString]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPath:(bImage.path!=nil) ? bImage.path : @"???"]]; switch(self.hyperlinksStyle) { case CUIHyperlinksHTML: { NSURL * tURL=[NSURL URLWithString:[NSString stringWithFormat:@"anchor://%@",tUUIDString]]; if (tURL!=nil) [tMutableAttributedString addAttributes:@{NSLinkAttributeName:tURL} range:NSMakeRange(0, tMutableAttributedString.length)]; break; } default: [tMutableAttributedString addAttributes:@{CUIBinaryAnchorAttributeName:[NSString stringWithFormat:@"bin:%@",tUUIDString]} range:NSMakeRange(0, tMutableAttributedString.length)]; break; } [tMutableArray addObject:tMutableAttributedString]; }]; [tMutableArray addObject:@""]; // External Modification Summary if (inIncident.extMods!=nil) { __auto_type (^processStatistics)(IPSExternalModificationStatistics *) = ^(IPSExternalModificationStatistics * inObject) { tMutableAttributedString=[[self attributedStringForPlainText:@" "] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForKey:@"task_for_pid:"]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@"%ld",(long)inObject.taskForPid]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForPlainText:@" "] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForKey:@"thread_create:"]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@"%ld",(long)inObject.threadCreate]]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForPlainText:@" "] mutableCopy]; [tMutableAttributedString appendAttributedString:[self attributedStringForKey:@"thread_set_state:"]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainTextWithFormat:@"%ld",(long)inObject.threadSetState]]; [tMutableAttributedString appendAttributedString:[self attributedStringForPlainText:@" "]]; [tMutableArray addObject:tMutableAttributedString]; }; tMutableAttributedString=[[self attributedStringForKey:@"External Modification Summary:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForKey:@" Calls made by other processes targeting this process:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; processStatistics(inIncident.extMods.targeted); tMutableAttributedString=[[self attributedStringForKey:@" Calls made by this process:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; processStatistics(inIncident.extMods.caller); tMutableAttributedString=[[self attributedStringForKey:@" Calls made by all processes on this machine:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; processStatistics(inIncident.extMods.system); [tMutableArray addObject:@""]; } // VM Summary if (inIncident.vmSummary!=nil) { tMutableAttributedString=[[self attributedStringForKey:@"VM Region Summary:"] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; tMutableAttributedString=[[self attributedStringForPlainText:inIncident.vmSummary] mutableCopy]; [tMutableArray addObject:tMutableAttributedString]; } tMutableAttributedString=tMutableArray.firstObject; if ([tMutableAttributedString isKindOfClass:[NSMutableAttributedString class]]==YES) { NSDictionary * tJumpAnchorAttributes=@{ CUISectionAnchorAttributeName:@"section:Binary Images" }; [tMutableAttributedString addAttributes:tJumpAnchorAttributes range:NSMakeRange(0,tMutableAttributedString.length)]; } return tMutableArray; } #pragma mark - - (BOOL)transform { if ([super transform]==NO) return NO; IPSReport * tReport=(IPSReport *)self.input; if ([tReport isKindOfClass:[IPSReport class]]==NO) { // A COMPLETER return NO; } [self updatesCachedAttributes]; IPSIncident * tIncident=tReport.incident; self.processPath=tIncident.header.processPath; NSMutableArray * tMutableArray=[NSMutableArray array]; // Header if ((self.displaySettings.visibleSections & CUIDocumentHeaderSection)==CUIDocumentHeaderSection) { NSArray * tAttributedLines=[self attributedLinesForHeaderOfIncident:tIncident]; if (tAttributedLines==nil) return NO; [tMutableArray addObjectsFromArray:tAttributedLines]; } // Exception Information if ((self.displaySettings.visibleSections & CUIDocumentExceptionInformationSection)==CUIDocumentExceptionInformationSection) { NSArray * tAttributedLines=[self attributedLinesForExceptionInformationOfIncident:tIncident]; if (tAttributedLines==nil) return NO; [tMutableArray addObjectsFromArray:tAttributedLines]; } // Diagnostic Message if ((self.displaySettings.visibleSections & CUIDocumentDiagnosticMessagesSection)==CUIDocumentDiagnosticMessagesSection) { NSArray * tAttributedLines=[self attributedLinesForDiagnosticMessageOfIncident:tIncident]; if (tAttributedLines==nil) return NO; [tMutableArray addObjectsFromArray:tAttributedLines]; } // Backtraces if ((self.displaySettings.visibleSections & CUIDocumentBacktracesSection)==CUIDocumentBacktracesSection) { NSArray * tAttributedLines=[self attributedLinesForBacktracesOfIncident:tIncident]; if (tAttributedLines==nil) return NO; [tMutableArray addObjectsFromArray:tAttributedLines]; } // Thread State if ((self.displaySettings.visibleSections & CUIDocumentThreadStateSection)==CUIDocumentThreadStateSection) { NSArray * tAttributedLines=[self attributedLinesForThreadStateOfIncident:tIncident]; if (tAttributedLines==nil) return NO; [tMutableArray addObjectsFromArray:tAttributedLines]; } // Binary Images if ((self.displaySettings.visibleSections & CUIDocumentBinaryImagesSection)==CUIDocumentBinaryImagesSection) { NSArray * tAttributedLines=[self attributedLinesForBinaryImagesOfIncident:tIncident]; if (tAttributedLines==nil) return NO; [tMutableArray addObjectsFromArray:tAttributedLines]; } self.output=[self joinLines:tMutableArray withString:@"\n"]; return YES; } #pragma mark - - (NSAttributedString *)joinLines:(NSArray *)inLines withString:(NSString *)inNewLineFeed { NSMutableAttributedString * tMutableAttributedString=[NSMutableAttributedString new]; [inLines enumerateObjectsUsingBlock:^(id bLine, NSUInteger bLineNumber, BOOL * bOutStop) { if ([bLine isKindOfClass:[NSString class]]==YES) { NSAttributedString * tAttributedString=[[NSAttributedString alloc] initWithString:bLine attributes:self.plainTextAttributes]; [tMutableAttributedString appendAttributedString:tAttributedString]; if (bLineNumber NS_ASSUME_NONNULL_BEGIN @interface CUIInactiveButton : NSButton @end NS_ASSUME_NONNULL_END ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInactiveButton.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInactiveButton.h" @implementation CUIInactiveButton - (NSView *)hitTest:(NSPoint)point { return nil; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorAlternateBackgroundView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIInspectorAlternateBackgroundView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorAlternateBackgroundView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorAlternateBackgroundView.h" @implementation CUIInspectorAlternateBackgroundView - (BOOL)isOpaque { return NO; } #pragma mark - - (void)drawRect:(NSRect)inRect { NSRect tRefreshRect=NSIntersectionRect(self.bounds, inRect); BOOL tIsDark=[self WB_isEffectiveAppearanceDarkAqua]; if (tIsDark==NO) [[NSColor colorWithDeviceWhite:0.95 alpha:1.0] set]; else [[NSColor colorWithDeviceWhite:0.0 alpha:0.15] set]; NSRectFillUsingOperation(tRefreshRect,NSCompositingOperationSourceOver); if (tIsDark==NO) [[NSColor colorWithDeviceWhite:0.85 alpha:1.0] setStroke]; else [[NSColor colorWithDeviceWhite:1.0 alpha:0.03] set]; NSRect tBounds=self.bounds; NSBezierPath * tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(NSMinX(tBounds)+0.5,NSMaxY(tBounds)-0.5)]; [tBezierPath lineToPoint:NSMakePoint(NSMaxX(tBounds)+0.5,NSMaxY(tBounds)-0.5)]; [tBezierPath stroke]; tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(NSMinX(tBounds)-0.5,NSMinY(tBounds)+0.5)]; [tBezierPath lineToPoint:NSMakePoint(NSMaxX(tBounds)-0.5,NSMinY(tBounds)+0.5)]; [tBezierPath stroke]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorExecutableViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorStackableViewController.h" @interface CUIInspectorExecutableViewController : CUIInspectorStackableViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorExecutableViewController.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorExecutableViewController.h" #import "CUICodeSigningInformationViewController.h" #import "CUICrashLog+UI.h" #import "CUIRawCrashLog+Path.h" @interface CUIInspectorExecutableViewController () { IBOutlet NSImageView * _executableIconView; IBOutlet NSTextField * _executableNameValue; IBOutlet NSButton * _codeSigningButton; IBOutlet NSTextField * _executableVersionValue; IBOutlet NSTextField * _executableArchitectureValue; IBOutlet NSTextField * _executablePathValue; IBOutlet NSButton * _executablePathShowButton; } - (void)layoutView; - (IBAction)showCodeSigningInformation:(id)sender; - (IBAction)showExecutableInFinder:(id)sender; @end @implementation CUIInspectorExecutableViewController - (void)viewDidLoad { [super viewDidLoad]; if (_executablePathShowButton.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft) { // Mirror image. NSImage * tOriginalImage=_executablePathShowButton.image; NSImage * newTemplate=[NSImage imageWithSize:_executablePathShowButton.bounds.size flipped:NO drawingHandler:^BOOL(NSRect dstRect) { NSAffineTransform * tTransform = [NSAffineTransform transform]; [tTransform translateXBy:NSWidth(self->_executablePathShowButton.bounds) yBy:0]; [tTransform scaleXBy:-1.0 yBy:1.0]; [tTransform concat]; [tOriginalImage drawInRect:dstRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; return YES; }]; newTemplate.template=YES; _executablePathShowButton.image=newTemplate; } } #pragma mark - - (void)refreshUI { CUICrashLog * tCrashLog=self.crashLog; CUICrashLogHeader * tHeader=tCrashLog.header; _executableIconView.image=tCrashLog.processIcon; _executableNameValue.stringValue=tHeader.processName; _codeSigningButton.hidden=(tCrashLog.ipsReport.incident.header.codeSigningInfo==nil); IPSIncidentHeader * tIncidentHeader=tCrashLog.ipsReport.incident.header; if (tIncidentHeader!=nil) { NSString * tShorttVersionString=tIncidentHeader.bundleInfo.bundleShortVersionString; if (tShorttVersionString==nil || [tShorttVersionString isEqualToString:@"???"]==YES) { _executableVersionValue.stringValue=NSLocalizedString(@"Unknown version",@""); } else { NSString * tBundleVersion=tIncidentHeader.bundleInfo.bundleVersion; if (tBundleVersion!=nil) { _executableVersionValue.stringValue=[NSString stringWithFormat:NSLocalizedString(@"Version %@ (%@)",@""),tShorttVersionString, tBundleVersion]; } else { _executableVersionValue.stringValue=[NSString stringWithFormat:NSLocalizedString(@"Version %@",@""),tShorttVersionString]; } } } else { NSString * tVersion=tHeader.executableVersion; if (tVersion==nil || [tVersion isEqualToString:@"???"]==YES) { _executableVersionValue.stringValue=NSLocalizedString(@"Unknown version",@""); } else { _executableVersionValue.stringValue=[NSString stringWithFormat:NSLocalizedString(@"Version %@",@""),tVersion]; } } NSString * tArchitectureValue=@"-"; switch(tHeader.codeType) { case CUICodeTypeX86: tArchitectureValue=@"i386"; break; case CUICodeTypeX86_64: tArchitectureValue=@"x86-64"; break; case CUICodeTypeARM_64: tArchitectureValue=@"ARM-64"; break; default: tArchitectureValue=@"TBD"; break; } _executableArchitectureValue.stringValue=tArchitectureValue; NSString * tExecutablePath=[tCrashLog stringByResolvingUSERInPath:tHeader.executablePath]; if (tExecutablePath==nil) tExecutablePath=tCrashLog.reopenFilePath; if (tExecutablePath==nil) { _executablePathValue.stringValue=@""; _executablePathShowButton.enabled=NO; } else { _executablePathValue.stringValue=tExecutablePath; _executablePathShowButton.enabled=[[NSFileManager defaultManager] fileExistsAtPath:tExecutablePath]; } // Optimize Layout [self layoutView]; } - (CGFloat)heightForMaxWidth:(CGFloat)inMaxWidth { NSTextContainer * tTextContainer= [[NSTextContainer alloc] initWithContainerSize: NSMakeSize(inMaxWidth, FLT_MAX)]; tTextContainer.lineFragmentPadding=0.0; NSLayoutManager * tLayoutManager = [NSLayoutManager new]; tLayoutManager.typesetterBehavior=NSTypesetterBehavior_10_2_WithCompatibility; [tLayoutManager addTextContainer:tTextContainer]; NSTextStorage * tTextStorage=[[NSTextStorage alloc] initWithAttributedString:_executablePathValue.attributedStringValue]; [tTextStorage addLayoutManager:tLayoutManager]; [tLayoutManager glyphRangeForTextContainer:tTextContainer]; CGFloat tHeight=NSHeight([tLayoutManager usedRectForTextContainer:tTextContainer]); if (tHeight<14.0) { // Min Value return 14.0; } return tHeight; } - (void)layoutView { NSRect tFrame=_executablePathValue.frame; CGFloat tOldHeight=NSHeight(tFrame); CGFloat tFittingHeight = [self heightForMaxWidth:tFrame.size.width]; _executablePathValue.frame=tFrame; NSRect tViewFrame=self.view.frame; tViewFrame.origin.y-=(tFittingHeight-tOldHeight); tViewFrame.size.height+=(tFittingHeight-tOldHeight); self.view.frame=tViewFrame; } #pragma mark - - (IBAction)showCodeSigningInformation:(id)sender { NSPopover * tCodeSigningInformationPopOver = [NSPopover new]; tCodeSigningInformationPopOver.contentSize=NSMakeSize(500.0, 20.0); tCodeSigningInformationPopOver.behavior=NSPopoverBehaviorTransient; tCodeSigningInformationPopOver.animates=NO; tCodeSigningInformationPopOver.delegate=self; NSAppearanceName tAppearanceName = ([self.view WB_isEffectiveAppearanceDarkAqua] == NO) ? WB_NSAppearanceNameAqua : WB_NSAppearanceNameDarkAqua; tCodeSigningInformationPopOver.appearance = [NSAppearance appearanceNamed:tAppearanceName]; NSViewController * tPopUpViewController=[[CUICodeSigningInformationViewController alloc] initWithCodeSigningInfo:self.crashLog.ipsReport.incident.header.codeSigningInfo]; tCodeSigningInformationPopOver.contentViewController=tPopUpViewController; tCodeSigningInformationPopOver.contentSize=tPopUpViewController.view.bounds.size; NSView * tTrick=tPopUpViewController.view; // This is used to trigger the viewDidLoad method of the contentViewController. (void)tTrick; [tCodeSigningInformationPopOver showRelativeToRect:_codeSigningButton.bounds ofView:_codeSigningButton preferredEdge:NSMaxXEdge]; } - (IBAction)showExecutableInFinder:(id)sender { NSWorkspace * tSharedWorkspace=[NSWorkspace sharedWorkspace]; NSString * tExecutablePath=self.crashLog.reopenFilePath; if (tExecutablePath==nil) tExecutablePath=self.crashLog.header.executablePath; [tSharedWorkspace selectFile:tExecutablePath inFileViewerRootedAtPath:@""]; } #pragma mark - NSPopoverDelegate - (void)popoverDidClose:(NSNotification *)inNotification { NSWindow * tWindow=self.view.window; if (tWindow.firstResponder==tWindow.contentView) [tWindow makeFirstResponder:self]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorGeneralViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorStackableViewController.h" @interface CUIInspectorGeneralViewController : CUIInspectorStackableViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorGeneralViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorGeneralViewController.h" @interface CUIInspectorGeneralViewController () { IBOutlet NSTextField * _crashDateValue; IBOutlet NSTextField * _operatingSystemVersionLabel; IBOutlet NSTextField * _operatingSystemVersionValue; IBOutlet NSTextField * _bridgeOSVersionValue; } // Notifications - (void)viewFrameDidChange:(NSNotification *)inNotification; - (void)systemClockDidChange:(NSNotification *)inNotification; @end @implementation CUIInspectorGeneralViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidAppear { [super viewDidAppear]; [self refreshDate]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(viewFrameDidChange:) name:NSViewFrameDidChangeNotification object:self.view]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(systemClockDidChange:) name:NSCurrentLocaleDidChangeNotification object:nil]; } - (void)viewWillDisappear { [super viewWillDisappear]; [NSNotificationCenter.defaultCenter removeObserver:self name:NSViewFrameDidChangeNotification object:self.view]; [NSNotificationCenter.defaultCenter removeObserver:self name:NSCurrentLocaleDidChangeNotification object:nil]; } #pragma mark - - (void)refreshDate { static NSArray * sDateFormatters=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSDateFormatter * tLongMediumFormatter=[NSDateFormatter new]; tLongMediumFormatter.locale=[NSLocale autoupdatingCurrentLocale]; tLongMediumFormatter.formatterBehavior=NSDateFormatterBehavior10_4; tLongMediumFormatter.dateStyle=NSDateFormatterLongStyle; tLongMediumFormatter.timeStyle=NSDateFormatterMediumStyle; NSDateFormatter * tMediumMediumFormatter=[NSDateFormatter new]; tMediumMediumFormatter.formatterBehavior=NSDateFormatterBehavior10_4; tMediumMediumFormatter.locale=[NSLocale autoupdatingCurrentLocale]; tMediumMediumFormatter.dateStyle=NSDateFormatterMediumStyle; tMediumMediumFormatter.timeStyle=NSDateFormatterMediumStyle; NSDateFormatter * tShortMediumFormatter=[NSDateFormatter new]; tShortMediumFormatter.formatterBehavior=NSDateFormatterBehavior10_4; tShortMediumFormatter.locale=[NSLocale autoupdatingCurrentLocale]; tShortMediumFormatter.dateStyle=NSDateFormatterShortStyle; tShortMediumFormatter.timeStyle=NSDateFormatterMediumStyle; sDateFormatters=@[ tLongMediumFormatter, tMediumMediumFormatter, tShortMediumFormatter ]; }); CUICrashLog * tCrashLog=self.crashLog; CUICrashLogHeader * tHeader=tCrashLog.header; NSDate * tDate=tHeader.dateTime; NSRect tSavedFrame=_crashDateValue.frame; _crashDateValue.objectValue=tDate; // Try different formatters (from longest string to smallest string) for(NSDateFormatter * tDateFormatter in sDateFormatters) { _crashDateValue.formatter=tDateFormatter; [_crashDateValue sizeToFit]; NSRect tFrame=_crashDateValue.frame; if (NSWidth(tFrame)<=NSWidth(tSavedFrame)) break; } _crashDateValue.frame=tSavedFrame; } - (void)refreshUI { CUICrashLog * tCrashLog=self.crashLog; CUICrashLogHeader * tHeader=tCrashLog.header; [self refreshDate]; CUIOperatingSystemVersion * tOSVersion=tHeader.operatingSystemVersion; if (tOSVersion==nil) { _operatingSystemVersionValue.stringValue=@"-"; } else { NSString * tDeviceOS=@"macOS"; if (tOSVersion.majorVersion>10) { tDeviceOS=@"macOS"; } else { if (tOSVersion.minorVersion>10) { tDeviceOS=@"macOS"; } else if (tOSVersion.minorVersion>7) { tDeviceOS=@"OS X"; } else { tDeviceOS=@"Mac OS X"; } } _operatingSystemVersionLabel.stringValue=[NSString stringWithFormat:NSLocalizedString(@"%@:", @""),tDeviceOS]; _operatingSystemVersionValue.stringValue=tOSVersion.stringValue; } } #pragma mark - Notifications - (void)viewFrameDidChange:(NSNotification *)inNotification { [self refreshDate]; } - (void)systemClockDidChange:(NSNotification *)inNotification { [self refreshDate]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorProcessesViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorStackableViewController.h" @interface CUIInspectorProcessesViewController : CUIInspectorStackableViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorProcessesViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorProcessesViewController.h" @interface CUIInspectorProcessesViewController () { IBOutlet NSTextField * _processNameValue; IBOutlet NSTextField * _parentProcessNameValue; IBOutlet NSTextField * _responsibleProcessNameValue; } @end @implementation CUIInspectorProcessesViewController - (void)refreshUI { CUICrashLog * tCrashLog=self.crashLog; CUICrashLogHeader * tHeader=tCrashLog.header; // Processes NSString * tProcessFormatString=NSLocalizedString(@"%@ (%u)", @""); _processNameValue.stringValue=[NSString stringWithFormat:tProcessFormatString,tHeader.processName,tHeader.processIdentifier]; NSString * tParentProcessName=tHeader.parentProcessName; if ([tParentProcessName isEqualToString:@"???"]==YES && tHeader.parentProcessIdentifier==1) tParentProcessName=@"launchd"; _parentProcessNameValue.stringValue=[NSString stringWithFormat:tProcessFormatString,tParentProcessName,tHeader.parentProcessIdentifier]; if (tHeader.responsibleProcessName==nil && tHeader.responsibleProcessIdentifier==0) _responsibleProcessNameValue.stringValue=@"-"; else _responsibleProcessNameValue.stringValue=[NSString stringWithFormat:tProcessFormatString,tHeader.responsibleProcessName,tHeader.responsibleProcessIdentifier]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorStackableViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" extern NSString * const CUIInspectorStackableViewFrameDidChangeNotification; @interface CUIInspectorStackableViewController : NSViewController @property (nonatomic) CUICrashLog * crashLog; - (void)refreshUI; - (void)layoutView; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorStackableViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorStackableViewController.h" NSString * const CUIInspectorStackableViewFrameDidChangeNotification=@"CUIInspectorStackableViewFrameDidChangeNotification"; @implementation CUIInspectorStackableViewController - (void)setCrashLog:(CUICrashLog *)inCrashLog { if (_crashLog==inCrashLog) return; _crashLog=inCrashLog; [self refreshUI]; } #pragma mark - - (void)refreshUI { } - (void)layoutView { } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorUserViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorStackableViewController.h" @interface CUIInspectorUserViewController : CUIInspectorStackableViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorUserViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorUserViewController.h" @interface CUIInspectorUserViewController () { IBOutlet NSTextField * _userIDValue; } @end @implementation CUIInspectorUserViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - - (void)refreshUI { CUICrashLog * tCrashLog=self.crashLog; CUICrashLogHeader * tHeader=tCrashLog.header; // User NSString * tUserIDValue=@"root"; if (tHeader.userIdentifier!=0) { tUserIDValue=[NSString stringWithFormat:@"%u",tHeader.userIdentifier]; } _userIDValue.stringValue=tUserIDValue; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" @interface CUIInspectorViewController : NSViewController @property (nonatomic) CUICrashLog * crashLog; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIInspectorViewController.h" #import "CUICrashLog+UI.h" #import "CUIInspectorGeneralViewController.h" #import "CUIInspectorUserViewController.h" #import "CUIInspectorExecutableViewController.h" #import "CUIInspectorProcessesViewController.h" @interface CUIInspectorViewController () { NSMutableArray * _stackableViewControllers; } - (void)refreshLayout; // Notifications - (void)viewFrameDidChange:(NSNotification *)inNotification; @end @implementation CUIInspectorViewController - (instancetype)init { self=[super init]; if (self!=nil) { _stackableViewControllers=[NSMutableArray array]; CUIInspectorGeneralViewController * tGeneralViewController=[CUIInspectorGeneralViewController new]; [_stackableViewControllers addObject:tGeneralViewController]; CUIInspectorUserViewController * tUserViewController=[CUIInspectorUserViewController new]; [_stackableViewControllers addObject:tUserViewController]; CUIInspectorExecutableViewController * tExecutableViewController=[CUIInspectorExecutableViewController new]; [_stackableViewControllers addObject:tExecutableViewController]; CUIInspectorProcessesViewController * tProcessesViewController=[CUIInspectorProcessesViewController new]; [_stackableViewControllers addObject:tProcessesViewController]; } return self; } - (NSString *)nibName { return @"CUIInspectorViewController"; } - (void)viewDidLoad { [super viewDidLoad]; for(CUIInspectorStackableViewController * tViewController in _stackableViewControllers) { tViewController.crashLog=self.crashLog; [self.view addSubview:tViewController.view]; } [self refreshLayout]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(viewFrameDidChange:) name:NSViewFrameDidChangeNotification object:self.view]; } #pragma mark - - (void)setCrashLog:(CUICrashLog *)inCrashLog { if (_crashLog==inCrashLog) return; _crashLog=inCrashLog; for(CUIInspectorStackableViewController * tViewController in _stackableViewControllers) { tViewController.crashLog=inCrashLog; } [self refreshLayout]; } #pragma mark - - (void)refreshLayout { NSRect tFrame=self.view.frame; CGFloat tMaxY=NSMaxY(tFrame); for(CUIInspectorStackableViewController * tViewController in _stackableViewControllers) { [tViewController layoutView]; NSRect tInspectorViewFrame=tViewController.view.bounds; tInspectorViewFrame.origin.y=tMaxY-NSHeight(tInspectorViewFrame); tViewController.view.frame=tInspectorViewFrame; tMaxY=tInspectorViewFrame.origin.y; } } #pragma mark - Notifications - (void)viewFrameDidChange:(NSNotification *)inNotification { [self refreshLayout]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIInspectorViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIKeyViews.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @protocol CUIKeyViews - (NSView *)firstKeyView; - (NSView *)lastKeyView; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableDockedThreadView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILightTableThreadView.h" @interface CUILightTableDockedThreadView : CUILightTableThreadView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableDockedThreadView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILightTableDockedThreadView.h" @implementation CUILightTableDockedThreadView - (void)drawRect:(NSRect)dirtyRect { [NSGraphicsContext saveGraphicsState]; // Background NSShadow *shadow = [NSShadow new]; shadow.shadowBlurRadius=5.0; shadow.shadowOffset=NSMakeSize(0.0, -2.0); shadow.shadowColor=[NSColor colorWithCalibratedWhite:0.0 alpha:0.5]; [shadow set]; NSRect tRect=NSInsetRect(self.bounds,5,0); tRect.origin.y+=5; tRect.size.height-=5; NSBezierPath * tBackgroundBezierPath=[NSBezierPath bezierPathWithRoundedRect:tRect xRadius:5 yRadius:5]; [[NSColor colorWithDeviceWhite:0.95 alpha:1.0] set]; [tBackgroundBezierPath fill]; [NSGraphicsContext restoreGraphicsState]; // Header tRect.origin.y=NSMaxY(tRect)-32.0; tRect.size.height=32.0; NSBezierPath * tHeaderBezierPath=[NSBezierPath bezierPath]; [tHeaderBezierPath moveToPoint:tRect.origin]; [tHeaderBezierPath lineToPoint:NSMakePoint(NSMaxX(tRect),NSMinY(tRect))]; [tHeaderBezierPath lineToPoint:NSMakePoint(NSMaxX(tRect),NSMaxY(tRect)-8.0)]; [tHeaderBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(tRect)-8.0,NSMaxY(tRect)-8.0) radius:8.0 startAngle:0 endAngle:90 clockwise:NO]; [tHeaderBezierPath lineToPoint:NSMakePoint(NSMinX(tRect)+8.0,NSMaxY(tRect))]; [tHeaderBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(tRect)+8.0,NSMaxY(tRect)-8.0) radius:8.0 startAngle:90 endAngle:180 clockwise:NO]; [tHeaderBezierPath closePath]; if (self.crashed==YES) [[NSColor colorWithDeviceRed:203.0/255.0 green:49.0/255.0 blue:34.0/255.0 alpha:1.0 ] set]; else { if (self.applicationSpecificBacktrace==YES) [[NSColor orangeColor] set]; else [[NSColor colorWithDeviceWhite:0.60 alpha:1.0] set]; } [tHeaderBezierPath fill]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableThreadView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUILightTableThreadView : NSView @property (nonatomic) NSCollectionViewItemHighlightState highlightState; @property (nonatomic) BOOL selected; @property (nonatomic) BOOL crashed; @property (nonatomic) BOOL applicationSpecificBacktrace; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableThreadView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILightTableThreadView.h" @implementation CUILightTableThreadView - (void)setHighlightState:(NSCollectionViewItemHighlightState)inHighlightState { _highlightState=inHighlightState; [self setNeedsDisplay:YES]; } - (void)setSelected:(BOOL)inSelected { _selected=inSelected; [self setNeedsDisplay:YES]; } - (void)setCrashed:(BOOL)inCrashed { _crashed=inCrashed; [self setNeedsDisplay:YES]; } - (void)setApplicationSpecificBacktrace:(BOOL)inApplicationSpecificBacktrace { _applicationSpecificBacktrace=inApplicationSpecificBacktrace; [self setNeedsDisplay:YES]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadsViewController.h" @interface CUILightTableViewController : CUIThreadsViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILightTableViewController.h" #import "CUICollectionViewVisibleThreadsLayout.h" #import "CUICollectionViewDockedThreadsLayout.h" #import "CUICollectionViewVisibleThreadItem.h" #import "CUICollectionViewDockedThreadItem.h" #import "CUILightTableVisibleThreadView.h" #import "CUILightTableVisibleInterGapView.h" @interface CUILightTableViewController () { IBOutlet NSCollectionView * _visiblethreadsCollectionView; IBOutlet NSCollectionView * _dockedThreadsCollectionView; NSMutableArray * _visibleThreads; NSMutableArray * _dockedThreads; NSSet * _indexPathOfVisibleThreadsBeingDragged; } - (void)minimizeThread:(CUIThread *)inThread; @end @implementation CUILightTableViewController - (NSString *)nibName { return @"CUILightTableViewController"; } - (void)awakeFromNib { // Table Collection View _visiblethreadsCollectionView.collectionViewLayout=[CUICollectionViewVisibleThreadsLayout new]; _visiblethreadsCollectionView.dataSource=self; _visiblethreadsCollectionView.delegate=self; NSNib * tNib=[[NSNib alloc] initWithNibNamed:@"CUICollectionViewVisibleThreadItem" bundle:[NSBundle mainBundle]]; [_visiblethreadsCollectionView registerNib:tNib forItemWithIdentifier:@"visibleThread"]; [_visiblethreadsCollectionView registerForDraggedTypes:@[NSPasteboardTypeString]]; [_visiblethreadsCollectionView setDraggingSourceOperationMask:NSDragOperationMove forLocal:YES]; // Dock Collection View _dockedThreadsCollectionView.collectionViewLayout=[CUICollectionViewDockedThreadsLayout new]; _dockedThreadsCollectionView.dataSource=self; _dockedThreadsCollectionView.delegate=self; tNib=[[NSNib alloc] initWithNibNamed:@"CUICollectionViewDockedThreadItem" bundle:[NSBundle mainBundle]]; [_dockedThreadsCollectionView registerNib:tNib forItemWithIdentifier:@"dockedThread"]; [_dockedThreadsCollectionView registerForDraggedTypes:@[NSPasteboardTypeString]]; [_dockedThreadsCollectionView setDraggingSourceOperationMask:NSDragOperationMove forLocal:YES]; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - - (void)setCrashLog:(CUICrashLog *)inCrashLog { [super setCrashLog:inCrashLog]; _visibleThreads=[inCrashLog.backtraces.threads mutableCopy]; _dockedThreads=[NSMutableArray array]; [_visiblethreadsCollectionView reloadData]; [_dockedThreadsCollectionView reloadData]; } - (void)setVisibleStackFrameComponents:(CUIStackFrameComponents)inVisibleStackFrameComponents { [super setVisibleStackFrameComponents:inVisibleStackFrameComponents]; [_visiblethreadsCollectionView reloadData]; } #pragma mark - - (void)minimizeThread:(CUIThread *)inThread { NSUInteger tIndex=[_visibleThreads indexOfObject:inThread]; if (tIndex==NSNotFound) return; [_visibleThreads removeObjectAtIndex:tIndex]; __block NSUInteger tInsertionIndex=0; NSUInteger tThreadNumber=inThread.number; [_dockedThreads enumerateObjectsUsingBlock:^(CUIThread * bThread, NSUInteger bIndex, BOOL * bOutStop) { if (tThreadNumber *)inIndexPaths { // A COMPLETER } #pragma mark - NSCollectionViewDelegate - Drag and Drop - (BOOL)collectionView:(NSCollectionView *)inCollectionView canDragItemsAtIndexPaths:(NSSet *)inIndexPaths withEvent:(NSEvent *)inEvent { return YES; } - (nullable id )collectionView:(NSCollectionView *)inCollectionView pasteboardWriterForItemAtIndexPath:(NSIndexPath *)indexPath { NSPasteboardItem * tPasteboardItem=[NSPasteboardItem new]; [tPasteboardItem setString:@"something" forType:NSPasteboardTypeString]; return tPasteboardItem; } - (void)collectionView:(NSCollectionView *)inCollectionView draggingSession:(nonnull NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint forItemsAtIndexPaths:(nonnull NSSet *)indexPaths { _indexPathOfVisibleThreadsBeingDragged=indexPaths; } - (NSDragOperation)collectionView:(NSCollectionView *)inCollectionView validateDrop:(nonnull id)draggingInfo proposedIndexPath:(NSIndexPath *__autoreleasing _Nonnull * _Nonnull)proposedDropIndexPath dropOperation:(nonnull NSCollectionViewDropOperation *)proposedDropOperation { if (*proposedDropOperation==NSCollectionViewDropOn) return NSDragOperationNone; if (_indexPathOfVisibleThreadsBeingDragged==nil) return NSDragOperationCopy; NSIndexPath * tIndexPathOfFirstItem = [_indexPathOfVisibleThreadsBeingDragged anyObject]; if ((*proposedDropIndexPath).item==tIndexPathOfFirstItem.item || (*proposedDropIndexPath).item==(tIndexPathOfFirstItem.item+1)) return NO; return NSDragOperationMove; } - (BOOL)collectionView:(NSCollectionView *)inCollectionView acceptDrop:(nonnull id)draggingInfo indexPath:(nonnull NSIndexPath *)indexPath dropOperation:(NSCollectionViewDropOperation)dropOperation { if (_indexPathOfVisibleThreadsBeingDragged != nil) { // 2 NSIndexPath * tIndexPathOfFirstItem = [_indexPathOfVisibleThreadsBeingDragged anyObject]; NSIndexPath * toIndexPath; if ([tIndexPathOfFirstItem compare:indexPath] == NSOrderedAscending) { toIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section]; } else { toIndexPath = [NSIndexPath indexPathForItem:indexPath.item inSection:indexPath.section]; } // 3 // 4 id tObject=_visibleThreads[tIndexPathOfFirstItem.item]; [_visibleThreads removeObjectAtIndex:tIndexPathOfFirstItem.item]; [_visibleThreads insertObject:tObject atIndex:toIndexPath.item]; [inCollectionView.animator moveItemAtIndexPath:tIndexPathOfFirstItem toIndexPath:toIndexPath]; } return YES; } - (void)collectionView:(NSCollectionView *)inCollectionView draggingSession:(nonnull NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint dragOperation:(NSDragOperation)operation { _indexPathOfVisibleThreadsBeingDragged=nil; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableVisibleInterGapView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUILightTableVisibleInterGapView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableVisibleInterGapView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILightTableVisibleInterGapView.h" @implementation CUILightTableVisibleInterGapView - (void)drawRect:(NSRect)dirtyRect { [[NSColor alternateSelectedControlColor] set]; NSRectFill(self.bounds); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableVisibleThreadView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILightTableThreadView.h" @interface CUILightTableVisibleThreadView : CUILightTableThreadView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILightTableVisibleThreadView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILightTableVisibleThreadView.h" @implementation CUILightTableVisibleThreadView - (void)drawRect:(NSRect)dirtyRect { [NSGraphicsContext saveGraphicsState]; // Background NSShadow *shadow = [NSShadow new]; shadow.shadowBlurRadius=5.0; shadow.shadowOffset=NSMakeSize(0.0, -2.0); shadow.shadowColor=[NSColor colorWithCalibratedWhite:0.0 alpha:0.5]; [shadow set]; NSRect tRect=NSInsetRect(self.bounds,5,0); tRect.origin.y+=5; tRect.size.height-=5; NSBezierPath * tBackgroundBezierPath=[NSBezierPath bezierPathWithRoundedRect:tRect xRadius:8 yRadius:8]; [[NSColor colorWithDeviceWhite:0.95 alpha:1.0] set]; [tBackgroundBezierPath fill]; [NSGraphicsContext restoreGraphicsState]; // Header tRect.origin.y=NSMaxY(tRect)-32.0; tRect.size.height=32.0; NSBezierPath * tHeaderBezierPath=[NSBezierPath bezierPath]; [tHeaderBezierPath moveToPoint:tRect.origin]; [tHeaderBezierPath lineToPoint:NSMakePoint(NSMaxX(tRect),NSMinY(tRect))]; [tHeaderBezierPath lineToPoint:NSMakePoint(NSMaxX(tRect),NSMaxY(tRect)-8.0)]; [tHeaderBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(tRect)-8.0,NSMaxY(tRect)-8.0) radius:8.0 startAngle:0 endAngle:90 clockwise:NO]; [tHeaderBezierPath lineToPoint:NSMakePoint(NSMinX(tRect)+8.0,NSMaxY(tRect))]; [tHeaderBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(tRect)+8.0,NSMaxY(tRect)-8.0) radius:8.0 startAngle:90 endAngle:180 clockwise:NO]; [tHeaderBezierPath closePath]; if (self.crashed==YES) [[NSColor colorWithDeviceRed:203.0/255.0 green:49.0/255.0 blue:34.0/255.0 alpha:1.0 ] set]; else { if (self.applicationSpecificBacktrace==YES) [[NSColor orangeColor] set]; else [[NSColor colorWithDeviceWhite:0.60 alpha:1.0] set]; } [tHeaderBezierPath fill]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILineJumperWindowController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUILineJumperWindowController : NSWindowController + (CUILineJumperWindowController *)sharedLineJumperWindowController; - (void)popUpForTextView:(NSTextView *)inTextView; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUILineJumperWindowController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUILineJumperWindowController.h" @interface CUILineNumberFormatter : NSFormatter @end @implementation CUILineNumberFormatter - (NSString *)stringForObjectValue:(id) inObject { if ([inObject isKindOfClass:NSString.class]==NO) return inObject; return inObject; } - (BOOL)getObjectValue:(id *) outObject forString:(NSString *) inString errorDescription:(NSString **) outError { *outObject=[inString copy]; return YES; } #pragma mark - - (BOOL)isPartialStringValid:(NSString *) inPartialString newEditingString:(NSString **) outNewString errorDescription:(NSString **) outError { if (inPartialString==nil) return YES; NSUInteger tLength=inPartialString.length; if (tLength==0) return YES; if (tLength>10) { *outNewString=nil; *outError=@"NSBeep"; return NO; } static NSCharacterSet * sForbidddenCharacterSet=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sForbidddenCharacterSet=[[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet]; }); if ([inPartialString rangeOfCharacterFromSet:sForbidddenCharacterSet].location!=NSNotFound) { *outNewString=nil; *outError=@"NSBeep"; return NO; } return YES; } @end @interface CUILineJumperWindowController () { IBOutlet NSTextField * _lineNumberField; IBOutlet NSButton * _resetButton; NSTextView * _targetedTextView; } - (IBAction)takeLineNumberFrom:(id)sender; - (IBAction)reset:(id)sender; @end @implementation CUILineJumperWindowController + (CUILineJumperWindowController *)sharedLineJumperWindowController { static CUILineJumperWindowController * sLineJumperWindowController=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sLineJumperWindowController=[CUILineJumperWindowController new]; }); return sLineJumperWindowController; } #pragma mark - - (NSString *)windowNibName { return @"CUILineJumperWindowController"; } - (void)windowDidLoad { [super windowDidLoad]; self.window.movableByWindowBackground=YES; _lineNumberField.formatter=[CUILineNumberFormatter new]; } #pragma mark - - (void)popUpForTextView:(NSTextView *)inTextView { if (inTextView==nil) return; _targetedTextView=inTextView; _lineNumberField.stringValue=@""; [self showWindow:self]; } - (void)_abortEditing { [_lineNumberField abortEditing]; _lineNumberField.stringValue=@""; [self.window close]; } #pragma mark - - (IBAction)cancel:(id)sender { [self _abortEditing]; } - (IBAction)takeLineNumberFrom:(NSTextField *)sender { NSString * tString=sender.stringValue; if (tString.length==0) { NSBeep(); return; } NSInteger tLineNumberToJumpTo=tString.integerValue; if (tLineNumberToJumpTo<=0) { NSBeep(); return; } NSLayoutManager * tLayoutManager = _targetedTextView.layoutManager; NSUInteger tNumberOfGlyphs = tLayoutManager.numberOfGlyphs; NSUInteger tGlyphIndex = 0; NSString *text = _targetedTextView.string; for (NSUInteger tLineNumber = 1; tGlyphIndex < tNumberOfGlyphs;) { NSRange tLineRange; [tLayoutManager lineFragmentRectForGlyphAtIndex:tGlyphIndex effectiveRange:&tLineRange]; if (tLineNumber == tLineNumberToJumpTo) { // Scroll to line NSRect tBounds=[_targetedTextView.layoutManager boundingRectForGlyphRange:tLineRange inTextContainer:_targetedTextView.textContainer]; tBounds.origin.x=0; [_targetedTextView scrollPoint:tBounds.origin]; // Select line [_targetedTextView setSelectedRange:tLineRange]; // Hide # Line Number window and set the focus on the text view [self.window orderOut:nil]; [_targetedTextView.window makeFirstResponder:_targetedTextView]; return; } tGlyphIndex=NSMaxRange(tLineRange); NSUInteger characterIndex=[tLayoutManager characterIndexForGlyphAtIndex:tGlyphIndex]; if (characterIndex > 0) { if ([text characterAtIndex:characterIndex-1]=='\n') tLineNumber++; } else { tLineNumber++; } } // Line not found (tLineNumberToJumpTo > number of lines) NSBeep(); } - (IBAction)reset:(id)sender { _lineNumberField.currentEditor.string=@""; _resetButton.hidden=YES; } #pragma mark - NSTextFieldDelegate - (void)controlTextDidChange:(NSNotification *)inNotification { NSText * tFieldEditor=inNotification.userInfo[@"NSFieldEditor"]; NSString * tString=tFieldEditor.string; _resetButton.hidden=(tString.length==0); } - (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(nullable NSString *)error { NSBeep(); } #pragma mark - NSWindowDelegate - (void)windowDidResignMain:(NSNotification *)notification { [self _abortEditing]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIMainWindow.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIMainWindow : NSWindow @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIMainWindow.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIMainWindow.h" #import "CUICrashLogsSelection.h" NSString * const CUIDefaultsWindowToolbarVisibleKey=@"window.toolbar.visible"; @implementation CUIMainWindow + (void)initialize { [[NSUserDefaults standardUserDefaults] registerDefaults:@{ CUIDefaultsWindowToolbarVisibleKey:@(YES) }]; } - (void)awakeFromNib { NSUserDefaults * tDefaults=[NSUserDefaults standardUserDefaults]; if ([tDefaults boolForKey:CUIDefaultsWindowToolbarVisibleKey]==NO) { self.toolbar.visible=NO; self.titleVisibility=NSWindowTitleVisible; self.representedFilename=@""; self.title=@"Unexpectedly"; } else { self.titleVisibility=NSWindowTitleHidden; } } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(toggleToolbarShown:)) { if (self.toolbar.isVisible==YES) inMenuItem.title=NSLocalizedString(@"Hide Toolbar",@""); else inMenuItem.title=NSLocalizedString(@"Show Toolbar",@""); } return [super validateMenuItem:inMenuItem]; } - (void)toggleToolbarShown:(id)sender { [super toggleToolbarShown:sender]; self.titleVisibility=(self.toolbar.isVisible==YES) ? NSWindowTitleHidden : NSWindowTitleVisible; if (self.titleVisibility==NSWindowTitleVisible) { self.representedFilename=@""; // Set to @"" so that the next call to setRepresentedFileName shows the proxy icon and enables the menu (if the value does not change, the API does not do its job) CUICrashLogsSelection * tSelection=[CUICrashLogsSelection sharedSelection]; CUIRawCrashLog * tCrashLog=tSelection.crashLogs.firstObject; if (tCrashLog==nil) { self.title=@"Unexpectedly"; return; } NSString * tCrashLogFilePath=tCrashLog.crashLogFilePath; self.title=[tCrashLogFilePath lastPathComponent]; self.representedFilename=tCrashLogFilePath; } // Remember whether the toolbar is shown or not [[NSUserDefaults standardUserDefaults] setBool:(self.toolbar.isVisible==YES) forKey:CUIDefaultsWindowToolbarVisibleKey]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIMainWindowController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIMainWindowController : NSWindowController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIMainWindowController.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIMainWindowController.h" #import "CUICrashLogsMainViewController.h" #import "CUICrashLogsSelection.h" #import "CUIRegistersWindowController.h" #import "CUIApplicationPreferences.h" extern NSString * const CUICrashLogContentsViewPresentationModeDidChangeNotification; extern NSString * const CUIBottomViewCollapseStateDidChangeNotification; extern NSString * const CUIDefaultsBottomViewCollapsedKey; @interface CUIMainWindowController () { CUICrashLogsMainViewController * _mainViewController; IBOutlet NSButton * _registersWindowButton; IBOutlet NSSegmentedControl * _presentationModeSegmentedControl; IBOutlet NSSegmentedControl * _mainLayoutSegmentedControl; } - (IBAction)CUIMENUACTION_showHideRegisters:(id)sender; // Notifications - (void)splitViewDidResizeSubviews:(NSNotification *)inNotification; - (void)bottomViewCollapseStateDidChange:(NSNotification *)inNotification; - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification; - (void)contentsViewPresentationModeDidChange:(NSNotification *)inNotification; @end @implementation CUIMainWindowController - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSString *)windowNibName { return @"CUIMainWindowController"; } - (void)windowDidLoad { [super windowDidLoad]; // Register for notifications NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(crashLogsSelectionDidChange:) name:CUICrashLogsSelectionDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(contentsViewPresentationModeDidChange:) name:CUICrashLogContentsViewPresentationModeDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(splitViewDidResizeSubviews:) name:NSSplitViewDidResizeSubviewsNotification object:_mainViewController.splitView]; [tNotificationCenter addObserver:self selector:@selector(bottomViewCollapseStateDidChange:) name:CUIBottomViewCollapseStateDidChangeNotification object:self.window]; [tNotificationCenter addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:nil]; // Add main view _mainViewController=[CUICrashLogsMainViewController new]; _mainViewController.view.frame=self.window.contentView.bounds; [self.window.contentView addSubview:_mainViewController.view]; [self.window makeFirstResponder:_mainViewController]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(CUIMENUACTION_showHideRegisters:)) { CUIRegistersWindowController * tRegistersWindowController=[CUIRegistersWindowController sharedRegistersWindowController]; if ([tRegistersWindowController.window isVisible]==YES) { inMenuItem.title=NSLocalizedString(@"Hide Registers", @""); } else { inMenuItem.title=NSLocalizedString(@"Show Registers", @""); } } return YES; } - (void)noResponderFor:(SEL)inEventSelector { if (inEventSelector!=@selector(keyDown:)) return; [NSNotificationCenter.defaultCenter postNotificationName:@"windowDidNotHandleKeyEventNotification" object:self.window userInfo:@{@"Event":[NSApp currentEvent]}]; } - (IBAction)CUIMENUACTION_showHideRegisters:(id)sender { CUIRegistersWindowController * tRegistersWindowController=[CUIRegistersWindowController sharedRegistersWindowController]; if ([tRegistersWindowController.window isVisible]==YES) { [tRegistersWindowController.window close]; } else { [tRegistersWindowController showWindow:nil]; _registersWindowButton.state=NSControlStateValueOn; } } - (void)showWindow:(id)sender { [super showWindow:sender]; // Show Registers window? if ([CUIApplicationPreferences sharedPreferences].showsRegistersWindowAutomaticallyAtLaunch==YES) [self CUIMENUACTION_showHideRegisters:self]; } #pragma mark - Notifications - (void)splitViewDidResizeSubviews:(NSNotification *)inNotification { [_mainLayoutSegmentedControl setSelected:([_mainViewController.splitView isSubviewCollapsed:_mainViewController.splitView.subviews[0]]==NO) forSegment:0]; [_mainLayoutSegmentedControl setSelected:([_mainViewController.splitView isSubviewCollapsed:_mainViewController.splitView.subviews[2]]==NO) forSegment:2]; } - (void)bottomViewCollapseStateDidChange:(NSNotification *)inNotification { BOOL tIsCollapsed=[inNotification.userInfo[@"Collapsed"] boolValue]; [_mainLayoutSegmentedControl setSelected:(tIsCollapsed==NO) forSegment:1]; } - (void)contentsViewPresentationModeDidChange:(NSNotification *)inNotification { NSNumber * tNumber=inNotification.userInfo[@"mode"]; if (tNumber==nil) return; NSUInteger tMode=tNumber.integerValue; [_presentationModeSegmentedControl selectSegmentWithTag:tMode]; [_mainLayoutSegmentedControl setEnabled:(tMode==1) forSegment:1]; if (tMode!=1) { [_mainLayoutSegmentedControl setSelected:NO forSegment:1]; } else { BOOL tIsCollapsed=NO; tNumber=[[NSUserDefaults standardUserDefaults] objectForKey:CUIDefaultsBottomViewCollapsedKey]; if (tNumber==nil || [tNumber boolValue]==YES) tIsCollapsed=YES; [_mainLayoutSegmentedControl setSelected:(tIsCollapsed==NO) forSegment:1]; } } - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification { CUICrashLogsSelection * tSelection=inNotification.object; if ([tSelection isKindOfClass:[CUICrashLogsSelection class]]==NO) return; _presentationModeSegmentedControl.enabled=(tSelection.crashLogs.count>0); if ([_presentationModeSegmentedControl tagForSegment:_presentationModeSegmentedControl.selectedSegment]==1) { [_mainLayoutSegmentedControl setEnabled:(tSelection.crashLogs.count>0) forSegment:1]; } CUIRawCrashLog * tCrashLog=tSelection.crashLogs.firstObject; if (tCrashLog==nil) { self.window.title=@"Unexpectedly"; self.window.representedFilename=@""; return; } NSString * tCrashLogFilePath=tCrashLog.crashLogFilePath; self.window.title=tCrashLogFilePath.lastPathComponent; self.window.representedFilename=tCrashLogFilePath; } - (void)windowWillClose:(NSNotification *)inNotification { NSWindow * tWindow=inNotification.object; if (tWindow==self.window) { [NSApp terminate:self]; return; } if ([tWindow.windowController isKindOfClass:[CUIRegistersWindowController class]]==YES) { _registersWindowButton.state=NSControlStateValueOff; } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUINavigationChevronView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUINavigationChevronView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUINavigationChevronView.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUINavigationChevronView.h" @implementation CUINavigationChevronView - (void)drawRect:(NSRect)dirtyRect { NSRect tBounds=self.bounds; [[NSColor colorWithDeviceWhite:0.55 alpha:1.0] set]; CGFloat tMidY=round(NSMidY(tBounds)); NSBezierPath * tBezierPath=[NSBezierPath bezierPath]; if (self.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { [tBezierPath moveToPoint:NSMakePoint(NSMaxX(tBounds)-5,NSMaxY(tBounds))]; [tBezierPath lineToPoint:NSMakePoint(NSMaxX(tBounds)-1,tMidY)]; [tBezierPath lineToPoint:NSMakePoint(NSMaxX(tBounds)-5,NSMinY(tBounds))]; } else { [tBezierPath moveToPoint:NSMakePoint(NSMaxX(tBounds)-5,NSMaxY(tBounds))]; [tBezierPath lineToPoint:NSMakePoint(NSMaxX(tBounds)-9,tMidY)]; [tBezierPath lineToPoint:NSMakePoint(NSMaxX(tBounds)-5,NSMinY(tBounds))]; } [tBezierPath stroke]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUINavigationView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUINavigationView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUINavigationView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUINavigationView.h" @implementation CUINavigationView - (void)drawRect:(NSRect)dirtyRect { NSRect tBounds=self.bounds; BOOL tIsDark=[self WB_isEffectiveAppearanceDarkAqua]; if (tIsDark==NO) [[NSColor colorWithDeviceWhite:0.95 alpha:1.0] set]; else [[NSColor colorWithDeviceWhite:0.0 alpha:0.15] set]; NSRectFillUsingOperation(dirtyRect, NSCompositingOperationSourceOver); [[NSColor colorWithDeviceWhite:0.0 alpha:0.25] set]; [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(tBounds),NSMinY(tBounds)+0.5) toPoint:NSMakePoint(NSMaxX(tBounds),NSMinY(tBounds)+0.5)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIOperatingSystemVersion.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIOperatingSystemVersion : NSObject @property (readonly) NSInteger majorVersion; @property (readonly) NSInteger minorVersion; @property (readonly) NSInteger patchVersion; @property (readonly,copy) NSString * buildNumber; - (instancetype)initWithString:(NSString *)inString; - (NSString *)stringValue; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIOperatingSystemVersion.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIOperatingSystemVersion.h" @interface CUIOperatingSystemVersion () @property NSInteger majorVersion; @property NSInteger minorVersion; @property NSInteger patchVersion; @property (copy) NSString * buildNumber; @end @implementation CUIOperatingSystemVersion - (instancetype)initWithString:(NSString *)inString { if ([inString isKindOfClass:[NSString class]]==NO) return nil; self=[super init]; if (self!=nil) { NSArray * tComponents=[inString componentsSeparatedByString:@" "]; if (tComponents.count==0 || [tComponents.firstObject length]==0) return nil; NSString * tNumericVersion=tComponents.firstObject; NSArray * tVersionComponents=[tNumericVersion componentsSeparatedByString:@"."]; NSUInteger tComponentsCount=tVersionComponents.count; _majorVersion=[tVersionComponents[0] integerValue]; if (tComponentsCount>1) _minorVersion=[tVersionComponents[1] integerValue]; if (tComponentsCount>2) _patchVersion=[tVersionComponents[2] integerValue]; if (tComponents.count>1) _buildNumber=[tComponents[1] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"()"]]; } return self; } #pragma mark - - (NSString *)stringValue { return [NSString stringWithFormat:@"%ld.%ld.%ld",self.majorVersion,self.minorVersion,self.patchVersion]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIOutlineModeDisplaySettings.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIStackFrameComponents.h" @interface CUIOutlineModeDisplaySettings : NSObject @property BOOL showOnlyCrashedThread; @property CUIStackFrameComponents visibleStackFrameComponents; - (instancetype)initWithRepresentation:(NSDictionary *)inDictionary; - (NSDictionary *)representation; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIOutlineModeDisplaySettings.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIOutlineModeDisplaySettings.h" NSString * const CUIOutlineModeDisplaySettingsShowOnlyCrashedThreadKey=@"backtrace.crashedThreadOnly"; NSString * const CUIOutlineModeDisplaySettingsVisibleStackFrameComponentsKey=@"stack-frame.components.visible"; @implementation CUIOutlineModeDisplaySettings - (instancetype)initWithRepresentation:(NSDictionary *)inDictionary { if ([inDictionary isKindOfClass:NSDictionary.class]==NO) return nil; self=[super init]; if (self!=nil) { NSNumber * tNumber=inDictionary[CUIOutlineModeDisplaySettingsShowOnlyCrashedThreadKey]; if ([tNumber isKindOfClass:NSNumber.class]==NO) return nil; _showOnlyCrashedThread=tNumber.boolValue; tNumber=inDictionary[CUIOutlineModeDisplaySettingsVisibleStackFrameComponentsKey]; if ([tNumber isKindOfClass:NSNumber.class]==NO) return nil; _visibleStackFrameComponents=tNumber.unsignedIntegerValue; } return self; } - (NSDictionary *)representation { return @{ CUIOutlineModeDisplaySettingsShowOnlyCrashedThreadKey:@(self.showOnlyCrashedThread), CUIOutlineModeDisplaySettingsVisibleStackFrameComponentsKey:@(self.visibleStackFrameComponents) }; } #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { CUIOutlineModeDisplaySettings * nSettings=[CUIOutlineModeDisplaySettings new]; nSettings.showOnlyCrashedThread=self.showOnlyCrashedThread; nSettings.visibleStackFrameComponents=self.visibleStackFrameComponents; return nSettings; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIParsingErrors.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUIParsingErrorDomain; extern NSString * const CUIParsingErrorLineKey; extern NSString * const CUIParsingErrorSectionNameKey; typedef NS_ENUM(NSUInteger, CUIParsingError) { CUIParsingUnknownError=0, CUIParsingSectionDetectionFailedError=1, CUIParsingDateTimeParsingError=2, }; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIParsingErrors.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIParsingErrors.h" NSString * const CUIParsingErrorDomain=@"fr.whitebox.unexpectedly.parsing"; NSString * const CUIParsingErrorLineKey=@"line"; NSString * const CUIParsingErrorSectionNameKey=@"section"; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneAdvancedViewController.h ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneViewController.h" NS_ASSUME_NONNULL_BEGIN @interface CUIPreferencePaneAdvancedViewController : CUIPreferencePaneViewController @end NS_ASSUME_NONNULL_END ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneAdvancedViewController.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneAdvancedViewController.h" #import "WBRemoteVersionChecker.h" extern NSString * const CUIApplicationShowDebugMenuKey; extern NSString * const CUIApplicationShowDebugDidChangeNotification; @interface CUIPreferencePaneAdvancedViewController () { IBOutlet NSButton * _remoteVersionCheckerCheckbox; IBOutlet NSButton * _showDebugMenuCheckbox; } - (IBAction)switchRemoteVersionCheck:(id)sender; - (IBAction)switchShowDebugMenu:(id)sender; @end @implementation CUIPreferencePaneAdvancedViewController - (NSString *)nibName { return @"CUIPreferencePaneAdvancedViewController"; } #pragma mark - - (void)viewWillAppear { [super viewWillAppear]; // Remote Version Check _remoteVersionCheckerCheckbox.state=([WBRemoteVersionChecker sharedChecker].isCheckEnabled==YES) ? NSControlStateValueOn: NSControlStateValueOff; // Show Debug Menu NSUserDefaults * tDefaults=[NSUserDefaults standardUserDefaults]; _showDebugMenuCheckbox.state=([tDefaults boolForKey:CUIApplicationShowDebugMenuKey]==YES) ? NSControlStateValueOn: NSControlStateValueOff; } #pragma mark - - (IBAction)switchRemoteVersionCheck:(NSButton *)sender { [WBRemoteVersionChecker sharedChecker].checkEnabled=(sender.state==NSControlStateValueOn); } - (IBAction)switchShowDebugMenu:(NSButton *)sender { NSUserDefaults * tDefaults=[NSUserDefaults standardUserDefaults]; [tDefaults setBool:(sender.state==NSControlStateValueOn) forKey:CUIApplicationShowDebugMenuKey]; [NSNotificationCenter.defaultCenter postNotificationName:CUIApplicationShowDebugDidChangeNotification object:nil]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneCrashreporterViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneViewController.h" @interface CUIPreferencePaneCrashreporterViewController : CUIPreferencePaneViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneCrashreporterViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneCrashreporterViewController.h" #import "CUICrashReporterDefaults.h" @interface CUIPreferencePaneCrashreporterViewController () { IBOutlet NSView * _dialogTypeGroup; IBOutlet NSView * _notificationModeGroup; IBOutlet NSButton * _reportUncaughtExceptionsCheckbox; NSTimer * _refreshTimer; } - (IBAction)switchCrashReporterDialogType:(id)sender; - (IBAction)switchCrashReporterNotificationMode:(id)sender; - (IBAction)switchReportUncaughtException:(id)sender; // Notifications - (void)applicationDidBecomeActive:(NSNotification *)inNotification; - (void)applicationDidResignActive:(NSNotification *)inNotification; @end @implementation CUIPreferencePaneCrashreporterViewController - (NSString *)nibName { return @"CUIPreferencePaneCrashreporterViewController"; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear { [super viewWillAppear]; [self refresh]; } - (void)viewDidAppear { [super viewDidAppear]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:NSApplicationDidBecomeActiveNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationDidResignActive:) name:NSApplicationDidResignActiveNotification object:nil]; } - (void)viewWillDisappear { [super viewWillDisappear]; // Remove timer (if needed) [_refreshTimer invalidate]; _refreshTimer=nil; // Remove observer [NSNotificationCenter.defaultCenter removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil]; [NSNotificationCenter.defaultCenter removeObserver:self name:NSApplicationDidResignActiveNotification object:nil]; } #pragma mark - - (void)refresh { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; // Operation Mode NSButton * tRadioButton=[_dialogTypeGroup viewWithTag:tDefaults.dialogType]; tRadioButton.state=NSControlStateValueOn; // Notification Mode tRadioButton=[_notificationModeGroup viewWithTag:tDefaults.notificationMode]; tRadioButton.state=NSControlStateValueOn; // Report Uncaught Exceptions _reportUncaughtExceptionsCheckbox.state=(tDefaults.reportUncaughtExceptions==YES) ? NSControlStateValueOn : NSControlStateValueOff; } #pragma mark - - (IBAction)switchCrashReporterDialogType:(NSButton *)sender { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; tDefaults.dialogType=sender.tag; } - (IBAction)switchCrashReporterNotificationMode:(NSButton *)sender { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; tDefaults.notificationMode=sender.tag; } - (IBAction)switchReportUncaughtException:(NSButton *)sender { CUICrashReporterDefaults * tDefaults=[CUICrashReporterDefaults standardCrashReporterDefaults]; tDefaults.reportUncaughtExceptions=(sender.state==NSControlStateValueOn); } #pragma mark - Notifications - (void)applicationDidBecomeActive:(NSNotification *)inNotification { // Remove refresh timer [_refreshTimer invalidate]; _refreshTimer=nil; // Refresh [self refresh]; } - (void)applicationDidResignActive:(NSNotification *)inNotification { // Add refresh timer (Info > macOS 10.12 API) _refreshTimer=[NSTimer scheduledTimerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) { [[CUICrashReporterDefaults standardCrashReporterDefaults] refresh]; [self refresh]; }]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneFontscolorsViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneViewController.h" @interface CUIPreferencePaneFontscolorsViewController : CUIPreferencePaneViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneFontscolorsViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneFontscolorsViewController.h" #import "CUICategoriesClipView.h" #import "CUIApplicationPreferences.h" #import "CUIApplicationPreferences+Themes.h" #import "CUITableCustomSelectionColorRowView.h" #import "CUIAATextFieldCell.h" #import "CUIThemesManager.h" #import "CUIThemeItemsGroup+UI.h" #import "NSTableView+Selection.h" #import "NSArray+UniqueName.h" NSString * const CUICustomColorSelectionRowViewIdentifier=@"whitebox.colorSelectionRowView"; @interface CUITheme (Private) - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation newUUID:(BOOL)inNewUUID; @end @interface CUIPreferencePaneFontscolorsViewController () { IBOutlet NSTableView * _themesTableView; IBOutlet NSButton * _duplicateThemeButton; IBOutlet NSButton * _removeThemeButton; IBOutlet NSView * _presentationModeTabHeaderView; IBOutlet CUICategoriesClipView * _categoriesClipView; IBOutlet NSTableView * _categoriesTableView; IBOutlet NSTextField * _fontLabel; IBOutlet NSButton * _fontPanelButton; IBOutlet NSColorWell * _textColorWell; IBOutlet NSColorWell * _backgroundColorWell; IBOutlet NSColorWell * _textSelectionBackgroundColorWell; IBOutlet NSColorWell * _selectedTextColorWell; CUIThemesManager * _sharedThemeManager; NSArray * _cachedSortedThemes; CUIPresentationMode _selectedPresentationMode; CUIThemeItemsGroup * _selectedThemeItemsGroup; NSArray * _cachedItemsNames; NSString * _selectedItemName; NSColor * _cachedBackgroundColor; } - (void)refreshPresentationModeUI; - (void)refreshBottomUI; - (IBAction)switchSelectedPresentationMode:(id)sender; - (IBAction)showFontPanel:(id)sender; - (IBAction)takeTextColor:(NSColorWell *)sender; - (IBAction)takeBackgroundColor:(id)sender; - (IBAction)takeTextSelectionBackgroundColor:(id)sender; - (IBAction)takeSelectedTextColor:(id)sender; - (IBAction)restoreDefaults:(id)sender; // Notifications - (void)currentThemeDidChange:(NSNotification *)inNotification; - (void)themesListDidChange:(NSNotification *)inNotification; @end @implementation CUIPreferencePaneFontscolorsViewController - (instancetype)init { self=[super init]; if (self!=nil) { _sharedThemeManager=[CUIThemesManager sharedManager]; } return self; } - (NSString *)nibName { return @"CUIPreferencePaneFontscolorsViewController"; } - (void)viewDidLoad { [super viewDidLoad]; _selectedPresentationMode=CUIPresentationModeText; [((NSButton *)[_presentationModeTabHeaderView viewWithTag:_selectedPresentationMode]) setState:NSControlStateValueOn]; ((NSClipView *)_categoriesTableView.superview).drawsBackground=YES; [NSColorPanel sharedColorPanel].continuous=YES; } #pragma mark - - (void)viewWillAppear { [super viewWillAppear]; _cachedSortedThemes=[[_sharedThemeManager allThemes] sortedArrayUsingComparator:^NSComparisonResult(CUITheme * bTheme, CUITheme * bOtherTheme) { return [bTheme.name caseInsensitiveCompare:bOtherTheme.name]; }]; _removeThemeButton.enabled=(_cachedSortedThemes.count>1); _themesTableView.allowsEmptySelection=YES; [_themesTableView reloadData]; NSUInteger tIndex=[_cachedSortedThemes indexOfObject:_sharedThemeManager.currentTheme]; [_themesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tIndex] byExtendingSelection:NO]; _themesTableView.allowsEmptySelection=NO; [self refreshPresentationModeUI]; } - (void)viewDidAppear { [super viewDidAppear]; [self.view.window makeFirstResponder:_categoriesTableView]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(currentThemeDidChange:) name:CUIThemesManagerCurrentThemeDidChangeNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(themesListDidChange:) name:CUIThemesManagerThemesListDidChangeNotification object:nil]; } - (void)viewWillDisappear { [super viewWillDisappear]; [NSNotificationCenter.defaultCenter removeObserver:self name:CUIThemesManagerCurrentThemeDidChangeNotification object:nil]; [NSNotificationCenter.defaultCenter removeObserver:self name:CUIThemesManagerThemesListDidChangeNotification object:nil]; } #pragma mark - - (CGFloat)minimumHeight { return 350; } - (CGFloat)maximumHeight { return 800; } #pragma mark - - (void)refreshPresentationModeUI { _selectedThemeItemsGroup=[_sharedThemeManager.currentTheme itemsGroupWithIdentifier:[CUIApplicationPreferences groupIdentifierForPresentationMode:_selectedPresentationMode]]; if (_selectedThemeItemsGroup==nil) { NSLog(@"Error: Missing Theme Items Group: %@",[CUIApplicationPreferences groupIdentifierForPresentationMode:_selectedPresentationMode]); return; } NSMutableArray * tItemsNames=[_selectedThemeItemsGroup.itemsNames mutableCopy]; [tItemsNames removeObject:CUIThemeItemBackground]; [tItemsNames removeObject:CUIThemeItemLineNumber]; [tItemsNames removeObject:CUIThemeItemSelectionBackground]; [tItemsNames removeObject:CUIThemeItemSelectionText]; _cachedItemsNames=[tItemsNames copy]; _cachedBackgroundColor=[[_selectedThemeItemsGroup attributesForItem:CUIThemeItemBackground] color]; if (floor(NSAppKitVersionNumber)<=NSAppKitVersionNumber10_13) { _categoriesTableView.backgroundColor=_cachedBackgroundColor; } _categoriesClipView.themeBackgroundColor=_cachedBackgroundColor; NSInteger tSelectedRow=_categoriesTableView.selectedRow; [_categoriesTableView reloadData]; if (tSelectedRow!=-1) [_categoriesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tSelectedRow] byExtendingSelection:NO]; [self refreshBottomUI]; _backgroundColorWell.color=_cachedBackgroundColor; _textSelectionBackgroundColorWell.color=[[_selectedThemeItemsGroup attributesForItem:CUIThemeItemSelectionBackground] color]; _selectedTextColorWell.color=[[_selectedThemeItemsGroup attributesForItem:CUIThemeItemSelectionText] color]; } - (void)refreshBottomUI { CUIThemeItemAttributes * tAttributes=[_selectedThemeItemsGroup attributesForItem:_selectedItemName]; NSFont * tFont=tAttributes.font; _fontLabel.stringValue=[NSString stringWithFormat:@"%@ - %.1f",tFont.displayName,tFont.pointSize]; NSColor * tColor=tAttributes.color; if (tColor==nil) return; _textColorWell.color=tColor; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(delete:)) { return (_cachedSortedThemes.count>1); // A REVOIR } return YES; } #pragma mark - Themes actions - (IBAction)takeThemeName:(NSTextField *)sender { NSString * tNewName=sender.stringValue; if (tNewName.length==0) { NSBeep(); return; } NSInteger tEditedRow=[_themesTableView rowForView:sender]; if (tEditedRow==-1) return; CUITheme * tTheme=_cachedSortedThemes[tEditedRow]; if ([tTheme.name isEqualToString:tNewName]==YES) return; NSMutableArray * tExistingThemes=[_cachedSortedThemes mutableCopy]; [tExistingThemes removeObject:tTheme]; NSArray * tAllNames=[tExistingThemes WB_arrayByMappingObjectsUsingBlock:^NSString *(CUITheme *bTheme, NSUInteger bIndex) { return bTheme.name; }]; if ([tAllNames containsObject:tNewName]==YES) { NSAlert * tAlert=[NSAlert new]; tAlert.alertStyle=NSAlertStyleCritical; tAlert.messageText=[NSString stringWithFormat:NSLocalizedString(@"The name \"%@\" is already taken.",@""),tNewName]; tAlert.informativeText=NSLocalizedString(@"Please choose a different name.",@""); [tAlert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse returnCode) { [self->_themesTableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:tEditedRow] columnIndexes:[NSIndexSet indexSetWithIndex:0]]; [self->_themesTableView editColumn:0 row:tEditedRow withEvent:nil select:YES]; }]; return; } BOOL tSuccess=[_sharedThemeManager renameTheme:_sharedThemeManager.currentTheme withName:tNewName]; if (tSuccess==NO) { NSLog(@"Error when trying to rename theme %@ to name %@",_sharedThemeManager.currentTheme,tNewName); } } - (IBAction)duplicate:(id)sender { NSIndexSet * tIndexSet=[_themesTableView WB_selectedOrClickedRowIndexes]; if (tIndexSet.count!=1) return; CUITheme * tNewTheme=[_sharedThemeManager duplicateTheme:_cachedSortedThemes[tIndexSet.firstIndex]]; _sharedThemeManager.currentTheme=tNewTheme; _removeThemeButton.enabled=YES; } - (IBAction)delete:(id)sender { NSIndexSet * tIndexSet=[_themesTableView WB_selectedOrClickedRowIndexes]; if (tIndexSet.count!=1) return; CUITheme * tTheme=_cachedSortedThemes[tIndexSet.firstIndex]; NSAlert * tAlert=[NSAlert new]; tAlert.messageText=[NSString stringWithFormat:NSLocalizedString(@"Do you really want to remove the \"%@\" theme?", @""),tTheme.name]; tAlert.informativeText=NSLocalizedString(@"This cannot be undone.", @""); [tAlert addButtonWithTitle:NSLocalizedString(@"Remove",@"")]; [tAlert addButtonWithTitle:NSLocalizedString(@"Cancel",@"")]; [tAlert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse bReturnCode) { if (bReturnCode!=NSAlertFirstButtonReturn) return; [self->_sharedThemeManager removeTheme:tTheme]; self->_removeThemeButton.enabled=(self->_sharedThemeManager.allThemes.count>1); }]; } - (IBAction)exportTheme:(id)sender { NSIndexSet * tIndexSet=[_themesTableView WB_selectedOrClickedRowIndexes]; if (tIndexSet.count!=1) return; CUITheme * tTheme=_cachedSortedThemes[tIndexSet.firstIndex]; if (tTheme==nil) return; NSDictionary * tRepresentation=[tTheme representation]; if (tRepresentation==nil) return; NSSavePanel * tExportPanel=[NSSavePanel savePanel]; tExportPanel.canSelectHiddenExtension=YES; tExportPanel.allowedFileTypes=@[@"fr.whitebox.unexpectedly.theme"]; tExportPanel.nameFieldLabel=NSLocalizedString(@"Export As:", @""); tExportPanel.nameFieldStringValue=tTheme.name; tExportPanel.prompt=NSLocalizedString(@"Export", @""); [tExportPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger bResult){ if (bResult!=NSModalResponseOK) return; if ([tRepresentation writeToURL:tExportPanel.URL atomically:NO]==NO) { NSBeep(); // A COMPLETER } }]; } - (IBAction)importTheme:(id)sender { NSOpenPanel * tImportPanel=[NSOpenPanel openPanel]; tImportPanel.resolvesAliases=YES; tImportPanel.canChooseFiles=YES; //tImportPanel.allowsMultipleSelection=YES; tImportPanel.canCreateDirectories=NO; tImportPanel.prompt=NSLocalizedString(@"Import", @""); //tImportPanel.delegate=self; [tImportPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger bResult){ if (bResult!=NSModalResponseOK) return; NSDictionary * tDictionary=[NSDictionary dictionaryWithContentsOfURL:tImportPanel.URL]; if (tDictionary==nil) { // A COMPLETER return; } CUITheme * tTheme=[[CUITheme alloc] initWithRepresentation:tDictionary newUUID:YES]; if (tTheme==nil) { // A COMPLETER return; } // Check that no themes exist with that name CUIThemesManager * tThemesManager=[CUIThemesManager sharedManager]; NSArray * tAllThemes=tThemesManager.allThemes; NSUInteger tIndex=[tAllThemes indexOfObjectPassingTest:^BOOL(CUITheme * bTheme, NSUInteger bIndex, BOOL * bOutStop) { return [bTheme.name isEqualToString:tTheme.name]; }]; if (tIndex!=NSNotFound) { NSAlert * tAlert=[NSAlert new]; tAlert.messageText=[NSString stringWithFormat:NSLocalizedString(@"A theme named \"%@\" already exists. Do you want to replace it with the one you're importing?", @""),tTheme.name]; [tAlert addButtonWithTitle:NSLocalizedString(@"Replace", @"")]; [tAlert addButtonWithTitle:NSLocalizedString(@"Cancel", @"")]; [tAlert addButtonWithTitle:NSLocalizedString(@"Keep Both", @"")]; NSModalResponse tResponse=[tAlert runModal]; switch(tResponse) { case NSAlertFirstButtonReturn: // Replace { dispatch_async(dispatch_get_main_queue(), ^{ [tThemesManager removeTheme:tAllThemes[tIndex]]; [tThemesManager addTheme:tTheme]; }); return; } case NSAlertSecondButtonReturn: // Cancel return; case NSAlertThirdButtonReturn: // Keep Both { NSString * tNewName=[tAllThemes uniqueNameWithBaseName:[tTheme.name stringByAppendingString:NSLocalizedString(@" copy", @"")] usingNameExtractor:^NSString *(CUITheme * bThene, NSUInteger bIndex) { return bThene.name; }]; if (tNewName==nil) { NSLog(@"Uh oh"); NSBeep(); return; } tTheme.name=tNewName; break; } } } dispatch_async(dispatch_get_main_queue(), ^{ [tThemesManager addTheme:tTheme]; }); }]; } #pragma mark - - (IBAction)switchSelectedPresentationMode:(NSButton *)sender { _selectedPresentationMode=sender.tag; [self refreshPresentationModeUI]; } - (IBAction)showFontPanel:(id)sender { NSFontManager * tFontManager = [NSFontManager sharedFontManager]; [tFontManager setSelectedFont:[[_selectedThemeItemsGroup attributesForItem:_selectedItemName] font] isMultiple:NO]; tFontManager.target=self; tFontManager.action=@selector(changeFont:); [[tFontManager fontPanel:YES] orderFront:self]; } - (void)changeFont:(id)sender { NSInteger tSelectedRow=_categoriesTableView.selectedRow; if (tSelectedRow==-1) return; NSFontManager * tFontManager = [NSFontManager sharedFontManager]; CUIThemeItemAttributes * tItemAttributes=[_selectedThemeItemsGroup attributesForItem:_selectedItemName]; NSFont * tOldFont=tItemAttributes.font; NSFont * tNewFont=[tFontManager convertFont:tFontManager.selectedFont]; if ([tNewFont isEqual:tOldFont]==NO) { tItemAttributes.font=tNewFont; [self refreshBottomUI]; NSIndexSet * tIndexSet=[NSIndexSet indexSetWithIndex:tSelectedRow]; [_categoriesTableView reloadDataForRowIndexes:tIndexSet columnIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,1)]]; [_categoriesTableView noteHeightOfRowsWithIndexesChanged:tIndexSet]; } } - (IBAction)takeTextColor:(NSColorWell *)sender { CUIThemeItemAttributes * tItemAttributes=[_selectedThemeItemsGroup attributesForItem:_selectedItemName]; tItemAttributes.color=sender.color; [_categoriesTableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:[_categoriesTableView selectedRow]] columnIndexes:[NSIndexSet indexSetWithIndex:0]]; } - (IBAction)takeBackgroundColor:(NSColorWell *)sender { _cachedBackgroundColor=sender.color; CUIThemeItemAttributes * tItemAttributes=[_selectedThemeItemsGroup attributesForItem:CUIThemeItemBackground]; tItemAttributes.color=_cachedBackgroundColor; [self refreshPresentationModeUI]; } - (IBAction)takeTextSelectionBackgroundColor:(NSColorWell *)sender { CUIThemeItemAttributes * tItemAttributes=[_selectedThemeItemsGroup attributesForItem:CUIThemeItemSelectionBackground]; tItemAttributes.color=sender.color; [self refreshPresentationModeUI]; } - (IBAction)takeSelectedTextColor:(NSColorWell *)sender { CUIThemeItemAttributes * tItemAttributes=[_selectedThemeItemsGroup attributesForItem:CUIThemeItemSelectionText]; tItemAttributes.color=sender.color; [self refreshPresentationModeUI]; } - (IBAction)restoreDefaults:(id)sender { NSAlert * tAlert=[NSAlert new]; tAlert.messageText=NSLocalizedString(@"Do you really want to restore the default Fonts & Colors settings?", @""); tAlert.informativeText=NSLocalizedString(@"You will lose all the changes you made.", @""); [tAlert addButtonWithTitle:NSLocalizedString(@"Restore",@"")]; [tAlert addButtonWithTitle:NSLocalizedString(@"Cancel",@"")]; [tAlert beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse bReturnCode) { if (bReturnCode!=NSAlertFirstButtonReturn) return; [self->_sharedThemeManager reset]; [self->_themesTableView reloadData]; }]; } #pragma mark - NSTableViewDataSource - (NSInteger)numberOfRowsInTableView:(NSTableView *)inTableView { if (inTableView==_themesTableView) return _cachedSortedThemes.count; if (inTableView==_categoriesTableView) return _cachedItemsNames.count; return 0; } #pragma mark - NSTableViewDelegate - (NSTableRowView *)tableView:(NSTableView *)inTableView rowViewForRow:(NSInteger)inRow { if (inTableView==_themesTableView) return nil; CUITableCustomSelectionColorRowView * tTableRowView=[inTableView makeViewWithIdentifier:CUICustomColorSelectionRowViewIdentifier owner:self]; if (tTableRowView==nil) { tTableRowView=[[CUITableCustomSelectionColorRowView alloc] initWithFrame:NSZeroRect]; tTableRowView.identifier=CUICustomColorSelectionRowViewIdentifier; } tTableRowView.selectionColor=[[_selectedThemeItemsGroup attributesForItem:CUIThemeItemSelectionBackground] color]; tTableRowView.backgroundColor=_cachedBackgroundColor; return tTableRowView; } - (NSView *)tableView:(NSTableView *)inTableView viewForTableColumn:(NSTableColumn *)inTableColumn row:(NSInteger)inRow { NSString * tTableColumnIdentifier=inTableColumn.identifier; NSTableCellView * tTableCellView=[inTableView makeViewWithIdentifier:tTableColumnIdentifier owner:self]; if (inTableView==_themesTableView) { tTableCellView.textField.stringValue=[_cachedSortedThemes[inRow] name]; tTableCellView.textField.editable=YES; return tTableCellView; } if (inTableView==_categoriesTableView) { NSString * tItemName=_cachedItemsNames[inRow]; tTableCellView.textField.stringValue=[CUIThemeItemsGroup displayNameForItemNamed:tItemName]; CUIThemeItemAttributes * tItemAttributes=[_selectedThemeItemsGroup attributesForItem:tItemName]; tTableCellView.textField.font=tItemAttributes.font; if ([_categoriesTableView isRowSelected:inRow]==YES) tTableCellView.textField.backgroundColor=[[_selectedThemeItemsGroup attributesForItem:CUIThemeItemSelectionBackground] color]; else tTableCellView.textField.backgroundColor=_cachedBackgroundColor; tTableCellView.textField.textColor=tItemAttributes.color; return tTableCellView; } return nil; } - (CGFloat)tableView:(NSTableView *)inTableView heightOfRow:(NSInteger)inRow { if (inTableView==_themesTableView) return 26.0; if (inTableView==_categoriesTableView) { NSString * tItemName=_cachedItemsNames[inRow]; CUIThemeItemAttributes * tItemAttributes=[_selectedThemeItemsGroup attributesForItem:tItemName]; NSFont * tFont=tItemAttributes.font; return 10.0+(tFont.ascender-tFont.descender+tFont.leading); } return 18.0; } - (void)tableViewSelectionDidChange:(NSNotification *)inNotification { if (inNotification.object==_themesTableView) { NSInteger tSelectedRow=_themesTableView.selectedRow; if (tSelectedRow==-1 || self.view.window==nil) return; _sharedThemeManager.currentTheme=_cachedSortedThemes[tSelectedRow]; return; } if (inNotification.object==_categoriesTableView) { NSInteger tSelectedRow=_categoriesTableView.selectedRow; if (tSelectedRow==-1) return; _selectedItemName=_cachedItemsNames[tSelectedRow]; [self refreshBottomUI]; return; } } #pragma mark - Notifications - (void)currentThemeDidChange:(NSNotification *)inNotification { NSUInteger tIndex=[_cachedSortedThemes indexOfObject:_sharedThemeManager.currentTheme]; [_themesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tIndex] byExtendingSelection:NO]; [self refreshPresentationModeUI]; } - (void)themesListDidChange:(NSNotification *)inNotification { _cachedSortedThemes=[[_sharedThemeManager allThemes] sortedArrayUsingComparator:^NSComparisonResult(CUITheme * bTheme, CUITheme * bOtherTheme) { return [bTheme.name caseInsensitiveCompare:bOtherTheme.name]; }]; _themesTableView.allowsEmptySelection=YES; [_themesTableView deselectAll:nil]; [_themesTableView reloadData]; NSUInteger tIndex=[_cachedSortedThemes indexOfObject:_sharedThemeManager.currentTheme]; if (tIndex!=NSNotFound) [_themesTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tIndex] byExtendingSelection:NO]; _themesTableView.allowsEmptySelection=NO; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneGeneralViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneViewController.h" @interface CUIPreferencePaneGeneralViewController : CUIPreferencePaneViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneGeneralViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneGeneralViewController.h" #import "CUIApplicationPreferences.h" #import "CUIApplicationItemAttributes.h" @interface CUIPreferencePaneGeneralViewController () { IBOutlet NSButton * _showsRegistersWindowAtLaunchCheckbox; IBOutlet NSPopUpButton * _sourceEditorsPopUpButton; IBOutlet NSPopUpButton * _reportViewersPopUpButton; } + (NSMenu *)reportViewersMenu; - (IBAction)switchShowsRegisterWindowAtLaunch:(id)sender; - (IBAction)switchPreferedSourceCodeEditor:(id)sender; - (IBAction)switchDefaultReportsViewer:(id)sender; @end @implementation CUIPreferencePaneGeneralViewController + (NSMenu *)reportViewersMenu { NSArray * tBundleIdentifiers=(__bridge_transfer NSArray *)LSCopyAllRoleHandlersForContentType(CFSTR("com.apple.crashreport"),kLSRolesViewer); NSMutableArray * tMutableApplicationsURLs=[NSMutableArray array]; for(NSString * tBundleIdentifier in tBundleIdentifiers) { NSArray * tApplicationsURLs=(__bridge_transfer NSArray *)LSCopyApplicationURLsForBundleIdentifier((__bridge CFStringRef)tBundleIdentifier,NULL); if (tApplicationsURLs.count>0) [tMutableApplicationsURLs addObject:tApplicationsURLs.firstObject]; } NSMenu * tMenu=[[NSMenu alloc] initWithTitle:@""]; if (tMenu==nil) return nil; NSMutableArray * tApplicationsAttributes=[[tMutableApplicationsURLs WB_arrayByMappingObjectsUsingBlock:^CUIApplicationItemAttributes *(NSURL * bApplicationURL, NSUInteger bIndex) { return [[CUIApplicationItemAttributes alloc] initWithURL:bApplicationURL]; }] mutableCopy]; // Filter the array tApplicationsAttributes=[tApplicationsAttributes WB_filteredArrayUsingBlock:^BOOL(CUIApplicationItemAttributes * bAttributes, NSUInteger bIndex) { return (bAttributes.duplicate==NO); }]; // Sort the array [tApplicationsAttributes sortUsingSelector:@selector(compare:)]; for(CUIApplicationItemAttributes * tAttributes in tApplicationsAttributes) { tAttributes.showsVersion=NO; NSMenuItem * tMenuItem=tAttributes.applicationMenuItem; [tMenu addItem:tMenuItem]; } return tMenu; } + (NSMenu *)sourceEditorsMenu { NSURL * tCSourceFileURL=[[NSBundle mainBundle] URLForResource:@"template" withExtension:@"c"]; NSArray * tApplicationsURLs=(__bridge_transfer NSArray *)LSCopyApplicationURLsForURL((__bridge CFURLRef)tCSourceFileURL,kLSRolesEditor); NSMenu * tMenu=[[NSMenu alloc] initWithTitle:@""]; if (tMenu==nil) return nil; NSMutableArray * tApplicationsAttributes=[[tApplicationsURLs WB_arrayByMappingObjectsUsingBlock:^CUIApplicationItemAttributes *(NSURL * bApplicationURL, NSUInteger bIndex) { return [[CUIApplicationItemAttributes alloc] initWithURL:bApplicationURL]; }] mutableCopy]; // Sort the array [tApplicationsAttributes sortUsingSelector:@selector(compare:)]; // Filter the array tApplicationsAttributes=[tApplicationsAttributes WB_filteredArrayUsingBlock:^BOOL(CUIApplicationItemAttributes * bAttributes, NSUInteger bIndex) { return (bAttributes.duplicate==NO); }]; for(CUIApplicationItemAttributes * tAttributes in tApplicationsAttributes) { NSMenuItem * tMenuItem=tAttributes.applicationMenuItem; [tMenu addItem:tMenuItem]; } return tMenu; } - (NSString *)nibName { return @"CUIPreferencePaneGeneralViewController"; } - (void)viewDidLoad { [super viewDidLoad]; NSMenu * tMenu=[CUIPreferencePaneGeneralViewController sourceEditorsMenu]; if (tMenu.numberOfItems>0) _sourceEditorsPopUpButton.menu=tMenu; else _sourceEditorsPopUpButton.enabled=NO; // Default reports viewer tMenu=[CUIPreferencePaneGeneralViewController reportViewersMenu]; _reportViewersPopUpButton.menu=tMenu; } #pragma mark - - (void)viewWillAppear { [super viewWillAppear]; CUIApplicationPreferences * tPreferences=[CUIApplicationPreferences sharedPreferences]; _showsRegistersWindowAtLaunchCheckbox.state=(tPreferences.showsRegistersWindowAutomaticallyAtLaunch==YES) ? NSControlStateValueOn : NSControlStateValueOff; NSURL * tPreferedApplicationURL=tPreferences.preferedSourceCodeEditorURL; NSUInteger tIndex=[_sourceEditorsPopUpButton.menu.itemArray indexOfObjectPassingTest:^BOOL(NSMenuItem * bMenuItem, NSUInteger bIndex, BOOL * bOutStop) { CUIApplicationItemAttributes * tAttributes=bMenuItem.representedObject; return [tAttributes.applicationURL isEqualTo:tPreferedApplicationURL]; }]; if (tIndex==NSNotFound) { tPreferedApplicationURL=[CUIApplicationPreferences defaultSourceCodeEditorURL]; tIndex=[_sourceEditorsPopUpButton.menu.itemArray indexOfObjectPassingTest:^BOOL(NSMenuItem * bMenuItem, NSUInteger bIndex, BOOL * bOutStop) { CUIApplicationItemAttributes * tAttributes=bMenuItem.representedObject; return [tAttributes.applicationURL isEqualTo:tPreferedApplicationURL]; }]; if (tIndex!=NSNotFound) tPreferences.preferedSourceCodeEditorURL=tPreferedApplicationURL; } if (tIndex!=NSNotFound) [_sourceEditorsPopUpButton selectItemAtIndex:tIndex]; else NSLog(@"Ouille ouille ouille!"); // Default reports viewer NSString * tBundleIdentifier=(__bridge_transfer NSString *)LSCopyDefaultRoleHandlerForContentType(CFSTR("com.apple.crashreport"),kLSRolesViewer); tIndex=[_reportViewersPopUpButton.menu.itemArray indexOfObjectPassingTest:^BOOL(NSMenuItem * bMenuItem, NSUInteger bIndex, BOOL * bOutStop) { CUIApplicationItemAttributes * tAttributes=bMenuItem.representedObject; return [tAttributes.bundleIdentifier isEqualToString:tBundleIdentifier]; }]; if (tIndex!=NSNotFound) [_reportViewersPopUpButton selectItemAtIndex:tIndex]; } #pragma mark - - (IBAction)switchShowsRegisterWindowAtLaunch:(NSButton *)sender { [CUIApplicationPreferences sharedPreferences].showsRegistersWindowAutomaticallyAtLaunch=(sender.state==NSControlStateValueOn); } - (IBAction)switchPreferedSourceCodeEditor:(NSPopUpButton *)sender { CUIApplicationItemAttributes * tAttributes=sender.selectedItem.representedObject; [CUIApplicationPreferences sharedPreferences].preferedSourceCodeEditorURL=tAttributes.applicationURL; } - (IBAction)switchDefaultReportsViewer:(NSPopUpButton *)sender { CUIApplicationItemAttributes * tAttributes=sender.selectedItem.representedObject; OSStatus tResult=LSSetDefaultRoleHandlerForContentType(CFSTR("com.apple.crashreport"),kLSRolesViewer,(__bridge CFStringRef) tAttributes.bundleIdentifier); if (tResult != noErr) { // A VOIR (report error if we can figure out which error values this method can return) } tResult=LSSetDefaultRoleHandlerForContentType(CFSTR("com.apple.ips"),kLSRolesViewer,(__bridge CFStringRef) tAttributes.bundleIdentifier); if (tResult != noErr) { // A VOIR (report error if we can figure out which error values this method can return) } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePanePresentationOutlineViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencePanePresentationOutlineViewController : NSViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePanePresentationOutlineViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePanePresentationOutlineViewController.h" #import "CUIApplicationPreferences.h" #import "CUIOutlineModeDisplaySettings.h" @interface CUIPreferencePanePresentationOutlineViewController () { // Strack Frame IBOutlet NSButton * _showBinaryNameCheckbox; IBOutlet NSButton * _showMachineInstructionAddressCheckbox; IBOutlet NSButton * _showByteOffsetCheckbox; CUIApplicationPreferences * _applicationPreferences; CUIOutlineModeDisplaySettings * _displaySettings; } - (void)_setStackFrameComponent:(CUIStackFrameComponents)inComponent visible:(BOOL)inVisible; - (IBAction)switchShowBinaryName:(id)sender; - (IBAction)switchShowMachineInstructionAddress:(id)sender; - (IBAction)switchShowByteOffset:(id)sender; @end @implementation CUIPreferencePanePresentationOutlineViewController - (instancetype)init { self=[super init]; if (self!=nil) { _applicationPreferences=[CUIApplicationPreferences sharedPreferences]; _displaySettings=[_applicationPreferences.defaultOutlineModeDisplaySettings copy]; } return self; } - (NSString *)nibName { return @"CUIPreferencePanePresentationOutlineViewController"; } - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewWillAppear { [super viewWillAppear]; // Stack Frame _showBinaryNameCheckbox.state=((_displaySettings.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showMachineInstructionAddressCheckbox.state=((_displaySettings.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showByteOffsetCheckbox.state=((_displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; } #pragma mark - - (void)_setStackFrameComponent:(CUIStackFrameComponents)inComponent visible:(BOOL)inVisible { if (inVisible==YES) _displaySettings.visibleStackFrameComponents|=inComponent; else _displaySettings.visibleStackFrameComponents&=~inComponent; _applicationPreferences.defaultOutlineModeDisplaySettings=_displaySettings; } #pragma mark - - (IBAction)switchShowBinaryName:(NSButton *)sender { [self _setStackFrameComponent:CUIStackFrameBinaryNameComponent visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowMachineInstructionAddress:(NSButton *)sender { [self _setStackFrameComponent:CUIStackFrameMachineInstructionAddressComponent visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowByteOffset:(NSButton *)sender { [self _setStackFrameComponent:CUIStackFrameByteOffsetComponent visible:(sender.state==NSControlStateValueOn)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePanePresentationTextViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencePanePresentationTextViewController : NSViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePanePresentationTextViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePanePresentationTextViewController.h" #import "CUIApplicationPreferences.h" @interface CUIPreferencePanePresentationTextViewController () { // Document IBOutlet NSButton * _showsLineNumbersCheckbox; IBOutlet NSButton * _lineWrappingCheckbox; // Sections IBOutlet NSButton * _showHeaderCheckbox; IBOutlet NSButton * _showExceptionInformationCheckbox; IBOutlet NSButton * _showDiagnosticMessagesCheckbox; IBOutlet NSButton * _showBacktracesCheckbox; IBOutlet NSButton * _showThreadStateCheckbox; IBOutlet NSButton * _showBinaryImagesCheckbox; // Strack Frame IBOutlet NSButton * _showBinaryNameCheckbox; IBOutlet NSButton * _showMachineInstructionAddressCheckbox; IBOutlet NSButton * _showByteOffsetCheckbox; CUIApplicationPreferences * _applicationPreferences; CUITextModeDisplaySettings * _displaySettings; } - (IBAction)switchLineWrapping:(id)sender; - (IBAction)switchShowHeader:(id)sender; - (IBAction)switchShowExceptionInformation:(id)sender; - (IBAction)switchShowDiagnosticMessages:(id)sender; - (IBAction)switchShowBacktraces:(id)sender; - (IBAction)switchShowThreadState:(id)sender; - (IBAction)switchShowBinaryImages:(id)sender; - (IBAction)switchShowBinaryName:(id)sender; - (IBAction)switchShowMachineInstructionAddress:(id)sender; - (IBAction)switchShowByteOffset:(id)sender; @end @implementation CUIPreferencePanePresentationTextViewController - (instancetype)init { self=[super init]; if (self!=nil) { _applicationPreferences=[CUIApplicationPreferences sharedPreferences]; _displaySettings=[_applicationPreferences.defaultTextModeDisplaySettings copy]; } return self; } #pragma mark - - (NSString *)nibName { return @"CUIPreferencePanePresentationTextViewController"; } - (void)viewWillAppear { [super viewWillAppear]; // Document _showsLineNumbersCheckbox.state=(_applicationPreferences.showsLineNumbers==YES) ? NSControlStateValueOn : NSControlStateValueOff; _lineWrappingCheckbox.state=(_applicationPreferences.lineWrapping==YES) ? NSControlStateValueOn : NSControlStateValueOff; // Sections _showHeaderCheckbox.state=((_displaySettings.visibleSections & CUIDocumentHeaderSection)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showExceptionInformationCheckbox.state=((_displaySettings.visibleSections & CUIDocumentExceptionInformationSection)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showDiagnosticMessagesCheckbox.state=((_displaySettings.visibleSections & CUIDocumentDiagnosticMessagesSection)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showBacktracesCheckbox.state=((_displaySettings.visibleSections & CUIDocumentBacktracesSection)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showThreadStateCheckbox.state=((_displaySettings.visibleSections & CUIDocumentThreadStateSection)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showBinaryImagesCheckbox.state=((_displaySettings.visibleSections & CUIDocumentBinaryImagesSection)!=0) ? NSControlStateValueOn : NSControlStateValueOff; // Stack Frame _showBinaryNameCheckbox.state=((_displaySettings.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showMachineInstructionAddressCheckbox.state=((_displaySettings.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; _showByteOffsetCheckbox.state=((_displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) ? NSControlStateValueOn : NSControlStateValueOff; } #pragma mark - - (void)_setSection:(CUIDocumentSections)inSection visible:(BOOL)inVisible { if (inVisible==YES) _displaySettings.visibleSections|=inSection; else _displaySettings.visibleSections&=~inSection; _applicationPreferences.defaultTextModeDisplaySettings=_displaySettings; } - (void)_setStackFrameComponent:(CUIStackFrameComponents)inComponent visible:(BOOL)inVisible { if (inVisible==YES) _displaySettings.visibleStackFrameComponents|=inComponent; else _displaySettings.visibleStackFrameComponents&=~inComponent; _applicationPreferences.defaultTextModeDisplaySettings=_displaySettings; } - (IBAction)switchShowsLineNumbers:(NSButton *)sender { _applicationPreferences.showsLineNumbers=(sender.state==NSControlStateValueOn); } - (IBAction)switchLineWrapping:(NSButton *)sender { _applicationPreferences.lineWrapping=(sender.state==NSControlStateValueOn); } - (IBAction)switchShowHeader:(NSButton *)sender { [self _setSection:CUIDocumentHeaderSection visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowExceptionInformation:(NSButton *)sender { [self _setSection:CUIDocumentExceptionInformationSection visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowDiagnosticMessages:(NSButton *)sender { [self _setSection:CUIDocumentDiagnosticMessagesSection visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowBacktraces:(NSButton *)sender { [self _setSection:CUIDocumentBacktracesSection visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowThreadState:(NSButton *)sender { [self _setSection:CUIDocumentThreadStateSection visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowBinaryImages:(NSButton *)sender { [self _setSection:CUIDocumentBinaryImagesSection visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowBinaryName:(NSButton *)sender { [self _setStackFrameComponent:CUIStackFrameBinaryNameComponent visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowMachineInstructionAddress:(NSButton *)sender { [self _setStackFrameComponent:CUIStackFrameMachineInstructionAddressComponent visible:(sender.state==NSControlStateValueOn)]; } - (IBAction)switchShowByteOffset:(NSButton *)sender { [self _setStackFrameComponent:CUIStackFrameByteOffsetComponent visible:(sender.state==NSControlStateValueOn)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePanePresentationViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneViewController.h" @interface CUIPreferencePanePresentationViewController : CUIPreferencePaneViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePanePresentationViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePanePresentationViewController.h" #import "CUIPreferencePanePresentationTextViewController.h" #import "CUIPreferencePanePresentationOutlineViewController.h" #import "CUIApplicationPreferences.h" @interface CUIPreferencePanePresentationViewController () { IBOutlet NSView * _presentationModeTabHeaderView; IBOutlet NSView * _contentsView; NSMutableDictionary * _paneControllersDictionary; NSViewController * _currentViewController; } - (void)showPaneForPresentationMode:(CUIPresentationMode)inPresentationMode; - (IBAction)showPresentationOptions:(id)sender; @end @implementation CUIPreferencePanePresentationViewController - (NSString *)nibName { return @"CUIPreferencePanePresentationViewController"; } - (void)viewDidLoad { [super viewDidLoad]; [((NSButton *)[_presentationModeTabHeaderView viewWithTag:CUIPresentationModeText]) setState:NSControlStateValueOn]; [self showPaneForPresentationMode:CUIPresentationModeText]; } #pragma mark - - (void)showPaneForPresentationMode:(CUIPresentationMode)inPresentationMode { if (inPresentationMode==CUIPresentationModeUnknown) return; NSViewController * tViewController=_paneControllersDictionary[@(inPresentationMode)]; if (tViewController==nil) { switch(inPresentationMode) { case CUIPresentationModeText: tViewController=[CUIPreferencePanePresentationTextViewController new]; break; case CUIPresentationModeOutline: tViewController=[CUIPreferencePanePresentationOutlineViewController new]; break; default: break; } if (tViewController==nil) return; _paneControllersDictionary[@(inPresentationMode)]=tViewController; } if (_currentViewController!=nil) [_currentViewController.view removeFromSuperview]; _currentViewController=tViewController; _currentViewController.view.frame=_contentsView.bounds; [_contentsView addSubview:_currentViewController.view]; } #pragma mark - - (IBAction)showPresentationOptions:(NSButton *)sender { [self showPaneForPresentationMode:sender.tag]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneSymbolicationViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneViewController.h" @interface CUIPreferencePaneSymbolicationViewController : CUIPreferencePaneViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneSymbolicationViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneSymbolicationViewController.h" #import "CUIApplicationPreferences.h" #import "CUISymbolsFilesLibraryViewController.h" @interface CUIPreferencePaneSymbolicationViewController () { IBOutlet NSButton * _symbolicateButton; IBOutlet NSButton * _searchForSymbolsFilesButton; IBOutlet NSView * _dSYMLibraryPlaceHolderView; CUISymbolsFilesLibraryViewController * _symbolFilesLibraryViewController; } - (IBAction)switchSymbolicate:(id)sender; - (IBAction)switchSearchForSymbolFiles:(id)sender; @end @implementation CUIPreferencePaneSymbolicationViewController - (NSString *)nibName { return @"CUIPreferencePaneSymbolicationViewController"; } - (void)viewDidLoad { [super viewDidLoad]; _symbolFilesLibraryViewController=[CUISymbolsFilesLibraryViewController new]; _symbolFilesLibraryViewController.view.frame=_dSYMLibraryPlaceHolderView.bounds; [_dSYMLibraryPlaceHolderView addSubview:_symbolFilesLibraryViewController.view]; } - (void)viewWillAppear { [super viewWillAppear]; CUIApplicationPreferences * tPreferences=[CUIApplicationPreferences sharedPreferences]; _symbolicateButton.state=(tPreferences.symbolicateAutomatically==YES) ? NSControlStateValueOn : NSControlStateValueOff; _searchForSymbolsFilesButton.state=(tPreferences.searchForSymbolsFilesAutomatically==YES) ? NSControlStateValueOn : NSControlStateValueOff; } #pragma mark - - (CGFloat)minimumHeight { return 350; } - (CGFloat)maximumHeight { return 800; } #pragma mark - - (IBAction)switchSymbolicate:(NSButton *)sender { [CUIApplicationPreferences sharedPreferences].symbolicateAutomatically=(sender.state==NSControlStateValueOn); } - (IBAction)switchSearchForSymbolFiles:(NSButton *)sender { [CUIApplicationPreferences sharedPreferences].searchForSymbolsFilesAutomatically=(sender.state==NSControlStateValueOn); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencePaneViewController : NSViewController @property (nonatomic,readonly) CGFloat minimumHeight; @property (nonatomic,readonly) CGFloat maximumHeight; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencePaneViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencePaneViewController.h" @implementation CUIPreferencePaneViewController - (CGFloat)minimumHeight { return NSHeight(self.view.bounds); } - (CGFloat)maximumHeight { return NSHeight(self.view.bounds); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesTabBox.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencesTabBox : NSBox @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesTabBox.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencesTabBox.h" @implementation CUIPreferencesTabBox - (void)awakeFromNib { self.boxType=NSBoxCustom; self.borderType=NSLineBorder; self.borderWidth=1.0; self.borderColor=[NSColor containerBorderColor]; self.fillColor=(NSAppKitVersionNumber>=NSAppKitVersionNumber10_14) ? [NSColor controlBackgroundColor] : [NSColor whiteColor]; self.contentViewMargins=NSZeroSize; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesTabButton.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencesTabButton : NSButton @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesTabButton.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencesTabButton.h" @interface CUIPreferencesTabButton () { BOOL _pushed; } @end @implementation CUIPreferencesTabButton - (void)mouseDown:(NSEvent *)inEvent { _pushed=YES; [self setNeedsDisplay:YES]; } - (void)mouseDragged:(NSEvent *)inEvent { NSPoint tMouseLocation=[self convertPoint:[inEvent locationInWindow] fromView:nil]; if (NSPointInRect(tMouseLocation, [self bounds])!=_pushed) { _pushed=!_pushed; [self setNeedsDisplay:YES]; } } - (void)mouseUp:(NSEvent *)inEvent { if (_pushed==YES) { if ([self state]!=NSControlStateValueOn) { [self setState:NSControlStateValueOn]; [self sendAction:[self action] to:[self target]]; } _pushed=NO; [self setNeedsDisplay:YES]; } } #pragma mark - - (void)drawRect:(NSRect)inRect { NSMutableAttributedString * tAttributedString=[[self attributedTitle] mutableCopy]; BOOL tIsDark=[self WB_isEffectiveAppearanceDarkAqua]; NSColor * tColor; if (self.state==NSControlStateValueOn) { if (tIsDark==NO) { if (_pushed==YES) tColor=[NSColor blueColor]; else tColor=[NSColor colorWithDeviceRed:25.0/255.0 green:116.0/255.0 blue:219.0/255.0 alpha:1.0]; } else { if (_pushed==YES) tColor=[NSColor colorWithDeviceRed:83.0/255.0 green:165.0/255.0 blue:251.0/255.0 alpha:1.0]; else tColor=[NSColor colorWithDeviceRed:83.0/255.0 green:165.0/255.0 blue:251.0/255.0 alpha:1.0]; } } else { if (_pushed==YES) { tColor=(tIsDark==NO) ? [NSColor blackColor] : [NSColor whiteColor]; } else { tColor=[NSColor labelColor]; } } [tAttributedString addAttribute:NSForegroundColorAttributeName value:tColor range:NSMakeRange(0,[tAttributedString length])]; [self setAttributedTitle:tAttributedString]; [super drawRect:inRect]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesTabHeaderView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencesTabHeaderView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesTabHeaderView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencesTabHeaderView.h" @implementation CUIPreferencesTabHeaderView - (BOOL)isOpaque { return NO; } - (void)drawRect:(NSRect)inRect { [[NSColor containerBorderColor] set]; if (NSMinY(inRect)<=1) [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMinX(inRect),0.5) toPoint:NSMakePoint(NSMaxX(inRect), 0.5)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesWindow.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencesWindow : NSWindow @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesWindow.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencesWindow.h" @implementation CUIPreferencesWindow - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(toggleToolbarShown:)) { return NO; } return [super validateMenuItem:inMenuItem]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesWindowController+Convenience.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencesWindowController.h" @interface CUIPreferencesWindowController (Convenience) - (void)showFontsAndColorsPrefPane; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesWindowController+Convenience.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencesWindowController+Convenience.h" @implementation CUIPreferencesWindowController (Convenience) - (void)showFontsAndColorsPrefPane { [self showWindow:nil]; NSString * tIdentifier=@"toolbarItem.fontscolors"; [self showPaneWithIdentifier:tIdentifier]; self.window.toolbar.selectedItemIdentifier=tIdentifier; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesWindowController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIPreferencesWindowController : NSWindowController + (CUIPreferencesWindowController *)sharedPreferencesWindowController; - (void)showPaneWithIdentifier:(NSString *)inIdentifier; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPreferencesWindowController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPreferencesWindowController.h" #import "CUIPreferencePaneViewController.h" #import "NSToolbar+Packages.h" NSString * const CUIPreferencesWindowSelectedPaneIdentifierKey=@"preferences.ui.selected.identifier"; @interface CUIPreferencesWindowController () { IBOutlet NSToolbar * _toolBar; NSMutableDictionary * _paneControllersDictionary; CUIPreferencePaneViewController * _currentViewController; } - (void)showPaneWithIdentifier:(NSString *)inIdentifier; - (IBAction)showPane:(id)sender; @end @implementation CUIPreferencesWindowController + (CUIPreferencesWindowController *)sharedPreferencesWindowController { static dispatch_once_t onceToken; static CUIPreferencesWindowController * sPreferencesWindowController=nil; dispatch_once(&onceToken, ^{ sPreferencesWindowController=[CUIPreferencesWindowController new]; }); return sPreferencesWindowController; } - (instancetype)init { self=[super init]; if (self!=nil) { _paneControllersDictionary=[NSMutableDictionary dictionary]; } return self; } #pragma mark - - (NSString *)windowNibName { return @"CUIPreferencesWindowController"; } - (void)windowDidLoad { [self.window center]; // Set the toolbar style to deal with macOS BS #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101600 if (@available(*, macOS 11)) { self.window.toolbarStyle=NSWindowToolbarStylePreference; } #endif self.window.showsToolbarButton=NO; self.window.collectionBehavior^=NSWindowCollectionBehaviorFullScreenAuxiliary; // Set the icon for Fonts & Colors NSToolbarItem * tFontsAndColorsToolbarItem=[self.window.toolbar PKG_toolBarItemWithIdentifier:@"toolbarItem.fontscolors"]; NSImage * tFontsAndColorsIcon=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ProfileFontAndColor.icns"]; if (tFontsAndColorsIcon==nil) { tFontsAndColorsIcon=[NSImage imageWithSize:NSMakeSize(48, 48) flipped:NO drawingHandler:^BOOL(NSRect dstRect) { NSImage * tColorsImage=[NSImage imageNamed:@"NSToolbarShowColorsItemImage"]; [tColorsImage drawInRect:NSMakeRect(6,0,48,48) fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:0.6]; NSImage * tFontsImage=[NSImage imageNamed:@"NSToolbarShowFontsItemImage"]; [tFontsImage drawInRect:NSMakeRect(-6,0,48,48) fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; return YES; }]; } tFontsAndColorsToolbarItem.image=tFontsAndColorsIcon; // Show the first pane if not found in defaults NSString * tSelectedIdentifier=[[NSUserDefaults standardUserDefaults] objectForKey:CUIPreferencesWindowSelectedPaneIdentifierKey]; if (tSelectedIdentifier==nil) tSelectedIdentifier=((NSToolbarItem *)[_toolBar items][0]).itemIdentifier; _toolBar.selectedItemIdentifier=tSelectedIdentifier; [self showPaneWithIdentifier:tSelectedIdentifier]; } #pragma mark - - (void)showPaneWithIdentifier:(NSString *)inIdentifier { if (inIdentifier==nil) return; CUIPreferencePaneViewController * tViewController=_paneControllersDictionary[inIdentifier]; if (tViewController==nil) { NSArray * tArray=[inIdentifier componentsSeparatedByString:@"."]; if ([tArray count]!=2) return; Class tClass=NSClassFromString([NSString stringWithFormat:@"CUIPreferencePane%@ViewController",[tArray[1] capitalizedString]]); if (tClass==nil) return; tViewController=[tClass new]; if (tViewController==nil) return; _paneControllersDictionary[inIdentifier]=tViewController; } if (_currentViewController!=nil) [_currentViewController.view removeFromSuperview]; _currentViewController=tViewController; NSRect tOldWindowFrame=self.window.frame; NSRect tNewContentRect=[[self.window contentView] bounds]; tNewContentRect.size=_currentViewController.view.frame.size; NSRect tWindowFrame=[self.window frameRectForContentRect:tNewContentRect]; tWindowFrame.origin.x=NSMinX(tOldWindowFrame); tWindowFrame.origin.y=NSMaxY(tOldWindowFrame)-NSHeight(tWindowFrame); self.window.title=[_toolBar PKG_toolBarItemWithIdentifier:inIdentifier].label; [self.window setFrame:tWindowFrame display:YES animate:NO]; // Set Minimum and Maximum Height NSSize tSize=self.window.contentMinSize; tSize.height=_currentViewController.minimumHeight; self.window.contentMinSize=tSize; tSize.height=_currentViewController.maximumHeight; self.window.contentMaxSize=tSize; [[self.window contentView] addSubview:_currentViewController.view]; [[NSUserDefaults standardUserDefaults] setObject:inIdentifier forKey:CUIPreferencesWindowSelectedPaneIdentifierKey]; } #pragma mark - - (IBAction)showPane:(id)sender { [self showPaneWithIdentifier:[sender itemIdentifier]]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPresentationTextNavigationViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogPresentationViewController.h" @interface CUIPresentationTextNavigationViewController : NSViewController @property (nonatomic) CUICrashLogPresentationViewController * presentationViewController; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPresentationTextNavigationViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIPresentationTextNavigationViewController.h" #import "CUICrashLogsSource+UI.h" #import "CUIRawCrashLog+UI.h" #import "CUICrashLog+UI.h" #import "CUICrashLogsSourcesManager.h" #import "CUICrashLogsSourcesSelection.h" #import "CUICrashLogsSelection.h" #import "CUIApplicationPreferences.h" #import "CUICrashLogPresentationTextViewController.h" #import "CUICrashLogContentsViewController.h" #define GROSSE_CHIURE_APPKIT_VERSION_NUMBER 1894 #define GROSSE_CHIURE_EXTRA_WIDTH 5 @interface CUIPresentationTextNavigationViewController () { IBOutlet NSPopUpButton * _sourcesPopUpButton; IBOutlet NSView * _sourcesChevronView; IBOutlet NSPopUpButton * _crashLogsPopUpButton; IBOutlet NSView * _crashLogsChevronView; IBOutlet NSPopUpButton * _sectionsPopUpButton; CUICrashLogsSourcesManager * _sourcesManager; CUICrashLogsSourcesSelection * _sourcesSelection; CUICrashLogsSelection * _crashLogsSelection; NSDateFormatter * _crashLogDateFormatter; } - (void)refreshSourcesMenu; - (void)refreshCrashLogsMenu; - (void)refreshSectionsMenu; - (void)updateLayout; - (IBAction)switchSourceCrashLog:(id)sender; - (IBAction)switchCrashLog:(id)sender; - (IBAction)switchSection:(id)sender; // Notifications - (void)viewFrameDidChange:(NSNotification *)inNotification; - (void)sourcesManagerSourcesDidChange:(NSNotification *)inNotification; - (void)sourceDidUpdateSource:(NSNotification *)inNotification; - (void)sourcesSelectionDidChange:(NSNotification *)inNotification; - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification; - (void)crashLogsSortTypeDidChange:(NSNotification *)inNotification; - (void)presentationModeDidChange:(NSNotification *)inNotification; - (void)displayedSectionsDidChange:(NSNotification *)inNotification; - (void)visibleSectionsDidChange:(NSNotification *)inNotification; @end @implementation CUIPresentationTextNavigationViewController - (instancetype)init { self=[super init]; if (self!=nil) { _sourcesManager=[CUICrashLogsSourcesManager sharedManager]; _sourcesSelection=[CUICrashLogsSourcesSelection sharedSourcesSelection]; _crashLogsSelection=[CUICrashLogsSelection sharedSelection]; _crashLogDateFormatter=[NSDateFormatter new]; _crashLogDateFormatter.formatterBehavior=NSDateFormatterBehavior10_4; _crashLogDateFormatter.dateStyle=NSDateFormatterMediumStyle; _crashLogDateFormatter.timeStyle=NSDateFormatterShortStyle; } return self; } - (NSString *)nibName { return @"CUIPresentationTextNavigationViewController"; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; // Set the autoresizing masks based on the layout direction if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { _sourcesPopUpButton.autoresizingMask=NSViewMaxXMargin|NSViewMinYMargin; _sourcesPopUpButton.imagePosition=NSImageLeading; _sourcesChevronView.autoresizingMask=NSViewMaxXMargin|NSViewMinYMargin; _crashLogsPopUpButton.autoresizingMask=NSViewMaxXMargin|NSViewMinYMargin; _crashLogsPopUpButton.imagePosition=NSImageLeading; _crashLogsChevronView.autoresizingMask=NSViewMaxXMargin|NSViewMinYMargin; _sectionsPopUpButton.autoresizingMask=NSViewMaxXMargin|NSViewMinYMargin; _sectionsPopUpButton.imagePosition=NSImageLeading; } else { _sourcesPopUpButton.autoresizingMask=NSViewMinXMargin|NSViewMinYMargin; _sourcesPopUpButton.imagePosition=NSImageTrailing; _sourcesChevronView.autoresizingMask=NSViewMinXMargin|NSViewMinYMargin; _crashLogsPopUpButton.autoresizingMask=NSViewMinXMargin|NSViewMinYMargin; _crashLogsPopUpButton.imagePosition=NSImageTrailing; _crashLogsChevronView.autoresizingMask=NSViewMinXMargin|NSViewMinYMargin; _sectionsPopUpButton.autoresizingMask=NSViewMinXMargin|NSViewMinYMargin; _sectionsPopUpButton.imagePosition=NSImageTrailing; } } - (void)viewDidAppear { [super viewDidAppear]; [self refreshSourcesMenu]; [self refreshCrashLogsMenu]; [self refreshSectionsMenu]; [self updateLayout]; // Register for Notifications NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(viewFrameDidChange:) name:NSViewFrameDidChangeNotification object:self.view]; [tNotificationCenter addObserver:self selector:@selector(sourcesManagerSourcesDidChange:) name:CUICrashLogsSourcesManagerSourcesDidChangeNotification object:_sourcesManager]; [tNotificationCenter addObserver:self selector:@selector(sourceDidUpdateSource:) name:CUICrashLogsSourceDidUpdateSourceNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(sourcesSelectionDidChange:) name:CUICrashLogsSourcesSelectionDidChangeNotification object:_sourcesSelection]; [tNotificationCenter addObserver:self selector:@selector(crashLogsSelectionDidChange:) name:CUICrashLogsSelectionDidChangeNotification object:[CUICrashLogsSelection sharedSelection]]; [tNotificationCenter addObserver:self selector:@selector(crashLogsSortTypeDidChange:) name:CUIPreferencesCrashLogsSortTypeDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(presentationModeDidChange:) name:CUICrashLogContentsViewPresentationModeDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(displayedSectionsDidChange:) name:CUICrashLogPresentationDisplayedSectionsDidChangeNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(visibleSectionsDidChange:) name:CUICrashLogPresentationVisibleSectionsDidChangeNotification object:nil]; } - (void)viewWillDisappear { [super viewWillDisappear]; [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (void)setPresentationViewController:(CUICrashLogPresentationViewController *)inPresentationViewController { if (_presentationViewController==inPresentationViewController) return; _presentationViewController=inPresentationViewController; [self refreshSectionsMenu]; [self updateLayout]; } #pragma mark - - (void)refreshSourcesMenu { NSString * tTitleFormatString=NSLocalizedString(@"%@ - %@", @""); [_sourcesPopUpButton removeAllItems]; _sourcesPopUpButton.action=@selector(switchSourceCrashLog:); _sourcesPopUpButton.target=self; [_sourcesManager.allSources enumerateObjectsUsingBlock:^(CUICrashLogsSource * bSource, NSUInteger bIndex, BOOL * bOutStop) { switch(bSource.type) { case CUICrashLogsSourceTypeUnknown: return; case CUICrashLogsSourceTypeSeparator: [self->_sourcesPopUpButton.menu addItem:[NSMenuItem separatorItem]]; return; default: break; } NSMenuItem * tMenuItem=[[NSMenuItem alloc] initWithTitle:bSource.name action:nil keyEquivalent:@""]; NSImage * tImage=[NSImage imageWithSize:NSMakeSize(16.0,16.0) flipped:NO drawingHandler:^BOOL(NSRect dstRect) { [bSource.icon drawInRect:dstRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; return YES; }]; tImage.template=YES; tMenuItem.image=tImage; if (bSource.type==CUICrashLogsSourceTypeFile) { tMenuItem.action=@selector(switchSourceCrashLog:); tMenuItem.target=self; } else { NSMenu * tMenu=[[NSMenu alloc] initWithTitle:bSource.name]; NSMutableArray * tMutableCrashLogs=[bSource.crashLogs mutableCopy]; switch([CUIApplicationPreferences sharedPreferences].crashLogsSortType) { case CUICrashLogsSortDateDescending: [tMutableCrashLogs sortUsingSelector:@selector(compareDateReverse:)]; break; case CUICrashLogsSortProcessNameAscending: [tMutableCrashLogs sortUsingSelector:@selector(compareProcessName:)]; break; } for(CUIRawCrashLog * tCrashLog in tMutableCrashLogs) { NSString * tTitle=[NSString localizedStringWithFormat:tTitleFormatString,tCrashLog.processName,[self->_crashLogDateFormatter stringFromDate:tCrashLog.dateTime]]; NSMenuItem * tSubMenuItem=[[NSMenuItem alloc] initWithTitle:tTitle action:@selector(switchSourceCrashLog:) keyEquivalent:@""]; NSImage * tImage=[NSImage imageWithSize:NSMakeSize(16.0,16.0) flipped:NO drawingHandler:^BOOL(NSRect dstRect) { NSImage * tProcessIcon=tCrashLog.processIcon; [tProcessIcon drawInRect:dstRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; return YES; }]; tSubMenuItem.image=tImage; tSubMenuItem.target=self; tSubMenuItem.representedObject=tCrashLog; [tMenu addItem:tSubMenuItem]; } tMenuItem.submenu=tMenu; } tMenuItem.representedObject=bSource; [self->_sourcesPopUpButton.menu addItem:tMenuItem]; }]; } - (void)refreshCrashLogsMenu { NSString * tTitleFormatString=NSLocalizedString(@"%@ - %@", @""); [_crashLogsPopUpButton removeAllItems]; NSMutableArray * tMutableCrashLogs=[_sourcesSelection.crashLogs mutableCopy]; switch([CUIApplicationPreferences sharedPreferences].crashLogsSortType) { case CUICrashLogsSortDateDescending: [tMutableCrashLogs sortUsingSelector:@selector(compareDateReverse:)]; break; case CUICrashLogsSortProcessNameAscending: [tMutableCrashLogs sortUsingSelector:@selector(compareProcessName:)]; break; } if (tMutableCrashLogs.count==0) { _sourcesChevronView.hidden=YES; _crashLogsPopUpButton.hidden=YES; _crashLogsChevronView.hidden=YES; _sectionsPopUpButton.hidden=YES; return; } NSMenu * tMenu=_crashLogsPopUpButton.menu; for(CUIRawCrashLog * tCrashLog in tMutableCrashLogs) { NSString * tTitle=[NSString localizedStringWithFormat:tTitleFormatString,tCrashLog.processName,[_crashLogDateFormatter stringFromDate:tCrashLog.dateTime]]; NSMenuItem * tSubMenuItem=[[NSMenuItem alloc] initWithTitle:tTitle action:@selector(switchCrashLog:) keyEquivalent:@""]; NSImage * tImage=[NSImage imageWithSize:NSMakeSize(16.0,16.0) flipped:NO drawingHandler:^BOOL(NSRect dstRect) { NSImage * tProcessIcon=tCrashLog.processIcon; [tProcessIcon drawInRect:dstRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; return YES; }]; tSubMenuItem.image=tImage; tSubMenuItem.target=self; tSubMenuItem.representedObject=tCrashLog; [tMenu addItem:tSubMenuItem]; } NSArray * tSelectedCrashLogs=_crashLogsSelection.crashLogs; if (tSelectedCrashLogs.count==0) { // A VOIR (Maybe add a - menu item) } else if (tSelectedCrashLogs.count!=1) { NSLog(@"Multiple selection of crash logs is not supported"); } else { NSInteger tIndex=[tMenu indexOfItemWithRepresentedObject:tSelectedCrashLogs.firstObject]; if (tIndex==-1) { NSLog(@"Menu index not found for item: %@",tSelectedCrashLogs.firstObject); } else { [_crashLogsPopUpButton selectItemAtIndex:tIndex]; } } _sourcesChevronView.hidden=NO; _crashLogsPopUpButton.hidden=NO; } - (void)refreshSectionsMenu { if (self.presentationViewController==nil) { _crashLogsChevronView.hidden=YES; _sectionsPopUpButton.hidden=YES; return; } CUICrashLogPresentationTextViewController * tPresentationTextViewController=(CUICrashLogPresentationTextViewController *)self.presentationViewController; if ([tPresentationTextViewController isKindOfClass:[CUICrashLogPresentationTextViewController class]]==NO) { _crashLogsChevronView.hidden=YES; _sectionsPopUpButton.hidden=YES; return; } CUIDocumentSections tDocumentSections=tPresentationTextViewController.displaySettings.visibleSections; [_sectionsPopUpButton removeAllItems]; NSArray * tSelectedCrashLogs=_crashLogsSelection.crashLogs; if (tSelectedCrashLogs.count!=1) { NSLog(@"Multiple selection of crash logs is not supported"); return; } NSMenu * tMenu=_sectionsPopUpButton.menu; NSMenuItem * tMenuItem=nil; CUICrashLog * tCrashLog=tSelectedCrashLogs.firstObject; if ([tCrashLog isKindOfClass:[CUICrashLog class]]==NO) { _crashLogsChevronView.hidden=YES; _sectionsPopUpButton.hidden=YES; return; } NSArray * tArray=@[ @{ @"title":NSLocalizedString(@"Header",@""), @"available":@(tCrashLog.isHeaderAvailable), @"tag":@"section:Header", @"visible":@(tDocumentSections&CUIDocumentHeaderSection), @"icon":@"menuHeader", }, @{ @"title":NSLocalizedString(@"Exception Information",@""), @"available":@(tCrashLog.isExceptionInformationAvailable), @"tag":@"section:Exception Information", @"visible":@(tDocumentSections&CUIDocumentExceptionInformationSection), @"icon":@"menuException", }, @{ @"title":NSLocalizedString(@"Diagnostic Messages",@""), @"available":@(tCrashLog.isDiagnosticMessageAvailable), @"tag":@"section:Diagnostic Messages", @"visible":@(tDocumentSections&CUIDocumentDiagnosticMessagesSection), @"icon":@"menuDiagnostic", }, ]; for(NSDictionary * tDictionary in tArray) { NSUInteger tVisibleFlag=[tDictionary[@"visible"] unsignedIntegerValue]; if (tVisibleFlag==0) continue; if ([tDictionary[@"available"] boolValue]==YES) { tMenuItem=[[NSMenuItem alloc] initWithTitle:tDictionary[@"title"] action:@selector(switchSection:) keyEquivalent:@""]; NSString * tIconName=tDictionary[@"icon"]; if (tIconName==nil) tIconName=@"templateBlue"; tMenuItem.image=[NSImage imageNamed:tIconName]; tMenuItem.target=self; tMenuItem.representedObject=tDictionary[@"tag"]; [tMenu addItem:tMenuItem]; } } CUICrashLogBacktraces * tBacktraces=tCrashLog.backtraces; if (tBacktraces.threads.count>0 && (tDocumentSections & CUIDocumentBacktracesSection)!=0) { // Separator tMenuItem=[NSMenuItem separatorItem]; [tMenu addItem:tMenuItem]; // Backtraces tMenuItem=[[NSMenuItem alloc] initWithTitle:@"" action:@selector(switchSection:) keyEquivalent:@""]; NSAttributedString * tAttributedString=[[NSAttributedString alloc] initWithString:NSLocalizedString(@"Backtraces",@"") attributes:@{ NSFontAttributeName:[NSFont boldSystemFontOfSize:10.0] }]; tMenuItem.image=[NSImage imageNamed:@"menuBacktraces"]; tMenuItem.attributedTitle=tAttributedString; tMenuItem.target=self; tMenuItem.representedObject=@"section:Backtraces"; [tMenu addItem:tMenuItem]; for(CUIThread * tThread in tBacktraces.threads) { NSString * tName=nil; if (tThread.isApplicationSpecificBacktrace==YES) { tName=tThread.name; } else { tName=[NSString stringWithFormat:@"Thread %lu",tThread.number]; if (tThread.name!=nil) tName=[tName stringByAppendingFormat:@" :: %@",tThread.name]; } tMenuItem=[[NSMenuItem alloc] initWithTitle:tName action:@selector(switchSection:) keyEquivalent:@""]; tMenuItem.image=(tThread.isCrashed==YES) ? [NSImage imageNamed:@"menuThreadCrashed"] : [NSImage imageNamed:@"menuThread"]; tMenuItem.indentationLevel=1; tMenuItem.target=self; tMenuItem.representedObject=(tThread.isApplicationSpecificBacktrace==YES) ? @"thread:Application Specific Backtrace" : [NSString stringWithFormat:@"thread:%lu",tThread.number]; [tMenu addItem:tMenuItem]; } // Separator tMenuItem=[NSMenuItem separatorItem]; [tMenu addItem:tMenuItem]; } tArray=@[ @{ @"title":NSLocalizedString(@"Thread State",@""), @"available":@(tCrashLog.isThreadStateAvailable), @"tag":@"section:Thread State", @"visible":@(tDocumentSections&CUIDocumentThreadStateSection), @"icon":@"menuThreadState", }, @{ @"title":NSLocalizedString(@"Binary Images",@""), @"available":@(tCrashLog.isBinaryImagesAvailable), @"tag":@"section:Binary Images", @"visible":@(tDocumentSections&CUIDocumentBinaryImagesSection), @"icon":@"menuBinaryImage", } ]; for(NSDictionary * tDictionary in tArray) { NSUInteger tVisibleFlag=[tDictionary[@"visible"] unsignedIntegerValue]; if (tVisibleFlag==0) continue; if ([tDictionary[@"available"] boolValue]==YES) { tMenuItem=[[NSMenuItem alloc] initWithTitle:tDictionary[@"title"] action:@selector(switchSection:) keyEquivalent:@""]; NSString * tIconName=tDictionary[@"icon"]; if (tIconName==nil) tIconName=@"templateBlue"; tMenuItem.image=[NSImage imageNamed:tIconName]; tMenuItem.target=self; tMenuItem.representedObject=tDictionary[@"tag"]; [tMenu addItem:tMenuItem]; } } _crashLogsChevronView.hidden=NO; _sectionsPopUpButton.hidden=NO; } - (void)updateLayout { #define MIN_WIDTH 30.0 #define MARGIN 0.0 #define BEGIN_PADDING 3.0 #define END_PADDING 10.0 NSRect tBounds=self.view.bounds; NSRect tRect=_sourcesPopUpButton.frame; tRect.size.width=[_sourcesPopUpButton sizeThatFits:tRect.size].width; if (NSAppKitVersionNumber>GROSSE_CHIURE_APPKIT_VERSION_NUMBER) { tRect.size.width+=GROSSE_CHIURE_EXTRA_WIDTH; } NSMutableArray * tMutableArray=[NSMutableArray arrayWithObject:[NSValue valueWithRect:tRect]]; if (_crashLogsPopUpButton.hidden==NO) { tRect=_crashLogsPopUpButton.frame; tRect.size.width=[_crashLogsPopUpButton sizeThatFits:tRect.size].width; if (NSAppKitVersionNumber>GROSSE_CHIURE_APPKIT_VERSION_NUMBER) { tRect.size.width+=GROSSE_CHIURE_EXTRA_WIDTH; } [tMutableArray addObject:[NSValue valueWithRect:tRect]]; } if (_sectionsPopUpButton.hidden==NO) { tRect=_sectionsPopUpButton.frame; tRect.size.width=[_sectionsPopUpButton sizeThatFits:tRect.size].width; if (NSAppKitVersionNumber>GROSSE_CHIURE_APPKIT_VERSION_NUMBER) { tRect.size.width+=GROSSE_CHIURE_EXTRA_WIDTH; } [tMutableArray addObject:[NSValue valueWithRect:tRect]]; } __block CGFloat tTotalWidth=0.0; [tMutableArray enumerateObjectsUsingBlock:^(NSValue * bValue, NSUInteger bIndex, BOOL * outStop) { NSRect tRect=[bValue rectValue]; tTotalWidth+=NSWidth(tRect); }]; NSRect tChevronFrame=_sourcesChevronView.frame; tTotalWidth+=BEGIN_PADDING+(tMutableArray.count-1)*(NSWidth(tChevronFrame)+2.0*MARGIN)+END_PADDING; CGFloat tDifference=tTotalWidth-NSWidth(tBounds); if (tDifference<0) tDifference=0; NSUInteger tPopupsCount=tMutableArray.count; tRect=_sourcesPopUpButton.frame; NSSize tSize=[_sourcesPopUpButton sizeThatFits:tRect.size]; if (NSAppKitVersionNumber>GROSSE_CHIURE_APPKIT_VERSION_NUMBER) { tSize.width+=GROSSE_CHIURE_EXTRA_WIDTH; } if (tPopupsCount==1) { // Only the sources popup button is displayed so resize it to fit the parent view width if (tDifference>0) { tSize.width=NSMaxX(tBounds)-NSMinX(tRect); } tRect.size.width=tSize.width; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft) { tRect.origin.x=NSMaxX(tBounds)-NSWidth(tRect)-BEGIN_PADDING; } _sourcesPopUpButton.frame=tRect; return; } if (tPopupsCount==2) { // Only the sources and the crashlogs popup buttons are displayed if (tDifference>0.0) { if (tDifference>(tSize.width-MIN_WIDTH)) { tDifference-=(tSize.width-MIN_WIDTH); tSize.width=MIN_WIDTH; } else { tSize.width-=tDifference; tDifference=0.0; } } tRect.size.width=tSize.width; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft) { tRect.origin.x=NSMaxX(tBounds)-NSWidth(tRect)-BEGIN_PADDING; } _sourcesPopUpButton.frame=tRect; NSRect tFrame=_sourcesChevronView.frame; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tFrame.origin.x=NSMaxX(tRect)+MARGIN; } else { tFrame.origin.x=NSMinX(tRect)-MARGIN-NSWidth(tFrame); } _sourcesChevronView.frame=tFrame; tRect=_crashLogsPopUpButton.frame; tSize=[_crashLogsPopUpButton sizeThatFits:tRect.size]; if (NSAppKitVersionNumber>GROSSE_CHIURE_APPKIT_VERSION_NUMBER) { tSize.width+=GROSSE_CHIURE_EXTRA_WIDTH; } if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tRect.origin.x=NSMaxX(_sourcesChevronView.frame)+MARGIN; if (tDifference>0.0) { tSize.width=NSMaxX(tBounds)-NSMinX(tRect); } } else { tRect.origin.x=NSMinX(_sourcesChevronView.frame)-MARGIN-tSize.width; if (tDifference>0.0) { tSize.width=NSMaxX(tRect)-NSMinX(tBounds); tRect.origin.x=NSMinX(tBounds); } } tRect.size.width=tSize.width; _crashLogsPopUpButton.frame=tRect; return; } if (tPopupsCount==3) { if (tDifference>0.0) { if (tDifference>(tSize.width-MIN_WIDTH)) { tDifference-=(tSize.width-MIN_WIDTH); tSize.width=MIN_WIDTH; } else { tSize.width-=tDifference; tDifference=0.0; } } tRect.size.width=tSize.width; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft) { tRect.origin.x=NSMaxX(tBounds)-NSWidth(tRect)-BEGIN_PADDING; } _sourcesPopUpButton.frame=tRect; NSRect tFrame=_sourcesChevronView.frame; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tFrame.origin.x=NSMaxX(tRect)+MARGIN; } else { tFrame.origin.x=NSMinX(tRect)-MARGIN-NSWidth(tFrame); } _sourcesChevronView.frame=tFrame; tRect=_crashLogsPopUpButton.frame; tRect.origin.x=NSMaxX(_sourcesChevronView.frame)+MARGIN; tSize=[_crashLogsPopUpButton sizeThatFits:tRect.size]; if (NSAppKitVersionNumber>GROSSE_CHIURE_APPKIT_VERSION_NUMBER) { tSize.width+=GROSSE_CHIURE_EXTRA_WIDTH; } if (tDifference>(tSize.width-MIN_WIDTH)) { tDifference-=(tSize.width-MIN_WIDTH); tSize.width=MIN_WIDTH; } else { tSize.width-=tDifference; tDifference=0.0; } tRect.size.width=tSize.width; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tRect.origin.x=NSMaxX(_sourcesChevronView.frame)+MARGIN; } else { tRect.origin.x=NSMinX(_sourcesChevronView.frame)-MARGIN-tSize.width; } _crashLogsPopUpButton.frame=tRect; tFrame=_crashLogsChevronView.frame; if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tFrame.origin.x=NSMaxX(tRect)+MARGIN; } else { tFrame.origin.x=NSMinX(tRect)-MARGIN-NSWidth(tFrame); } _crashLogsChevronView.frame=tFrame; tRect=_sectionsPopUpButton.frame; tSize=[_sectionsPopUpButton sizeThatFits:tRect.size]; if (NSAppKitVersionNumber>GROSSE_CHIURE_APPKIT_VERSION_NUMBER) { tSize.width+=GROSSE_CHIURE_EXTRA_WIDTH; } if (tDifference>0.0) { tSize.width=NSMaxX(tBounds)-NSMinX(tRect); } if (self.view.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) { tRect.origin.x=NSMaxX(_crashLogsChevronView.frame)+MARGIN; } else { tRect.origin.x=NSMinX(_crashLogsChevronView.frame)-MARGIN-tSize.width; } tRect.size.width=tSize.width; _sectionsPopUpButton.frame=tRect; } } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { return YES; } - (IBAction)switchSourceCrashLog:(NSMenuItem *)sender { id tRepresentedObject=sender.representedObject; if ([tRepresentedObject isKindOfClass:[CUICrashLogsSource class]]==YES) { CUICrashLogsSource * tSource=(CUICrashLogsSource *)tRepresentedObject; if (tSource.type!=CUICrashLogsSourceTypeFile) { return; } if ([_sourcesSelection.sources containsObject:tSource]==NO) { _sourcesSelection.sources=[NSSet setWithObject:tSource]; } [_crashLogsSelection setSource:tSource crashLogs:@[tSource.crashLogs.firstObject]]; [self updateLayout]; return; } if ([tRepresentedObject isKindOfClass:[CUIRawCrashLog class]]==NO) { NSLog(@"switchCrashLog: Represented object for the menu item is not a crash log object"); return; } id tCrashLog=tRepresentedObject; NSMenuItem * tParentMenuItem=sender.parentItem; id tParentRepresentedItem=tParentMenuItem.representedObject; if ([tParentRepresentedItem isKindOfClass:[CUICrashLogsSource class]]==NO) { return; } CUICrashLogsSource * tSource=(CUICrashLogsSource *)tParentRepresentedItem; if ([_sourcesSelection.sources containsObject:tSource]==NO) { _sourcesSelection.sources=[NSSet setWithObject:tSource]; } [_crashLogsSelection setSource:tSource crashLogs:@[tCrashLog]]; [self updateLayout]; } - (IBAction)switchCrashLog:(NSMenuItem *)sender { id tRepresentedObject=sender.representedObject; if ([tRepresentedObject isKindOfClass:[CUIRawCrashLog class]]==NO) { NSLog(@"switchCrashLog: Represented object for the menu item is not a crash log object"); return; } [_crashLogsSelection setSource:_crashLogsSelection.source crashLogs:@[tRepresentedObject]]; [self updateLayout]; } - (IBAction)switchSection:(NSMenuItem *)sender { id tRepresentedObject=sender.representedObject; if ([tRepresentedObject isKindOfClass:[NSString class]]==NO) { NSLog(@"switchSection: Represented object for the menu item is not a NSString"); return; } [NSNotificationCenter.defaultCenter postNotificationName:@"jumpToSectionNotification" object:tRepresentedObject userInfo:@{}]; [self updateLayout]; } #pragma mark - Notifications - (void)viewFrameDidChange:(NSNotification *)inNotification { [self updateLayout]; } - (void)sourcesManagerSourcesDidChange:(NSNotification *)inNotification { [self refreshSourcesMenu]; } - (void)sourceDidUpdateSource:(NSNotification *)inNotification { // A COMPLETER } - (void)sourcesSelectionDidChange:(NSNotification *)inNotification { NSSet * tSet=_sourcesSelection.sources; CUICrashLogsSource * tCrashLogsSource=[tSet anyObject]; if (tCrashLogsSource==nil) return; switch(tCrashLogsSource.type) { case CUICrashLogsSourceTypeUnknown: case CUICrashLogsSourceTypeSeparator: return; default: break; } // Select the appropriate menu item NSInteger tIndex=[_sourcesPopUpButton.menu indexOfItemWithRepresentedObject:tCrashLogsSource]; if (tIndex==-1) { NSLog(@"Menu index not found for source %@",tCrashLogsSource); return; } [_sourcesPopUpButton selectItemAtIndex:tIndex]; // Refresh the CrashLogs menu if needed [self refreshCrashLogsMenu]; [self updateLayout]; } - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification { // Refresh Selection NSMenu * tMenu=_crashLogsPopUpButton.menu; NSArray * tSelectedCrashLogs=_crashLogsSelection.crashLogs; if (tSelectedCrashLogs.count!=1) { if (tSelectedCrashLogs.count>0) NSLog(@"Multiple selection of crash logs is not supported"); } else { NSInteger tIndex=[tMenu indexOfItemWithRepresentedObject:tSelectedCrashLogs.firstObject]; if (tIndex==-1) { // This can happen if we actually did change the source and then log selection automatically changed return; } else { [_crashLogsPopUpButton selectItemAtIndex:tIndex]; [self refreshSectionsMenu]; } } [self updateLayout]; } - (void)crashLogsSortTypeDidChange:(NSNotification *)inNotification { [self refreshCrashLogsMenu]; } - (void)presentationModeDidChange:(NSNotification *)inNotification { CUICrashLogContentsViewController * tContentsViewController=inNotification.object; self.presentationViewController=tContentsViewController.presentationViewController; } - (void)displayedSectionsDidChange:(NSNotification *)inNotification { [self refreshSectionsMenu]; [self updateLayout]; } - (void)visibleSectionsDidChange:(NSNotification *)inNotification { NSArray * tVisibleSections=inNotification.object; NSInteger tIndex=[_sectionsPopUpButton indexOfItemWithRepresentedObject:tVisibleSections.firstObject]; if (tIndex==-1) return; [_sectionsPopUpButton selectItemAtIndex:tIndex]; [self updateLayout]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIPresentationTextNavigationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIQuickHelpPopUpViewController.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @class CUIQuickHelpPopUpViewController; @protocol CUIQuickHelpPopUpViewControllerDelegate - (void)quickHelpPopUpViewController:(CUIQuickHelpPopUpViewController *)inController didComputeSizeOfPopover:(NSPopover *)inPopover; @end @interface CUIQuickHelpPopUpViewController : NSViewController @property NSPopover * popover; @property (weak) id delegate; @property NSRange textRange; @property (nonatomic) NSURL * contentsFileURL; @property (readonly) NSBundle * bundle; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIQuickHelpPopUpViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIQuickHelpPopUpViewController.h" #import @interface CUINoScrollingWebView : WKWebView @end @implementation CUINoScrollingWebView - (void)scrollWheel:(NSEvent *)inEvent { [self.nextResponder scrollWheel:inEvent]; } @end @interface CUIQuickHelpPopUpViewController () /**/ { IBOutlet CUINoScrollingWebView * _webView; } @property (readwrite) NSBundle * bundle; @end @implementation CUIQuickHelpPopUpViewController - (instancetype)init { self=[super init]; if (self!=nil) { _bundle=[NSBundle mainBundle]; } return self; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; _webView.navigationDelegate=self; [_webView setValue:@(NO) forKey:@"drawsBackground"]; NSError * tError=nil; NSString * tHTMLContents=[NSString stringWithContentsOfURL:_contentsFileURL encoding:NSUTF8StringEncoding error:&tError]; if (tHTMLContents==nil) { NSLog(@"HTML data could not be loaded from file \"%@\".",_contentsFileURL); return; } [_webView loadHTMLString:tHTMLContents baseURL:_bundle.resourceURL]; } - (NSString *)nibName { return @"CUIQuickHelpPopUpViewController"; } #pragma mark - - (void)webView:(WKWebView *)inWebView decidePolicyForNavigationAction:(WKNavigationAction *)inNavigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { if (inNavigationAction.navigationType==WKNavigationTypeLinkActivated) { decisionHandler(WKNavigationActionPolicyCancel); [[NSWorkspace sharedWorkspace] openURL:inNavigationAction.request.URL]; } else { decisionHandler(WKNavigationActionPolicyAllow); } } - (void)webView:(WKWebView *)inWebView didFinishNavigation:(WKNavigation *)inNavigation { if (self.popover==nil) return; __block NSSize tCurrentSize=self.popover.contentSize; [_webView evaluateJavaScript:@"document.body.scrollHeight;" completionHandler:^(NSString * bResult, NSError * bError) { tCurrentSize.height=[bResult integerValue]; dispatch_async(dispatch_get_main_queue(), ^{ self.popover.contentSize=tCurrentSize; [self.delegate quickHelpPopUpViewController:self didComputeSizeOfPopover:self.popover]; }); }]; } #pragma mark - - (void)setContentsFileURL:(NSURL *)inURL { _contentsFileURL=inURL; if (_webView==nil) return; NSError * tError=nil; NSString * tHTMLContents=[NSString stringWithContentsOfURL:_contentsFileURL encoding:NSUTF8StringEncoding error:&tError]; if (tHTMLContents==nil) { NSLog(@"Missing HTML document at %@",_contentsFileURL.path); // A COMPLETER (Provide a basic HTML error report to display) return; } [_webView loadHTMLString:tHTMLContents baseURL:_bundle.resourceURL]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIQuickHelpPopUpViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRawCrashLog+Path.h ================================================ // // CUIRawCrashLog+Path.h // Unexpectedly // // Created by stephane on 13/03/2021. // Copyright © 2021 Acme, Inc. All rights reserved. // #import "CUIRawCrashLog.h" @interface CUIRawCrashLog (Path) - (NSString *)stringByResolvingUSERInPath:(NSString *)inPath; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRawCrashLog+Path.m ================================================ // // CUIRawCrashLog+Path.m // Unexpectedly // // Created by stephane on 13/03/2021. // Copyright © 2021 Acme, Inc. All rights reserved. // #import "CUIRawCrashLog+Path.h" NSString * const CUIUSERHomeFolderPath=@"/Users/USER/"; @implementation CUIRawCrashLog (Path) - (NSString *)stringByResolvingUSERInPath:(NSString *)inPath { if (self.USERPathComponent==nil) return inPath; if ([inPath hasPrefix:CUIUSERHomeFolderPath]==NO) return inPath; return [NSString stringWithFormat:@"/Users/%@/%@",self.USERPathComponent,[inPath substringFromIndex:CUIUSERHomeFolderPath.length]]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRawCrashLog+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRawCrashLog.h" @interface CUIRawCrashLog (UI) - (NSImage *)processIcon; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRawCrashLog+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRawCrashLog+UI.h" @implementation CUIRawCrashLog (UI) - (NSImage *)processIcon { static NSImage * sExecutableBinaryIcon=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sExecutableBinaryIcon=[[NSImage alloc] initWithContentsOfFile:@"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ExecutableBinaryIcon.icns"]; }); return sExecutableBinaryIcon; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRawCrashLog.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogErrors.h" #import "IPSReport.h" typedef NS_ENUM(NSUInteger, CUICrashLogReportSourceType) { CUICrashLogReportSourceTypeSystem=0, CUICrashLogReportSourceTypeUser, CUICrashLogReportSourceTypeOther }; @interface CUIRawCrashLog : NSObject @property (readonly) id resourceIdentifier; @property (readonly) IPSReport * ipsReport; // Can be nil @property (readonly,copy) NSString * rawText; // Can be nil @property (readonly,copy) NSString * crashLogFilePath; @property (nonatomic,readonly) CUICrashLogReportSourceType reportSourceType; @property (nonatomic,readonly) BOOL isFullyParsed; @property (nonatomic,readonly,getter=isHeaderAvailable) BOOL headerAvailable; @property (nonatomic,readonly,getter=isExceptionInformationAvailable) BOOL exceptionInformationAvailable; @property (nonatomic,readonly,getter=isDiagnosticMessageAvailable) BOOL diagnosticMessageAvailable; @property (nonatomic,readonly,getter=isBacktracesAvailable) BOOL backtracesAvailable; @property (nonatomic,readonly,getter=isThreadStateAvailable) BOOL threadStateAvailable; @property (nonatomic,readonly,getter=isBinaryImagesAvailable) BOOL binaryImagesAvailable; @property (nonatomic,readonly,copy) NSString * processName; @property (nonatomic,readonly) NSDate * dateTime; @property (nonatomic,readonly) NSUInteger reportVersion; @property (nonatomic,readonly) NSNumber * numberOfHoursSinceCrash; // Extended Attributes @property (readonly,copy) NSString * reopenFilePath; @property (readonly,copy) NSString * USERPathComponent; - (instancetype)initWithContentsOfURL:(NSURL *)inURL error:(NSError **)outError; - (instancetype)initWithContentsOfFile:(NSString *)inPath error:(NSError **)outError; - (instancetype)initWithData:(NSData *)inData error:(NSError **)outError; - (instancetype)initWithString:(NSString *)inString error:(NSError **)outError; - (BOOL)finalizeParsing; @property (nonatomic,readonly,copy) NSString * crashLogFileName; - (NSComparisonResult)compareCrashLogFileName:(CUIRawCrashLog *)otherCrashLog; - (NSComparisonResult)compareProcessName:(CUIRawCrashLog *)otherCrashLog; - (NSComparisonResult)compareDateReverse:(CUIRawCrashLog *)otherCrashLog; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRawCrashLog.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRawCrashLog.h" #import "CUICrashLogSectionsDetector.h" #import "CUICrashLogHeader.h" #import "NSFileManager+ExtendedAttributes.h" @interface CUIRawCrashLog () { BOOL _isLastHopeParseDone; id _reserved1; // processName id _reserved2; // dateTime id _reserved3; // header.bundleIdentifier id _reserved4; // header.executablePath id _reserved5; // header.executableVersion id _reserved6; // header.operatingSystemVersion.stringValue } @property (copy) NSString * crashLogFilePath; @property (copy) NSString * rawText; // Extended Attributes @property (copy) NSString * reopenFilePath; - (instancetype)initWithString:(NSString *)inString error:(NSError **)outError; @end @implementation CUIRawCrashLog - (instancetype)initWithContentsOfURL:(NSURL *)inURL error:(NSError **)outError { if ([inURL isKindOfClass:NSURL.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } NSError * tError=nil; NSData * tData=[NSData dataWithContentsOfURL:inURL options:0 error:&tError]; if (tData==nil) { if (outError!=NULL) *outError=tError; return nil; } self=[self initWithData:tData error:outError]; if (self!=nil) { id tResourceIdentifier=nil; if ([inURL getResourceValue:&tResourceIdentifier forKey:NSURLFileResourceIdentifierKey error:NULL]==YES) { _resourceIdentifier=tResourceIdentifier; } _crashLogFilePath=[inURL.path copy]; NSDictionary * tExtendedAttributes=[[NSFileManager defaultManager] WB_extendedAttributesOfItemAtURL:inURL error:nil]; NSData * tData=tExtendedAttributes[@"ReopenPath"]; if (tData!=nil) { _reopenFilePath=[[NSString alloc] initWithData:tData encoding:NSUTF8StringEncoding]; if ([_reopenFilePath hasPrefix:@"/Users/"]==YES) { NSArray * tComponents=[_reopenFilePath componentsSeparatedByString:@"/"]; if (tComponents.count>2) _USERPathComponent=[tComponents[2] copy]; } } } return self; } - (instancetype)initWithContentsOfFile:(NSString *)inPath error:(NSError **)outError { if ([inPath isKindOfClass:NSString.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } return [self initWithContentsOfURL:[NSURL fileURLWithPath:inPath] error:outError]; } - (instancetype)initWithData:(NSData *)inData error:(NSError **)outError { if ([inData isKindOfClass:NSData.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } NSString * tString=[[NSString alloc] initWithData:inData encoding:NSUTF8StringEncoding]; if (tString==nil) tString=[[NSString alloc] initWithData:inData encoding:NSASCIIStringEncoding]; if (tString==nil) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:ENOMEM userInfo:@{}]; return nil; } return [self initWithString:tString error:outError]; } - (instancetype)initWithString:(NSString *)inString error:(NSError **)outError { if ([inString isKindOfClass:NSString.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSCocoaErrorDomain code:EINVAL userInfo:@{}]; return nil; } if ([inString hasPrefix:@"Process:"]==YES) { self=[super init]; if (self!=nil) { _rawText=[inString copy]; _resourceIdentifier=[NSUUID UUID]; } } else if ([inString hasPrefix:@"{"]==YES) { self=[super init]; if (self!=nil) { NSError * tError=nil; _ipsReport=[[IPSReport alloc] initWithString:inString error:&tError]; if (_ipsReport==nil) { if (outError!=NULL) *outError=tError; return nil; } _rawText=nil; _resourceIdentifier=[NSUUID UUID]; } } else { if (outError!=NULL) { if (inString.length==0) { *outError=[NSError errorWithDomain:CUICrashLogDomain code:CUICrashLogEmptyFileError userInfo:@{}]; } else { *outError=[NSError errorWithDomain:CUICrashLogDomain code:CUICrashLogInvalidFormatFileError userInfo:@{}]; } } return nil; } return self; } #pragma mark - - (BOOL)isHeaderAvailable { return (self.ipsReport.incident.header!=nil); } - (BOOL)isExceptionInformationAvailable { return (self.ipsReport.incident.exceptionInformation!=nil); } - (BOOL)isDiagnosticMessageAvailable { return (self.ipsReport.incident.diagnosticMessage!=nil); } - (BOOL)isBacktracesAvailable { return (self.ipsReport.incident.threads!=nil); } - (BOOL)isThreadStateAvailable { NSUInteger tFaultingThreadIndex=self.ipsReport.incident.exceptionInformation.faultingThread; NSArray * tThreadsArray=self.ipsReport.incident.threads; if (tFaultingThreadIndex>=tThreadsArray.count) return NO; IPSThread * tThread=tThreadsArray[tFaultingThreadIndex]; return (tThread.threadState!=nil); } - (BOOL)isBinaryImagesAvailable { return (self.ipsReport.incident.binaryImages!=nil); } - (id)valueForUndefinedKey:(NSString *)inKey { NSLog(@"Undefined key '%@'",inKey); return @""; } - (id)valueForKeyPath:(NSString *)inKeyPath { if ([inKeyPath isEqualToString:@"header.bundleIdentifier"]==YES) return (_reserved3==nil) ? @"" : _reserved3; if ([inKeyPath isEqualToString:@"header.executablePath"]==YES) return (_reserved4==nil) ? @"" : _reserved4; if ([inKeyPath isEqualToString:@"header.executableVersion"]==YES) return (_reserved5==nil) ? @"" : _reserved5; if ([inKeyPath isEqualToString:@"header.operatingSystemVersion.stringValue"]==YES) return (_reserved6==nil) ? @"" : _reserved6; if ([inKeyPath isEqualToString:@"exceptionInformation.crashedThreadName"]==YES) return @""; id tValue=nil; @try { tValue=[super valueForKeyPath:inKeyPath]; } @catch(NSException * bException) { tValue=@""; } return tValue; } - (NSString *)processName { if (_isLastHopeParseDone==NO) [self finalizeParsing]; return (_reserved1!=nil) ? _reserved1 : @""; } - (NSDate *)dateTime { if (_isLastHopeParseDone==NO) [self finalizeParsing]; return (_reserved2!=nil) ? _reserved2 : nil; } - (NSUInteger)reportVersion { return NSNotFound; } - (NSNumber *)numberOfHoursSinceCrash { if (_reserved2==nil) return @(NSUIntegerMax); NSDate * tDate=[NSDate date]; NSTimeInterval tTimeInterval=[tDate timeIntervalSinceDate:_reserved2]; NSInteger tNumberOfHours=round(tTimeInterval/3600); return @(tNumberOfHours); } - (CUICrashLogReportSourceType)reportSourceType { static NSString * sSystemReportsDirectoryPath=nil; static NSString * sSystemUsersDirectoryPath=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSArray * tArray=NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSLocalDomainMask, YES); sSystemReportsDirectoryPath=[tArray.firstObject stringByAppendingPathComponent:@"Logs/DiagnosticReports"]; tArray=NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); sSystemUsersDirectoryPath=[tArray.firstObject stringByAppendingPathComponent:@"Logs/DiagnosticReports"]; }); NSString * tParentDirectory=[self.crashLogFilePath stringByDeletingLastPathComponent]; if ([sSystemReportsDirectoryPath isEqualToString:tParentDirectory]==YES) return CUICrashLogReportSourceTypeSystem; if ([sSystemUsersDirectoryPath isEqualToString:tParentDirectory]==YES) return CUICrashLogReportSourceTypeUser; return CUICrashLogReportSourceTypeOther; } #pragma mark - - (BOOL)isFullyParsed { return _isLastHopeParseDone; } - (BOOL)finalizeParsing { _isLastHopeParseDone=YES; NSRange tRange; NSMutableArray * tLines=[NSMutableArray array]; [self.rawText enumerateLinesUsingBlock:^(NSString * bLine, BOOL * bOutStop) { [tLines addObject:bLine]; }]; NSUInteger tFirstLine=0; // Try to parse at least the header tRange=[CUICrashLogSectionsDetector detectHeaderSectionRangeInTextualRepresentation:tLines atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(tFirstLine,tLines.count-tFirstLine)]]; if (tRange.location==NSNotFound) { /*if (outError!=NULL) *outError=[NSError errorWithDomain:CUIParsingErrorDomain code:CUIParsingSectionDetectionFailedError userInfo:@{CUIParsingErrorSectionNameKey:@"Header"}];*/ return NO; } CUICrashLogHeader * tHeader=[[CUICrashLogHeader alloc] initWithTextualRepresentation:[tLines subarrayWithRange:tRange] error:NULL]; if (tHeader!=nil) { _reserved1=[tHeader.processName copy]; _reserved2=[tHeader.dateTime copy]; _reserved3=[tHeader.bundleIdentifier copy]; _reserved4=[tHeader.executablePath copy]; _reserved5=[tHeader.executableVersion copy]; _reserved6=[tHeader.operatingSystemVersion.stringValue copy]; } return YES; } #pragma mark - - (NSString *)crashLogFileName { return self.crashLogFilePath.lastPathComponent.stringByDeletingPathExtension; } #pragma mark - - (NSComparisonResult)compareCrashLogFileName:(CUIRawCrashLog *)otherCrashLog { return [self.crashLogFileName compare:otherCrashLog.crashLogFileName options:NSNumericSearch|NSCaseInsensitiveSearch]; } - (NSComparisonResult)compareProcessName:(CUIRawCrashLog *)otherCrashLog { NSComparisonResult tResult=[self.processName compare:otherCrashLog.processName options:NSNumericSearch|NSCaseInsensitiveSearch]; if (tResult!=NSOrderedSame) return tResult; return [self.crashLogFilePath compare:self.crashLogFilePath]; } - (NSComparisonResult)compareDateReverse:(CUIRawCrashLog *)otherCrashLog { return -[self.dateTime compare:otherCrashLog.dateTime]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegister.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIRegister : NSObject @property (copy) NSString * name; @property NSUInteger value; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegister.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRegister.h" @implementation CUIRegister - (NSString *)description { return [NSString stringWithFormat:@"%@:0x%016lx",self.name,self.value]; } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { CUIRegister * nRegister=[CUIRegister new]; nRegister.name=[self.name copy]; nRegister.value=self.value; return nRegister; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegisterLabel.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_ENUM(NSUInteger, CUIRegisterViewValueAsType) { CUIRegisterViewValueAsBinary, CUIRegisterViewValueAsBoolean, CUIRegisterViewValueAsFloat, CUIRegisterViewValueAsDecimal, CUIRegisterViewValueAsHex, CUIRegisterViewValueAsOctal, CUIRegisterViewValueAsUnsignedDecimal }; @class CUIRegisterLabel; @protocol CUIRegisterLabelDelegate - (void)registerLabel:(CUIRegisterLabel *)inRegisterLabel viewValueAsDidChange:(CUIRegisterViewValueAsType)inType; @end @interface CUIRegisterLabel : NSView @property (nonatomic) NSUInteger registerValue; @property (nonatomic) CUIRegisterViewValueAsType viewValueAs; @property (weak) id delegate; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegisterLabel.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRegisterLabel.h" NSString * const CUIRegisterLabelViewAsValueDidChangeNotification=@"CUIRegisterLabelViewAsValueDidChangeNotification"; @interface CUIRegisterLabel () { IBOutlet NSTextField * _textField; IBOutlet NSPopUpButton * _popUpButton; } - (IBAction)switchDisplayFormat:(id)sender; @end @implementation CUIRegisterLabel - (instancetype)initWithFrame:(NSRect)inFrame { self=[super initWithFrame:inFrame]; if (self!=nil) { _viewValueAs=CUIRegisterViewValueAsHex; } return self; } - (instancetype)initWithCoder:(NSCoder *)inCoder { self=[super initWithCoder:inCoder]; if (self!=nil) { _viewValueAs=CUIRegisterViewValueAsHex; } return self; } - (void)awakeFromNib { [_popUpButton selectItemWithTag:self.viewValueAs]; } #pragma mark - - (void)setRegisterValue:(NSUInteger)inRegisterValue { _registerValue=inRegisterValue; [self refreshUI]; } - (void)setViewValueAs:(CUIRegisterViewValueAsType)inViewAs { _viewValueAs=inViewAs; [self refreshUI]; } #pragma mark - - (void)refreshUI { static NSArray * sFormats=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sFormats=@[ @"N/A", // CUIRegisterViewValueAsBinary @"N/A", // CUIRegisterViewValueAsBoolean @"%g", // CUIRegisterViewValueAsFloat @"%ld", // CUIRegisterViewValueAsDecimal @"0x%016lx", // CUIRegisterViewValueAsHex @"0%o", // CUIRegisterViewAValuesOctal @"%lu", // CUIRegisterViewValueAsUnsignedDecimal ]; }); switch(self.viewValueAs) { case CUIRegisterViewValueAsBinary: break; case CUIRegisterViewValueAsBoolean: _textField.stringValue=(self.registerValue==0) ? @"false" : @"true"; break; case CUIRegisterViewValueAsFloat: { double tDouble=*((double *)&_registerValue); _textField.stringValue=[NSString stringWithFormat:@"%g",tDouble]; break; } default: _textField.stringValue=[NSString stringWithFormat:sFormats[self.viewValueAs],self.registerValue]; break; } } #pragma mark - - (IBAction)switchDisplayFormat:(NSPopUpButton *)sender { CUIRegisterViewValueAsType tViewValueAs=sender.selectedTag; if (self.viewValueAs==tViewValueAs) return; self.viewValueAs=tViewValueAs; if (self.delegate!=nil) [self.delegate registerLabel:self viewValueAsDidChange:tViewValueAs]; // Post notification [NSNotificationCenter.defaultCenter postNotificationName:CUIRegisterLabelViewAsValueDidChangeNotification object:self userInfo:@{ @"viewAs":@(tViewValueAs) }]; } #pragma mark - - (void)drawRect:(NSRect)dirtyRect { // Draw the rounded rect NSRect tRect=NSInsetRect(self.bounds, 0.5, 0.5); NSBezierPath * tPath=[NSBezierPath bezierPathWithRoundedRect:tRect xRadius:4 yRadius:4]; if ([self WB_isEffectiveAppearanceDarkAqua]==YES) { [[NSColor colorWithWhite:1.0 alpha:0.07] set]; } else { [[NSColor colorWithWhite:1.0 alpha:0.9] set]; } [tPath fill]; [[NSColor quaternaryLabelColor] set]; [tPath stroke]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegistersMainViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUIRegistersMainViewContentsViewDidChangeNotificaton; @interface CUIRegistersMainViewController : NSViewController - (NSSize)idealSizeForNumberOfColumns:(NSUInteger)inColumnsNumber; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegistersMainViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRegistersMainViewController.h" #import "CUICenteredLabelViewController.h" #import "CUIRegistersViewController.h" #import "CUICrashLogsSelection.h" #import "CUICrashLogBrowsingStateRegistry.h" #import "CUICrashLogThreadState+UI.h" NSString * const CUIRegistersMainViewContentsViewDidChangeNotificaton=@"CUIRegistersMainViewContentsViewDidChangeNotificaton"; @interface CUIRegistersMainViewController () { CUICenteredLabelViewController * _noRegistersViewController; CUIRegistersViewController * _registersViewController; cpu_type_t _currentCPUType; NSViewController * _currentViewController; } @property (nonatomic,copy) CUICrashLogsSelection * selection; // Notifications - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification; @end @implementation CUIRegistersMainViewController - (instancetype)init { self=[super init]; if (self!=nil) { _noRegistersViewController=[CUICenteredLabelViewController new]; _noRegistersViewController.label=NSLocalizedString(@"Registers state not available",@""); _registersViewController=[CUIRegistersViewController new]; _selection=[CUICrashLogsSelection new]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSString *)nibName { return @"CUIRegistersMainViewController"; } - (void)viewDidLoad { [super viewDidLoad]; // Register for Notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(crashLogsSelectionDidChange:) name:CUICrashLogsSelectionDidChangeNotification object:nil]; } - (void)viewWillAppear { CUICrashLogsSelection * tSelection=[CUICrashLogsSelection sharedSelection]; self.selection=tSelection; // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUIRegistersMainViewContentsViewDidChangeNotificaton object:self]; } #pragma mark - - (void)setSelection:(CUICrashLogsSelection *)inSelection { if ([_selection isEqual:inSelection]==YES) return; _selection=[inSelection copy]; CUICrashLogThreadState * tThreadState=nil; if (_selection.crashLogs.count==0) { tThreadState=nil; } else { CUICrashLog * tCrashLog=_selection.crashLogs.firstObject; if ([tCrashLog isMemberOfClass:[CUIRawCrashLog class]]==YES) { tThreadState=nil; } else { tThreadState=tCrashLog.threadState; } } // Update Window title NSString * tCPUTypeLabel=tThreadState.displayedCPUType; if (tCPUTypeLabel==nil) { self.view.window.title=NSLocalizedString(@"Registers",@""); } else { self.view.window.title=[NSString stringWithFormat:NSLocalizedString(@"Registers - %@",@""),tCPUTypeLabel]; } if (tThreadState==nil) { if (_currentViewController==_noRegistersViewController) return; [_currentViewController.view removeFromSuperview]; NSRect tFrame=self.view.bounds; _noRegistersViewController.view.frame=tFrame; [self.view addSubview:_noRegistersViewController.view]; _currentViewController=_noRegistersViewController; _currentCPUType=0; } else { CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; _registersViewController.browsingState=[tRegistry browsingStateForCrashLog:_selection.crashLogs.firstObject windowNumber:self.view.window.windowNumber]; _registersViewController.threadState=tThreadState; if (_currentViewController!=_registersViewController) { [_currentViewController.view removeFromSuperview]; NSRect tFrame=self.view.bounds; _registersViewController.view.frame=tFrame; [self.view addSubview:_registersViewController.view]; _currentViewController=_registersViewController; } if (tThreadState.CPUType==_currentCPUType) return; _currentCPUType=tThreadState.CPUType; } // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUIRegistersMainViewContentsViewDidChangeNotificaton object:self]; } - (NSSize)idealSizeForNumberOfColumns:(NSUInteger)inColumnsNumber { static NSSize sLastIdealSize={.width=300, .height=200}; if (_currentViewController!=_registersViewController) return NSZeroSize; // A VOIR (We can get rid of the static if we stay with this implementation) sLastIdealSize=[_registersViewController idealSizeForNumberOfColumns:inColumnsNumber]; return sLastIdealSize; } #pragma mark - Notifications - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification { CUICrashLogsSelection * tSelection=inNotification.object; if ([tSelection isKindOfClass:[CUICrashLogsSelection class]]==NO) return; self.selection=tSelection; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegistersMainViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegistersViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLogThreadState.h" #import "CUICrashLogBrowsingState.h" @interface CUIRegistersViewController : NSViewController @property (nonatomic) CUICrashLogBrowsingState * browsingState; @property (nonatomic) CUICrashLogThreadState * threadState; - (NSSize)idealSizeForNumberOfColumns:(NSUInteger)inColumnsNumber; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegistersViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRegistersViewController.h" #import "CUIRegister.h" #import "CUIRegisterLabel.h" #import "CUICollectionViewRegisterItem.h" @interface CUIRegistersViewController () { IBOutlet NSCollectionView * _collectionView; } // Notifications - (void)registerItemValueAsDidChange:(NSNotification *)inNotification; @end @implementation CUIRegistersViewController - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } - (NSString *)nibName { return @"CUIRegistersViewController"; } - (void)viewDidLoad { [super viewDidLoad]; _collectionView.dataSource=self; _collectionView.delegate=self; _collectionView.backgroundColors=@[[NSColor clearColor]]; NSNib * tNib=[[NSNib alloc] initWithNibNamed:@"CUICollectionViewRegisterItem" bundle:[NSBundle mainBundle]]; [_collectionView registerNib:tNib forItemWithIdentifier:@"register"]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(registerItemValueAsDidChange:) name:CUIRegisterItemViewAsValueDidChangeNotification object:nil]; } #pragma mark - - (void)setBrowsingState:(CUICrashLogBrowsingState *)inBrowsingState { _browsingState=inBrowsingState; [self refreshUI]; } - (void)setThreadState:(CUICrashLogThreadState *)inThreadState { _threadState=inThreadState; [self refreshUI]; } - (NSSize)idealSizeForNumberOfColumns:(NSUInteger)inColumnsNumber { if (inColumnsNumber==0) return NSZeroSize; NSCollectionViewFlowLayout * tFlowLayout=(NSCollectionViewFlowLayout *)_collectionView.collectionViewLayout; NSEdgeInsets tMarginInsets=tFlowLayout.sectionInset; NSSize tItemSize=tFlowLayout.itemSize; CGFloat tHorizontalPadding=tFlowLayout.minimumInteritemSpacing; CGFloat tIdealWidth=tMarginInsets.left+inColumnsNumber*tItemSize.width+(inColumnsNumber-1)*tHorizontalPadding+tMarginInsets.right+22; NSUInteger tNumberOfSections=[self numberOfSectionsInCollectionView:_collectionView]; NSUInteger tNumberOfItems=0; for(NSUInteger tSectionIndex=0;tSectionIndex ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegistersWindowController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIRegistersWindowController : NSWindowController + (CUIRegistersWindowController *)sharedRegistersWindowController; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRegistersWindowController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRegistersWindowController.h" #import "CUIRegistersMainViewController.h" #define REGISTERS_LAYOUT_1_COLUMN 1 #define REGISTERS_LAYOUT_4_COLUMNS 4 @interface CUIRegistersWindowController () { CUIRegistersMainViewController * _mainViewController; NSUInteger _columnsCount; } - (NSRect)windowFrameForNumberOfColumns:(NSUInteger)inNumberOfColumns; // Notifications - (void)registersMainViewContentsViewDidChange:(NSNotification *)inNotification; @end @implementation CUIRegistersWindowController + (void)initialize { [[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"registers.columnsCount":@(REGISTERS_LAYOUT_4_COLUMNS) }]; } + (CUIRegistersWindowController *)sharedRegistersWindowController { static dispatch_once_t onceToken; static CUIRegistersWindowController * sRegistersWindowController=nil; dispatch_once(&onceToken, ^{ sRegistersWindowController=[CUIRegistersWindowController new]; }); return sRegistersWindowController; } #pragma mark - - (NSString *)windowNibName { return @"CUIRegistersWindowController"; } - (void)windowDidLoad { [super windowDidLoad]; _columnsCount=[[NSUserDefaults standardUserDefaults] integerForKey:@"registers.columnsCount"]; _mainViewController=[CUIRegistersMainViewController new]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(registersMainViewContentsViewDidChange:) name:CUIRegistersMainViewContentsViewDidChangeNotificaton object:_mainViewController]; NSRect tContentsBounds=self.window.contentView.bounds; _mainViewController.view.frame=tContentsBounds; [self.window.contentView addSubview:_mainViewController.view]; } #pragma mark - - (IBAction)showWindow:(id)sender { // Make sure the window is visible on screen // A COMPLETER [super showWindow:sender]; } #pragma mark - - (NSRect)windowFrameForNumberOfColumns:(NSUInteger)inNumberOfColumns { NSSize tSize=[_mainViewController idealSizeForNumberOfColumns:inNumberOfColumns]; if (NSEqualSizes(tSize,NSZeroSize)==YES) return NSZeroRect; NSRect tWindowFrame=self.window.frame; NSRect tOldContentBounds=self.window.contentView.bounds; if (NSEqualSizes(tSize, tOldContentBounds.size)==YES) return NSZeroRect; NSRect tContentRect; tContentRect.origin=NSZeroPoint; tContentRect.size=tSize; NSRect tNewFrame=[self.window frameRectForContentRect:tContentRect]; tNewFrame.origin.x=tWindowFrame.origin.x; tNewFrame.origin.y=tWindowFrame.origin.y+NSHeight(tWindowFrame)-NSHeight(tNewFrame); return tNewFrame; } #pragma mark - NSWindowDelegate - (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)newFrame { NSUInteger tNewColumnCount=(_columnsCount==REGISTERS_LAYOUT_4_COLUMNS) ? REGISTERS_LAYOUT_1_COLUMN : REGISTERS_LAYOUT_4_COLUMNS; NSRect tWindowFrame=[self windowFrameForNumberOfColumns:tNewColumnCount]; if (NSIsEmptyRect(tWindowFrame)==YES) return self.window.frame; _columnsCount=tNewColumnCount; [[NSUserDefaults standardUserDefaults] setInteger:_columnsCount forKey:@"registers.columnsCount"]; return tWindowFrame; } - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame { /*NSRect tWindowFrame=[self windowFrameForNumberOfColumns:REGISTERS_LAYOUT_1_COLUMN]; if (NSIsEmptyRect(tWindowFrame)==YES) return NO;*/ if (_columnsCount==REGISTERS_LAYOUT_1_COLUMN) window.minSize=NSMakeSize(NSWidth(newFrame), 310); else window.minSize=newFrame.size; window.maxSize=newFrame.size; return YES; } - (void)registersMainViewContentsViewDidChange:(NSNotification *)inNotification { NSRect tWindowFrame=[self windowFrameForNumberOfColumns:_columnsCount]; if (NSIsEmptyRect(tWindowFrame)==YES) return; // Make sure the window is fully visible on screen NSScreen * tScreen=self.window.screen; if (tScreen!=nil) { NSRect tScreenVisibleRect=tScreen.visibleFrame; if (NSMaxX(tWindowFrame)>NSMaxX(tScreenVisibleRect)) { tWindowFrame.origin.x=NSMaxX(tScreenVisibleRect)-NSWidth(tWindowFrame); } else if (NSMinX(tWindowFrame)NSMaxY(tScreenVisibleRect)) { tWindowFrame.origin.y=NSMaxY(tScreenVisibleRect)-NSHeight(tWindowFrame); } else if (NSMinY(tWindowFrame) ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIReportThemedTransform.h ================================================ /* Copyright (c) 2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIDataTransform.h" #import #import "CUICrashLog.h" #import "CUITheme.h" #ifndef __DISABLE_SYMBOLICATION_ #import "CUISymbolicationManager.h" #import "CUISymbolicationDataFormatter.h" #endif @interface CUIReportThemedTransform : CUIDataTransform @property (readonly) id themesProvider; @property (readonly) NSDictionary * plainTextAttributes; @property (readonly) NSDictionary * keyAttributes; @property (readonly) NSDictionary * versionAttributes; @property (readonly) NSDictionary * pathAttributes; @property (readonly) NSDictionary * UUIDAttributes; @property (readonly) NSDictionary * crashedThreadLabelAttributes; @property (readonly) NSDictionary * threadLabelAttributes; @property (readonly) NSDictionary * executableCodeAttributes; @property (readonly) NSDictionary * OSCodeAttributes; @property (readonly) NSDictionary * memoryAddressAttributes; @property (readonly) NSDictionary * registerValueAttributes; @property (readonly) NSDictionary * parsingErrorAttributes; @property (readonly) NSColor * underlineColor; @property (readonly) NSCharacterSet * whitespaceCharacterSet; #ifndef __DISABLE_SYMBOLICATION_ @property (readonly) CUISymbolicationDataFormatter * symbolicationDataFormatter; #endif @property (copy) NSString * processPath; @property (nonatomic) CUICrashLog * crashlog; - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithThemesProvider:(id )inThemesProvider NS_DESIGNATED_INITIALIZER; - (void)updatesCachedAttributes; - (id)processedStackFrameLine:(NSString *)inLine stackFrame:(CUIStackFrame *)inStackFrame; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIReportThemedTransform.m ================================================ /* Copyright (c) 2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIReportThemedTransform.h" #import "CUIApplicationPreferences.h" #import "CUIApplicationPreferences+Themes.h" #import "CUIThemeItemsGroup+UI.h" @interface CUIReportThemedTransform () @property (readwrite) NSDictionary * plainTextAttributes; @property (readwrite) NSDictionary * keyAttributes; @property (readwrite) NSDictionary * versionAttributes; @property (readwrite) NSDictionary * pathAttributes; @property (readwrite) NSDictionary * UUIDAttributes; @property (readwrite) NSDictionary * crashedThreadLabelAttributes; @property (readwrite) NSDictionary * threadLabelAttributes; @property (readwrite) NSDictionary * executableCodeAttributes; @property (readwrite) NSDictionary * OSCodeAttributes; @property (readwrite) NSDictionary * memoryAddressAttributes; @property (readwrite) NSDictionary * registerValueAttributes; @property (readwrite) NSDictionary * parsingErrorAttributes; @property (readwrite) NSColor * underlineColor; @end @implementation CUIReportThemedTransform - (instancetype)initWithThemesProvider:(id )inThemesProvider; { self=[super init]; if (self!=nil) { _themesProvider=inThemesProvider; #ifndef __DISABLE_SYMBOLICATION_ _symbolicationDataFormatter=[CUISymbolicationDataFormatter new]; #endif _whitespaceCharacterSet=[NSCharacterSet whitespaceCharacterSet]; } return self; } #pragma mark - - (void)updatesCachedAttributes { NSFontManager * tFontManager = [NSFontManager sharedFontManager]; CUIThemeItemsGroup * tItemsGroup=[self.themesProvider.currentTheme itemsGroupWithIdentifier:[CUIApplicationPreferences groupIdentifierForPresentationMode:CUIPresentationModeText]]; NSMutableArray * tItemsNames=[tItemsGroup.itemsNames mutableCopy]; [tItemsNames removeObject:CUIThemeItemBackground]; [tItemsNames removeObject:CUIThemeItemLineNumber]; [tItemsNames removeObject:CUIThemeItemSelectionBackground]; [tItemsNames removeObject:CUIThemeItemSelectionText]; // TabStops settings NSMutableParagraphStyle * tMutableParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; tMutableParagraphStyle.tabStops=@[]; [tMutableParagraphStyle setLineSpacing:2.0]; for (NSUInteger tIndex = 1; tIndex <= 20; tIndex++) { NSTextTab *tabStop = [[NSTextTab alloc] initWithType:NSLeftTabStopType location: 40 * (tIndex)]; [tMutableParagraphStyle addTabStop:tabStop]; } NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; for(NSString * tItemName in tItemsNames) { CUIThemeItemAttributes * tItemAttributes=[tItemsGroup attributesForItem:tItemName]; NSFont * tFont=tItemAttributes.font; NSFont * tAdjustedFont=nil; tAdjustedFont=[tFontManager convertFont:tFont toSize:tFont.pointSize + self.fontSizeDelta]; if (tAdjustedFont==nil) tAdjustedFont=tFont; tMutableDictionary[tItemName]=@{ NSFontAttributeName:tAdjustedFont, NSForegroundColorAttributeName:tItemAttributes.color, NSParagraphStyleAttributeName:tMutableParagraphStyle }; } self.plainTextAttributes=tMutableDictionary[CUIThemeItemPlainText]; NSColor * tForegroundColor=self.plainTextAttributes[NSForegroundColorAttributeName]; self.underlineColor=[tForegroundColor colorWithAlphaComponent:0.35]; self.keyAttributes=tMutableDictionary[CUIThemeItemKey]; self.threadLabelAttributes=tMutableDictionary[CUIThemeItemThreadLabel]; self.crashedThreadLabelAttributes=tMutableDictionary[CUIThemeItemCrashedThreadLabel]; self.executableCodeAttributes=tMutableDictionary[CUIThemeItemExecutableCode]; self.OSCodeAttributes=tMutableDictionary[CUIThemeItemOSCode]; self.versionAttributes=tMutableDictionary[CUIThemeItemVersion]; self.memoryAddressAttributes=tMutableDictionary[CUIThemeItemMemoryAddress]; self.pathAttributes=tMutableDictionary[CUIThemeItemPath]; self.UUIDAttributes=tMutableDictionary[CUIThemeItemUUID]; self.registerValueAttributes=tMutableDictionary[CUIThemeItemRegisterValue]; NSMutableDictionary * tParsingErrorDictionary=[self.plainTextAttributes mutableCopy]; tParsingErrorDictionary[NSForegroundColorAttributeName]=[NSColor redColor]; self.parsingErrorAttributes=[tParsingErrorDictionary copy]; } #pragma mark - - (id)processedStackFrameLine:(NSString *)inLine stackFrame:(CUIStackFrame *)inStackFrame { NSScanner * tScanner=[NSScanner scannerWithString:inLine]; if ([tScanner scanInteger:NULL]==NO) return nil; __block NSString * tLine=inLine; tScanner.charactersToBeSkipped=nil; [tScanner scanCharactersFromSet:self.whitespaceCharacterSet intoString:NULL]; tScanner.charactersToBeSkipped=self.whitespaceCharacterSet; NSUInteger tBinaryImageIdentifierStart=tScanner.scanLocation; if ([tScanner scanUpToString:@"0x" intoString:nil]==NO) return nil; NSRange tBinaryImageIdentifierRange; if (tScanner.scanLocation==tLine.length) { // try to find a \t tScanner.scanLocation=tBinaryImageIdentifierStart; if ([tScanner scanUpToString:@"\t" intoString:NULL]==NO) return [[NSAttributedString alloc] initWithString:tLine attributes:self.parsingErrorAttributes]; if (tScanner.scanLocation==tLine.length) return [[NSAttributedString alloc] initWithString:tLine attributes:self.parsingErrorAttributes]; tBinaryImageIdentifierRange=NSMakeRange(tBinaryImageIdentifierStart,tScanner.scanLocation-tBinaryImageIdentifierStart+1); } else { tBinaryImageIdentifierRange=NSMakeRange(tBinaryImageIdentifierStart,tScanner.scanLocation-1-tBinaryImageIdentifierStart+1); } NSRange tBinEndRange=[[tLine substringWithRange:tBinaryImageIdentifierRange] rangeOfCharacterFromSet:self.whitespaceCharacterSet.invertedSet options:NSBackwardsSearch]; NSString * tBinaryImageIdentifier=[tLine substringWithRange:NSMakeRange(tBinaryImageIdentifierRange.location, tBinEndRange.location+1)]; tScanner.charactersToBeSkipped=self.whitespaceCharacterSet; unsigned long long tMachineInstructionAddress=0; if ([tScanner scanHexLongLong:&tMachineInstructionAddress]==NO) return [[NSAttributedString alloc] initWithString:tLine]; BOOL tIsUserCode=NO; CUICrashLogBinaryImages * tBinaryImages=self.crashlog.binaryImages; CUIBinaryImage * tBinaryImage=[tBinaryImages binaryImageWithIdentifierOrName:tBinaryImageIdentifier identifier:&tBinaryImageIdentifier]; if (tBinaryImage!=nil) { tIsUserCode = tBinaryImage.isUserCode; if (tIsUserCode==NO && [tBinaryImage.path isEqualToString:self.processPath]==YES) tIsUserCode=YES; } if (tIsUserCode==NO) tIsUserCode=[tBinaryImages isUserCodeAtMemoryAddress:tMachineInstructionAddress inBinaryImage:tBinaryImageIdentifier]; NSRange tMemoryAddressRange=NSMakeRange(tBinaryImageIdentifierRange.location+tBinaryImageIdentifierRange.length,tScanner.scanLocation-(tBinaryImageIdentifierRange.location+tBinaryImageIdentifierRange.length)+1); NSString * tSymbol=nil; if ([tScanner scanUpToString:@" +" intoString:&tSymbol]==NO) return [[NSAttributedString alloc] initWithString:tLine]; __block NSUInteger tSavedScanLocation=tScanner.scanLocation; #ifndef __DISABLE_SYMBOLICATION_ BOOL tSymbolicateAutomatically=[CUIApplicationPreferences sharedPreferences].symbolicateAutomatically; if (self.symbolicationMode==CUISymbolicationModeNone) tSymbolicateAutomatically=NO; CUISymbolicationData * tSymbolicationData=nil; if (tSymbolicateAutomatically==YES) { tSymbolicationData=inStackFrame.symbolicationData; } if (tSymbolicationData!=nil) { NSMutableString * tTemporaryLine=[[tLine substringToIndex:tScanner.scanLocation-tSymbol.length] mutableCopy]; if (tSymbolicationData.stackFrameSymbol==nil) { NSLog(@"Missing stackFrameSymbol"); } tSavedScanLocation+=(tSymbolicationData.stackFrameSymbol.length-tSymbol.length); [tTemporaryLine appendString:[self.symbolicationDataFormatter stringForObjectValue:tSymbolicationData]]; tLine=[tTemporaryLine copy]; } else { if (tSymbolicateAutomatically==YES) { // Default values NSUInteger tAddress=tMachineInstructionAddress-tBinaryImage.binaryImageOffset; [[CUISymbolicationManager sharedSymbolicationManager] lookUpSymbolicationDataForMachineInstructionAddress:tAddress binaryUUID:tBinaryImage.UUID completionHandler:^(CUISymbolicationDataLookUpResult bLookUpResult, CUISymbolicationData *bSymbolicationData) { switch(bLookUpResult) { case CUISymbolicationDataLookUpResultError: case CUISymbolicationDataLookUpResultNotFound: break; case CUISymbolicationDataLookUpResultFound: { inStackFrame.symbolicationData=bSymbolicationData; [NSNotificationCenter.defaultCenter postNotificationName:CUIStackFrameSymbolicationDidSucceedNotification object:self.input]; break; } case CUISymbolicationDataLookUpResultFoundInCache: { inStackFrame.symbolicationData=bSymbolicationData; NSMutableString * tTemporaryLine=[[tLine substringToIndex:tScanner.scanLocation-tSymbol.length] mutableCopy]; tSavedScanLocation+=(bSymbolicationData.stackFrameSymbol.length-tSymbol.length); [tTemporaryLine appendString:[self.symbolicationDataFormatter stringForObjectValue:bSymbolicationData]]; tLine=[tTemporaryLine copy]; break; } } }]; } } #endif NSMutableAttributedString * tProcessedLine=[[NSMutableAttributedString alloc] initWithString:tLine attributes:self.plainTextAttributes]; NSRange tRange=NSMakeRange(0,tLine.length); NSDictionary * tDictionary=(tIsUserCode==YES) ? self.executableCodeAttributes : self.OSCodeAttributes; [tProcessedLine addAttributes:tDictionary range:tRange]; if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)==0) { [tProcessedLine deleteCharactersInRange:NSMakeRange(tSavedScanLocation, tLine.length-1-tSavedScanLocation+1)]; } else { #ifndef __DISABLE_SYMBOLICATION_ if (tSymbolicationData!=nil) { NSString * tAbsolutePath=inStackFrame.symbolicationData.sourceFilePath; NSString * tLastPathComponent=tAbsolutePath.lastPathComponent; if (tLastPathComponent!=nil) { NSRange tRange=[tLine rangeOfString:tLastPathComponent]; if (tRange.location!=0) { if ([[NSFileManager defaultManager] fileExistsAtPath:tAbsolutePath]==YES) { NSURLComponents * tURLComponents=[NSURLComponents new]; tURLComponents.scheme=[NSString stringWithFormat:@"sourcecode-%lu",inStackFrame.symbolicationData.lineNumber]; tURLComponents.path=tAbsolutePath; NSURL * tURL=tURLComponents.URL; if (tURL!=nil) { [tProcessedLine addAttributes:@{ NSLinkAttributeName:tURL, NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle), NSUnderlineColorAttributeName:self.underlineColor } range:tRange]; } } } } } #endif } if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)==0) { [tProcessedLine deleteCharactersInRange:tMemoryAddressRange]; } else { [tProcessedLine addAttributes:self.memoryAddressAttributes range:tMemoryAddressRange]; } if ((self.displaySettings.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)==0) { [tProcessedLine deleteCharactersInRange:tBinaryImageIdentifierRange]; } else { if (self.hyperlinksStyle!=CUIHyperlinksNone && ((self.displaySettings.visibleSections & CUIDocumentBinaryImagesSection)==CUIDocumentBinaryImagesSection)) { NSString * tCleanedUpIdentifier=[tBinaryImageIdentifier stringByTrimmingCharactersInSet:self.whitespaceCharacterSet]; CUIBinaryImage * tBinaryImage=[tBinaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { tBinaryImage=[tBinaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; } NSString * tBinaryImageUUID=tBinaryImage.UUID; if (tBinaryImageUUID!=nil) { NSURL * tURL=nil; switch(self.hyperlinksStyle) { case CUIHyperlinksInternal: tURL=[NSURL URLWithString:[NSString stringWithFormat:@"bin://%@",tBinaryImageUUID]]; break; case CUIHyperlinksHTML: tURL=[NSURL URLWithString:[NSString stringWithFormat:@"sharp://%@",tBinaryImageUUID]]; break; default: break; } if (tURL!=nil) [tProcessedLine addAttributes:@{NSLinkAttributeName:tURL} range:NSMakeRange(tBinaryImageIdentifierRange.location,tCleanedUpIdentifier.length)]; } } } return tProcessedLine; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRightViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIRightViewController : NSViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRightViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRightViewController.h" #import "CUIInspectorViewController.h" #import "CUICenteredLabelViewController.h" #import "CUICrashLogsSelection.h" @interface CUIRightViewController () { CUIInspectorViewController * _inspectorViewController; CUICenteredLabelViewController * _emptySelectionViewController; CUICenteredLabelViewController * _unavailableViewController; NSViewController * _currentController; } @property (nonatomic,copy) CUICrashLogsSelection * selection; // Notifications - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification; @end @implementation CUIRightViewController - (instancetype)init { self=[super init]; if (self!=nil) { _inspectorViewController=[CUIInspectorViewController new]; _emptySelectionViewController=[CUICenteredLabelViewController new]; _emptySelectionViewController.label=NSLocalizedString(@"No Selection",@""); _unavailableViewController=[CUICenteredLabelViewController new]; _unavailableViewController.label=NSLocalizedString(@"Not Available",@""); } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; self.selection=[CUICrashLogsSelection new]; // Register for Notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(crashLogsSelectionDidChange:) name:CUICrashLogsSelectionDidChangeNotification object:nil]; } #pragma mark - - (void)setSelection:(CUICrashLogsSelection *)inSelection { if ([_selection isEqual:inSelection]==YES) return; _selection=[inSelection copy]; [_currentController.view removeFromSuperview]; if (_selection.crashLogs.count==0) { _emptySelectionViewController.view.frame=self.view.bounds; [self.view addSubview:_emptySelectionViewController.view]; _currentController=_emptySelectionViewController; } else { CUICrashLog * tCrashLog=_selection.crashLogs.firstObject; if ([tCrashLog isMemberOfClass:CUIRawCrashLog.class]==YES) { _unavailableViewController.view.frame=self.view.bounds; [self.view addSubview:_unavailableViewController.view]; _currentController=_unavailableViewController; } else { _inspectorViewController.view.frame=self.view.bounds; [self.view addSubview:_inspectorViewController.view]; _currentController=_inspectorViewController; _inspectorViewController.crashLog=tCrashLog; } } } #pragma mark - Notifications - (void)crashLogsSelectionDidChange:(NSNotification *)inNotification { CUICrashLogsSelection * tSelection=inNotification.object; if ([tSelection isKindOfClass:CUICrashLogsSelection.class]==NO) return; self.selection=tSelection; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRightViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRoundedRectBezelView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIRoundedRectBezelView : NSView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIRoundedRectBezelView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIRoundedRectBezelView.h" @implementation CUIRoundedRectBezelView - (void)drawRect:(NSRect)dirtyRect { NSRect tRect=NSInsetRect(self.bounds, 2.5, 2.5); BOOL tIsDark=[self WB_isEffectiveAppearanceDarkAqua]; NSBezierPath * tBezierPath=[NSBezierPath bezierPathWithRoundedRect:tRect xRadius:4 yRadius:4]; if (tIsDark==YES) { [[NSColor colorWithWhite:0.0 alpha:0.1] setStroke]; } else { [[NSColor colorWithWhite:1.0 alpha:0.9] setStroke]; } [tBezierPath stroke]; tBezierPath=[NSBezierPath bezierPathWithRoundedRect:NSOffsetRect(tRect, 0, 1) xRadius:4 yRadius:4]; if (tIsDark==YES) { [[NSColor colorWithWhite:1 alpha:0.4] setStroke]; } else { [[NSColor colorWithWhite:0 alpha:0.2] setStroke]; } [tBezierPath stroke]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISelectedWhiteTextFieldCell.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUISelectedWhiteTextFieldCell : NSTextFieldCell @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISelectedWhiteTextFieldCell.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISelectedWhiteTextFieldCell.h" @implementation CUISelectedWhiteTextFieldCell - (NSColor *)textColor { if (self.backgroundStyle==NSBackgroundStyleEmphasized) return [NSColor whiteColor]; return [super textColor]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISidebarViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIKeyViews.h" @interface CUISidebarViewController : NSViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISidebarViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISidebarViewController.h" #import "CUICrashLogsSourcesViewController.h" #import "CUICrashLogsListViewController.h" #define CUICrashLogsListMinimumHeight 340.0 #define CUICrashLogsSourcesMinimumHeight 153.0 NSString * const CUIDefaultsSidebarTopHeightKey=@"sidebar.top.height"; NSString * const CUIDefaultsSidebarTopCollapsedKey=@"sidebar.top.collapsed"; @interface CUISidebarViewController () { IBOutlet NSSplitView * _splitView; IBOutlet NSView * _crashLogsSourcesContainerView; IBOutlet NSView * _crashLogsListContainerView; CUICrashLogsSourcesViewController * _sourcesViewController; CUICrashLogsListViewController * _listViewController; } - (void)_splitView:(NSSplitView *)inSplitView resizeSubviewsWithTopHeight:(CGFloat)inTopHeight; @end @implementation CUISidebarViewController - (instancetype)init { self=[super init]; if (self!=nil) { _sourcesViewController=[CUICrashLogsSourcesViewController new]; _listViewController=[CUICrashLogsListViewController new]; [self addChildViewController:_sourcesViewController]; [self addChildViewController:_listViewController]; } return self; } - (NSString *)nibName { return @"CUISidebarViewController"; } #pragma mark - NSObject - (id)forwardingTargetForSelector:(SEL)aSelector { if ([_sourcesViewController respondsToSelector:aSelector]==YES) return _sourcesViewController; if ([_listViewController respondsToSelector:aSelector]==YES) return _listViewController; return nil; } - (BOOL)respondsToSelector:(SEL)aSelector { BOOL tResponds=[super respondsToSelector:aSelector]; if (tResponds==YES) return YES; NSString * tSelectorName=NSStringFromSelector(aSelector); if ([tSelectorName hasPrefix:@"CUI_MENUACTION_"]==NO) return NO; tResponds=[_sourcesViewController respondsToSelector:aSelector]; if (tResponds==YES) return YES; return [_listViewController respondsToSelector:aSelector]; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; _listViewController.view.frame=_crashLogsListContainerView.bounds; [_crashLogsListContainerView addSubview:_listViewController.view]; _sourcesViewController.view.frame=_crashLogsSourcesContainerView.bounds; [_crashLogsSourcesContainerView addSubview:_sourcesViewController.view]; [_sourcesViewController.lastKeyView setNextKeyView:_listViewController.firstKeyView]; } - (void)viewDidAppear { [super viewDidAppear]; // Restore SplitView divider position NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; NSNumber * tNumber=[tUserDefaults objectForKey:CUIDefaultsSidebarTopCollapsedKey]; if ([tNumber boolValue]==YES) { [_splitView setPosition:[_splitView minPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0]; } else { tNumber=[tUserDefaults objectForKey:CUIDefaultsSidebarTopHeightKey]; if (tNumber!=nil) [self _splitView:_splitView resizeSubviewsWithTopHeight:[tNumber doubleValue]]; } [self.view.window makeFirstResponder:_listViewController.firstKeyView]; } - (void)viewWillDisappear { // Save SplitView divider position NSView * tViewTop=_splitView.subviews.firstObject; NSUserDefaults * tUserDefaults=[NSUserDefaults standardUserDefaults]; [tUserDefaults setObject:@(NSHeight(tViewTop.frame)) forKey:CUIDefaultsSidebarTopHeightKey]; [tUserDefaults setBool:[_splitView isSubviewCollapsed:tViewTop] forKey:CUIDefaultsSidebarTopCollapsedKey]; } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if ([_sourcesViewController respondsToSelector:tAction]==YES) return [_sourcesViewController validateMenuItem:inMenuItem]; if ([_listViewController respondsToSelector:tAction]==YES) return [_listViewController validateMenuItem:inMenuItem]; if ([self respondsToSelector:tAction]==NO) return [self.parentViewController validateMenuItem:inMenuItem]; return YES; } - (void)_splitView:(NSSplitView *)inSplitView resizeSubviewsWithTopHeight:(CGFloat)inTopHeight { NSRect tSplitViewFrame=inSplitView.frame; NSArray * tSubviews=inSplitView.subviews; NSView *tViewTop=tSubviews[0]; NSRect tTopFrame=tViewTop.frame; tTopFrame.size.height=inTopHeight; NSView *tViewBottom=tSubviews[1]; NSRect tBottomFrame=tViewBottom.frame; CGFloat tTopHeight=([inSplitView isSubviewCollapsed:tViewTop]==NO) ? NSHeight(tTopFrame) : 0; tBottomFrame.size.height=NSHeight(tSplitViewFrame)-inSplitView.dividerThickness-tTopHeight; if (NSHeight(tBottomFrame) ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISourceFileTableCellView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUISourceFileTableCellView : NSTableCellView @property (assign) IBOutlet NSButton * openButton; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISourceFileTableCellView.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISourceFileTableCellView.h" @implementation CUISourceFileTableCellView - (void)awakeFromNib { [super awakeFromNib]; if (self.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft) { // Mirror image. NSImage * tOriginalImage=self.openButton.image; NSRect tBounds=self.openButton.bounds; NSImage * newTemplate=[NSImage imageWithSize:tBounds.size flipped:NO drawingHandler:^BOOL(NSRect dstRect) { NSAffineTransform * tTransform = [NSAffineTransform transform]; [tTransform translateXBy:NSWidth(tBounds) yBy:0]; [tTransform scaleXBy:-1.0 yBy:1.0]; [tTransform concat]; [tOriginalImage drawInRect:dstRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; return YES; }]; newTemplate.template=YES; self.openButton.image=newTemplate; } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIStackFrame+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIStackFrame.h" #import #import "CUIStackFrameComponents.h" @interface CUIStackFrame (UI) - (NSImage *)binaryImageIcon; - (NSString *)pasteboardRepresentationWithComponents:(CUIStackFrameComponents)inComponents; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIStackFrame+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIStackFrame+UI.h" #import "CUIBinaryImageUtility.h" @implementation CUIStackFrame (UI) - (NSImage *)binaryImageIcon { return [CUIBinaryImageUtility iconForIdentifier:self.binaryImageIdentifier]; } - (NSString *)pasteboardRepresentationWithComponents:(CUIStackFrameComponents)inComponents { NSMutableString * tMutableString=[NSMutableString stringWithFormat:@"%lu ",self.index]; if ((inComponents & CUIStackFrameBinaryNameComponent)!=0) [tMutableString appendFormat:@"%@ ",self.binaryImageIdentifier]; if ((inComponents & CUIStackFrameMachineInstructionAddressComponent)!=0) [tMutableString appendFormat:@"0x%lx ",self.machineInstructionAddress]; [tMutableString appendString:self.symbol]; if ((inComponents & CUIStackFrameByteOffsetComponent)!=0) [tMutableString appendFormat:@" + %lu",self.byteOffset]; return [tMutableString copy]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIStackFrame.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUISymbolicationData.h" #import "IPSThreadFrame.h" #import "IPSImage.h" extern NSString * const CUIStackFrameSymbolicationDidSucceedNotification; @interface CUIStackFrame : NSObject @property (readonly) NSUInteger index; @property (nullable,readonly,copy) NSString * binaryImageIdentifier; @property (readonly) NSUInteger machineInstructionAddress; @property (readonly,copy) NSString * symbol; @property (readonly) NSUInteger byteOffset; @property (readonly,copy) NSString * sourceFile; @property (readonly) NSUInteger lineNumber; @property CUISymbolicationData * symbolicationData; - (instancetype)initWithString:(NSString *)inString error:(NSError **)outError; - (instancetype)initWithThreadFrame:(IPSThreadFrame *)inFrame atIndex:(NSUInteger)inIndex image:(IPSImage *)inImage error:(NSError **)outError; - (CUIStackFrame *)stackFrameCloneWithBinaryImageIdentifier:(NSString *)inBinaryImageIdentifier; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIStackFrame.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIStackFrame.h" NSString * const CUIStackFrameSymbolicationDidSucceedNotification=@"CUIStackFrameSymbolicationDidSucceedNotification"; @interface CUIStackFrame () @property NSUInteger index; @property (copy) NSString * binaryImageIdentifier; @property NSUInteger machineInstructionAddress; @property (copy) NSString * symbol; @property NSUInteger byteOffset; @property (copy) NSString * sourceFile; @property NSUInteger lineNumber; @end @implementation CUIStackFrame - (instancetype)initWithString:(NSString *)inString error:(NSError **)outError { if ([inString isKindOfClass:[NSString class]]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { NSUInteger tLength=inString.length; NSCharacterSet * tWhitespaceCharacterSet=[NSCharacterSet whitespaceCharacterSet]; NSScanner * tScanner=[NSScanner scannerWithString:inString]; tScanner.charactersToBeSkipped=tWhitespaceCharacterSet; NSInteger tInteger=-1; if ([tScanner scanInteger:&tInteger]==NO) return nil; _index=tInteger; tScanner.charactersToBeSkipped=[NSCharacterSet characterSetWithCharactersInString:@"\t"]; NSString * tString=nil; NSUInteger tCurrentScanLocation=tScanner.scanLocation; if ([tScanner scanUpToString:@"0x" intoString:&tString]==NO) return nil; if (tScanner.scanLocation==tLength) { // try to find a \t tScanner.scanLocation=tCurrentScanLocation; if ([tScanner scanUpToString:@"\t" intoString:&tString]==NO) return nil; } _binaryImageIdentifier=[tString stringByTrimmingCharactersInSet:tWhitespaceCharacterSet]; tScanner.charactersToBeSkipped=tWhitespaceCharacterSet; unsigned long long tHexaValue=0; if ([tScanner scanHexLongLong:&tHexaValue]==NO) return nil; _machineInstructionAddress=tHexaValue; if ([tScanner scanUpToString:@" +" intoString:&tString]==NO) return nil; _symbol=[tString copy]; if ([tScanner scanInteger:&tInteger]==NO) { if ([_symbol isEqualToString:@"???"]==NO) return nil; tInteger=0; } _byteOffset=tInteger; if (tScanner.scanLocation<(tLength-3)) { tScanner.charactersToBeSkipped=nil; if ([tScanner scanUpToString:@"(" intoString:NULL]==YES) { tScanner.scanLocation+=1; NSString * tFileReference=nil; if ([tScanner scanUpToString:@")" intoString:&tFileReference]==YES) { NSRange tRange=[tFileReference rangeOfString:@":" options:NSBackwardsSearch]; if (tRange.location==NSNotFound) { _sourceFile=[tFileReference copy]; } else { _sourceFile=[tFileReference substringToIndex:tRange.location]; _lineNumber=[[tFileReference substringFromIndex:tRange.location+1] integerValue]; } } } } } return self; } - (instancetype)initWithThreadFrame:(IPSThreadFrame *)inFrame atIndex:(NSUInteger)inIndex image:(IPSImage *)inImage error:(NSError **)outError { if ([inFrame isKindOfClass:[IPSThreadFrame class]]==NO || [inImage isKindOfClass:[IPSImage class]]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _index=inIndex; _binaryImageIdentifier=[(inImage.bundleIdentifier!=nil) ? inImage.bundleIdentifier : inImage.name copy]; _machineInstructionAddress=inImage.loadAddress+inFrame.imageOffset; if (inFrame.symbol!=nil) { _symbol=[inFrame.symbol copy]; _byteOffset=inFrame.symbolLocation; } else { _symbol=[NSString stringWithFormat:@"0x%lx",(unsigned long)inImage.loadAddress]; _byteOffset=_machineInstructionAddress-inImage.loadAddress; } _sourceFile=[inFrame.sourceFile copy]; _lineNumber=inFrame.sourceLine; } return self; } #pragma mark - - (CUIStackFrame *)stackFrameCloneWithBinaryImageIdentifier:(NSString *)inBinaryImageIdentifier { CUIStackFrame * tStackFrameClone=[self copy]; tStackFrameClone.binaryImageIdentifier=inBinaryImageIdentifier; return tStackFrameClone; } #pragma mark - - (NSString *)description { return [NSString stringWithFormat:@"%lu %@ 0x%lx %@ + %lu",self.index,self.binaryImageIdentifier,(unsigned long)self.machineInstructionAddress,self.symbol,self.byteOffset]; } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { CUIStackFrame * nStackFrame=[CUIStackFrame new]; nStackFrame.index=self.index; nStackFrame.binaryImageIdentifier=[self.binaryImageIdentifier copy]; nStackFrame.machineInstructionAddress=self.machineInstructionAddress; nStackFrame.symbol=[self.symbol copy]; nStackFrame.byteOffset=self.byteOffset; nStackFrame.sourceFile=[self.sourceFile copy]; nStackFrame.lineNumber=self.lineNumber; return nStackFrame; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIStackFrameComponents.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_OPTIONS(NSUInteger, CUIStackFrameComponents) { CUIStackFrameBinaryNameComponent = 1 << 0, CUIStackFrameMachineInstructionAddressComponent = 1 << 1, CUIStackFrameByteOffsetComponent = 1 << 2, CUIStackFrameAllComponents=0x7 }; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationData.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_ENUM(NSUInteger, CUISymbolicationDataLookUpResult) { CUISymbolicationDataLookUpResultError=-1, CUISymbolicationDataLookUpResultNotFound=0, CUISymbolicationDataLookUpResultFound, CUISymbolicationDataLookUpResultFoundInCache }; @interface CUISymbolicationData : NSObject @property (copy) NSString * stackFrameSymbol; @property NSUInteger byteOffset; @property (copy) NSString * sourceFilePath; @property NSUInteger lineNumber; @property NSUInteger columnNumber; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationData.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISymbolicationData.h" @implementation CUISymbolicationData @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationDataCache.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUISymbolicationData.h" @interface CUISymbolicationDataCache : NSObject + (CUISymbolicationDataCache *)sharedCache; - (CUISymbolicationData *)symbolicationDataForAddress:(uint64_t)inAddress binary:(NSString *)inBinaryUUID; - (void)setSymbolicationData:(CUISymbolicationData *)inSymbolicationData forAddress:(uint64_t)inAddress binary:(NSString *)inBinaryUUID; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationDataCache.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISymbolicationDataCache.h" #include @interface CUISymbolicationDataCache () { NSCache * _cache; pthread_rwlock_t _readWriteLock; } @end @implementation CUISymbolicationDataCache + (CUISymbolicationDataCache *)sharedCache { static CUISymbolicationDataCache * sSymbolsCache=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSymbolsCache=[CUISymbolicationDataCache new]; }); return sSymbolsCache; } - (instancetype)init { self=[super init]; if (self!=nil) { if (pthread_rwlock_init(&_readWriteLock, NULL)!=0) { NSLog(@"Unable to initialize read-write lock"); return nil; } _cache=[NSCache new]; } return self; } #pragma mark - - (CUISymbolicationData *)symbolicationDataForAddress:(uint64_t)inAddress binary:(NSString *)inBinaryUUID { if (inBinaryUUID==nil) return nil; NSCache * tAddressesCache=[_cache objectForKey:inBinaryUUID]; if (tAddressesCache==nil) return nil; return [tAddressesCache objectForKey:@(inAddress)]; } - (void)setSymbolicationData:(CUISymbolicationData *)inSymbolicationData forAddress:(uint64_t)inAddress binary:(NSString *)inBinaryUUID { if (inSymbolicationData==nil || inBinaryUUID==nil) return; NSCache * tAddressesCache=[_cache objectForKey:inBinaryUUID]; if (tAddressesCache==nil) { tAddressesCache=[NSCache new]; if (tAddressesCache==nil) return; [_cache setObject:tAddressesCache forKey:inBinaryUUID]; } [tAddressesCache setObject:inSymbolicationData forKey:@(inAddress)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationDataFormatter.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUISymbolicationData.h" typedef NS_ENUM(NSUInteger, CUISymbolicationDataFormatterStyle) { CUISymbolicationDataFormatterNoStyle = 0, /* */ CUISymbolicationDataFormatterShortStyle = 1, /* symbol file.x L[C] */ CUISymbolicationDataFormatterFullStyle = 4 /* symbol + O /full/path/file.x line L : column C */ }; typedef NS_OPTIONS(NSUInteger, CUISymbolicationDataFormatterOptions) { CUISymbolicationDataFormatterOptionAlwaysHidesColumnNumber = 0x01, CUISymbolicationDataFormatterOptionDefaults=CUISymbolicationDataFormatterOptionAlwaysHidesColumnNumber }; @interface CUISymbolicationDataFormatter : NSFormatter @property CUISymbolicationDataFormatterStyle symbolStyle; @property CUISymbolicationDataFormatterStyle pathStyle; @property CUISymbolicationDataFormatterStyle coordinatesStyle; @property CUISymbolicationDataFormatterOptions options; + (NSString *)localizedStringFromSymbolicationData:(CUISymbolicationData *)inSymbolicationData symbolStyle:(CUISymbolicationDataFormatterStyle)inSymbolStyle pathStyle:(CUISymbolicationDataFormatterStyle)inPathStyle coordinatesStyle:(CUISymbolicationDataFormatterStyle)inCoordinatesStyle options:(CUISymbolicationDataFormatterOptions)inOptions; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationDataFormatter.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISymbolicationDataFormatter.h" @implementation CUISymbolicationDataFormatter + (NSString *)localizedStringFromSymbolicationData:(CUISymbolicationData *)inSymbolicationData symbolStyle:(CUISymbolicationDataFormatterStyle)inSymbolStyle pathStyle:(CUISymbolicationDataFormatterStyle)inPathStyle coordinatesStyle:(CUISymbolicationDataFormatterStyle)inCoordinatesStyle options:(CUISymbolicationDataFormatterOptions)inOptions { CUISymbolicationDataFormatter * tFormatter=[CUISymbolicationDataFormatter new]; tFormatter.symbolStyle=inSymbolStyle; tFormatter.pathStyle=inPathStyle; tFormatter.coordinatesStyle=inCoordinatesStyle; tFormatter.options=inOptions; return [tFormatter stringForObjectValue:inSymbolicationData]; } #pragma mark - - (instancetype)init { self=[super init]; if (self!=nil) { _symbolStyle=CUISymbolicationDataFormatterFullStyle; _pathStyle=CUISymbolicationDataFormatterShortStyle; _coordinatesStyle=CUISymbolicationDataFormatterShortStyle; _options=CUISymbolicationDataFormatterOptionDefaults; } return self; } - (NSString *)stringForObjectValue:(CUISymbolicationData *)inSymbolicationData { if ([inSymbolicationData isKindOfClass:CUISymbolicationData.class]==NO) return nil; NSMutableString * tMutableString=[NSMutableString string]; // stack frame symbol switch(self.symbolStyle) { case CUISymbolicationDataFormatterNoStyle: break; case CUISymbolicationDataFormatterShortStyle: [tMutableString appendFormat:@"%@",inSymbolicationData.stackFrameSymbol]; break; case CUISymbolicationDataFormatterFullStyle: [tMutableString appendFormat:@"%@ + %lu",inSymbolicationData.stackFrameSymbol,inSymbolicationData.byteOffset]; break; } // source file if (self.pathStyle==CUISymbolicationDataFormatterNoStyle) return [tMutableString copy]; if (self.symbolStyle!=CUISymbolicationDataFormatterNoStyle) [tMutableString appendString:@" ("]; switch(self.pathStyle) { case CUISymbolicationDataFormatterShortStyle: [tMutableString appendFormat:@"%@",inSymbolicationData.sourceFilePath.lastPathComponent]; break; case CUISymbolicationDataFormatterFullStyle: [tMutableString appendFormat:@"%@",inSymbolicationData.sourceFilePath]; break; default: break; } if (self.coordinatesStyle==CUISymbolicationDataFormatterNoStyle || inSymbolicationData.lineNumber==0) { if (self.symbolStyle!=CUISymbolicationDataFormatterNoStyle) [tMutableString appendString:@")"]; return [tMutableString copy]; } switch(self.coordinatesStyle) { case CUISymbolicationDataFormatterShortStyle: [tMutableString appendFormat:@":%lu",inSymbolicationData.lineNumber]; break; case CUISymbolicationDataFormatterFullStyle: [tMutableString appendFormat:@" - %@ %lu",NSLocalizedString(@"line",@""),inSymbolicationData.lineNumber]; break; default: break; } if ((self.options & CUISymbolicationDataFormatterOptionAlwaysHidesColumnNumber)==0 && inSymbolicationData.columnNumber!=0) { switch(self.coordinatesStyle) { case CUISymbolicationDataFormatterShortStyle: [tMutableString appendFormat:@"[%lu]",inSymbolicationData.columnNumber]; break; case CUISymbolicationDataFormatterFullStyle: [tMutableString appendFormat:@" : %@ %lu",NSLocalizedString(@"column",@""),inSymbolicationData.columnNumber]; break; default: break; } } if (self.symbolStyle!=CUISymbolicationDataFormatterNoStyle) [tMutableString appendString:@")"]; return [tMutableString copy]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationManager.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUISymbolicationData.h" @interface CUISymbolicationManager : NSObject + (CUISymbolicationManager *)sharedSymbolicationManager; - (void)lookUpSymbolicationDataForMachineInstructionAddress:(NSUInteger)inAddress binaryUUID:(NSString *)inBinaryUUID completionHandler:(void (^)(CUISymbolicationDataLookUpResult bLookUpResult,CUISymbolicationData * bSymbolicationData))handler; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolicationManager.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISymbolicationManager.h" #import "CUISymbolicationDataCache.h" #import "CUIdSYMBundlesManager.h" @interface CUISymbolicationManager () { CUISymbolicationDataCache * _cache; CUIdSYMBundlesManager * _bundlesManager; } @end @implementation CUISymbolicationManager + (CUISymbolicationManager *)sharedSymbolicationManager { static CUISymbolicationManager *sSymbolicationManager=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSymbolicationManager=[CUISymbolicationManager new]; }); return sSymbolicationManager; } - (instancetype)init { self=[super init]; if (self!=nil) { _cache=[CUISymbolicationDataCache sharedCache]; _bundlesManager=[CUIdSYMBundlesManager sharedManager]; } return self; } #pragma mark - - (void)lookUpSymbolicationDataForMachineInstructionAddress:(NSUInteger)inAddress binaryUUID:(NSString *)inBinaryUUID completionHandler:(void (^)(CUISymbolicationDataLookUpResult bLookUpResult,CUISymbolicationData * bSymbolicationData))handler; { CUISymbolicationData * tData=[_cache symbolicationDataForAddress:inAddress binary:inBinaryUUID]; if (tData!=nil) { if (handler!=nil) handler(CUISymbolicationDataLookUpResultFoundInCache,tData); return; } CUIdSYMBundle * tBundle=[_bundlesManager bundleForBinaryUUID:inBinaryUUID]; if (tBundle==nil) { if (handler!=nil) handler(CUISymbolicationDataLookUpResultNotFound,tData); return; } [tBundle lookUpSymbolicationDataForMachineInstructionAddress:inAddress binaryUUID:inBinaryUUID completionHandler:handler]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolsFilesLibraryViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUISymbolsFilesLibraryViewController : NSViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUISymbolsFilesLibraryViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISymbolsFilesLibraryViewController.h" #import "CUIdSYMBundlesManager.h" #import "CUIdSYMBundle.h" #import "CUIdSYMBundle+UI.h" #import "NSArray+WBExtensions.h" #import "NSTableView+Selection.h" @interface CUISymbolsFilesLibraryViewController () { IBOutlet NSTableView * _tableView; IBOutlet NSButton * _removeButton; IBOutlet NSSearchField * _filterField; NSImage * _cachedBundleIcon; CUIdSYMBundlesManager * _dSYMBundlesManager; NSMutableArray * _filteredAndSortedBundlesArray; NSString * _filterPattern; } - (IBAction)addDebuggingSymbolsFile:(id)sender; - (IBAction)delete:(id)sender; - (IBAction)showInFinder:(id)sender; - (IBAction)takeFilterPatternFrom:(NSSearchField *)sender; // Notifications - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification; - (void)dSYMBundlesManagerDidRemoveBundles:(NSNotification *)inNotification; @end @implementation CUISymbolsFilesLibraryViewController - (instancetype)init { self=[super init]; if (self!=nil) { _dSYMBundlesManager=[CUIdSYMBundlesManager sharedManager]; _filterPattern=@""; } return self; } #pragma mark - - (NSString *)nibName { return @"CUISymbolsFilesLibraryViewController"; } - (void)viewDidLoad { [super viewDidLoad]; _cachedBundleIcon=[[NSWorkspace sharedWorkspace] iconForFileType:@"com.apple.xcode.dsym"]; [_tableView registerForDraggedTypes:@[NSPasteboardTypeFileURL]]; NSSortDescriptor *buildETASortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES selector:@selector(compareNameAndVersion:)]; _tableView.sortDescriptors=@[buildETASortDescriptor]; _filterField.centersPlaceholder=NO; NSSearchFieldCell * tSearchFieldCell=_filterField.cell; NSButtonCell * tButtonCell=tSearchFieldCell.searchButtonCell; tButtonCell.image=[NSImage imageNamed:@"filter_Template"]; tButtonCell.alternateImage=tButtonCell.image; _filteredAndSortedBundlesArray=[_dSYMBundlesManager.bundlesSet.allObjects mutableCopy]; } - (void)viewWillAppear { [super viewWillAppear]; [self refreshList]; } - (void)viewDidAppear { [super viewDidAppear]; // Register for notifications [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(dSYMBundlesManagerDidAddBundles:) name:CUIdSYMBundlesManagerDidAddBundlesNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(dSYMBundlesManagerDidRemoveBundles:) name:CUIdSYMBundlesManagerDidRemoveBundlesNotification object:nil]; } - (void)viewWillDisappear { [super viewWillDisappear]; [NSNotificationCenter.defaultCenter removeObserver:self name:CUIdSYMBundlesManagerDidAddBundlesNotification object:nil]; [NSNotificationCenter.defaultCenter removeObserver:self name:CUIdSYMBundlesManagerDidRemoveBundlesNotification object:nil]; } #pragma mark - - (void)refreshList { NSIndexSet * tIndexSet=_tableView.selectedRowIndexes; NSArray * tSelectedItems=[_filteredAndSortedBundlesArray objectsAtIndexes:tIndexSet]; NSArray * tSelectedPaths=[tSelectedItems WB_arrayByMappingObjectsUsingBlock:^id(CUIdSYMBundle * bBundle, NSUInteger bIndex) { return bBundle.bundlePath; }]; NSSet * tSet=_dSYMBundlesManager.bundlesSet; if (_filterPattern.length>0) { _filteredAndSortedBundlesArray=[NSMutableArray array]; [tSet enumerateObjectsUsingBlock:^(CUIdSYMBundle * bBundle, BOOL * bOutStop) { if ([bBundle.bundlePath.lastPathComponent rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound) { [self->_filteredAndSortedBundlesArray addObject:bBundle]; return; } for(NSString * tUUID in bBundle.binaryUUIDs) { if ([tUUID rangeOfString:self->_filterPattern options:NSCaseInsensitiveSearch].location!=NSNotFound) { [self->_filteredAndSortedBundlesArray addObject:bBundle]; return; } } }]; } else { _filteredAndSortedBundlesArray=[tSet.allObjects mutableCopy]; } [_filteredAndSortedBundlesArray sortUsingDescriptors: _tableView.sortDescriptors]; [_tableView deselectAll:self]; [_tableView reloadData]; NSMutableIndexSet * tNewSelectionIndexSet=[NSMutableIndexSet indexSet]; [_filteredAndSortedBundlesArray enumerateObjectsUsingBlock:^(CUIdSYMBundle * bBundle, NSUInteger bIndex,BOOL * bOutStop) { if ([tSelectedPaths containsObject:bBundle.bundlePath]==YES) [tNewSelectionIndexSet addIndex:bIndex]; }]; if (tNewSelectionIndexSet.count>0) { [_tableView selectRowIndexes:tNewSelectionIndexSet byExtendingSelection:NO]; } } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; if (tAction==@selector(delete:)) { NSIndexSet * tIndexSet=[_tableView WB_selectedOrClickedRowIndexes]; return (tIndexSet.count>=1); } if (tAction==@selector(selectAll:)) return (_filteredAndSortedBundlesArray.count>0); if (tAction==@selector(showInFinder:)) { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; if (tSelectionIndexSet.count==0) return NO; NSArray * tBundles=_filteredAndSortedBundlesArray; __block BOOL tResult=YES; [tSelectionIndexSet enumerateIndexesUsingBlock:^(NSUInteger bIndex,BOOL * bOutStop){ CUIdSYMBundle * tBundle=tBundles[bIndex]; NSString * tPath=tBundle.bundlePath; if (tPath.length==0 || [[NSFileManager defaultManager] fileExistsAtPath:tPath]==NO) { tResult=NO; *bOutStop=NO; return; } }]; return tResult; } return YES; } - (IBAction)addDebuggingSymbolsFile:(id)sender { NSOpenPanel * tOpenPanel=[NSOpenPanel openPanel]; tOpenPanel.prompt=NSLocalizedString(@"Add",@""); tOpenPanel.canChooseFiles=YES; tOpenPanel.canChooseDirectories=NO; tOpenPanel.allowsMultipleSelection=YES; tOpenPanel.allowedFileTypes=@[@"dSYM"]; [tOpenPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse bReturnCode) { if (bReturnCode==NSModalResponseCancel) return; CUIdSYMBundlesManager * tBundlesManager=[CUIdSYMBundlesManager sharedManager]; NSArray * tFilteredBundles=[tOpenPanel.URLs WB_arrayByMappingObjectsLenientlyUsingBlock:^CUIdSYMBundle *(NSURL * bURL, NSUInteger bIndex) { CUIdSYMBundle * tBundle=[CUIdSYMBundle bundleWithURL:bURL]; if (tBundle.isDSYMBundle==NO) return nil; if ([tBundlesManager containsBundle:tBundle]==YES) return nil; return tBundle; }]; if (tFilteredBundles.count==0) { NSBeep(); return; } dispatch_async(dispatch_get_main_queue(), ^{ [tBundlesManager addBundles:tFilteredBundles]; // Select new bundles NSIndexSet * tIndexSet=[self->_filteredAndSortedBundlesArray indexesOfObjectsPassingTest:^BOOL(CUIdSYMBundle * bBundle, NSUInteger bIndex, BOOL * bOutStop) { return [tFilteredBundles containsObject:bBundle]; }]; [self->_tableView selectRowIndexes:tIndexSet byExtendingSelection:NO]; }); }]; } - (IBAction)delete:(id)sender { NSIndexSet * tIndexSet=[_tableView WB_selectedOrClickedRowIndexes]; if (tIndexSet.count==0) return; NSArray * tSelectedBundles=[_filteredAndSortedBundlesArray objectsAtIndexes:tIndexSet]; [_tableView deselectAll:nil]; [_dSYMBundlesManager removeBundles:tSelectedBundles]; } - (IBAction)showInFinder:(id)sender { NSIndexSet * tSelectionIndexSet=_tableView.WB_selectedOrClickedRowIndexes; NSWorkspace * tSharedWorkspace=[NSWorkspace sharedWorkspace]; [_filteredAndSortedBundlesArray enumerateObjectsAtIndexes:tSelectionIndexSet options:0 usingBlock:^(CUIdSYMBundle * bBundle, NSUInteger bIndex, BOOL * bOutStop) { NSString * tPath=bBundle.bundlePath; if (tPath.length>0) [tSharedWorkspace selectFile:tPath inFileViewerRootedAtPath:@""]; }]; } - (IBAction)takeFilterPatternFrom:(NSSearchField *)sender { _filterPattern=sender.stringValue; [self refreshList]; } #pragma mark - NSTableViewDataSource - (NSInteger)numberOfRowsInTableView:(NSTableView *)inTableView { if (inTableView==_tableView) return _filteredAndSortedBundlesArray.count; return 0; } #pragma mark - NSTableViewDelegate - (NSView *)tableView:(NSTableView *)inTableView viewForTableColumn:(NSTableColumn *)inTableColumn row:(NSInteger)inRow { NSString * tTableColumnIdentifier=inTableColumn.identifier; NSTableCellView * tTableCellView=[inTableView makeViewWithIdentifier:tTableColumnIdentifier owner:self]; CUIdSYMBundle * tBundle=_filteredAndSortedBundlesArray[inRow]; if (inTableView==_tableView) { if ([tTableColumnIdentifier isEqualToString:@"name"]==YES) { tTableCellView.imageView.image=_cachedBundleIcon; tTableCellView.textField.stringValue=tBundle.displayName; tTableCellView.textField.toolTip=tBundle.bundlePath; } else if ([tTableColumnIdentifier isEqualToString:@"version"]==YES) { tTableCellView.textField.stringValue=tBundle.displayVersion; } else if ([tTableColumnIdentifier isEqualToString:@"uuids"]==YES) { NSArray * tUUIDs=[tBundle binaryUUIDs]; tTableCellView.textField.stringValue=[tUUIDs componentsJoinedByString:@". "]; } tTableCellView.textField.editable=NO; return tTableCellView; } return nil; } - (void)tableView:(NSTableView *)inTableView sortDescriptorsDidChange:(NSArray *)inOldDescriptors { [self refreshList]; } #pragma mark - Drag and Drop support - (NSDragOperation)tableView:(NSTableView *)inTableView validateDrop:(id )info proposedRow:(NSInteger)inRow proposedDropOperation:(NSTableViewDropOperation)inDropOperation { if (inDropOperation==NSTableViewDropOn) return NSDragOperationNone; NSPasteboard * tPasteBoard=[info draggingPasteboard]; if ([tPasteBoard availableTypeFromArray:@[NSPasteboardTypeFileURL]]==nil) return NSDragOperationNone; NSArray *tClasses = @[NSURL.class]; NSArray *tURLArray = [tPasteBoard readObjectsForClasses:tClasses options:@{NSPasteboardURLReadingFileURLsOnlyKey:@(YES)}]; if (tURLArray==nil) { // We were provided invalid data NSLog(@"Unable to validate drop. Unexpected type of data"); return NSDragOperationNone; } if (tURLArray.count!=1) return NSDragOperationNone; for(NSURL * tURL in tURLArray) { NSNumber *tIsDirectoryNumber; if ([tURL getResourceValue:&tIsDirectoryNumber forKey:NSURLIsDirectoryKey error:NULL]==NO) return NSDragOperationNone; if (tIsDirectoryNumber.boolValue==NO) return NSDragOperationNone; // Should have .crash extension if ([tURL.pathExtension caseInsensitiveCompare:@"dSYM"]!=NSOrderedSame) return NSDragOperationNone; // Do not have the same dSYM twice for(CUIdSYMBundle * tBundle in _filteredAndSortedBundlesArray) { if ([tBundle.bundleURL isEqual:tURL]==YES) return NSDragOperationNone; } } // Check that these are dSYM bundles and that the UUIDs are not already listed CUIdSYMBundlesManager * tBundlesManager=[CUIdSYMBundlesManager sharedManager]; for(NSURL * tURL in tURLArray) { CUIdSYMBundle * tBundle=[[CUIdSYMBundle alloc] initWithURL:tURL]; if (tBundle.isDSYMBundle==NO) return NSDragOperationNone; if ([tBundlesManager containsBundle:tBundle]==YES) return NSDragOperationNone; } [_tableView setDropRow:-1 dropOperation:NSTableViewDropOn]; return NSDragOperationCopy; } - (BOOL)tableView:(NSTableView *)inTableView acceptDrop:(id )info row:(NSInteger)inRow dropOperation:(NSTableViewDropOperation)inDropOperation { if (inTableView!=_tableView) return NO; NSPasteboard * tPasteBoard=[info draggingPasteboard]; if ([tPasteBoard availableTypeFromArray:@[NSPasteboardTypeFileURL]]==nil) return NO; NSArray *tClasses = @[NSURL.class]; NSArray *tURLArray = [tPasteBoard readObjectsForClasses:tClasses options:@{NSPasteboardURLReadingFileURLsOnlyKey:@(YES)}]; NSArray * tNewBundles=[tURLArray WB_arrayByMappingObjectsUsingBlock:^id(NSURL * bURL, NSUInteger bIndex) { return [[CUIdSYMBundle alloc] initWithURL:bURL]; }]; if (tNewBundles==nil) return NO; [_tableView deselectAll:nil]; CUIdSYMBundlesManager * tBundlesManager=[CUIdSYMBundlesManager sharedManager]; [tBundlesManager addBundles:tNewBundles]; return YES; } #pragma mark - Notifications - (void)tableViewSelectionDidChange:(NSNotification *)inNotification { NSIndexSet * tIndexSet=_tableView.selectedRowIndexes; if (tIndexSet.count==0) { _removeButton.enabled=NO; return; } _removeButton.enabled=YES; } - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification { [self refreshList]; } - (void)dSYMBundlesManagerDidRemoveBundles:(NSNotification *)inNotification { [self refreshList]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUITableCustomSelectionColorRowView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUITableCustomSelectionColorRowView : NSTableRowView @property NSColor * selectionColor; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUITableCustomSelectionColorRowView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUITableCustomSelectionColorRowView.h" @implementation CUITableCustomSelectionColorRowView - (void)drawSelectionInRect:(NSRect)dirtyRect { [self.selectionColor set]; NSRectFillUsingOperation(dirtyRect, NSCompositingOperationSourceOver); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUITableViewNoSpace.h ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import NS_ASSUME_NONNULL_BEGIN @interface CUITableViewNoSpace : NSTableView @end NS_ASSUME_NONNULL_END ================================================ FILE: app_unexpectedly/app_unexpectedly/CUITableViewNoSpace.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUITableViewNoSpace.h" @implementation CUITableViewNoSpace - (void)keyDown:(NSEvent *)inEvent { NSString * tTypedText=inEvent.characters; NSUInteger tLength=tTypedText.length; for(NSUInteger tIndex=0;tIndex #import "CUIStackFrameComponents.h" typedef NS_OPTIONS(NSUInteger, CUIDocumentSections) { CUIDocumentHeaderSection = 1 << 0, CUIDocumentExceptionInformationSection = 1 << 1, CUIDocumentDiagnosticMessagesSection = 1 << 2, CUIDocumentBacktracesSection = 1 << 3, CUIDocumentThreadStateSection = 1 << 4, CUIDocumentBinaryImagesSection = 1 << 5, CUIDocumentAllSections=0x3F, // Sub-sections CUIDocumentBacktraceCrashedThreadSubSection = 1 << 24 }; @interface CUITextModeDisplaySettings : NSObject @property CUIDocumentSections visibleSections; @property CUIStackFrameComponents visibleStackFrameComponents; - (instancetype)initWithRepresentation:(NSDictionary *)inDictionary; - (NSDictionary *)representation; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUITextModeDisplaySettings.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUITextModeDisplaySettings.h" //NSString * const CUITextModeDisplaySettingsHyperlinksKey=@"hyperlinks"; NSString * const CUITextModeDisplaySettingsVisibleSectionKey=@"sections.visible"; NSString * const CUITextModeDisplaySettingsVisibleStackFrameComponentsKey=@"stack-frame.components.visible"; @implementation CUITextModeDisplaySettings - (instancetype)initWithRepresentation:(NSDictionary *)inDictionary { if ([inDictionary isKindOfClass:NSDictionary.class]==NO) return nil; self=[super init]; if (self!=nil) { NSNumber * tNumber=inDictionary[CUITextModeDisplaySettingsVisibleSectionKey]; if ([tNumber isKindOfClass:NSNumber.class]==NO) return nil; _visibleSections=tNumber.unsignedIntegerValue; tNumber=inDictionary[CUITextModeDisplaySettingsVisibleStackFrameComponentsKey]; if ([tNumber isKindOfClass:NSNumber.class]==NO) return nil; _visibleStackFrameComponents=tNumber.unsignedIntegerValue; } return self; } - (NSDictionary *)representation { return @{ CUITextModeDisplaySettingsVisibleSectionKey:@(self.visibleSections), CUITextModeDisplaySettingsVisibleStackFrameComponentsKey:@(self.visibleStackFrameComponents) }; } #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { CUITextModeDisplaySettings * nSettings=[CUITextModeDisplaySettings new]; nSettings.visibleSections=self.visibleSections; nSettings.visibleStackFrameComponents=self.visibleStackFrameComponents; return nSettings; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUITheme.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIApplicationPreferences.h" #import "CUIThemeItemsGroup.h" @class CUITheme; @protocol CUIThemesProvider - (NSArray *)allThemes; - (CUITheme *)currentTheme; @end @protocol CUIThemeDelegate - (void)theme:(CUITheme *)inTheme didRenameTo:(NSString *)inNewName; @end @interface CUITheme : NSObject @property (readonly,copy) NSString * UUID; @property (copy) NSString * name; @property (readonly,getter=isMonochrome) BOOL monochrome; - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation; - (NSDictionary *)representation; - (NSDictionary *)exportedRepresentation; @property (nonatomic,readonly) NSArray * allItemsGroups; - (CUIThemeItemsGroup *)itemsGroupWithIdentifier:(NSString *)inIdentifier; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUITheme.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUITheme.h" #import "NSDictionary+WBExtensions.h" NSString * const CUIThemeNameKey=@"name"; NSString * const CUIThemeUUIDKey=@"UUID"; NSString * const CUIThemeMonochromeKey=@"monochrome"; NSString * const CUIThemeGroupsKey=@"groups"; @interface CUITheme () @property NSDictionary * itemsGroupsRegistry; @property (copy) NSString * UUID; - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation newUUID:(BOOL)inNewUUID; @end @implementation CUITheme - (instancetype)init { self=[super init]; if (self!=nil) { _name=@""; _UUID=[NSUUID UUID].UUIDString; _monochrome=NO; _itemsGroupsRegistry=@{}; } return self; } - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { return [self initWithRepresentation:inRepresentation newUUID:NO]; } - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation newUUID:(BOOL)inNewUUID { if ([inRepresentation isKindOfClass:[NSDictionary class]]==NO) return nil; self=[super init]; if (self!=nil) { NSString * tString=inRepresentation[CUIThemeNameKey]; if ([tString isKindOfClass:[NSString class]]==NO) return nil; _name=[tString copy]; if (inNewUUID==NO) { tString=inRepresentation[CUIThemeUUIDKey]; if ([tString isKindOfClass:[NSString class]]==NO) return nil; _UUID=[tString copy]; } else { _UUID=[NSUUID UUID].UUIDString; } NSNumber * tNumber=inRepresentation[CUIThemeMonochromeKey]; if (tNumber!=nil) { if ([tNumber isKindOfClass:[NSNumber class]]==NO) return nil; _monochrome=tNumber.boolValue; } else { _monochrome=NO; } NSArray * tArray=inRepresentation[CUIThemeGroupsKey]; if ([tArray isKindOfClass:[NSArray class]]==NO) return nil; NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; for(NSDictionary * bGroupRepresentation in tArray) { if ([bGroupRepresentation isKindOfClass:[NSDictionary class]]==NO) return nil; CUIThemeItemsGroup * tItemsGroup=[[CUIThemeItemsGroup alloc] initWithRepresentation:bGroupRepresentation]; if (tItemsGroup==nil) return nil; tMutableDictionary[tItemsGroup.identifier]=tItemsGroup; } self.itemsGroupsRegistry=[tMutableDictionary copy]; } return self; } #pragma mark - - (NSDictionary *)representation { NSMutableArray * tMutableArray=[NSMutableArray array]; [self.itemsGroupsRegistry enumerateKeysAndObjectsUsingBlock:^(id bKey, CUIThemeItemsGroup * bItemsGroup, BOOL * bOutStop) { NSDictionary * tRepresentation=[bItemsGroup representation]; [tMutableArray addObject:tRepresentation]; }]; return @{ CUIThemeNameKey:self.name, CUIThemeUUIDKey:self.UUID, CUIThemeMonochromeKey:@(self.monochrome), CUIThemeGroupsKey:[tMutableArray copy] }; } - (NSDictionary *)exportedRepresentation { // We don't want exported Themes to have the same UUID as the listed ones NSMutableDictionary * tMutableDictionary=[[self representation] mutableCopy]; tMutableDictionary[CUIThemeUUIDKey]=[NSUUID UUID].UUIDString; return [tMutableDictionary copy]; } #pragma mark - - (NSArray *)allItemsGroups { return [_itemsGroupsRegistry allValues]; } - (CUIThemeItemsGroup *)itemsGroupWithIdentifier:(NSString *)inIdentifier { if (inIdentifier==nil) return nil; return _itemsGroupsRegistry[inIdentifier]; } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { CUITheme * nTheme=[CUITheme new]; nTheme.name=self.name; // We don't copy the monochrone key nTheme.itemsGroupsRegistry=[self.itemsGroupsRegistry WB_dictionaryByMappingObjectsUsingBlock:^id(id bKey, CUIThemeItemsGroup * bItemsGroup) { return [bItemsGroup copy]; }]; return nTheme; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemeItemAttributes.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIThemeItemAttributes : NSObject @property (nonatomic) NSColor * color; @property (nonatomic) NSFont * font; // can be nil - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation; - (NSDictionary *)representation; @end extern NSString * const CUIThemeItemAttributesDidChangeNotification; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemeItemAttributes.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThemeItemAttributes.h" #import "NSColor+String.h" NSString * const CUIThemeAttributeColorKey=@"color"; NSString * const CUIThemeAttributeFontKey=@"font"; NSString * const CUIThemeItemAttributesDidChangeNotification=@"CUIThemeItemAttributesDidChangeNotification"; @implementation CUIThemeItemAttributes - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { if ([inRepresentation isKindOfClass:NSDictionary.class]==NO) return nil; self=[super init]; if (self!=nil) { NSString * tString=inRepresentation[CUIThemeAttributeColorKey]; if ([tString isKindOfClass:NSString.class]==NO) return nil; _color=[NSColor colorFromString:tString]; tString=inRepresentation[CUIThemeAttributeFontKey]; if (tString!=nil) { if ([tString isKindOfClass:NSString.class]==NO) return nil; NSArray * tComponents=[tString componentsSeparatedByString:@"::"]; _font=[NSFont fontWithName:tComponents[0] size:[tComponents[1] floatValue]]; if (_font==nil) _font=[NSFont systemFontOfSize:11.0]; } } return self; } #pragma mark - - (NSDictionary *)representation { return @{ CUIThemeAttributeColorKey:self.color.stringValue, CUIThemeAttributeFontKey:[NSString stringWithFormat:@"%@::%0.1f",self.font.fontName,self.font.pointSize] }; } #pragma mark - - (void)setFont:(NSFont *)inFont { if (_font!=inFont) { _font=inFont; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemeItemAttributesDidChangeNotification object:self]; } } - (void)setColor:(NSColor *)inColor { if (_color!=inColor) { _color=inColor; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemeItemAttributesDidChangeNotification object:self]; } } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { CUIThemeItemAttributes * nThemeItemAttributes=[CUIThemeItemAttributes new]; nThemeItemAttributes.color=[self.color copy]; nThemeItemAttributes.font=[self.font copy]; return nThemeItemAttributes; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThemeItemsGroup.h" extern NSString * const CUIThemeItemBackground; extern NSString * const CUIThemeItemSelectionBackground; extern NSString * const CUIThemeItemSelectionText; extern NSString * const CUIThemeItemPlainText; extern NSString * const CUIThemeItemKey; extern NSString * const CUIThemeItemThreadLabel; extern NSString * const CUIThemeItemCrashedThreadLabel; extern NSString * const CUIThemeItemExecutableCode; extern NSString * const CUIThemeItemOSCode; extern NSString * const CUIThemeItemMemoryAddress; extern NSString * const CUIThemeItemRegisterValue; extern NSString * const CUIThemeItemPath; extern NSString * const CUIThemeItemVersion; extern NSString * const CUIThemeItemUUID; extern NSString * const CUIThemeItemLineNumber; @interface CUIThemeItemsGroup (UI) + (NSString *)displayNameForItemNamed:(NSString *)inItemName; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThemeItemsGroup+UI.h" NSString * const CUIThemeItemBackground=@"background"; NSString * const CUIThemeItemSelectionBackground=@"selection-background"; NSString * const CUIThemeItemSelectionText=@"selection-text"; NSString * const CUIThemeItemPlainText=@"plaintext"; NSString * const CUIThemeItemKey=@"key"; NSString * const CUIThemeItemThreadLabel=@"threadLabel"; NSString * const CUIThemeItemCrashedThreadLabel=@"crashedThreadLabel"; NSString * const CUIThemeItemExecutableCode=@"executableCode"; NSString * const CUIThemeItemOSCode=@"OSCode"; NSString * const CUIThemeItemMemoryAddress=@"memoryAddress"; NSString * const CUIThemeItemRegisterValue=@"registerValue"; NSString * const CUIThemeItemPath=@"path"; NSString * const CUIThemeItemVersion=@"version"; NSString * const CUIThemeItemUUID=@"uuid"; NSString * const CUIThemeItemLineNumber=@"lineNumber"; @implementation CUIThemeItemsGroup (UI) + (NSString *)displayNameForItemNamed:(NSString *)inItemName { static NSDictionary * sDisplayedNames=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sDisplayedNames=@{ CUIThemeItemBackground: NSLocalizedString(@"Background",@""), CUIThemeItemPlainText: NSLocalizedString(@"Plain Text",@""), CUIThemeItemKey: NSLocalizedString(@"Key",@""), CUIThemeItemThreadLabel: NSLocalizedString(@"Thread Label",@""), CUIThemeItemCrashedThreadLabel: NSLocalizedString(@"Crashed Thread Label",@""), CUIThemeItemExecutableCode: NSLocalizedString(@"Executable Code",@""), CUIThemeItemOSCode: NSLocalizedString(@"OS Code",@""), CUIThemeItemMemoryAddress: NSLocalizedString(@"Memory Address",@""), CUIThemeItemRegisterValue: NSLocalizedString(@"Register Value",@""), CUIThemeItemPath: NSLocalizedString(@"File Path",@""), CUIThemeItemVersion: NSLocalizedString(@"Version",@""), CUIThemeItemUUID: NSLocalizedString(@"UUID",@""), CUIThemeItemLineNumber: NSLocalizedString(@"Line Number",@"") }; }); NSString * tString=sDisplayedNames[inItemName]; if (tString==nil) tString=inItemName; return tString; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIThemeItemAttributes.h" @interface CUIThemeItemsGroup : NSObject @property (readonly,copy) NSString * identifier; @property (readonly) NSArray * itemsNames; - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation; - (NSDictionary *)representation; - (CUIThemeItemAttributes *)attributesForItem:(NSString *)inItemName; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThemeItemsGroup.h" #import "NSDictionary+WBExtensions.h" NSString * const CUIThemeItemsGroupIdentifierKey=@"identifier"; NSString * const CUIThemeItemsGroupItemsNamesKey=@"items"; NSString * const CUIThemeItemsGroupItemsAttributesKey=@"attributes"; @interface CUIThemeItemsGroup () { NSDictionary * _itemsRegistry; } @property (copy) NSString * identifier; @property NSArray * itemsNames; @end @implementation CUIThemeItemsGroup - (instancetype)initWithRepresentation:(NSDictionary *)inRepresentation { if ([inRepresentation isKindOfClass:[NSDictionary class]]==NO) return nil; self=[super init]; if (self!=nil) { NSString * tString=inRepresentation[CUIThemeItemsGroupIdentifierKey]; if ([tString isKindOfClass:[NSString class]]==NO) return nil; _identifier=[tString copy]; NSArray * tArray=inRepresentation[CUIThemeItemsGroupItemsNamesKey]; if ([tArray isKindOfClass:[NSArray class]]==NO) return nil; _itemsNames=[tArray copy]; NSDictionary * tDictionary=inRepresentation[CUIThemeItemsGroupItemsAttributesKey]; if ([tDictionary isKindOfClass:[NSDictionary class]]==NO) return nil; _itemsRegistry=[tDictionary WB_dictionaryByMappingObjectsUsingBlock:^id(NSString * bItemName, NSDictionary * bItemAttributesRepresentation) { return [[CUIThemeItemAttributes alloc] initWithRepresentation:bItemAttributesRepresentation]; }]; } return self; } - (NSDictionary *)representation { return @{ CUIThemeItemsGroupIdentifierKey:self.identifier, CUIThemeItemsGroupItemsNamesKey:self.itemsNames, CUIThemeItemsGroupItemsAttributesKey:[_itemsRegistry WB_dictionaryByMappingObjectsUsingBlock:^id(id bKey, CUIThemeItemAttributes * bItemAttributes) { return [bItemAttributes representation]; }] }; } #pragma mark - - (CUIThemeItemAttributes *)attributesForItem:(NSString *)inItemName { if (inItemName==nil) return nil; return _itemsRegistry[inItemName]; } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { CUIThemeItemsGroup * nThemeItemsGroup=[CUIThemeItemsGroup new]; nThemeItemsGroup.identifier=[self.identifier copy]; nThemeItemsGroup.itemsNames=[self.itemsNames copy]; nThemeItemsGroup->_itemsRegistry=[self->_itemsRegistry WB_dictionaryByMappingObjectsUsingBlock:^id(NSString * bItemName, CUIThemeItemAttributes * bItemAttributes) { return [bItemAttributes copy]; }]; return nThemeItemsGroup; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemesManager.h ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUITheme.h" @interface CUIThemesManager : NSObject + (CUIThemesManager *)sharedManager; @property (nonatomic) CUITheme * currentTheme; - (CUITheme *)themeWithUUID:(NSString *)inUUID; - (BOOL)renameTheme:(CUITheme *)inTheme withName:(NSString *)inNewName; - (void)addTheme:(CUITheme *)inTheme; // Use to import themes only - (CUITheme *)duplicateTheme:(CUITheme *)inTheme; - (void)removeTheme:(CUITheme *)inTheme; - (void)reset; @end extern NSString * const CUIThemesManagerCurrentThemeDidChangeNotification; extern NSString * const CUIThemesManagerThemesListDidChangeNotification; ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemesManager.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThemesManager.h" #import "CUIApplicationPreferences.h" #import "NSArray+WBExtensions.h" #import "NSArray+UniqueName.h" NSString * const CUIThemesCurrentThemeUUIDKey=@"themes.current.UUID"; NSString * const CUIThemesListKey=@"themes.list"; NSString * const CUIThemesManagerCurrentThemeDidChangeNotification=@"CUIThemesManagerCurrentThemeDidChangeNotification"; NSString * const CUIThemesManagerThemesListDidChangeNotification=@"CUIThemesManagerThemesListDidChangeNotification"; @interface CUIThemesManager () { NSUserDefaults * _defaults; NSMutableArray * _themes; NSMutableDictionary * _cachedThemeUUIDsRegistry; } // Notifications - (void)itemAttributesDidChange:(NSNotification *)inNotification; - (void)themesListDidChange:(NSNotification *)inNotification; @end @implementation CUIThemesManager + (void)initialize { NSArray * tThemesArray=[NSArray arrayWithContentsOfURL:[[NSBundle bundleForClass:CUIThemesManager.class] URLForResource:@"default_themes" withExtension:@"plist"]]; [[NSUserDefaults standardUserDefaults] registerDefaults:@{ CUIThemesListKey:tThemesArray, CUIThemesCurrentThemeUUIDKey:@"UUID2" }]; } + (CUIThemesManager *)sharedManager { static CUIThemesManager * sSharedManager=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSharedManager=[CUIThemesManager new]; }); return sSharedManager; } - (instancetype)init { self=[super init]; if (self!=nil) { _defaults=[NSUserDefaults standardUserDefaults]; _cachedThemeUUIDsRegistry=[NSMutableDictionary dictionary]; _themes=[[[_defaults objectForKey:CUIThemesListKey] WB_arrayByMappingObjectsLenientlyUsingBlock:^id(NSDictionary * bThemeRepresentation, NSUInteger bIndex) { CUITheme * tTheme=[[CUITheme alloc] initWithRepresentation:bThemeRepresentation]; if (tTheme==nil) { NSLog(@"Archive representation of theme could not be loaded"); return nil; } self->_cachedThemeUUIDsRegistry[tTheme.UUID]=tTheme; return tTheme; }] mutableCopy]; if (_themes==nil) { NSLog(@"Error when retrieving the list of themes"); return nil; } NSString * tUUID=[_defaults objectForKey:CUIThemesCurrentThemeUUIDKey]; if (tUUID!=nil) _currentTheme=_cachedThemeUUIDsRegistry[tUUID]; if (_currentTheme==nil) _currentTheme=_themes.firstObject; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(itemAttributesDidChange:) name:CUIThemeItemAttributesDidChangeNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(themesListDidChange:) name:CUIThemesManagerThemesListDidChangeNotification object:nil]; } return self; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSArray *)allThemes { return [_themes copy]; } - (void)setCurrentTheme:(CUITheme *)inTheme { if (inTheme==nil) return; if ([_themes containsObject:inTheme]==NO) return; if (_currentTheme!=inTheme) { _currentTheme=inTheme; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerCurrentThemeDidChangeNotification object:nil]; [_defaults setObject:_currentTheme.UUID forKey:CUIThemesCurrentThemeUUIDKey]; } } - (CUITheme *)themeWithUUID:(NSString *)inUUID { if (inUUID==nil) return nil; return _cachedThemeUUIDsRegistry[inUUID]; } #pragma mark - - (BOOL)renameTheme:(CUITheme *)inTheme withName:(NSString *)inNewName { if (inTheme==nil || inNewName==nil) return NO; inTheme.name=inNewName; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerThemesListDidChangeNotification object:nil]; return YES; } - (void)addTheme:(CUITheme *)inTheme { if (inTheme==nil) return; if (_cachedThemeUUIDsRegistry[inTheme.UUID]!=nil) return; _cachedThemeUUIDsRegistry[inTheme.UUID]=inTheme; [_themes addObject:inTheme]; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerThemesListDidChangeNotification object:nil]; } - (CUITheme *)duplicateTheme:(CUITheme *)inTheme { if (inTheme==nil) return nil; CUITheme * nTheme=[inTheme copy]; // Find a unique name NSString * tNewName=[self.allThemes uniqueNameWithBaseName:[nTheme.name stringByAppendingString:NSLocalizedString(@" copy", @"")] usingNameExtractor:^NSString *(CUITheme * bThene, NSUInteger bIndex) { return bThene.name; }]; if (tNewName!=nil) nTheme.name=tNewName; _cachedThemeUUIDsRegistry[nTheme.UUID]=nTheme; [_themes addObject:nTheme]; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerThemesListDidChangeNotification object:nil]; return nTheme; } - (void)removeTheme:(CUITheme *)inTheme { if (_themes.count<2) return; if (inTheme==self.currentTheme) { NSUInteger tIndex=[_themes indexOfObjectPassingTest:^BOOL(CUITheme * bTheme, NSUInteger idx, BOOL * _Nonnull stop) { return (bTheme!=inTheme); }]; if (tIndex==NSNotFound) return; self.currentTheme=_themes[tIndex]; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerCurrentThemeDidChangeNotification object:nil]; } [_cachedThemeUUIDsRegistry removeObjectForKey:inTheme.UUID]; [_themes removeObject:inTheme]; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerThemesListDidChangeNotification object:nil]; } - (void)reset { [NSNotificationCenter.defaultCenter removeObserver:self name:CUIThemeItemAttributesDidChangeNotification object:nil]; [NSNotificationCenter.defaultCenter removeObserver:self name:CUIThemesManagerThemesListDidChangeNotification object:nil]; [_defaults removeObjectForKey:CUIThemesCurrentThemeUUIDKey]; [_defaults removeObjectForKey:CUIThemesCurrentThemeUUIDKey]; NSArray * tThemesArray=[NSArray arrayWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"default_themes" withExtension:@"plist"]]; _cachedThemeUUIDsRegistry=[NSMutableDictionary dictionary]; _themes=[[tThemesArray WB_arrayByMappingObjectsLenientlyUsingBlock:^id(NSDictionary * bThemeRepresentation, NSUInteger bIndex) { CUITheme * tTheme=[[CUITheme alloc] initWithRepresentation:bThemeRepresentation]; if (tTheme==nil) { NSLog(@"Archive representation of theme could not be loaded"); return nil; } self->_cachedThemeUUIDsRegistry[tTheme.UUID]=tTheme; return tTheme; }] mutableCopy]; if (_themes==nil) { NSLog(@"Error when retrieving the list of themes"); return; } _currentTheme=_themes.firstObject; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerThemesListDidChangeNotification object:nil]; [NSNotificationCenter.defaultCenter postNotificationName:CUIThemesManagerCurrentThemeDidChangeNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(itemAttributesDidChange:) name:CUIThemeItemAttributesDidChangeNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(themesListDidChange:) name:CUIThemesManagerThemesListDidChangeNotification object:nil]; // Save defaults NSArray * tRepresentation=[_themes WB_arrayByMappingObjectsUsingBlock:^id(CUITheme * bTheme, NSUInteger bIndex) { return [bTheme representation]; }]; [_defaults setObject:tRepresentation forKey:CUIThemesListKey]; } #pragma mark - Notifications - (void)itemAttributesDidChange:(NSNotification *)inNotification { // Save defaults NSArray * tRepresentation=[_themes WB_arrayByMappingObjectsUsingBlock:^id(CUITheme * bTheme, NSUInteger bIndex) { return [bTheme representation]; }]; [_defaults setObject:tRepresentation forKey:CUIThemesListKey]; } - (void)themesListDidChange:(NSNotification *)inNotification { // Save defaults NSArray * tRepresentation=[_themes WB_arrayByMappingObjectsUsingBlock:^id(CUITheme * bTheme, NSUInteger bIndex) { return [bTheme representation]; }]; [_defaults setObject:tRepresentation forKey:CUIThemesListKey]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemesTableView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIThemesTableView : NSTableView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThemesTableView.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThemesTableView.h" @implementation CUIThemesTableView - (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event { if ([responder isKindOfClass:NSTextField.class]) { if (event.type==NSEventTypeRightMouseDown) { return NO; } } return [super validateProposedFirstResponder:responder forEvent:event]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThread.h ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICallStackBacktrace.h" #import "IPSThread.h" #import "IPSImage.h" @interface CUIThread : NSObject @property (readonly,getter=isApplicationSpecificBacktrace) BOOL applicationSpecificBackTrace; @property (readonly,getter=isCrashed) BOOL crashed; @property (readonly) NSUInteger number; @property (readonly,copy) NSString * name; @property (readonly) CUICallStackBacktrace * callStackBacktrace; - (instancetype)initWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError; - (instancetype)initApplicationSpecificBacktraceWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError; - (instancetype)initApplicationSpecificBacktraceWithThreadFrames:(NSArray *)inFrames binaryImages:(NSArray *)inImages error:(NSError **)outError; - (instancetype)initWithIPSThread:(IPSThread *)inThread atIndex:(NSUInteger)inIndex binaryImages:(NSArray *)inImages error:(NSError **)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThread.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThread.h" @interface CUIThread () @property BOOL crashed; @property NSUInteger number; @property (copy) NSString * name; @property CUICallStackBacktrace * callStackBacktrace; @end @implementation CUIThread - (instancetype)initWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError { if ([inLines isKindOfClass:NSArray.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } if (inLines.count==0) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { NSString * tHeaderLine=inLines.firstObject; if ([tHeaderLine hasPrefix:@"Application Specific Backtrace"]==YES) { _applicationSpecificBackTrace=YES; _name=@"Application Specific Backtrace"; } else { NSArray * tComponents=[tHeaderLine componentsSeparatedByString:@"::"]; NSString * tLeftPart; if (tComponents.count==0) { // Uh oh return nil; } if (tComponents.count==1) { NSRange tRange=[tHeaderLine rangeOfString:@"Dispatch queue:"]; if (tRange.location!=NSNotFound) { tComponents=@[[tHeaderLine substringToIndex:tRange.location], [tHeaderLine substringFromIndex:tRange.location]]; } } tLeftPart=tComponents.firstObject; if (tComponents.count==2) { _name=[tComponents[1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; } else { tLeftPart=[tLeftPart stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]; } NSArray * tThreadNumberComponents=[tLeftPart componentsSeparatedByString:@" "]; if (tThreadNumberComponents.count<2) { // Uh oh // A COMPLETER } _number=[tThreadNumberComponents[1] integerValue]; if (tThreadNumberComponents.count==3) { if ([tThreadNumberComponents[2] caseInsensitiveCompare:@"Crashed"]==NSOrderedSame) _crashed=YES; } } // backtrace _callStackBacktrace=[[CUICallStackBacktrace alloc] initWithTextualRepresentation:[inLines subarrayWithRange:NSMakeRange(1,inLines.count-1)] error:outError]; if (_callStackBacktrace==nil) return nil; } return self; } - (instancetype)initApplicationSpecificBacktraceWithTextualRepresentation:(NSArray *)inLines error:(NSError **)outError { self=[self initWithTextualRepresentation:inLines error:outError]; if (self!=nil) { _crashed=NO; _applicationSpecificBackTrace=YES; _name=@"Application Specific Backtrace"; } return self; } - (instancetype)initApplicationSpecificBacktraceWithThreadFrames:(NSArray *)inFrames binaryImages:(NSArray *)inImages error:(NSError **)outError { self=[super init]; if (self!=nil) { _crashed=NO; _applicationSpecificBackTrace=YES; _name=@"Application Specific Backtrace"; _callStackBacktrace=[[CUICallStackBacktrace alloc] initWithFrames:inFrames binaryImages:inImages error:outError]; if (_callStackBacktrace==nil) { return nil; } } return self; } - (instancetype)initWithIPSThread:(IPSThread *)inThread atIndex:(NSUInteger)inIndex binaryImages:(NSArray *)inImages error:(NSError **)outError { if ([inThread isKindOfClass:IPSThread.class]==NO) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:EINVAL userInfo:@{}]; return nil; } self=[super init]; if (self!=nil) { _crashed=inThread.triggered; _number=inIndex; if (inThread.queue!=nil) _name=[NSString stringWithFormat:@"Dispatch queue: %@",inThread.queue]; _callStackBacktrace=[[CUICallStackBacktrace alloc] initWithFrames:inThread.frames binaryImages:inImages error:NULL]; if (_callStackBacktrace==nil) { // A COMPLETER } } return self; } #pragma mark - - (NSString *)description { if (_applicationSpecificBackTrace==YES) return [NSString stringWithFormat:@"%@ 1\n%@",self.name,self.callStackBacktrace]; else return [NSString stringWithFormat:@"Thread %ld %@ :: Dispatch queue: %@\n%@",self.number,(self.isCrashed==YES) ? @"(Crashed)": @"",self.name,self.callStackBacktrace]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadImageCell.h ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIThreadImageCell : NSImageCell @property (nonatomic,getter=isCrashed) BOOL crashed; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadImageCell.m ================================================ /* Copyright (c) 2020-2022, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadImageCell.h" @implementation CUIThreadImageCell + (NSImage *)crashedThreadImage { static NSImage * sCrahsedThreadImage=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sCrahsedThreadImage=[[NSImage imageNamed:@"crashedThread_Template"] copy]; [sCrahsedThreadImage lockFocus]; [[NSColor colorWithDeviceRed:203.0/255.0 green:49.0/255.0 blue:34.0/255.0 alpha:1.0 ] set]; NSRectFillUsingOperation(NSMakeRect(0,0,20,23), NSCompositingOperationSourceIn); [sCrahsedThreadImage unlockFocus]; sCrahsedThreadImage.template=NO; }); return sCrahsedThreadImage; } - (instancetype)initWithCoder:(NSCoder *)inCoder { self=[super initWithCoder:inCoder]; if (self!=nil) { self.image=[NSImage imageNamed:@"thread_Template"]; } return self; } #pragma mark - - (void)setCrashed:(BOOL)inCrashed { if (_crashed==inCrashed) return; _crashed=inCrashed; [self.controlView setNeedsDisplay:YES]; } - (NSImage *)image { if (self.isCrashed==NO) return [super image]; if (self.backgroundStyle==NSBackgroundStyleEmphasized || [self.controlView WB_isEffectiveAppearanceDarkAqua]==YES) return [NSImage imageNamed:@"crashedThread_Template"]; return [CUIThreadImageCell crashedThreadImage]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadImageView.h ================================================ /* Copyright (c) 2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIThreadImageView : NSImageView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadImageView.m ================================================ /* Copyright (c) 2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadImageView.h" @implementation CUIThreadImageView - (void)viewDidChangeEffectiveAppearance { [super viewDidChangeEffectiveAppearance]; self.cell.image=self.cell.image; // To refresh the icon when switching between Light and Dark Aqua. } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadNamedTableCellView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUIThreadNamedTableCellView : NSTableCellView @property (assign) IBOutlet NSTextField * dispatchQueueNameLabel; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadNamedTableCellView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadNamedTableCellView.h" @implementation CUIThreadNamedTableCellView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsColumnViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadsViewController.h" @interface CUIThreadsColumnViewController : CUIThreadsViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsColumnViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadsColumnViewController.h" #import "CUIApplicationSpecificBacktraceRowView.h" #import "CUICrashedThreadRowView.h" #import "CUIThreadNamedTableCellView.h" #import "CUICallTableCellView.h" #import "CUIThreadImageCell.h" #import "CUIStackFrame+UI.h" #import "CUICallsSelection.h" #import "CUICrashLogBacktraces+Utilities.h" #import "CUIdSYMBundlesManager.h" #import "CUISymbolicationManager.h" #import "CUIApplicationPreferences.h" #import "CUICrashLogBrowsingStateRegistry.h" #import "NSTableView+Selection.h" #import "CUIRawCrashLog+Path.h" #define CUIBinaryImageIdentifierTextFieldMaxWidth 200.0 @interface CUIThreadsColumnViewController () { IBOutlet NSTableView * _threadsTableView; IBOutlet NSTableView * _backtraceTableView; NSArray * _filteredThreads; CUIThread * _selectedThread; CGFloat _optimizedBinaryImageTextFieldWidth; } @property (nonatomic) NSArray * threads; - (void)delayedReloadSymbols; @end @implementation CUIThreadsColumnViewController - (instancetype)initWithUserInterfaceLayoutDirection:(NSUserInterfaceLayoutDirection)inUserInterfaceLayoutDirection { NSString *nibName=(inUserInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) ? @"CUIThreadsColumnViewController" : @"CUIThreadsColumnViewController_RTL"; return [super initWithNibName:nibName bundle:nil]; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; // TableView menu NSMenu * tMenu=[self createFrameContextualMenu]; _backtraceTableView.menu=tMenu; } - (void)viewWillDisappear { [super viewWillDisappear]; // Save browsing state [self saveBrowsingState]; } #pragma mark - - (void)saveBrowsingState { CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; if (self.crashLog!=nil) { CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; NSInteger tSelectedThread=_threadsTableView.selectedRow; if (tSelectedThread==-1) { tBrowsingState.columnSelectedThread=NSNotFound; tBrowsingState.columnSelectedStackFrame=NSNotFound; } else { tBrowsingState.columnSelectedThread=tSelectedThread; NSInteger tSelectedStackFrame=_backtraceTableView.selectedRow; tBrowsingState.columnSelectedStackFrame=(tSelectedStackFrame!=-1) ? tSelectedStackFrame : NSNotFound; tBrowsingState.columnSelectedStackFrame=(tSelectedStackFrame!=-1) ? tSelectedStackFrame : NSNotFound; } } } - (void)setCrashLog:(CUICrashLog *)inCrashLog { [self saveBrowsingState]; [super setCrashLog:inCrashLog]; _optimizedBinaryImageTextFieldWidth=-1.0; self.threads=inCrashLog.backtraces.threads; [_threadsTableView reloadData]; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:inCrashLog windowNumber:self.view.window.windowNumber]; NSUInteger tSelectedThread=tBrowsingState.columnSelectedThread; if (tSelectedThread==NSNotFound || self.showOnlyCrashedThread==YES) { [_filteredThreads enumerateObjectsUsingBlock:^(CUIThread * bThread, NSUInteger bIndex, BOOL * bOutStop) { if (bThread.isCrashed==YES) { [self->_threadsTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:bIndex] byExtendingSelection:NO]; *bOutStop=YES; } }]; } else { if (tSelectedThread<_threadsTableView.numberOfRows) { [_threadsTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tSelectedThread] byExtendingSelection:NO]; if (tBrowsingState.columnSelectedStackFrame!=NSNotFound) { [_backtraceTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tBrowsingState.columnSelectedStackFrame] byExtendingSelection:NO]; } } } } - (void)setThreads:(NSArray *)inThreads { _threads=inThreads; if (self.showOnlyCrashedThread==NO) { _filteredThreads=_threads; return; } NSUInteger tCrashedThreadIndex=self.crashLog.exceptionInformation.crashedThreadIndex; _filteredThreads=[_threads WB_filteredArrayUsingBlock:^BOOL(CUIThread * bThread, NSUInteger bIndex) { if (bThread.isApplicationSpecificBacktrace==YES) return YES; return (bThread.number==tCrashedThreadIndex); }]; } - (void)setShowOnlyCrashedThread:(BOOL)aBool { if (self.showOnlyCrashedThread==aBool) return; [super setShowOnlyCrashedThread:aBool]; [self saveBrowsingState]; if (self.showOnlyCrashedThread==NO) { _filteredThreads=self.threads; } else { NSUInteger tCrashedThreadIndex=self.crashLog.exceptionInformation.crashedThreadIndex; _filteredThreads=[self.threads WB_filteredArrayUsingBlock:^BOOL(CUIThread * bThread, NSUInteger bIndex) { if (bThread.isApplicationSpecificBacktrace==YES) return YES; return (bThread.number==tCrashedThreadIndex); }]; } [_threadsTableView reloadData]; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; NSUInteger tSelectedThread=tBrowsingState.columnSelectedThread; if (tSelectedThread==NSNotFound) { [_filteredThreads enumerateObjectsUsingBlock:^(CUIThread * bThread, NSUInteger bIndex, BOOL * bOutStop) { if (bThread.isCrashed==YES) { [self->_threadsTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:bIndex] byExtendingSelection:NO]; *bOutStop=YES; } }]; } else { if (tSelectedThread<_threadsTableView.numberOfRows) { [_threadsTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tSelectedThread] byExtendingSelection:NO]; if (tBrowsingState.columnSelectedStackFrame!=NSNotFound) { [_backtraceTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tBrowsingState.columnSelectedStackFrame] byExtendingSelection:NO]; } } } } - (void)setVisibleStackFrameComponents:(CUIStackFrameComponents)inVisibleStackFrameComponents { [super setVisibleStackFrameComponents:inVisibleStackFrameComponents]; // Save selection NSInteger tSelectedRow=_backtraceTableView.selectedRow; [_backtraceTableView reloadData]; // Restore selection if (tSelectedRow!=-1) [_backtraceTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:tSelectedRow] byExtendingSelection:NO]; } - (NSUInteger)numberOfSelectedStackFrames { return [_backtraceTableView WB_selectedOrClickedRowIndexes].count; } - (NSArray *)selectedStackFrames { NSIndexSet * tSelectedRows=[_backtraceTableView WB_selectedOrClickedRowIndexes]; if (tSelectedRows.count==0) return @[]; return [_selectedThread.callStackBacktrace.stackFrames objectsAtIndexes:tSelectedRows]; } #pragma mark - - (IBAction)openSourceFile:(id)sender { NSInteger tRow=[_backtraceTableView rowForView:sender]; if (tRow==-1) return; CUIStackFrame * tCall=(CUIStackFrame *)_selectedThread.callStackBacktrace.stackFrames[tRow]; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101600 if (@available(*, macOS 11.0)) { [[NSWorkspace sharedWorkspace] openURLs:@[[NSURL fileURLWithPath:tCall.symbolicationData.sourceFilePath]] withApplicationAtURL:[CUIApplicationPreferences sharedPreferences].preferedSourceCodeEditorURL configuration:[NSWorkspaceOpenConfiguration configuration] completionHandler:^(NSRunningApplication * _Nullable app, NSError * _Nullable error) { }]; } else #endif { [[NSWorkspace sharedWorkspace] openURLs:@[[NSURL fileURLWithPath:tCall.symbolicationData.sourceFilePath]] withApplicationAtURL:[CUIApplicationPreferences sharedPreferences].preferedSourceCodeEditorURL options:NSWorkspaceLaunchDefault configuration:@{} error:NULL]; } } #pragma mark - NSTableViewDataSource - (NSInteger)numberOfRowsInTableView:(NSTableView *)inTableView { if (inTableView==_threadsTableView) return _filteredThreads.count; if (inTableView==_backtraceTableView) return _selectedThread.callStackBacktrace.stackFrames.count; return 0; } #pragma mark - NSTableViewDelegate - (NSTableRowView *)tableView:(NSTableView *)inTableView rowViewForRow:(NSInteger)inRow { if (inTableView==_threadsTableView) { CUIThread * tThread=(CUIThread *)_filteredThreads[inRow]; if (tThread.isApplicationSpecificBacktrace==YES) { CUIApplicationSpecificBacktraceRowView * tTableRowView=[inTableView makeViewWithIdentifier:CUIApplicationSpecificBacktraceRowViewIdentifier owner:self]; if (tTableRowView==nil) { tTableRowView=[[CUIApplicationSpecificBacktraceRowView alloc] initWithFrame:NSZeroRect]; tTableRowView.identifier=CUIApplicationSpecificBacktraceRowViewIdentifier; } return tTableRowView; } if (tThread.isCrashed==YES) { CUICrashedThreadRowView * tTableRowView=[inTableView makeViewWithIdentifier:CUICrashedThreadRowViewIdentifier owner:self]; if (tTableRowView==nil) { tTableRowView=[[CUICrashedThreadRowView alloc] initWithFrame:NSZeroRect]; tTableRowView.identifier=CUICrashedThreadRowViewIdentifier; } return tTableRowView; } } return nil; } - (NSView *)tableView:(NSTableView *)inTableView viewForTableColumn:(NSTableColumn *)inTableColumn row:(NSInteger)inRow { if (inTableView==_threadsTableView) { CUIThread * tThread=(CUIThread *)_filteredThreads[inRow]; NSTableCellView * tTableCellView=nil; if (tThread.name.length==0 || tThread.isApplicationSpecificBacktrace==YES) { tTableCellView=[inTableView makeViewWithIdentifier:@"thread cell" owner:self]; } else { CUIThreadNamedTableCellView * tNamedCell=[inTableView makeViewWithIdentifier:@"thread named cell" owner:self]; tNamedCell.dispatchQueueNameLabel.stringValue=tThread.name; tTableCellView=tNamedCell; } ((CUIThreadImageCell *)tTableCellView.imageView.cell).crashed=tThread.crashed; if (tThread.isApplicationSpecificBacktrace==YES) tTableCellView.textField.stringValue=tThread.name; else tTableCellView.textField.stringValue=[NSString stringWithFormat:@"Thread %lu",tThread.number]; return tTableCellView; } if (inTableView==_backtraceTableView) { CUIStackFrame * tCall=(CUIStackFrame *)_selectedThread.callStackBacktrace.stackFrames[inRow]; NSString * tTableColumnIdentifier=inTableColumn.identifier; if ([tTableColumnIdentifier isEqualToString:@"source"]==YES) { CUISourceFileTableCellView * tTableCellView=(CUISourceFileTableCellView *)[inTableView makeViewWithIdentifier:@"source" owner:self]; BOOL tSymbolicateAutomatically=[CUIApplicationPreferences sharedPreferences].symbolicateAutomatically; CUISymbolicationData * tSymbolicationData=nil; if (tSymbolicateAutomatically==YES) tSymbolicationData=tCall.symbolicationData; if (tSymbolicationData!=nil) { [self setUpSourceFileCellView:tTableCellView withSymbolicationData:tSymbolicationData]; } else { // Default values if (tCall.sourceFile==nil) tTableCellView.textField.stringValue=@"-"; else tTableCellView.textField.stringValue=[NSString stringWithFormat:@"%@ - line %lu",tCall.sourceFile,tCall.lineNumber]; NSRect tFrame=tTableCellView.textField.frame; tFrame.size.width=NSMaxX(tTableCellView.frame)-NSMinX(tFrame)-4; tTableCellView.textField.frame=tFrame; tTableCellView.openButton.hidden=YES; NSString * tBinaryImageIdentifier=tCall.binaryImageIdentifier; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tAlternateIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tBinaryImageIdentifier]; if (tAlternateIdentifier!=nil) tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tAlternateIdentifier]; } if (tSymbolicateAutomatically==YES) { NSUInteger tAddress=tCall.machineInstructionAddress-tBinaryImage.binaryImageOffset; [[CUISymbolicationManager sharedSymbolicationManager] lookUpSymbolicationDataForMachineInstructionAddress:tAddress binaryUUID:tBinaryImage.UUID completionHandler:^(CUISymbolicationDataLookUpResult bLookUpResult, CUISymbolicationData *bSymbolicationData) { switch(bLookUpResult) { case CUISymbolicationDataLookUpResultError: case CUISymbolicationDataLookUpResultNotFound: break; case CUISymbolicationDataLookUpResultFound: { tCall.symbolicationData=bSymbolicationData; [NSNotificationCenter.defaultCenter postNotificationName:CUIStackFrameSymbolicationDidSucceedNotification object:self.crashLog]; break; } case CUISymbolicationDataLookUpResultFoundInCache: { tCall.symbolicationData=bSymbolicationData; [self setUpSourceFileCellView:tTableCellView withSymbolicationData:bSymbolicationData]; break; } } }]; } } return tTableCellView; } BOOL isRightToLeft=(inTableView.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft); NSString * tBinaryImageIdentifier=tCall.binaryImageIdentifier; BOOL tIsUserCode=NO; CUICrashLogBinaryImages * tBinaryImages=self.crashLog.binaryImages; CUIBinaryImage * tBinaryImage=[tBinaryImages binaryImageWithIdentifierOrName:tBinaryImageIdentifier identifier:&tBinaryImageIdentifier]; if (tBinaryImage!=nil) { tIsUserCode = tBinaryImage.isUserCode; if (tIsUserCode==NO && [tBinaryImage.path isEqualToString:self.crashLog.header.executablePath]==YES) tIsUserCode=YES; } if (tIsUserCode==NO) tIsUserCode=[tBinaryImages isUserCodeAtMemoryAddress:tCall.machineInstructionAddress inBinaryImage:tBinaryImageIdentifier]; CUICallTableCellView * tCallTableCellView=[inTableView makeViewWithIdentifier:@"call cell" owner:self]; // Call Index tCallTableCellView.callIndexLabel.stringValue=[NSString stringWithFormat:@"%lu ",tCall.index]; if (tIsUserCode==YES) { tCallTableCellView.callIndexLabel.textColor=[NSColor labelColor]; } else { tCallTableCellView.callIndexLabel.textColor=[NSColor secondaryLabelColor]; } NSRect tLeftFrame=tCallTableCellView.callIndexLabel.frame; // Binary Image if (((self.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)==0)) { tCallTableCellView.binaryImageLabel.hidden=YES; } else { if (_optimizedBinaryImageTextFieldWidth<0) { NSArray * tBinaryImageIdentifiers=[self.crashLog.backtraces allBinaryImagesIdentifiers]; __block CGFloat tMaxWidth=0.0; NSFont * tFont=tCallTableCellView.binaryImageLabel.font; [tBinaryImageIdentifiers enumerateObjectsUsingBlock:^(NSString * bString, NSUInteger bIndex, BOOL * bOutStop) { CGFloat tWidth=[bString sizeWithAttributes:@{NSFontAttributeName:tFont}].width; if (tWidth>tMaxWidth) tMaxWidth=tWidth; }]; _optimizedBinaryImageTextFieldWidth=tMaxWidth+10.0; if (_optimizedBinaryImageTextFieldWidth>CUIBinaryImageIdentifierTextFieldMaxWidth) _optimizedBinaryImageTextFieldWidth=CUIBinaryImageIdentifierTextFieldMaxWidth; } tCallTableCellView.binaryImageLabel.hidden=NO; NSRect tFrame=tCallTableCellView.binaryImageLabel.frame; tFrame.size.width=_optimizedBinaryImageTextFieldWidth; if (isRightToLeft==NO) { tFrame.origin.x=NSMaxX(tLeftFrame)+8; } else { tFrame.origin.x=NSMinX(tLeftFrame)-8-NSWidth(tFrame); } tCallTableCellView.binaryImageLabel.frame=tFrame; tLeftFrame=tFrame; tCallTableCellView.binaryImageLabel.stringValue=[NSString stringWithFormat:@"%@",tCall.binaryImageIdentifier]; if (tIsUserCode==YES) { tCallTableCellView.binaryImageLabel.textColor=[NSColor labelColor]; } else { tCallTableCellView.binaryImageLabel.textColor=[NSColor secondaryLabelColor]; } } // Address if ((self.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)==0) { tCallTableCellView.addressLabel.hidden=YES; } else { tCallTableCellView.addressLabel.hidden=NO; NSRect tFrame=tCallTableCellView.addressLabel.frame; if (isRightToLeft==NO) { tFrame.origin.x=NSMaxX(tLeftFrame)+8; } else { tFrame.origin.x=NSMinX(tLeftFrame)-8-NSWidth(tFrame); } tCallTableCellView.addressLabel.frame=tFrame; tLeftFrame=tFrame; tCallTableCellView.addressLabel.stringValue=[NSString stringWithFormat:@"0x%012lx",(tCall.machineInstructionAddress)]; if (tIsUserCode==YES) { tCallTableCellView.addressLabel.textColor=[NSColor labelColor]; } else { tCallTableCellView.addressLabel.textColor=[NSColor secondaryLabelColor]; } } // Symbol NSRect tFrame=tCallTableCellView.textField.frame; if (isRightToLeft==NO) { CGFloat tMaxX=NSMaxX(tFrame); tFrame.origin.x=NSMaxX(tLeftFrame)+8; tFrame.size.width=tMaxX-tFrame.origin.x; } else { CGFloat tMinX=NSMinX(tFrame); tFrame.origin.x=tMinX; tFrame.size.width=(NSMinX(tLeftFrame)-8-tMinX); } tCallTableCellView.textField.frame=tFrame; BOOL tSymbolicateAutomatically=[CUIApplicationPreferences sharedPreferences].symbolicateAutomatically; CUISymbolicationData * tData=nil; if (tSymbolicateAutomatically==YES) tData=tCall.symbolicationData; if (tData!=nil) { NSMutableString * tCallLine=[tData.stackFrameSymbol mutableCopy]; if ((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) { [tCallLine appendFormat:@" + %lu",tData.byteOffset]; } tCallTableCellView.textField.stringValue=tCallLine; } else { // Default values NSMutableString * tCallLine=[tCall.symbol mutableCopy]; if ((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) { [tCallLine appendFormat:@" + %lu",tCall.byteOffset]; } tCallTableCellView.textField.stringValue=tCallLine; NSString * tBinaryImageIdentifier=tCall.binaryImageIdentifier; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tAlternateIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tBinaryImageIdentifier]; if (tAlternateIdentifier!=nil) tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tAlternateIdentifier]; } if (tSymbolicateAutomatically==YES) { NSUInteger tAddress=tCall.machineInstructionAddress-tBinaryImage.binaryImageOffset; [[CUISymbolicationManager sharedSymbolicationManager] lookUpSymbolicationDataForMachineInstructionAddress:tAddress binaryUUID:tBinaryImage.UUID completionHandler:^(CUISymbolicationDataLookUpResult bLookUpResult, CUISymbolicationData *bSymbolicationData) { switch(bLookUpResult) { case CUISymbolicationDataLookUpResultError: case CUISymbolicationDataLookUpResultNotFound: break; case CUISymbolicationDataLookUpResultFound: { tCall.symbolicationData=bSymbolicationData; [NSNotificationCenter.defaultCenter postNotificationName:CUIStackFrameSymbolicationDidSucceedNotification object:self.crashLog]; break; } case CUISymbolicationDataLookUpResultFoundInCache: { tCall.symbolicationData=bSymbolicationData; NSMutableString * tCallLine=[bSymbolicationData.stackFrameSymbol mutableCopy]; if ((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) { [tCallLine appendFormat:@" + %lu",bSymbolicationData.byteOffset]; } tCallTableCellView.textField.stringValue=tCallLine; break; } } }]; } } if (tIsUserCode==YES) { tCallTableCellView.imageView.image=[NSImage imageNamed:@"call-usercode"]; tCallTableCellView.textField.textColor=[NSColor labelColor]; } else { tCallTableCellView.imageView.image=tCall.binaryImageIcon; tCallTableCellView.textField.textColor=[NSColor secondaryLabelColor]; } return tCallTableCellView; } return nil; } - (void)tableViewSelectionDidChange:(NSNotification *)inNotification { if (inNotification.object==_threadsTableView) { NSInteger tSelectedRow=_threadsTableView.selectedRow; [_backtraceTableView deselectAll:self]; if (tSelectedRow==-1) { _selectedThread=nil; [_backtraceTableView reloadData]; } else { _selectedThread=_filteredThreads[tSelectedRow]; [_backtraceTableView reloadData]; } } else if (inNotification.object==_backtraceTableView) { NSIndexSet * tIndexSet=_backtraceTableView.selectedRowIndexes; NSMutableSet * tMutableSet=[NSMutableSet set]; [tIndexSet enumerateIndexesUsingBlock:^(NSUInteger bIndex, BOOL * bOutStop) { CUIStackFrame * tCall=(CUIStackFrame *)self->_selectedThread.callStackBacktrace.stackFrames[bIndex]; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tCall.binaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tCall.binaryImageIdentifier]; if (tIdentifier!=nil) { tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tIdentifier]; if (tBinaryImage!=nil) tCall=[tCall stackFrameCloneWithBinaryImageIdentifier:tIdentifier]; } } [tMutableSet addObject:tCall]; }]; [CUICallsSelection sharedCallsSelection].calls=tMutableSet; } } #pragma mark - - (void)delayedReloadSymbols { [_backtraceTableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, _backtraceTableView.numberOfRows)] columnIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 4)]]; } #pragma mark - - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification { // Ideally we should just request to symbolicate the machineInstructionAddresses which can be //NSArray * tBinaryUUIDs=inNotification.object; // A COMPLETER [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayedReloadSymbols) object:nil]; [self performSelector:@selector(delayedReloadSymbols) withObject:nil afterDelay:0.1]; } - (void)stackFrameSymbolicationDidSucceed:(NSNotification *)inNotification { if (inNotification.object!=self.crashLog) return; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayedReloadSymbols) object:nil]; [self performSelector:@selector(delayedReloadSymbols) withObject:nil afterDelay:0.1]; } - (void)symbolicateAutomaticallyDidChange:(NSNotification *)inNotification { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayedReloadSymbols) object:nil]; [self performSelector:@selector(delayedReloadSymbols) withObject:nil afterDelay:0.1]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsColumnViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsColumnViewController_RTL.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsListViewController.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadsViewController.h" #import "CUIThread.h" @interface CUIThreadsListViewController : CUIThreadsViewController @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsListViewController.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadsListViewController.h" #import "CUIThreadNamedTableCellView.h" #import "CUIApplicationSpecificBacktraceRowView.h" #import "CUICrashedThreadRowView.h" #import "CUICrashedThreadCallRowView.h" #import "CUICallTableCellView.h" #import "CUIThreadImageCell.h" #import "CUICrashLog+UI.h" #import "CUIStackFrame+UI.h" #import "CUICallsSelection.h" #import "CUICrashLogBacktraces+Utilities.h" #import "CUIdSYMBundlesManager.h" #import "CUISymbolicationManager.h" #import "CUIApplicationPreferences.h" #import "CUICrashLogBrowsingStateRegistry.h" #import "NSTableView+Selection.h" #define CUIBinaryImageIdentifierTextFieldMaxWidth 200.0 @interface CUIThread (CUIStringHash) - (NSString *)stringHash; @end @implementation CUIThread (CUIStringHash) - (NSString *)stringHash { char tPrefix='t'; if (self.isApplicationSpecificBacktrace==YES) tPrefix='a'; else if (self.isCrashed==YES) tPrefix='c'; return [NSString stringWithFormat:@"%c%lu",tPrefix,self.number]; } @end @interface CUIThreadsListViewController () { IBOutlet NSOutlineView * _outlineView; IBOutlet NSTableRowView * myRowView; NSArray * _threads; CGFloat _threadStateRowHeight; BOOL _showCrashedThreadState; CGFloat _optimizedBinaryImageTextFieldWidth; } - (void)delayedReloadSymbols; @end @implementation CUIThreadsListViewController - (instancetype)initWithUserInterfaceLayoutDirection:(NSUserInterfaceLayoutDirection)inUserInterfaceLayoutDirection { NSString *nibName=(inUserInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionLeftToRight) ? @"CUIThreadsListViewController" : @"CUIThreadsListViewController_RTL"; return [super initWithNibName:nibName bundle:nil]; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; _threadStateRowHeight=205; // OutlineView menu NSMenu * tMenu=[self createFrameContextualMenu]; _outlineView.menu=tMenu; //[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(viewFrameDidChange:) name:NSViewFrameDidChangeNotification object:_outlineView]; } - (void)viewWillDisappear { [super viewWillDisappear]; // Save browsing state [self saveBrowsingState]; } #pragma mark - - (void)saveBrowsingState { CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; if (self.crashLog!=nil) { CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; tBrowsingState.listSelectedStackFrame=nil; NSInteger tSelectedRow=_outlineView.selectedRow; if (tSelectedRow!=-1) { id tItem=[_outlineView itemAtRow:tSelectedRow]; if (tItem!=nil) { CUIThread * tThread=[_outlineView parentForItem:tItem]; tBrowsingState.listSelectedStackFrame=[NSString stringWithFormat:@"%@:%lu",[tThread stringHash],[_outlineView childIndexForItem:tItem]]; } } } } - (void)setCrashLog:(CUICrashLog *)inCrashLog { [self saveBrowsingState]; [super setCrashLog:inCrashLog]; _optimizedBinaryImageTextFieldWidth=-1.0; _threads=inCrashLog.backtraces.threads; [_outlineView sizeLastColumnToFit]; [_outlineView reloadData]; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:inCrashLog windowNumber:self.view.window.windowNumber]; NSDictionary * tListDiclosedThreads=tBrowsingState.listDisclosedThreads; if (tListDiclosedThreads==nil) { // Disclose the crashed thread for(CUIThread * tThread in _threads) { if (tThread.isCrashed==YES) { [_outlineView expandItem:tThread]; break; } } [self outlineViewSelectionDidChange:[NSNotification notificationWithName:NSTableViewSelectionDidChangeNotification object:_outlineView]]; return; } for(CUIThread * tThread in _threads) { if (tListDiclosedThreads[[tThread stringHash]]!=nil) [_outlineView expandItem:tThread]; } NSString * tString=tBrowsingState.listSelectedStackFrame; if (tString!=nil) { NSArray * tComponents=[tString componentsSeparatedByString:@":"]; if (tComponents.count!=2) return; NSString * tStringHash=tComponents[0]; for(CUIThread * tThread in _threads) { if ([[tThread stringHash] isEqualToString:tStringHash]==YES) { if ([_outlineView isItemExpanded:tThread]==YES) { NSUInteger tItemRow=[_outlineView rowForItem:tThread]+[tComponents[1] integerValue]+1; dispatch_async(dispatch_get_main_queue(), ^{ [self->_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:tItemRow] byExtendingSelection:NO]; }); return; } break; } } } [self outlineViewSelectionDidChange:[NSNotification notificationWithName:NSTableViewSelectionDidChangeNotification object:_outlineView]]; } #pragma mark - - (void)setShowOnlyCrashedThread:(BOOL)aBool { [super setShowOnlyCrashedThread:aBool]; [self saveBrowsingState]; [_outlineView reloadData]; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; NSDictionary * tListDiclosedThreads=tBrowsingState.listDisclosedThreads; if (tListDiclosedThreads==nil) { // Disclose the crashed thread for(CUIThread * tThread in _threads) { if (tThread.isCrashed==YES) { [_outlineView expandItem:tThread]; NSString * tNodePath=[tThread stringHash]; tBrowsingState.listDisclosedThreads[tNodePath]=@(YES); break; } } return; } for(CUIThread * tThread in _threads) { if (tListDiclosedThreads[[tThread stringHash]]!=nil) [_outlineView expandItem:tThread]; } NSString * tString=tBrowsingState.listSelectedStackFrame; if (tString!=nil) { NSArray * tComponents=[tString componentsSeparatedByString:@":"]; if (tComponents.count!=2) return; NSString * tStringHash=tComponents[0]; for(CUIThread * tThread in _threads) { if ([[tThread stringHash] isEqualToString:tStringHash]==YES) { if ([_outlineView isItemExpanded:tThread]==YES) { NSUInteger tItemRow=[_outlineView rowForItem:tThread]+[tComponents[1] integerValue]+1; dispatch_async(dispatch_get_main_queue(), ^{ [self->_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:tItemRow] byExtendingSelection:NO]; }); return; } break; } } } [self outlineViewSelectionDidChange:[NSNotification notificationWithName:NSTableViewSelectionDidChangeNotification object:_outlineView]]; } - (void)setVisibleStackFrameComponents:(CUIStackFrameComponents)inVisibleStackFrameComponents { [super setVisibleStackFrameComponents:inVisibleStackFrameComponents]; [_outlineView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,_outlineView.numberOfRows)] columnIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,_outlineView.numberOfColumns)]]; } - (NSUInteger)numberOfSelectedStackFrames { NSIndexSet * tSelectedRows=[_outlineView WB_selectedOrClickedRowIndexes]; __block BOOL tContainsThreadRows=NO; [tSelectedRows enumerateIndexesUsingBlock:^(NSUInteger bIndex, BOOL * bOutStop) { if ([[self->_outlineView itemAtRow:bIndex] class]==[CUIThread class]) { tContainsThreadRows=YES; *bOutStop=YES; } }]; return (tContainsThreadRows==NO) ? [_outlineView WB_selectedOrClickedRowIndexes].count : 0; } - (NSArray *)selectedStackFrames { NSIndexSet * tSelectedRows=[_outlineView WB_selectedOrClickedRowIndexes]; if (tSelectedRows.count==0) return @[]; NSMutableArray * tMutableArray=[NSMutableArray array]; [tSelectedRows enumerateIndexesUsingBlock:^(NSUInteger bRow, BOOL * bOutStop) { CUIStackFrame * tStackFrame=[self->_outlineView itemAtRow:bRow]; if ([tStackFrame isKindOfClass:CUIStackFrame.class]==NO) return; [tMutableArray addObject:tStackFrame]; }]; return [tMutableArray copy]; } #pragma mark - - (IBAction)openSourceFile:(id)sender { NSInteger tRow=[_outlineView rowForView:sender]; if (tRow==-1) return; CUIStackFrame * tCall=(CUIStackFrame *)[_outlineView itemAtRow:tRow]; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101600 if (@available(*, macOS 11.0)) { [[NSWorkspace sharedWorkspace] openURLs:@[[NSURL fileURLWithPath:tCall.symbolicationData.sourceFilePath]] withApplicationAtURL:[CUIApplicationPreferences sharedPreferences].preferedSourceCodeEditorURL configuration:[NSWorkspaceOpenConfiguration configuration] completionHandler:^(NSRunningApplication * _Nullable app, NSError * _Nullable error) { }]; } else #endif { [[NSWorkspace sharedWorkspace] openURLs:@[[NSURL fileURLWithPath:tCall.symbolicationData.sourceFilePath]] withApplicationAtURL:[CUIApplicationPreferences sharedPreferences].preferedSourceCodeEditorURL options:NSWorkspaceLaunchDefault configuration:@{} error:NULL]; } } #pragma mark - - (void)delayedReloadSymbols { [_outlineView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, _outlineView.numberOfRows)] columnIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)]]; } #pragma mark - NSOutlineViewDataSource - (NSInteger)outlineView:(NSOutlineView *)inOutlineView numberOfChildrenOfItem:(id)inItem { if (_threads==nil) return 0; if (inItem==nil) { if (self.showOnlyCrashedThread==YES) { if (self.crashLog.backtraces.hasApplicationSpecificBacktrace==YES) return 2; return 1; } return _threads.count; } CUIThread * tThread=(CUIThread *)inItem; NSInteger tNumber=tThread.callStackBacktrace.stackFrames.count; if (tThread.isCrashed==YES && _showCrashedThreadState==YES) tNumber+=1; return tNumber; } - (id)outlineView:(NSOutlineView *)inOutlineView child:(NSInteger)inIndex ofItem:(id)inItem { if (inItem==nil) { if (self.showOnlyCrashedThread==YES) { if (self.crashLog.backtraces.hasApplicationSpecificBacktrace==NO) { return _threads[self.crashLog.exceptionInformation.crashedThreadIndex]; } if (inIndex==0) return _threads[0]; return _threads[self.crashLog.exceptionInformation.crashedThreadIndex+1]; } return _threads[inIndex]; } CUIThread * tThread=(CUIThread *)inItem; if (tThread.isCrashed==NO || _showCrashedThreadState==NO) return tThread.callStackBacktrace.stackFrames[inIndex]; if (inIndex>0) { return tThread.callStackBacktrace.stackFrames[inIndex-1]; } return self.crashLog.threadState; } - (BOOL)outlineView:(NSOutlineView *)inOutlineView isItemExpandable:(id)inItem { return [inItem isKindOfClass:[CUIThread class]]; } #pragma mark - NSOutlineViewDelegate - (NSTableRowView *)outlineView:(NSOutlineView *)inOutlineView rowViewForItem:(id)inItem { if (inOutlineView!=_outlineView || inItem==nil) return nil; if ([inItem isKindOfClass:[CUIThread class]]==YES) { CUIThread * tThread=(CUIThread *)inItem; if (tThread.isApplicationSpecificBacktrace==YES) { CUIApplicationSpecificBacktraceRowView * tTableRowView=[inOutlineView makeViewWithIdentifier:CUIApplicationSpecificBacktraceRowViewIdentifier owner:self]; if (tTableRowView==nil) { tTableRowView=[[CUIApplicationSpecificBacktraceRowView alloc] initWithFrame:NSZeroRect]; tTableRowView.identifier=CUIApplicationSpecificBacktraceRowViewIdentifier; } return tTableRowView; } if (tThread.isCrashed==YES) { CUICrashedThreadRowView * tTableRowView=[inOutlineView makeViewWithIdentifier:CUICrashedThreadRowViewIdentifier owner:self]; if (tTableRowView==nil) { tTableRowView=[[CUICrashedThreadRowView alloc] initWithFrame:NSZeroRect]; tTableRowView.identifier=CUICrashedThreadRowViewIdentifier; } return tTableRowView; } return nil; } if ([inItem isKindOfClass:[CUIStackFrame class]]==YES) { CUIThread * tThread=(CUIThread *)[inOutlineView parentForItem:inItem]; if (tThread.isCrashed==NO) return nil; CUICrashedThreadCallRowView * tTableRowView=[inOutlineView makeViewWithIdentifier:CUICrashedThreadCallRowViewIdentifier owner:self]; if (tTableRowView==nil) { tTableRowView=[[CUICrashedThreadCallRowView alloc] initWithFrame:NSZeroRect]; tTableRowView.identifier=CUICrashedThreadCallRowViewIdentifier; } CUIStackFrame * tCall=(CUIStackFrame *)inItem; tTableRowView.rootCall=(tCall.index==(tThread.callStackBacktrace.stackFrames.count-1)); return tTableRowView; } return nil; } - (NSView *)outlineView:(NSOutlineView *)inOutlineView viewForTableColumn:(NSTableColumn *)inTableColumn item:(id)inItem { if (inOutlineView!=_outlineView || inItem==nil) return nil; NSString * tTableColumnIdentifier=inTableColumn.identifier; if ([tTableColumnIdentifier isEqualToString:@"source"]==YES) { if ([inItem isKindOfClass:[CUIStackFrame class]]==YES) { CUIStackFrame * tCall=(CUIStackFrame *)inItem; CUISourceFileTableCellView * tTableCellView=(CUISourceFileTableCellView *)[inOutlineView makeViewWithIdentifier:@"source" owner:self]; BOOL tSymbolicateAutomatically=[CUIApplicationPreferences sharedPreferences].symbolicateAutomatically; CUISymbolicationData * tSymbolicationData=nil; if (tSymbolicateAutomatically==YES) tSymbolicationData=tCall.symbolicationData; if (tSymbolicationData!=nil) { [self setUpSourceFileCellView:tTableCellView withSymbolicationData:tSymbolicationData]; } else { // Default values NSTextField * tLabel=tTableCellView.textField; if (tCall.sourceFile==nil) tLabel.stringValue=@"-"; else tLabel.stringValue=[NSString stringWithFormat:@"%@ - line %lu",tCall.sourceFile,tCall.lineNumber]; tTableCellView.openButton.hidden=YES; NSString * tBinaryImageIdentifier=tCall.binaryImageIdentifier; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tAlternateIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tBinaryImageIdentifier]; if (tAlternateIdentifier!=nil) tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tAlternateIdentifier]; } if (tSymbolicateAutomatically==YES) { NSUInteger tAddress=tCall.machineInstructionAddress-tBinaryImage.binaryImageOffset; [[CUISymbolicationManager sharedSymbolicationManager] lookUpSymbolicationDataForMachineInstructionAddress:tAddress binaryUUID:tBinaryImage.UUID completionHandler:^(CUISymbolicationDataLookUpResult bLookUpResult, CUISymbolicationData *bSymbolicationData) { switch(bLookUpResult) { case CUISymbolicationDataLookUpResultError: case CUISymbolicationDataLookUpResultNotFound: { NSRect tFrame=tLabel.frame; tFrame.size.width=NSMaxX(tTableCellView.frame)-NSMinX(tFrame)-4; tLabel.frame=tFrame; break; } case CUISymbolicationDataLookUpResultFound: tCall.symbolicationData=bSymbolicationData; [NSNotificationCenter.defaultCenter postNotificationName:CUIStackFrameSymbolicationDidSucceedNotification object:self.crashLog]; break; case CUISymbolicationDataLookUpResultFoundInCache: { tCall.symbolicationData=bSymbolicationData; [self setUpSourceFileCellView:tTableCellView withSymbolicationData:bSymbolicationData]; break; } } }]; } else { NSRect tFrame=tLabel.frame; tFrame.size.width=NSMaxX(tTableCellView.frame)-NSMinX(tFrame)-4; tLabel.frame=tFrame; } } return tTableCellView; } return nil; } if ([tTableColumnIdentifier isEqualToString:@"symbol"]==YES) { if ([inItem isKindOfClass:[CUIThread class]]==YES) { CUIThread * tThread=(CUIThread *)inItem; NSTableCellView * tTableCellView=nil; if (tThread.name.length==0 || tThread.isApplicationSpecificBacktrace==YES) { tTableCellView=[inOutlineView makeViewWithIdentifier:@"thread cell" owner:self]; } else { CUIThreadNamedTableCellView * tNamedCell=[inOutlineView makeViewWithIdentifier:@"thread named cell" owner:self]; tNamedCell.dispatchQueueNameLabel.stringValue=tThread.name; tTableCellView=tNamedCell; } ((CUIThreadImageCell *)tTableCellView.imageView.cell).crashed=tThread.crashed; if (tThread.isApplicationSpecificBacktrace==YES) tTableCellView.textField.stringValue=tThread.name; else tTableCellView.textField.stringValue=[NSString stringWithFormat:@"Thread %lu",tThread.number]; return tTableCellView; } if ([inItem isKindOfClass:[CUIStackFrame class]]==YES) { BOOL isRightToLeft=(inOutlineView.userInterfaceLayoutDirection==NSUserInterfaceLayoutDirectionRightToLeft); CUIStackFrame * tCall=(CUIStackFrame *)inItem; NSString * tBinaryImageIdentifier=tCall.binaryImageIdentifier; BOOL tIsUserCode=NO; CUICrashLogBinaryImages * tBinaryImages=self.crashLog.binaryImages; CUIBinaryImage * tBinaryImage=[tBinaryImages binaryImageWithIdentifierOrName:tBinaryImageIdentifier identifier:&tBinaryImageIdentifier]; if (tBinaryImage!=nil) { tIsUserCode = tBinaryImage.isUserCode; if (tIsUserCode==NO && [tBinaryImage.path isEqualToString:self.crashLog.header.executablePath]==YES) tIsUserCode=YES; } if (tIsUserCode==NO) tIsUserCode=[tBinaryImages isUserCodeAtMemoryAddress:tCall.machineInstructionAddress inBinaryImage:tBinaryImageIdentifier]; CUICallTableCellView * tCallTableCellView=[inOutlineView makeViewWithIdentifier:@"call cell" owner:self]; // Call Index tCallTableCellView.callIndexLabel.stringValue=[NSString stringWithFormat:@"%lu ",tCall.index]; if (tIsUserCode==YES) { tCallTableCellView.callIndexLabel.textColor=[NSColor labelColor]; } else { tCallTableCellView.callIndexLabel.textColor=[NSColor secondaryLabelColor]; } NSRect tLeftFrame=tCallTableCellView.callIndexLabel.frame; // Binary Image if (((self.visibleStackFrameComponents & CUIStackFrameBinaryNameComponent)==0)) { tCallTableCellView.binaryImageLabel.hidden=YES; } else { if (_optimizedBinaryImageTextFieldWidth<0) { NSArray * tBinaryImageIdentifiers=[self.crashLog.backtraces allBinaryImagesIdentifiers]; __block CGFloat tMaxWidth=0.0; NSFont * tFont=tCallTableCellView.binaryImageLabel.font; [tBinaryImageIdentifiers enumerateObjectsUsingBlock:^(NSString * bString, NSUInteger bIndex, BOOL * bOutStop) { CGFloat tWidth=[bString sizeWithAttributes:@{NSFontAttributeName:tFont}].width; if (tWidth>tMaxWidth) tMaxWidth=tWidth; }]; _optimizedBinaryImageTextFieldWidth=tMaxWidth+10.0; if (_optimizedBinaryImageTextFieldWidth>CUIBinaryImageIdentifierTextFieldMaxWidth) _optimizedBinaryImageTextFieldWidth=CUIBinaryImageIdentifierTextFieldMaxWidth; } tCallTableCellView.binaryImageLabel.hidden=NO; NSRect tFrame=tCallTableCellView.binaryImageLabel.frame; tFrame.size.width=_optimizedBinaryImageTextFieldWidth; if (isRightToLeft==NO) { tFrame.origin.x=NSMaxX(tLeftFrame)+8; } else { tFrame.origin.x=NSMinX(tLeftFrame)-8-NSWidth(tFrame); } tCallTableCellView.binaryImageLabel.frame=tFrame; tLeftFrame=tFrame; tCallTableCellView.binaryImageLabel.stringValue=[NSString stringWithFormat:@"%@",tCall.binaryImageIdentifier]; if (tIsUserCode==YES) { tCallTableCellView.binaryImageLabel.textColor=[NSColor labelColor]; } else { tCallTableCellView.binaryImageLabel.textColor=[NSColor secondaryLabelColor]; } } // Address if ((self.visibleStackFrameComponents & CUIStackFrameMachineInstructionAddressComponent)==0) { tCallTableCellView.addressLabel.hidden=YES; } else { tCallTableCellView.addressLabel.hidden=NO; NSRect tFrame=tCallTableCellView.addressLabel.frame; if (isRightToLeft==NO) { tFrame.origin.x=NSMaxX(tLeftFrame)+8; } else { tFrame.origin.x=NSMinX(tLeftFrame)-8-NSWidth(tFrame); } tCallTableCellView.addressLabel.frame=tFrame; tLeftFrame=tFrame; tCallTableCellView.addressLabel.stringValue=[NSString stringWithFormat:@"0x%012lx",(tCall.machineInstructionAddress)]; if (tIsUserCode==YES) { tCallTableCellView.addressLabel.textColor=[NSColor labelColor]; } else { tCallTableCellView.addressLabel.textColor=[NSColor secondaryLabelColor]; } } // Symbol NSRect tFrame=tCallTableCellView.textField.frame; if (isRightToLeft==NO) { CGFloat tMaxX=NSMaxX(tFrame); tFrame.origin.x=NSMaxX(tLeftFrame)+8; tFrame.size.width=tMaxX-tFrame.origin.x; } else { CGFloat tMinX=NSMinX(tFrame); tFrame.origin.x=tMinX; tFrame.size.width=(NSMinX(tLeftFrame)-8-tMinX); } tCallTableCellView.textField.frame=tFrame; BOOL tSymbolicateAutomatically=[CUIApplicationPreferences sharedPreferences].symbolicateAutomatically; CUISymbolicationData * tData=nil; if (tSymbolicateAutomatically==YES) tData=tCall.symbolicationData; if (tData!=nil) { NSMutableString * tCallLine=[tData.stackFrameSymbol mutableCopy]; if ((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) { [tCallLine appendFormat:@" + %lu",tData.byteOffset]; } tCallTableCellView.textField.stringValue=tCallLine; } else { // Default values NSMutableString * tCallLine=[tCall.symbol mutableCopy]; if ((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) { [tCallLine appendFormat:@" + %lu",tCall.byteOffset]; } tCallTableCellView.textField.stringValue=tCallLine; NSString * tBinaryImageIdentifier=tCall.binaryImageIdentifier; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tAlternateIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tBinaryImageIdentifier]; if (tAlternateIdentifier!=nil) tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tAlternateIdentifier]; } if (tSymbolicateAutomatically==YES) { NSUInteger tAddress=tCall.machineInstructionAddress-tBinaryImage.binaryImageOffset; [[CUISymbolicationManager sharedSymbolicationManager] lookUpSymbolicationDataForMachineInstructionAddress:tAddress binaryUUID:tBinaryImage.UUID completionHandler:^(CUISymbolicationDataLookUpResult bLookUpResult, CUISymbolicationData *bSymbolicationData) { switch(bLookUpResult) { case CUISymbolicationDataLookUpResultError: case CUISymbolicationDataLookUpResultNotFound: break; case CUISymbolicationDataLookUpResultFound: { tCall.symbolicationData=bSymbolicationData; [NSNotificationCenter.defaultCenter postNotificationName:CUIStackFrameSymbolicationDidSucceedNotification object:self.crashLog]; break; } case CUISymbolicationDataLookUpResultFoundInCache: { tCall.symbolicationData=bSymbolicationData; NSMutableString * tCallLine=[bSymbolicationData.stackFrameSymbol mutableCopy]; if ((self.visibleStackFrameComponents & CUIStackFrameByteOffsetComponent)!=0) { [tCallLine appendFormat:@" + %lu",bSymbolicationData.byteOffset]; } tCallTableCellView.textField.stringValue=tCallLine; break; } } }]; } } if (tIsUserCode==YES) { tCallTableCellView.imageView.image=[NSImage imageNamed:@"call-usercode"]; tCallTableCellView.textField.textColor=[NSColor labelColor]; } else { tCallTableCellView.imageView.image=tCall.binaryImageIcon; tCallTableCellView.textField.textColor=[NSColor secondaryLabelColor]; } return tCallTableCellView; } return nil; } return nil; } - (CGFloat)outlineView:(NSOutlineView *) inOutlineView heightOfRowByItem:(id)inItem { if (inOutlineView!=_outlineView) return 17.0; if ([inItem isKindOfClass:[CUIThread class]]==YES) return 32.0; if ([inItem isKindOfClass:[CUICrashLogThreadState class]]==YES) { /*if (inOutlineView.frame.size.width>800) return 105.0;*/ return _threadStateRowHeight; } return 18.0; } - (BOOL)outlineView:(NSOutlineView *)inOutlineView shouldSelectItem:(id)inItem { if (inOutlineView!=_outlineView) return YES; return ([inItem isKindOfClass:[CUIStackFrame class]]==YES); } - (void)outlineViewItemDidExpand:(NSNotification *)inNotification { if (inNotification.object!=_outlineView) return; NSDictionary * tUserInfo=inNotification.userInfo; if (tUserInfo==nil) return; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; CUIThread * tThread=(CUIThread *) tUserInfo[@"NSObject"]; if (tThread==nil) return; NSString * tNodePath=[tThread stringHash]; if (tBrowsingState.listDisclosedThreads==nil) tBrowsingState.listDisclosedThreads=[NSMutableDictionary dictionary]; tBrowsingState.listDisclosedThreads[tNodePath]=@(YES); } - (void)outlineViewItemWillCollapse:(NSNotification *)inNotification { if (inNotification.object!=_outlineView) return; NSDictionary * tUserInfo=inNotification.userInfo; if (tUserInfo==nil) return; CUICrashLogBrowsingStateRegistry * tRegistry=[CUICrashLogBrowsingStateRegistry sharedRegistry]; CUICrashLogBrowsingState * tBrowsingState=[tRegistry browsingStateForCrashLog:self.crashLog windowNumber:self.view.window.windowNumber]; if (tBrowsingState.listDisclosedThreads==nil) return; CUIThread * tThread=(CUIThread *) tUserInfo[@"NSObject"]; if (tThread==nil) return; NSString * tNodePath=[tThread stringHash]; [tBrowsingState.listDisclosedThreads removeObjectForKey:tNodePath]; } - (void)outlineViewSelectionDidChange:(NSNotification *)inNotification { NSIndexSet * tIndexSet=_outlineView.selectedRowIndexes; NSMutableSet * tMutableSet=[NSMutableSet set]; [tIndexSet enumerateIndexesUsingBlock:^(NSUInteger bIndex, BOOL * bOutStop) { CUIStackFrame * tCall=[self->_outlineView itemAtRow:bIndex]; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tCall.binaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tCall.binaryImageIdentifier]; if (tIdentifier!=nil) { tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tIdentifier]; if (tBinaryImage!=nil) tCall=[tCall stackFrameCloneWithBinaryImageIdentifier:tIdentifier]; } } [tMutableSet addObject:tCall]; }]; [CUICallsSelection sharedCallsSelection].calls=tMutableSet; } - (void)idealHeightDidChange:(NSNotification *)inNotification { if (_showCrashedThreadState==YES) { _threadStateRowHeight=[inNotification.object doubleValue]; [_outlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:[_outlineView rowForItem:self.crashLog.threadState]]]; } } #pragma mark - - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification { // Ideally we should just request to symbolicate the machineInstructionAddresses which can be //NSArray * tBinaryUUIDs=inNotification.object; // A COMPLETER [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayedReloadSymbols) object:nil]; [self performSelector:@selector(delayedReloadSymbols) withObject:nil afterDelay:0.1]; } - (void)stackFrameSymbolicationDidSucceed:(NSNotification *)inNotification { if (inNotification.object!=self.crashLog) return; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayedReloadSymbols) object:nil]; [self performSelector:@selector(delayedReloadSymbols) withObject:nil afterDelay:0.1]; } - (void)symbolicateAutomaticallyDidChange:(NSNotification *)inNotification { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayedReloadSymbols) object:nil]; [self performSelector:@selector(delayedReloadSymbols) withObject:nil afterDelay:0.1]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsListViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsListViewController_RTL.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsViewController.h ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUICrashLog.h" #import "CUIStackFrame+UI.h" #import "CUIStackFrameComponents.h" #import "CUISourceFileTableCellView.h" #import "CUISymbolicationDataFormatter.h" #import "CUIHopperDisassemblerManager.h" @interface CUIThreadsViewController : NSViewController { IBOutlet NSMenuItem * _showWithMenuItem; } @property (nonatomic) CUICrashLog * crashLog; @property (nonatomic) BOOL showOnlyCrashedThread; @property (nonatomic) CUIStackFrameComponents visibleStackFrameComponents; @property (readonly) CUISymbolicationDataFormatter * symbolColumnFormatter; @property (readonly) CUISymbolicationDataFormatter * lineColumnFormatter; @property (nonatomic) NSUInteger numberOfSelectedStackFrames; @property (nonatomic) NSArray * selectedStackFrames; - (instancetype)initWithUserInterfaceLayoutDirection:(NSUserInterfaceLayoutDirection)inUserInterfaceLayoutDirection; - (NSMenu *)createFrameContextualMenu; - (IBAction)copyMachineInstructionAddress:(id)sender; - (IBAction)copyBinaryImageOffset:(id)sender; - (IBAction)openSourceFile:(id)sender; - (void)setUpSourceFileCellView:(CUISourceFileTableCellView *)inTableCellView withSymbolicationData:(CUISymbolicationData *)inSymbolicationData; // Notifications - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification; - (void)stackFrameSymbolicationDidSucceed:(NSNotification *)inNotification; - (void)symbolicateAutomaticallyDidChange:(NSNotification *)inNotification; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIThreadsViewController.m ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIThreadsViewController.h" #import "CUIApplicationPreferences.h" #import "CUIdSYMBundlesManager.h" #import "CUIRawCrashLog+Path.h" NSString * const CUIThreadsViewSelectedCallsDidChangeNotification=@"CUIThreadsViewSelectedCallsDidChangeNotification"; @interface CUIThreadsViewController () @property (readwrite) CUISymbolicationDataFormatter * symbolColumnFormatter; @property (readwrite) CUISymbolicationDataFormatter * lineColumnFormatter; @end @implementation CUIThreadsViewController - (instancetype)initWithUserInterfaceLayoutDirection:(NSUserInterfaceLayoutDirection)userInterfaceLayoutDirection { return [super init]; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (NSUInteger)numberOfSelectedStackFrames { return 0; } - (NSArray *)selectedStackFrames { return @[]; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; self.symbolColumnFormatter=[CUISymbolicationDataFormatter new]; self.symbolColumnFormatter.pathStyle=CUISymbolicationDataFormatterNoStyle; self.lineColumnFormatter=[CUISymbolicationDataFormatter new]; self.lineColumnFormatter.symbolStyle=CUISymbolicationDataFormatterNoStyle; self.lineColumnFormatter.pathStyle=CUISymbolicationDataFormatterShortStyle; self.lineColumnFormatter.coordinatesStyle=CUISymbolicationDataFormatterFullStyle; } - (void)viewDidAppear { [super viewDidAppear]; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter addObserver:self selector:@selector(dSYMBundlesManagerDidAddBundles:) name:CUIdSYMBundlesManagerDidAddBundlesNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(stackFrameSymbolicationDidSucceed:) name:CUIStackFrameSymbolicationDidSucceedNotification object:nil]; [tNotificationCenter addObserver:self selector:@selector(symbolicateAutomaticallyDidChange:) name:CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification object:nil]; } - (void)viewWillDisappear { [super viewWillDisappear]; NSNotificationCenter * tNotificationCenter=NSNotificationCenter.defaultCenter; [tNotificationCenter removeObserver:self name:CUIdSYMBundlesManagerDidAddBundlesNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIStackFrameSymbolicationDidSucceedNotification object:nil]; [tNotificationCenter removeObserver:self name:CUIPreferencesSymbolicationSymbolicateAutomaticallyDidChangeNotification object:nil]; } #pragma mark - - (NSMenu *)createFrameContextualMenu { NSMenu * tMenu=[[NSMenu alloc] initWithTitle:@""]; NSMenuItem * tMenuItem=[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy", @"") action:@selector(copy:) keyEquivalent:@""]; tMenuItem.target=self; [tMenu addItem:tMenuItem]; tMenuItem=[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy Machine Instruction Address", @"") action:@selector(copyMachineInstructionAddress:) keyEquivalent:@""]; tMenuItem.target=self; [tMenu addItem:tMenuItem]; tMenuItem=[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy Binary Image Offset", @"") action:@selector(copy:) keyEquivalent:@""]; tMenuItem.target=self; tMenuItem.keyEquivalentModifierMask=NSEventModifierFlagOption; tMenuItem.alternate=YES; [tMenu addItem:tMenuItem]; // Show With menu NSMenu * tHopperMenu=[[CUIHopperDisassemblerManager sharedManager] availableApplicationsMenuWithTarget:self]; if (tHopperMenu!=nil) { [tMenu addItem:[NSMenuItem separatorItem]]; tMenuItem=[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Show In", @"") action:nil keyEquivalent:@""]; tMenuItem.submenu=tHopperMenu; [tMenu addItem:tMenuItem]; } return tMenu; } #pragma mark - - (void)setUpSourceFileCellView:(CUISourceFileTableCellView *)inTableCellView withSymbolicationData:(CUISymbolicationData *)inSymbolicationData { NSString * tSourceFilePath=inSymbolicationData.sourceFilePath; NSTextField * tLabel=inTableCellView.textField; tLabel.stringValue=[self.lineColumnFormatter stringForObjectValue:inSymbolicationData]; tLabel.toolTip=tSourceFilePath; BOOL tHidesOpenButton=YES; NSURL * tURL=[NSURL fileURLWithPath:tSourceFilePath]; if (tURL.isFileURL==YES) { NSFileManager * tFileManager=[NSFileManager defaultManager]; if ([tFileManager fileExistsAtPath:tURL.path]==YES) { tHidesOpenButton=NO; } } inTableCellView.openButton.hidden=tHidesOpenButton; NSRect tFrame=tLabel.frame; if (tHidesOpenButton==YES) { tFrame.size.width=NSMaxX(inTableCellView.frame)-NSMinX(tFrame)-4; tLabel.frame=tFrame; } else { CGFloat tWidth=[tLabel.attributedStringValue size].width; NSRect tButtonFrame=inTableCellView.openButton.frame; switch(inTableCellView.userInterfaceLayoutDirection) { case NSUserInterfaceLayoutDirectionLeftToRight: tFrame.size.width=tWidth+5; tLabel.frame=tFrame; tButtonFrame.origin.x=NSMaxX(tLabel.frame)+2; break; case NSUserInterfaceLayoutDirectionRightToLeft: tFrame.size.width=tWidth+5; tLabel.frame=tFrame; tButtonFrame.origin.x=NSMinX(tLabel.frame)-15; break; } inTableCellView.openButton.frame=tButtonFrame; } } #pragma mark - - (BOOL)validateMenuItem:(NSMenuItem *)inMenuItem { SEL tAction=inMenuItem.action; NSUInteger tCount=self.numberOfSelectedStackFrames; if (tAction==@selector(copy:) || tAction==@selector(copyMachineInstructionAddress:) || tAction==@selector(copyBinaryImageOffset:)) { return (tCount>0); } if (tAction==@selector(openWithHopperDisassembler:)) { if (tCount!=1) return NO; NSArray * tCalls=self.selectedStackFrames; NSFileManager * tFileManager=[NSFileManager defaultManager]; for(CUIStackFrame * tStackFrame in tCalls) { NSString * tBinaryImageIdentifier=tStackFrame.binaryImageIdentifier; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tAlternateIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tBinaryImageIdentifier]; if (tAlternateIdentifier!=nil) tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tAlternateIdentifier]; } NSString * tPath=[self.crashLog stringByResolvingUSERInPath:tBinaryImage.path]; if (tPath.length==0) return NO; if ([tFileManager fileExistsAtPath:tPath]==NO) return NO; } } return YES; } - (IBAction)copy:(id)sender { NSArray * tCalls=self.selectedStackFrames; // A VOIR : Ideally I would like to put ... between 2 non sequential calls if multiple row selection is allowed NSArray * tLines=[tCalls WB_arrayByMappingObjectsUsingBlock:^id(CUIStackFrame * bStackFrame, NSUInteger bIndex) { NSString * tLine=[bStackFrame pasteboardRepresentationWithComponents:self.visibleStackFrameComponents]; return tLine; }]; NSString * tPasteboardString=[tLines componentsJoinedByString:@"\n"]; NSPasteboard * tPasteboard=[NSPasteboard generalPasteboard]; [tPasteboard declareTypes:@[WBPasteboardTypeString] owner:nil]; [tPasteboard setString:tPasteboardString forType:WBPasteboardTypeString]; } - (IBAction)copyMachineInstructionAddress:(id)sender { NSArray * tCalls=self.selectedStackFrames; NSArray * tAddresses=[tCalls WB_arrayByMappingObjectsUsingBlock:^id(CUIStackFrame * bStackFrame, NSUInteger bIndex) { NSString * tLine=[NSString stringWithFormat:@"0x%lx",bStackFrame.machineInstructionAddress]; return tLine; }]; NSString * tPasteboardString=[tAddresses componentsJoinedByString:@" "]; // Uses spaces so that the output can paste for atos(1) command line tool NSPasteboard * tPasteboard=[NSPasteboard generalPasteboard]; [tPasteboard declareTypes:@[WBPasteboardTypeString] owner:nil]; [tPasteboard setString:tPasteboardString forType:WBPasteboardTypeString]; } - (IBAction)copyBinaryImageOffset:(id)sender { NSArray * tCalls=self.selectedStackFrames; NSArray * tAddresses=[tCalls WB_arrayByMappingObjectsUsingBlock:^id(CUIStackFrame * bCall, NSUInteger bIndex) { NSString * tBinaryImageIdentifier=bCall.binaryImageIdentifier; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tAlternateIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tBinaryImageIdentifier]; if (tAlternateIdentifier!=nil) tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tAlternateIdentifier]; } NSUInteger tAddress=bCall.machineInstructionAddress-tBinaryImage.binaryImageOffset; NSString * tLine=[NSString stringWithFormat:@"0x%lx",tAddress]; return tLine; }]; NSString * tPasteboardString=[tAddresses componentsJoinedByString:@" "]; NSPasteboard * tPasteboard=[NSPasteboard generalPasteboard]; [tPasteboard declareTypes:@[WBPasteboardTypeString] owner:nil]; [tPasteboard setString:tPasteboardString forType:WBPasteboardTypeString]; } - (IBAction)openWithHopperDisassembler:(NSMenuItem *)sender { CUIApplicationItemAttributes * tApplicationItemAttributes=sender.representedObject; NSArray * tCalls=self.selectedStackFrames; [tCalls enumerateObjectsUsingBlock:^(CUIStackFrame * bCall, NSUInteger bIndex, BOOL * bOutStop) { NSString * tBinaryImageIdentifier=bCall.binaryImageIdentifier; CUIBinaryImage * tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tBinaryImageIdentifier]; if (tBinaryImage==nil) { NSString * tAlternateIdentifier=[self.crashLog.binaryImages binaryImageIdentifierForName:tBinaryImageIdentifier]; if (tAlternateIdentifier!=nil) tBinaryImage=[self.crashLog.binaryImages binaryImageWithIdentifier:tAlternateIdentifier]; } NSUInteger tAddress=bCall.machineInstructionAddress-tBinaryImage.binaryImageOffset; [[CUIHopperDisassemblerManager sharedManager] openBinaryImage:[self.crashLog stringByResolvingUSERInPath:tBinaryImage.path] withApplicationAttributes:tApplicationItemAttributes codeType:self.crashLog.header.codeType fileOffSet:(void *)tAddress]; }]; } - (IBAction)openSourceFile:(id)sender { } #pragma mark - Notifications - (void)dSYMBundlesManagerDidAddBundles:(NSNotification *)inNotification { } - (void)stackFrameSymbolicationDidSucceed:(NSNotification *)inNotification { } - (void)symbolicateAutomaticallyDidChange:(NSNotification *)inNotification { } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIdSYMBundlesManager.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIdSYMBundle.h" extern NSString * const CUIdSYMBundlesManagerDidAddBundlesNotification; extern NSString * const CUIdSYMBundlesManagerDidRemoveBundlesNotification; @interface CUIdSYMBundlesManager : NSObject + (CUIdSYMBundlesManager *)sharedManager; - (BOOL)addBundle:(CUIdSYMBundle *)inBundle; - (BOOL)addBundles:(NSArray *)inBundles; - (void)removeBundle:(CUIdSYMBundle *)inBundle; - (void)removeBundles:(NSArray *)inBundles; - (CUIdSYMBundle *)bundleForBinaryUUID:(NSString *)inBinaryUUID; @property (nonatomic,readonly) NSSet * bundlesSet; - (BOOL)containsBundle:(CUIdSYMBundle *)inBundle; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIdSYMBundlesManager.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIdSYMBundlesManager.h" NSString * const CUIdSYMBundlesManagerDidAddBundlesNotification=@"CUIdSYMBundlesManagerDidAddBundlesNotification"; NSString * const CUIdSYMBundlesManagerDidRemoveBundlesNotification=@"CUIdSYMBundlesManagerDidRemoveBundlesNotification"; NSString * const CUIdSYMBundlesManagerContentsKey=@"dSYMLibrary.contents"; @interface CUIdSYMBundlesManager () { NSMutableSet * _bundlesSet; NSMutableDictionary * _bundlesRegistry; } - (BOOL)_addBundles:(NSArray *)inBundles andNotify:(BOOL)inNotify; - (void)_synchronizeDefaults; @end @implementation CUIdSYMBundlesManager + (CUIdSYMBundlesManager *)sharedManager { static CUIdSYMBundlesManager * sdSYMBundlesManager=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sdSYMBundlesManager=[CUIdSYMBundlesManager new]; }); return sdSYMBundlesManager; } - (instancetype)init { self=[super init]; if (self!=nil) { _bundlesRegistry=[NSMutableDictionary dictionary]; _bundlesSet=[NSMutableSet set]; NSUserDefaults * tDefaults=[NSUserDefaults standardUserDefaults]; NSArray * tArray=[tDefaults arrayForKey:CUIdSYMBundlesManagerContentsKey]; if (tArray.count>0) { NSArray * tBundles=[tArray WB_arrayByMappingObjectsLenientlyUsingBlock:^CUIdSYMBundle *(NSString * bBundlePath, NSUInteger bIndex) { return [[CUIdSYMBundle alloc] initWithPath:bBundlePath]; }]; [self _addBundles:tBundles andNotify:NO]; } } return self; } #pragma mark - - (NSSet *)bundlesSet { return _bundlesSet; } #pragma mark - - (void)_synchronizeDefaults { NSUserDefaults * tDefaults=[NSUserDefaults standardUserDefaults]; NSMutableArray * tMutableArray=[NSMutableArray array]; [_bundlesSet enumerateObjectsUsingBlock:^(CUIdSYMBundle * bBundle, BOOL * bOutStop) { [tMutableArray addObject:bBundle.bundlePath]; }]; [tDefaults setValue:tMutableArray forKey:CUIdSYMBundlesManagerContentsKey]; } #pragma mark - - (BOOL)containsBundle:(CUIdSYMBundle *)inBundle { if (inBundle==nil) return NO; for(CUIdSYMBundle * tBundle in _bundlesSet) { if ([tBundle.bundlePath caseInsensitiveCompare:inBundle.bundlePath]==NSOrderedSame) return YES; } return NO; } - (BOOL)addBundle:(CUIdSYMBundle *)inBundle { if (inBundle==nil) return NO; return [self addBundles:@[inBundle]]; } - (BOOL)addBundles:(NSArray *)inBundles { return [self _addBundles:inBundles andNotify:YES]; } - (BOOL)_addBundles:(NSArray *)inBundles andNotify:(BOOL)inNotify { if (inBundles.count==0) return NO; NSMutableArray * tAllBinaryUUIDs=[NSMutableArray array]; for(CUIdSYMBundle * tBundle in inBundles) { NSArray * tBinaryUUIDs=[tBundle binaryUUIDs]; if (tBinaryUUIDs.count==0) return NO; NSMutableArray * tAddedBinaryUUIds=[NSMutableArray array]; for(NSString * tBinaryUUID in tBinaryUUIDs) { if (_bundlesRegistry[tBinaryUUID]!=nil) continue; _bundlesRegistry[tBinaryUUID]=tBundle; [tAddedBinaryUUIds addObject:tBinaryUUID]; } if (tAddedBinaryUUIds.count>0) { [tAllBinaryUUIDs addObjectsFromArray:tAddedBinaryUUIds]; [_bundlesSet addObject:tBundle]; } } // Post Notification? if (inNotify==YES) [NSNotificationCenter.defaultCenter postNotificationName:CUIdSYMBundlesManagerDidAddBundlesNotification object:tAllBinaryUUIDs]; [self _synchronizeDefaults]; return YES; } - (void)removeBundle:(CUIdSYMBundle *)inBundle { if (inBundle==nil) return; [self removeBundles:@[inBundle]]; } - (void)removeBundles:(NSArray *)inBundles { if (inBundles.count==0) return; NSMutableArray * tAllBinaryUUIDs=[NSMutableArray array]; for(CUIdSYMBundle * tBundle in inBundles) { NSArray * tBinaryUUIDs=tBundle.binaryUUIDs; [tAllBinaryUUIDs addObjectsFromArray:tBinaryUUIDs]; } [_bundlesRegistry removeObjectsForKeys:tAllBinaryUUIDs]; [_bundlesSet minusSet:[NSSet setWithArray:inBundles]]; // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUIdSYMBundlesManagerDidRemoveBundlesNotification object:tAllBinaryUUIDs]; [self _synchronizeDefaults]; } #pragma mark - - (CUIdSYMBundle *)bundleForBinaryUUID:(NSString *)inBinaryUUID { if (inBinaryUUID==nil) return nil; return _bundlesRegistry[inBinaryUUID]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIdSYMDropView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIFileDeadDropView.h" @interface CUIdSYMDropView : CUIFileDeadDropView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIdSYMDropView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIdSYMDropView.h" @implementation CUIdSYMDropView - (void)drawRect:(NSRect)inRect { if (self.isHighlighted==YES) { NSRect tRect=NSInsetRect(self.bounds,300.0,4.0); NSBezierPath * tPath=[NSBezierPath bezierPath]; [tPath moveToPoint:NSMakePoint(NSMinX(tRect), NSMinY(tRect))]; [tPath lineToPoint:NSMakePoint(NSMaxX(tRect), NSMinY(tRect))]; tPath.lineWidth=3.0; if (@available(*, macOS 10.14)) { [[NSColor selectedContentBackgroundColor] setStroke]; } else { [[NSColor alternateSelectedControlColor] setStroke]; } [tPath stroke]; } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIdSYMHunter.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import extern NSString * const CUIdSYMHunterHuntDidFinishNotification; @interface CUIdSYMHunter : NSObject @property (nonatomic,readonly) NSSet * huntingBundleUUIDs; + (CUIdSYMHunter *)sharedHunter; - (void)huntBundleWithUUIDs:(NSSet *)inBundleUUIDs; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CUIdSYMHunter.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIdSYMHunter.h" #import "CUIdSYMBundlesManager.h" NSString * const CUIdSYMHunterHuntDidFinishNotification=@"CUIdSYMHunterHuntDidFinishNotification"; @interface CUIdSYMHunter () { NSMutableSet * _runningQueries; NSMutableSet * _huntingBundleUUIDs; NSMutableDictionary * _registry; NSLock * _lock; } // Notifications - (void)metadataQueryDidFinishGathering:(NSNotification *)inNotification; @end @implementation CUIdSYMHunter + (CUIdSYMHunter *)sharedHunter { static CUIdSYMHunter * sHunter=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sHunter=[CUIdSYMHunter new]; }); return sHunter; } - (instancetype)init { self=[super init]; if (self!=nil) { _runningQueries=[NSMutableSet set]; _huntingBundleUUIDs=[NSMutableSet set]; _registry=[NSMutableDictionary dictionary]; _lock=[NSLock new]; } return self; } #pragma mark - - (NSSet *)huntingBundleUUIDs { NSSet * tSet=nil; [_lock lock]; tSet=[_huntingBundleUUIDs copy]; [_lock unlock]; return tSet; } #pragma mark - - (void)huntBundleWithUUIDs:(NSSet *)inBundleUUIDs { // Avoid looking for the same dSYM UUID multiple times at once NSMutableSet * tMutableSet=[inBundleUUIDs mutableCopy]; [_lock lock]; [tMutableSet minusSet:_huntingBundleUUIDs]; [_lock unlock]; if (tMutableSet.count==0) return; NSMetadataQuery * tMetadataQuery=[NSMetadataQuery new]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(metadataQueryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:tMetadataQuery]; // Look for dSYM with filtered UUIDs NSArray * tArray=[tMutableSet.allObjects WB_arrayByMappingObjectsUsingBlock:^NSString *(NSString * bUUID, NSUInteger bIndex) { return [NSString stringWithFormat:@"(com_apple_xcode_dsym_uuids == '%@')",bUUID]; }]; NSString * tPredicateString=[tArray componentsJoinedByString:@" OR "]; tMetadataQuery.predicate=[NSPredicate predicateWithFormat:tPredicateString]; tMetadataQuery.searchScopes=@[NSMetadataQueryLocalComputerScope]; [_lock lock]; [_runningQueries addObject:tMetadataQuery]; [_huntingBundleUUIDs unionSet:tMutableSet]; _registry[[NSValue valueWithNonretainedObject:tMetadataQuery]]=tMutableSet; [_lock unlock]; [tMetadataQuery startQuery]; } #pragma mark - Notifications - (void)metadataQueryDidFinishGathering:(NSNotification *)inNotification { NSMetadataQuery * tMetadataQuery=(NSMetadataQuery *)inNotification.object; [tMetadataQuery stopQuery]; NSValue * tKey=[NSValue valueWithNonretainedObject:tMetadataQuery]; [_lock lock]; NSSet * tSet=_registry[tKey]; [_huntingBundleUUIDs minusSet:tSet]; [_registry removeObjectForKey:tKey]; [_runningQueries removeObject:tMetadataQuery]; [_lock unlock]; dispatch_async(dispatch_get_main_queue(), ^{ [tMetadataQuery enumerateResultsUsingBlock:^(id bResult, NSUInteger idx, BOOL * _Nonnull stop) { if ([bResult isKindOfClass:NSMetadataItem.class]==YES) { NSMetadataItem * tMetaDataItem=(NSMetadataItem *)bResult; //NSLog(@"%@",[tMetaDataItem valuesForAttributes:@[NSMetadataItemPathKey,@"com_apple_xcode_dsym_uuids",@"com_apple_xcode_dsym_paths",@"kMDItemFSName"]]); NSString * tdSYMPath=[tMetaDataItem valueForAttribute:NSMetadataItemPathKey]; if (tdSYMPath!=nil) { CUIdSYMBundlesManager * tBundlesManager=[CUIdSYMBundlesManager sharedManager]; CUIdSYMBundle * tBundle=[[CUIdSYMBundle alloc] initWithPath:tdSYMPath]; if (tBundle.isDSYMBundle==NO) return; if ([tBundlesManager containsBundle:tBundle]==YES) return; [tBundlesManager addBundles:@[tBundle]]; } } }]; // Post Notification [NSNotificationCenter.defaultCenter postNotificationName:CUIdSYMHunterHuntDidFinishNotification object:nil]; }); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/CodeSigningFlags.plist ================================================ Host 1 Ad-hoc Signed 2 Get Task Allow 4 Installer 8 Forced Library Validation 16 Invalid Allowed 32 Force Hard 256 Force Kill 512 Force Expiration 1024 Restrict 2048 Enforcement 4096 Library Validation 8192 Runtime 65536 Linker Signed 131072 Platform Signed 67108864 Debugged 268435456 Signed 536870912 ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFEnums.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ typedef NS_ENUM(NSUInteger, DWRFVersion) { DWRFVersion4=4, DWRFVersion5=5 }; typedef NS_ENUM(uint16_t,DW_LANG) { DW_LANG_C89 = 0x0001, DW_LANG_C = 0x0002, DW_LANG_Ada83 = 0x0003, DW_LANG_C_plus_plus = 0x0004, DW_LANG_Cobol74 = 0x0005, DW_LANG_Cobol85 = 0x0006, DW_LANG_Fortran77 = 0x0007, DW_LANG_Fortran90 = 0x0008, DW_LANG_Pascal83 = 0x0009, DW_LANG_Modula2 = 0x000a, DW_LANG_Java = 0x000b, DW_LANG_C99 = 0x000c, DW_LANG_Ada95 = 0x000d, DW_LANG_Fortran95 = 0x000e, DW_LANG_PLI = 0x000f, DW_LANG_ObjC = 0x0010, DW_LANG_ObjC_plus_plus = 0x0011, DW_LANG_UPC = 0x0012, DW_LANG_D = 0x0013, DW_LANG_Python = 0x0014, DW_LANG_OpenCL = 0x0015, DW_LANG_Go = 0x0016, DW_LANG_Modula3 = 0x0017, DW_LANG_Haskell = 0x0018, DW_LANG_C_plus_plus_03 = 0x0019, DW_LANG_C_plus_plus_11 = 0x001a, DW_LANG_OCaml = 0x001b, DW_LANG_Rust = 0x001c, DW_LANG_C11 = 0x001d, DW_LANG_Swift = 0x001e, DW_LANG_Julia = 0x001f, DW_LANG_Dylan = 0x0020, DW_LANG_C_plus_plus_14 = 0x0021, DW_LANG_Fortran03 = 0x0022, DW_LANG_Fortran08 = 0x0023, DW_LANG_RenderScript = 0x0024, DW_LANG_BLISS = 0x0025, DW_LANG_lo_user = 0x8000, DW_LANG_hi_user = 0xffff, DW_LANG_Mips_Assembler = 0x8001, DW_LANG_GOOGLE_RenderScript = 0x8e57, DW_LANG_SUN_Assembler = 0x9001, DW_LANG_ALTIUM_Assembler = 0x9101, DW_LANG_BORLAND_Delphi = 0xb000, }; typedef NS_ENUM(uint16_t, DW_TAG) { DW_TAG_array_type = 0x01, DW_TAG_class_type = 0x02, DW_TAG_entry_point = 0x03, DW_TAG_enumeration_type = 0x04, DW_TAG_formal_parameter = 0x05, DW_TAG_imported_declaration = 0x08, DW_TAG_label = 0x0a, DW_TAG_lexical_block = 0x0b, DW_TAG_member = 0x0d, DW_TAG_pointer_type = 0x0f, DW_TAG_reference_type = 0x10, DW_TAG_compile_unit = 0x11, DW_TAG_string_type = 0x12, DW_TAG_structure_type = 0x13, DW_TAG_subroutine_type = 0x15, DW_TAG_typedef = 0x16, DW_TAG_union_type = 0x17, DW_TAG_unspecified_parameters = 0x18, DW_TAG_variant = 0x19, DW_TAG_common_block = 0x1a, DW_TAG_common_inclusion = 0x1b, DW_TAG_inheritance = 0x1c, DW_TAG_inlined_subroutine = 0x1d, DW_TAG_module = 0x1e, DW_TAG_ptr_to_member_type = 0x1f, DW_TAG_set_type = 0x20, DW_TAG_subrange_type = 0x21, DW_TAG_with_stmt = 0x22, DW_TAG_access_declaration = 0x23, DW_TAG_base_type = 0x24, DW_TAG_catch_block = 0x25, DW_TAG_const_type = 0x26, DW_TAG_constant = 0x27, DW_TAG_enumerator = 0x28, DW_TAG_file_type = 0x29, DW_TAG_friend = 0x2a, DW_TAG_namelist = 0x2b, DW_TAG_namelist_item = 0x2c, DW_TAG_packed_type = 0x2d, DW_TAG_subprogram = 0x2e, DW_TAG_template_type_parameter = 0x2f, DW_TAG_template_value_parameter = 0x30, DW_TAG_thrown_type = 0x31, DW_TAG_try_block = 0x32, DW_TAG_variant_part = 0x33, DW_TAG_variable = 0x34, DW_TAG_volatile_type = 0x35, DW_TAG_dwarf_procedure = 0x36, DW_TAG_restrict_type = 0x37, DW_TAG_interface_type = 0x38, DW_TAG_namespace = 0x39, DW_TAG_imported_module = 0x3a, DW_TAG_unspecified_type = 0x3b, DW_TAG_partial_unit = 0x3c, DW_TAG_imported_unit = 0x3d, DW_TAG_condition = 0x3f, DW_TAG_shared_type = 0x40, DW_TAG_rvalue_reference_type = 0x41, DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff }; typedef NS_ENUM(uint16_t, DW_AT) { DW_AT_null = 0x00, DW_AT_sibling = 0x01, DW_AT_location = 0x02, DW_AT_name = 0x03, DW_AT_ordering = 0x09, DW_AT_byte_size = 0x0b, DW_AT_bit_offset = 0x0c, DW_AT_bit_size = 0x0d, DW_AT_stmt_list = 0x10, DW_AT_low_pc = 0x11, DW_AT_high_pc = 0x12, DW_AT_language = 0x13, DW_AT_discr = 0x15, DW_AT_discr_value = 0x16, DW_AT_visibility = 0x17, DW_AT_import = 0x18, DW_AT_string_length = 0x19, DW_AT_common_reference = 0x1a, DW_AT_comp_dir = 0x1b, DW_AT_const_value = 0x1c, DW_AT_containing_type = 0x1d, DW_AT_default_value = 0x1e, DW_AT_inline = 0x20, DW_AT_is_optional = 0x21, DW_AT_lower_bound = 0x22, DW_AT_producer = 0x25, DW_AT_prototyped = 0x27, DW_AT_return_addr = 0x2a, DW_AT_start_scope = 0x2c, DW_AT_bit_stride = 0x2e, DW_AT_upper_bound = 0x2f, DW_AT_abstract_origin = 0x31, DW_AT_accessibility = 0x32, DW_AT_address_class = 0x33, DW_AT_artificial = 0x34, DW_AT_base_types = 0x35, DW_AT_calling_convention = 0x36, DW_AT_count = 0x37, DW_AT_data_member_location = 0x38, DW_AT_decl_column = 0x39, DW_AT_decl_file = 0x3a, DW_AT_decl_line = 0x3b, DW_AT_declaration = 0x3c, DW_AT_discr_list = 0x3d, DW_AT_encoding = 0x3e, DW_AT_external = 0x3f, DW_AT_frame_base = 0x40, DW_AT_friend = 0x41, DW_AT_identifier_case = 0x42, DW_AT_macro_info = 0x43, DW_AT_namelist_item = 0x44, DW_AT_priority = 0x45, DW_AT_segment = 0x46, DW_AT_specification = 0x47, DW_AT_static_link = 0x48, DW_AT_type = 0x49, DW_AT_use_location = 0x4a, DW_AT_variable_parameter = 0x4b, DW_AT_virtuality = 0x4c, DW_AT_vtable_elem_location = 0x4d, // DWARF 3 DW_AT_allocated = 0x4e, DW_AT_associated = 0x4f, DW_AT_data_location = 0x50, DW_AT_byte_stride = 0x51, DW_AT_entry_pc = 0x52, DW_AT_use_UTF8 = 0x53, DW_AT_extension = 0x54, DW_AT_ranges = 0x55, DW_AT_trampoline = 0x56, DW_AT_call_column = 0x57, DW_AT_call_file = 0x58, DW_AT_call_line = 0x59, DW_AT_description = 0x5a, DW_AT_binary_scale = 0x5b, DW_AT_decimal_scale = 0x5c, DW_AT_small = 0x5d, DW_AT_decimal_sign = 0x5e, DW_AT_digit_count = 0x5f, DW_AT_picture_string = 0x60, DW_AT_mutable = 0x61, DW_AT_threads_scaled = 0x62, DW_AT_explicit = 0x63, DW_AT_object_pointer = 0x64, DW_AT_endianity = 0x65, DW_AT_elemental = 0x66, DW_AT_pure = 0x67, DW_AT_recursive = 0x68, // DWARF 4 DW_AT_signature = 0x69, DW_AT_main_subprogram = 0x6a, DW_AT_data_bit_offset = 0x6b, DW_AT_const_expr = 0x6c, DW_AT_enum_class = 0x6d, DW_AT_linkage_name = 0x6e, DW_AT_str_offsets_base = 0x72, // DWARF 5 DW_AT_addr_base = 0x73, // DWARF 5 DW_AT_call_all_calls = 0x7a, DW_AT_lo_user = 0x2000, DW_AT_hi_user = 0x3fff, DW_AT_MIPS_linkage_name = 0x2007, /* GNU extensions. */ DW_AT_sf_names = 0x2101, DW_AT_src_info = 0x2102, DW_AT_mac_info = 0x2103, DW_AT_src_coords = 0x2104, DW_AT_body_begin = 0x2105, DW_AT_body_end = 0x2106, DW_AT_GNU_vector = 0x2107, DW_AT_GNU_guarded_by = 0x2108, DW_AT_GNU_pt_guarded_by = 0x2109, DW_AT_GNU_guarded = 0x210a, DW_AT_GNU_pt_guarded = 0x210b, DW_AT_GNU_locks_excluded = 0x210c, DW_AT_GNU_exclusive_locks_required = 0x210d, DW_AT_GNU_shared_locks_required = 0x210e, DW_AT_GNU_odr_signature = 0x210f, DW_AT_GNU_template_name = 0x2110, DW_AT_GNU_call_site_value = 0x2111, DW_AT_GNU_call_site_data_value = 0x2112, DW_AT_GNU_call_site_target = 0x2113, DW_AT_GNU_call_site_target_clobbered = 0x2114, DW_AT_GNU_tail_call = 0x2115, DW_AT_GNU_all_tail_call_sites = 0x2116, DW_AT_GNU_all_call_sites = 0x2117, DW_AT_GNU_all_source_call_sites = 0x2118, DW_AT_GNU_macros = 0x2119, DW_AT_GNU_deleted = 0x211a, DW_AT_GNU_dwo_name = 0x2130, DW_AT_GNU_dwo_id = 0x2131, DW_AT_GNU_ranges_base = 0x2132, DW_AT_GNU_addr_base = 0x2133, DW_AT_GNU_pubnames = 0x2134, DW_AT_GNU_pubtypes = 0x2135, DW_AT_GNU_discriminator = 0x2136, DW_AT_GNU_locviews = 0x2137, DW_AT_GNU_entry_view = 0x2138, // LLVM project extensions DW_AT_LLVM_include_path = 0x3e00, DW_AT_LLVM_config_macros = 0x3e01, DW_AT_LLVM_isysroot = 0x3e02, // Apple extensions DW_AT_APPLE_optimized = 0x3fe1, DW_AT_APPLE_flags = 0x3fe2, DW_AT_APPLE_isa = 0x3fe3, DW_AT_APPLE_block = 0x3fe4, DW_AT_APPLE_major_runtime_vers = 0x3fe5, DW_AT_APPLE_runtime_class = 0x3fe6, DW_AT_APPLE_omit_frame_ptr = 0x3fe7, DW_AT_APPLE_property_name = 0x3fe8, DW_AT_APPLE_property_getter = 0x3fe9, DW_AT_APPLE_property_setter = 0x3fea, DW_AT_APPLE_property_attribute = 0x3feb, DW_AT_APPLE_objc_complete_type = 0x3fec, DW_AT_APPLE_property = 0x3fed }; typedef NS_ENUM(NSUInteger, DW_FORM) { DW_FORM_addr = 0x01, DW_FORM_block2 = 0x03, DW_FORM_block4 = 0x04, DW_FORM_data2 = 0x05, DW_FORM_data4 = 0x06, DW_FORM_data8 = 0x07, DW_FORM_string = 0x08, DW_FORM_block = 0x09, DW_FORM_block1 = 0x0a, DW_FORM_data1 = 0x0b, DW_FORM_flag = 0x0c, DW_FORM_sdata = 0x0d, DW_FORM_strp = 0x0e, DW_FORM_udata = 0x0f, DW_FORM_ref_addr = 0x10, DW_FORM_ref1 = 0x11, DW_FORM_ref2 = 0x12, DW_FORM_ref4 = 0x13, DW_FORM_ref8 = 0x14, DW_FORM_ref_udata = 0x15, DW_FORM_indirect = 0x16, DW_FORM_sec_offset = 0x17, DW_FORM_exprloc = 0x18, DW_FORM_flag_present = 0x19, DW_FORM_reg_sig8 = 0x20, // DWARF v5 DW_FORM_strx = 0x1a, DW_FORM_addrx = 0x1b, DW_FORM_data16 = 0x1e, DW_FORM_implicit_const=0x21, DW_FORM_strx1 = 0x25, DW_FORM_strx2 = 0x26, DW_FORM_strx3 = 0x27, DW_FORM_strx4 = 0x28, DW_FORM_addrx1 = 0x29, DW_FORM_addrx2 = 0x2a, DW_FORM_addrx3 = 0x2b, DW_FORM_addrx4 = 0x2c }; ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFFileObject.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "MCHObjectFile.h" #import "CUISymbolicationData.h" #import "DWRFSection_debug_addr.h" #import "DWRFSection_debug_str.h" #import "DWRFSection_debug_str_offsets.h" #import "DWRFSection_debug_abbrev.h" #import "DWRFSection_debug_line.h" #import "DWRFSection_debug_info.h" #import "DWRFSection_debug_aranges.h" @interface DWRFFileObject : NSObject @property (readonly) DWRFSection_debug_addr * section_debug_addr; @property (readonly) DWRFSection_debug_str * section_debug_str; @property (readonly) DWRFSection_debug_str_offsets * section_debug_str_offsets; @property (readonly) DWRFSection_debug_abbrev * section_debug_abbrev; @property (readonly) DWRFSection_debug_line * section_debug_line; @property (readonly) DWRFSection_debug_info * section_debug_info; @property (readonly) DWRFSection_debug_aranges * section_debug_aranges; - (instancetype)initWithMachObjectFile:(MCHObjectFile *)inObjectFile; - (void)lookUpSymbolicationDataForMachineInstructionAddress:(uint64_t)inAddress completionHandler:(void (^)(BOOL bFound,CUISymbolicationData * bSymbolicationData))handler; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFFileObject.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFFileObject.h" #import "MCHSegmentLoadCommand.h" #include #include @interface DWRFFileObject () { MCHObjectFile * _cachedObjectFile; } @property DWRFSection_debug_addr * section_debug_addr; @property DWRFSection_debug_str * section_debug_str; @property DWRFSection_debug_str_offsets * section_debug_str_offsets; @property DWRFSection_debug_abbrev * section_debug_abbrev; @property DWRFSection_debug_line * section_debug_line; @property DWRFSection_debug_info * section_debug_info; @property DWRFSection_debug_aranges * section_debug_aranges; @end @implementation DWRFFileObject - (instancetype)initWithMachObjectFile:(MCHObjectFile *)inObjectFile { if (inObjectFile==nil) return nil; if (inObjectFile.fileType!=MH_DSYM) return nil; self=[super init]; if (self!=nil) { _cachedObjectFile=inObjectFile; } return self; } #pragma mark - - (BOOL)analyze { NSArray * tSegment64LoadCommands=[_cachedObjectFile loadCommandsOfType:LC_SEGMENT_64]; for(MCHSegmentLoadCommand * tLoadCommand in tSegment64LoadCommands) { if ([tLoadCommand.segment.name isEqualToString:@"__DWARF"]) { MCHSection * tSection=[tLoadCommand.segment sectionNamed:@"__debug_addr"]; if (tSection!=nil) { _section_debug_addr=[[DWRFSection_debug_addr alloc] initWithData:[NSData dataWithBytesNoCopy:(void *)tSection.buffer length:tSection.bufferSize freeWhenDone:NO]]; if (_section_debug_addr==nil) { // A COMPLETER return NO; } } tSection=[tLoadCommand.segment sectionNamed:@"__debug_str"]; if (tSection!=nil) { _section_debug_str=[[DWRFSection_debug_str alloc] initWithData:[NSData dataWithBytesNoCopy:(void *)tSection.buffer length:tSection.bufferSize freeWhenDone:NO]]; if (_section_debug_str==nil) { // A COMPLETER return NO; } } tSection=[tLoadCommand.segment sectionNamed:@"__debug_str_offsets"]; if (tSection!=nil) { _section_debug_str_offsets=[[DWRFSection_debug_str_offsets alloc] initWithData:[NSData dataWithBytesNoCopy:(void *)tSection.buffer length:tSection.bufferSize freeWhenDone:NO]]; if (_section_debug_str_offsets==nil) { // A COMPLETER return NO; } } tSection=[tLoadCommand.segment sectionNamed:@"__debug_abbrev"]; if (tSection!=nil) { _section_debug_abbrev=[[DWRFSection_debug_abbrev alloc] initWithData:[NSData dataWithBytesNoCopy:(void *)tSection.buffer length:tSection.bufferSize freeWhenDone:NO]]; if (_section_debug_abbrev==nil) { // A COMPLETER return NO; } } tSection=[tLoadCommand.segment sectionNamed:@"__debug_line"]; if (tSection!=nil) { _section_debug_line=[[DWRFSection_debug_line alloc] initWithData:[NSData dataWithBytesNoCopy:(void *)tSection.buffer length:tSection.bufferSize freeWhenDone:NO]]; if (_section_debug_line==nil) { // A COMPLETER return NO; } } tSection=[tLoadCommand.segment sectionNamed:@"__debug_info"]; if (tSection!=nil) { _section_debug_info=[[DWRFSection_debug_info alloc] initWithData:[NSData dataWithBytesNoCopy:(void *)tSection.buffer length:tSection.bufferSize freeWhenDone:NO] fileObject:self]; if (_section_debug_info==nil) { // A COMPLETER return NO; } } tSection=[tLoadCommand.segment sectionNamed:@"__debug_aranges"]; if (tSection!=nil) { _section_debug_aranges=[[DWRFSection_debug_aranges alloc] initWithData:[NSData dataWithBytesNoCopy:(void *)tSection.buffer length:tSection.bufferSize freeWhenDone:NO]]; if (_section_debug_aranges==nil) { // A COMPLETER return NO; } } return YES; } } return NO; } #pragma mark - - (void)lookUpSymbolicationDataForMachineInstructionAddress:(uint64_t)inAddress completionHandler:(void (^)(BOOL bFound,CUISymbolicationData * bSymbolicationData))handler { if (self.section_debug_info==nil) { if ([self analyze]==NO) { if (handler!=nil) handler(NO,nil); return; } } uint64_t tDebugInfoOffset=[self.section_debug_aranges debugInfoOffsetForAddress:inAddress]; if (tDebugInfoOffset==UINT64_MAX) { if (handler!=nil) handler(NO,nil); return; } DWRFDebuggingInformationCompilationUnit * tCompilationUnit=[self.section_debug_info compilationUnitAtOffset:tDebugInfoOffset]; if (tCompilationUnit==nil) { if (handler!=nil) handler(NO,nil); return; } // Look for the sub_program with inAddress for its AT_low_pc attribute DWRFSubProgramEntry * tSubProgramEntry=[tCompilationUnit subProgramForMachineInstructionAddress:inAddress]; if (tSubProgramEntry==nil) { if (handler!=nil) handler(NO,nil); return; } DWRFLineNumberProgramLocation * tLocation=[tCompilationUnit.lineNumberProgram locationForMachineInstructionAddress:inAddress]; if (tLocation!=nil) { CUISymbolicationData * tSymbolicationData=[CUISymbolicationData new]; tSymbolicationData.stackFrameSymbol=[tSubProgramEntry stackFrameSymbolWithLanguage:tCompilationUnit.language]; tSymbolicationData.byteOffset=inAddress-tSubProgramEntry.machineInstructionAddress; NSUInteger tFileIndex=tSubProgramEntry.sourcePathIndex; if (tFileIndex!=0) { // A AMELIORER (path absolu à trouver) } NSString * tFilePath=tLocation.fileName; if (tFilePath.length>0 && [tFilePath characterAtIndex:0]!='/') { NSString * tCompilationDirectory=tCompilationUnit.compilationDirectory; if (tCompilationDirectory.length>0) tFilePath=[tCompilationDirectory stringByAppendingPathComponent:tFilePath]; } tSymbolicationData.sourceFilePath=tFilePath; tSymbolicationData.lineNumber=tLocation.lineNumber; tSymbolicationData.columnNumber=tLocation.columnNumber; handler(YES,tSymbolicationData); return; } // Not found, use less accurate data NSLog(@"0x%llX -> %@ %@ - %llu %llu",inAddress,tSubProgramEntry.name,tLocation.fileName,tLocation.lineNumber,tLocation.columnNumber); NSString * tSourceFilePath=@"-"; NSUInteger tFileIndex=tSubProgramEntry.sourcePathIndex; if (tFileIndex!=0) { DWRFLineNumberProgram * tLineNumberProgram=[tCompilationUnit lineNumberProgram]; if (tLineNumberProgram!=nil) { tSourceFilePath=[tLineNumberProgram fileNameAtIndex:tFileIndex]; if (tSourceFilePath==nil) { tSourceFilePath=@"-"; } } } NSLog(@"0x%llX -> %@ %@ - %llu",inAddress,tSubProgramEntry.name,tSourceFilePath,tSubProgramEntry.line); if (handler!=nil) { CUISymbolicationData * tSymbolicationData=[CUISymbolicationData new]; tSymbolicationData.stackFrameSymbol=tSubProgramEntry.name; tSymbolicationData.byteOffset=inAddress-tSubProgramEntry.machineInstructionAddress; tSymbolicationData.sourceFilePath=tSourceFilePath; tSymbolicationData.lineNumber=tSubProgramEntry.line; handler(YES,tSymbolicationData); } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFObject.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_ENUM(NSUInteger, DWRFFormat) { DWRFUnknownFormat, DWRF32Format, DWRF64Format }; @interface DWRFObject : NSObject @property DWRFFormat dwarfFormat; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFObject.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFObject.h" @implementation DWRFObject - (instancetype)init { self=[super init]; if (self!=nil) { _dwarfFormat=DWRFUnknownFormat; } return self; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_abbrev.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "DWRFEnums.h" @interface DWRFAttributeSpecification : NSObject @property (readonly) DW_AT name; @property (readonly) DW_FORM form; @end @interface DWRFAbbreviationDeclaration : NSObject @property (readonly) uint64_t code; @property (readonly) DW_TAG tag; @property (readonly) BOOL hasChildren; @property (nonatomic,readonly) NSArray * allAttributesSpecifications; @end @interface DWRFAbbreviationDeclarationsSet : NSObject @property (nonatomic,readonly) NSArray * allAbbreviationDeclarations; - (DWRFAbbreviationDeclaration *)abbreviationDeclarationForCode:(uint64_t)inCode; @end @interface DWRFSection_debug_abbrev : NSObject - (instancetype)initWithData:(NSData *)inData; - (instancetype)initWithBytes:(uint8_t *)inBytes length:(NSUInteger)inLength; - (DWRFAbbreviationDeclarationsSet *)abbreviationDeclarationsSetAtOffset:(uint64_t)inOffset; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_abbrev.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFSection_debug_abbrev.h" #include "LEB128.h" typedef NS_ENUM(uint8_t, DW_CHILDREN) { DW_CHILDREN_no = 0x00, DW_CHILDREN_yes = 0x01 }; @interface DWRFAttributeSpecification () @property DW_AT name; @property DW_FORM form; - (instancetype)initWithName:(DW_AT)inName form:(DW_FORM)inForm; @end @implementation DWRFAttributeSpecification - (instancetype)initWithName:(DW_AT)inName form:(DW_FORM)inForm { self=[super init]; if (self!=nil) { _name=inName; _form=inForm; } return self; } @end @interface DWRFAbbreviationDeclaration () { NSMutableArray * _attributesSpecifications; } @property uint64_t code; @property DW_TAG tag; @property BOOL hasChildren; + (DWRFAbbreviationDeclaration *)nilDeclaration; @end @implementation DWRFAbbreviationDeclaration + (DWRFAbbreviationDeclaration *)nilDeclaration { static DWRFAbbreviationDeclaration * sNilAbbreviationDeclaration=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sNilAbbreviationDeclaration=[DWRFAbbreviationDeclaration new]; sNilAbbreviationDeclaration.code=0; sNilAbbreviationDeclaration.tag=0; }); return sNilAbbreviationDeclaration; } - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer { if (inBuffer==NULL) return nil; self=[super init]; if (self!=nil) { uint8_t * tBuffer=inBuffer; _code=DWRF_readULEB128(tBuffer, &tBuffer); if (_code==0) return [DWRFAbbreviationDeclaration nilDeclaration]; _tag=DWRF_readULEB128(tBuffer, &tBuffer); _hasChildren=((*((uint8_t *)tBuffer))==DW_CHILDREN_yes); tBuffer+=sizeof(uint8_t); _attributesSpecifications=[NSMutableArray array]; while (1) { DW_AT tName=DWRF_readULEB128(tBuffer, &tBuffer); DW_FORM tForm=DWRF_readULEB128(tBuffer, &tBuffer); if (tName==0 && tForm==0) break; DWRFAttributeSpecification * tAttributeSpecification=[[DWRFAttributeSpecification alloc] initWithName:tName form:tForm]; if (tAttributeSpecification!=nil) [_attributesSpecifications addObject:tAttributeSpecification]; } if (outBuffer!=NULL) *outBuffer=tBuffer; } return self; } #pragma mark - - (NSArray *)allAttributesSpecifications { return _attributesSpecifications; } @end @interface DWRFAbbreviationDeclarationsSet () { NSMutableArray * _abbreviationDeclarations; } @end @implementation DWRFAbbreviationDeclarationsSet - (instancetype)initWithBuffer:(uint8_t *)inBuffer { if (inBuffer==NULL) return nil; self=[super init]; if (self!=nil) { uint8_t *tBuffer=inBuffer; _abbreviationDeclarations=[NSMutableArray array]; while (1) { DWRFAbbreviationDeclaration * tAbreviationDeclaration=[[DWRFAbbreviationDeclaration alloc] initWithBuffer:tBuffer outBuffer:&tBuffer]; if (tAbreviationDeclaration==nil) { NSLog(@"Error when unarchiving abbreviation declaration"); return nil; } if (tAbreviationDeclaration.code==0) break; [_abbreviationDeclarations addObject:tAbreviationDeclaration]; } } return self; } #pragma mark - - (NSArray *)allAbbreviationDeclarations { return _abbreviationDeclarations; } - (DWRFAbbreviationDeclaration *)abbreviationDeclarationForCode:(uint64_t)inCode { if (inCode>_abbreviationDeclarations.count) return nil; return _abbreviationDeclarations[inCode]; } @end @interface DWRFSection_debug_abbrev () { NSData * _cachedData; NSMutableDictionary * _cachedAbbreviationDeclarationsSets; } @end @implementation DWRFSection_debug_abbrev - (instancetype)initWithData:(NSData *)inData { if (inData==nil || [inData isKindOfClass:NSData.class]==NO) return nil; self=[super init]; if (self!=nil) { _cachedData=inData; _cachedAbbreviationDeclarationsSets=[NSMutableDictionary dictionary]; } return self; } - (instancetype)initWithBytes:(uint8_t *)inBytes length:(NSUInteger)inLength { if (inBytes==NULL) return nil; return [self initWithData:[NSData dataWithBytesNoCopy:inBytes length:inLength]]; } #pragma mark - - (DWRFAbbreviationDeclarationsSet *)abbreviationDeclarationsSetAtOffset:(uint64_t)inOffset { DWRFAbbreviationDeclarationsSet * tDeclaration=_cachedAbbreviationDeclarationsSets[@(inOffset)]; if (tDeclaration!=nil) return tDeclaration; uint8_t * tBufferPtr=(uint8_t *)_cachedData.bytes; tDeclaration=[[DWRFAbbreviationDeclarationsSet alloc] initWithBuffer:tBufferPtr+inOffset]; if (tDeclaration!=nil) _cachedAbbreviationDeclarationsSets[@(inOffset)]=tDeclaration; return tDeclaration; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_addr.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "DWRFObject.h" @interface DWRFSection_debug_addr : NSObject - (instancetype)initWithData:(NSData *)inData; - (uint64_t)addressAtIndex:(uint64_t)inIndex base:(uint64_t)inBase format:(DWRFFormat)inFormat; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_addr.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFSection_debug_addr.h" @interface DWRFSection_debug_addr () { NSData * _cachedData; } @end @implementation DWRFSection_debug_addr - (instancetype)initWithData:(NSData *)inData { self=[super init]; if (self!=nil) { _cachedData=inData; } return self; } #pragma mark - - (uint64_t)addressAtIndex:(uint64_t)inIndex base:(uint64_t)inBase format:(DWRFFormat)inFormat { uint8_t * tBytes=(uint8_t *)_cachedData.bytes; tBytes+=inBase; uint64_t tAddress=0; if (inFormat==DWRF64Format) { tBytes+=(inIndex*sizeof(uint64_t)); tAddress=*((uint64_t *)tBytes); } else { tBytes+=(inIndex*sizeof(uint32_t)); tAddress=*((uint32_t *)tBytes); } return tAddress; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_aranges.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface DWRFCompilationUnitAddressSpace : NSObject @property (nonatomic,readonly) uint64_t debugInfoOffset; - (BOOL)containsAddress:(uint64_t)inAddress; @end @interface DWRFSection_debug_aranges : NSObject - (instancetype)initWithData:(NSData *)inData; @property (readonly) NSArray * allCompilationUnitsAddressSpaces; - (DWRFCompilationUnitAddressSpace *)compilationUnitAddressSpaceForAddress:(uint64_t)inAddress; - (uint64_t)debugInfoOffsetForAddress:(uint64_t)inAddress; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_aranges.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFSection_debug_aranges.h" #import "DWRFObject.h" @interface DWRFCompilationUnitAddressSpaceHeader : DWRFObject @property uint64_t unitLength; @property uint16_t version; @property uint64_t debugInfoOffset; @property uint8_t addressSize; @property uint8_t segmentSize; @property (nonatomic,readonly) size_t headerSize; @property (nonatomic,readonly) size_t addressRangeDescriptorSize; @property (nonatomic,readonly) size_t paddingSize; - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer; @end @implementation DWRFCompilationUnitAddressSpaceHeader - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer { if (inBuffer==NULL) return nil; self=[super init]; if (self!=nil) { uint8_t * tBufferPtr=inBuffer; uint32_t tUnsignedInteger=*((uint32_t *)tBufferPtr); tBufferPtr+=sizeof(uint32_t); if (tUnsignedInteger==0xffffffff) { self.dwarfFormat=DWRF64Format; _unitLength=*((uint64_t *)tBufferPtr); tBufferPtr+=sizeof(uint64_t); } else { self.dwarfFormat=DWRF32Format; _unitLength=tUnsignedInteger; } _version=*((uint16_t *)tBufferPtr); tBufferPtr+=sizeof(uint16_t); if (self.dwarfFormat==DWRF64Format) { _debugInfoOffset=*((uint64_t *)tBufferPtr); tBufferPtr+=sizeof(uint64_t); } else { _debugInfoOffset=*((uint32_t *)tBufferPtr); tBufferPtr+=sizeof(uint32_t); } _addressSize=*((uint8_t *)tBufferPtr); tBufferPtr+=sizeof(uint8_t); _segmentSize=*((uint8_t *)tBufferPtr); tBufferPtr+=sizeof(uint8_t); if (outBuffer!=NULL) *outBuffer=tBufferPtr; } return self; } #pragma mark - - (size_t)headerSize { switch(self.dwarfFormat) { case DWRF32Format: return 12*sizeof(uint8_t); case DWRF64Format: return 24*sizeof(uint8_t); default: return -1; } } - (size_t)addressRangeDescriptorSize { return _segmentSize+2*_addressSize; } - (size_t)paddingSize { size_t tDescriptorSize=self.addressRangeDescriptorSize; size_t tHeaderSize=self.headerSize; while (tHeaderSize>tDescriptorSize) tHeaderSize-=tDescriptorSize; return (tDescriptorSize-tHeaderSize); } @end @interface DWRFAddressRangeDescriptor : NSObject { uint64_t _segmentSelector; } @property uint64_t location; @property uint64_t length; + (DWRFAddressRangeDescriptor *)addressRangeDescriptionWithLocation:(uint64_t)inLocation length:(uint64_t)inLength; - (instancetype)initWithLocation:(uint64_t)inLocation length:(uint64_t)inLength; - (BOOL)containsAddress:(uint64_t)inAddress; @end @implementation DWRFAddressRangeDescriptor + (DWRFAddressRangeDescriptor *)addressRangeDescriptionWithLocation:(uint64_t)inLocation length:(uint64_t)inLength { return [[DWRFAddressRangeDescriptor alloc] initWithLocation:inLocation length:inLength]; } - (instancetype)initWithLocation:(uint64_t)inLocation length:(uint64_t)inLength { self=[super init]; if (self!=nil) { _location=inLocation; _length=inLength; } return self; } #pragma mark - - (NSUInteger)hash { return self.location; } #pragma mark - - (BOOL)containsAddress:(uint64_t)inAddress { return (inAddress>=self.location && inAddress<(self.location+self.length)); } #pragma mark - - (NSString *)description { return [NSString stringWithFormat:@"0x%lx - 0x%lx",(long)self.location,(long)(self.location+self.length-1)]; } @end @interface DWRFCompilationUnitAddressSpace () { DWRFCompilationUnitAddressSpaceHeader * _header; NSMutableArray * _addressRangeDescriptors; } - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer; @end @implementation DWRFCompilationUnitAddressSpace - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer { if (inBuffer==NULL) return nil; self=[super init]; if (self==nil) return nil; uint8_t * tBufferPtr=inBuffer; _header=[[DWRFCompilationUnitAddressSpaceHeader alloc] initWithBuffer:tBufferPtr outBuffer:NULL]; _addressRangeDescriptors=[NSMutableArray array]; tBufferPtr+=_header.addressRangeDescriptorSize*sizeof(uint8_t); while(1) { uint64_t tSegmentSelector=0; if (_header.segmentSize!=0) { // A COMPLETER } uint64_t tLocation; uint64_t tLength; if (_header.addressSize==4) { tLocation=*((uint32_t *)tBufferPtr); tBufferPtr+=sizeof(uint32_t); tLength=*((uint32_t *)tBufferPtr); tBufferPtr+=sizeof(uint32_t); } else { tLocation=*((uint64_t *)tBufferPtr); tBufferPtr+=sizeof(uint64_t); tLength=*((uint64_t *)tBufferPtr); tBufferPtr+=sizeof(uint64_t); } if (tSegmentSelector==0 && tLocation==0 && tLength==0) break; DWRFAddressRangeDescriptor * tDescription=[DWRFAddressRangeDescriptor addressRangeDescriptionWithLocation:tLocation length:tLength]; [_addressRangeDescriptors addObject:tDescription]; //printf("0x%llX-0x%llX\n",tLocation,tLocation+tLength-1); } if (outBuffer!=NULL) *outBuffer=tBufferPtr; return self; } #pragma mark - - (uint64_t)debugInfoOffset { return _header.debugInfoOffset; } - (BOOL)containsAddress:(uint64_t)inAddress { for(DWRFAddressRangeDescriptor * tAddressRangeDescription in _addressRangeDescriptors) { if ([tAddressRangeDescription containsAddress:inAddress]==YES) return YES; } return NO; } #pragma mark - - (NSString *)description { NSMutableString * tMutableString=[NSMutableString string]; [tMutableString appendFormat:@"unit_length: %llu\n",_header.unitLength]; [tMutableString appendFormat:@"version: %hu\n",_header.version]; [tMutableString appendFormat:@"debug_info_offset: %llu\n",_header.debugInfoOffset]; for(DWRFAddressRangeDescriptor * tDescriptor in _addressRangeDescriptors) [tMutableString appendFormat:@"%@\n",[tDescriptor description]]; return tMutableString; } @end @interface DWRFSection_debug_aranges () { NSMutableArray * _compilationUnitsAddressSpaces; } @end @implementation DWRFSection_debug_aranges - (instancetype)initWithData:(NSData *)inData { if (inData==nil || [inData isKindOfClass:NSData.class]==NO) return nil; self=[super init]; if (self!=nil) { _compilationUnitsAddressSpaces=[NSMutableArray array]; uint8_t * tBufferPtr=(uint8_t *)inData.bytes; uint8_t * tEndBufferPtr=tBufferPtr+inData.length; while(tBufferPtr *)allCompilationUnitsAddressSpaces { return _compilationUnitsAddressSpaces; } - (DWRFCompilationUnitAddressSpace *)compilationUnitAddressSpaceForAddress:(uint64_t)inAddress { for(DWRFCompilationUnitAddressSpace * tAddressSpace in _compilationUnitsAddressSpaces) { if ([tAddressSpace containsAddress:inAddress]==YES) return tAddressSpace; } return nil; } - (uint64_t)debugInfoOffsetForAddress:(uint64_t)inAddress { for(DWRFCompilationUnitAddressSpace * tAddressSpace in _compilationUnitsAddressSpaces) { if ([tAddressSpace containsAddress:inAddress]==YES) { return tAddressSpace.debugInfoOffset; } } return UINT64_MAX; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_info.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "DWRFEnums.h" #import "DWRFSection_debug_line.h" #import "DWRFObject.h" @class DWRFFileObject; @interface DWRFDIEAttribute : NSObject @property DW_FORM form; @property id object; @property (nonatomic,readonly) BOOL isAddress; @property (nonatomic,readonly) BOOL isConstant; @property (nonatomic,readonly) BOOL isString; @end @interface DWRFDebuggingInformationEntry : NSObject @property (readonly) uint64_t abbreviationCode; @property (readonly) DW_TAG tag; @property (readonly) NSDictionary * attributes; @property (readonly) DWRFDebuggingInformationEntry * parent; @property (readonly) DWRFDebuggingInformationEntry * next; @property (readonly) NSArray * children; @property (readonly) DWRFDebuggingInformationEntry * referencedEntry; @property (nonatomic,readonly,copy) NSString * name; // attributes[@(DW_AT_name)] + (DWRFDebuggingInformationEntry *)nilEntry; - (id)objectForAttribute:(DW_AT)inAttribute; - (DWRFDebuggingInformationEntry *)entryAtAddress:(uint8_t *)inAddress; - (BOOL)pcRangeContainsMachineInstructionAddress:(uint64_t)inMachineInstructionAddress; @end @interface DWRFCompileUnitEntry : DWRFDebuggingInformationEntry @property (nonatomic,readonly) uint64_t lineNumberProgramOffset; @property (nonatomic,readonly,copy) NSString * compiler; @property (nonatomic,readonly) DW_LANG language; @property (nonatomic,readonly,copy) NSString * compilationDirectory; @end @interface DWRFLexicalBlockEntry : DWRFDebuggingInformationEntry @end @interface DWRFSubProgramEntry : DWRFDebuggingInformationEntry @property (nonatomic,readonly) uint64_t machineInstructionAddress; @property (readonly) NSUInteger sourcePathIndex; @property (nonatomic,readonly) uint64_t line; - (NSString *)stackFrameSymbolWithLanguage:(DW_LANG)inLanguage; @end @interface DWRFDebuggingInformationCompilationUnit : DWRFObject @property (nonatomic,readonly) DWRFLineNumberProgram * lineNumberProgram; @property (nonatomic,readonly) DW_LANG language; @property (nonatomic,readonly) NSString * compilationDirectory; - (DWRFDebuggingInformationEntry *)entryAtAddress:(uint8_t *)inAddress; - (DWRFSubProgramEntry *)subProgramForMachineInstructionAddress:(uint64_t)inAddress; @end @interface DWRFSection_debug_info : NSObject @property (readonly) DWRFFileObject * fileObject; - (instancetype)initWithData:(NSData *)inData fileObject:(DWRFFileObject *)inFileObject; - (DWRFDebuggingInformationCompilationUnit *)compilationUnitAtOffset:(uint64_t)inOffset; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_info.m ================================================ /* Copyright (c) 2020-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFSection_debug_info.h" #import "DWRFFileObject.h" #include "LEB128.h" #import "CUICXXDemangler.h" #import "CUISwiftDemangler.h" @implementation DWRFDIEAttribute - (BOOL)isAddress { switch(self.form) { case DW_FORM_addr: case DW_FORM_addrx: case DW_FORM_addrx1: case DW_FORM_addrx2: case DW_FORM_addrx3: case DW_FORM_addrx4: return YES; default: break; } return NO; } - (BOOL)isConstant { switch(self.form) { case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_data16: case DW_FORM_sdata: case DW_FORM_udata: case DW_FORM_implicit_const: return YES; default: break; } return NO; } - (BOOL)iString { switch(self.form) { case DW_FORM_strp: case DW_FORM_strx1: case DW_FORM_strx2: case DW_FORM_strx3: case DW_FORM_strx4: case DW_FORM_strx: return YES; default: break; } return NO; } - (NSString *)description { if (self.isAddress==YES) { NSNumber * tNumber=self.object; return [NSString stringWithFormat:@"0x%016lx",[tNumber unsignedIntegerValue]]; } return [self.object description]; } @end @interface DWRFDebuggingInformationEntry () @property uint8_t * address; @property uint64_t abbreviationCode; @property DW_TAG tag; @property NSDictionary * attributes; @property DWRFDebuggingInformationEntry * parent; @property DWRFDebuggingInformationEntry * next; @property NSArray * children; @property DWRFDebuggingInformationEntry * referencedEntry; @end @implementation DWRFDebuggingInformationEntry + (DWRFDebuggingInformationEntry *)nilEntry { static DWRFDebuggingInformationEntry * sNilEntry=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sNilEntry=[DWRFDebuggingInformationEntry new]; sNilEntry.abbreviationCode=0; sNilEntry.tag=0; }); return sNilEntry; } #pragma mark - - (NSString *)name { NSString * tName=self.referencedEntry.attributes[@(DW_AT_name)].object; if (tName==nil) tName=self.attributes[@(DW_AT_name)].object; return [tName copy]; } #pragma mark - - (id)objectForAttribute:(DW_AT)inAttribute { return self.attributes[@(inAttribute)].object; } - (DWRFDebuggingInformationEntry *)entryAtAddress:(uint8_t *)inAddress { if (self.address==inAddress) return self; for(DWRFDebuggingInformationEntry * tChild in self.children) { DWRFDebuggingInformationEntry * tEntry=[tChild entryAtAddress:inAddress]; if (tEntry!=nil) return tEntry; } return nil; } - (BOOL)pcRangeContainsMachineInstructionAddress:(uint64_t)inMachineInstructionAddress { NSNumber * tNumber=[self objectForAttribute:DW_AT_low_pc]; if (tNumber==nil) return NO; uint64_t tLowPC=[tNumber unsignedLongLongValue]; if (inMachineInstructionAddress (%llu)\n",NSStringFromClass(self.class),(unsigned long long)self,self.abbreviationCode]; [tMutableString appendFormat:@"Tag: %@\n",[self nameForTag:self.tag]]; [tMutableString appendFormat:@"Attributes:\n"]; [self.attributes enumerateKeysAndObjectsUsingBlock:^(NSNumber * bKey, DWRFDIEAttribute * bAttribute, BOOL * bOutStop) { [tMutableString appendFormat:@"\t %@ : %@\n",[self nameForAttribute:[bKey unsignedShortValue]],bAttribute]; }]; return tMutableString; } @end @implementation DWRFCompileUnitEntry - (uint64_t)lineNumberProgramOffset { return [[self objectForAttribute:DW_AT_stmt_list] unsignedIntegerValue]; } - (NSString *)compiler { return [self objectForAttribute:DW_AT_producer]; } - (DW_LANG)language { return [[self objectForAttribute:DW_AT_language] unsignedShortValue]; } - (NSString *)compilationDirectory { return [self objectForAttribute:DW_AT_comp_dir]; } @end @implementation DWRFLexicalBlockEntry @end @implementation DWRFSubProgramEntry - (uint64_t)machineInstructionAddress { NSNumber * tNumber=[self.referencedEntry objectForAttribute:DW_AT_low_pc]; if (tNumber==nil) tNumber=[self objectForAttribute:DW_AT_low_pc]; return [tNumber unsignedIntegerValue]; } - (NSUInteger)sourcePathIndex { NSNumber * tNumber=[self.referencedEntry objectForAttribute:DW_AT_decl_file]; if (tNumber==nil) tNumber=[self objectForAttribute:DW_AT_decl_file]; return [tNumber unsignedIntegerValue]; } - (uint64_t)line { NSNumber * tNumber=[self.referencedEntry objectForAttribute:DW_AT_decl_line]; if (tNumber==nil) tNumber=[self objectForAttribute:DW_AT_decl_line]; return [tNumber unsignedIntegerValue]; } - (NSString *)stackFrameSymbolWithLanguage:(DW_LANG)inLanguage { switch(inLanguage) { case DW_LANG_Swift: { NSString * tName=nil; NSString * tLinkageName=[self objectForAttribute:DW_AT_linkage_name]; if (tLinkageName!=nil) { tName=[CUISwiftDemangler demangle:tLinkageName]; if (tName!=nil) return tName; } tName=self.name; DWRFDebuggingInformationEntry * tParentEntry=self; BOOL tNeedsParenthesis=NO; do { tParentEntry=tParentEntry.parent; DW_TAG tTag=tParentEntry.tag; if (tParentEntry==nil || tTag==DW_TAG_module || tTag==DW_TAG_compile_unit) break; NSString * tComponentName=tParentEntry.name; if (tComponentName==nil) break; tName=[NSString stringWithFormat:@"%@.%@",tComponentName,tName]; tNeedsParenthesis=YES; } while (1); if (tNeedsParenthesis==YES) tName=[tName stringByAppendingString:@"()"]; return tName; } case DW_LANG_C_plus_plus: { DWRFDebuggingInformationEntry * tParentEntry=self; NSString * tLinkageName=[self objectForAttribute:DW_AT_linkage_name]; NSString * tName=nil; if (tLinkageName==nil && self.referencedEntry!=nil) { tLinkageName=[self.referencedEntry objectForAttribute:DW_AT_linkage_name]; } if (tLinkageName!=nil) { tName=[CUICXXDemangler demangle:tLinkageName]; if (tName!=nil) return tName; } tName=tParentEntry.name; if (tName==nil && self.referencedEntry!=nil) { tParentEntry=self.referencedEntry; tName=tParentEntry.name; } BOOL tNeedsParenthesis=NO; do { tParentEntry=tParentEntry.parent; DW_TAG tTag=tParentEntry.tag; if (tParentEntry==nil || tTag==DW_TAG_module || tTag==DW_TAG_compile_unit) break; NSString * tComponentName=tParentEntry.name; if (tComponentName==nil) break; tName=[NSString stringWithFormat:@"%@::%@",tComponentName,tName]; tNeedsParenthesis=YES; } while (1); // Parameters (A COMPLETER) if (tNeedsParenthesis==YES) tName=[tName stringByAppendingString:@"()"]; return tName; } default: break; } return self.name; } @end @interface DWRFDebuggingInformationCompilationUnitHeader : DWRFObject @property uint64_t unit_length; @property uint16_t version; @property uint8_t unit_type; @property uint64_t debug_abbrev_offset; @property uint8_t address_size; - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer; @end @implementation DWRFDebuggingInformationCompilationUnitHeader - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer { if (inBuffer==NULL) return nil; self=[super init]; if (self!=nil) { uint32_t tUnsignedInteger=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); if (tUnsignedInteger==0xffffffff) { self.dwarfFormat=DWRF64Format; _unit_length=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); } else { self.dwarfFormat=DWRF32Format; _unit_length=tUnsignedInteger; } _version=*((uint16_t *)inBuffer); inBuffer+=sizeof(uint16_t); if (_version>=5) { _unit_type=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); _address_size=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); if (self.dwarfFormat==DWRF64Format) { _debug_abbrev_offset=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); } else { _debug_abbrev_offset=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); } } else { if (self.dwarfFormat==DWRF64Format) { _debug_abbrev_offset=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); } else { _debug_abbrev_offset=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); } _address_size=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); } } if (outBuffer!=NULL) *outBuffer=inBuffer; return self; } @end @interface DWRFDebuggingInformationCompilationUnit () { uint8_t * _address; DWRFFileObject *_fileObject; NSArray * _abbreviationDeclarations; DWRFCompileUnitEntry * _compileUnitEntry; NSMutableArray * _allSubProgramEntities; } @property DWRFDebuggingInformationCompilationUnitHeader * header; - (instancetype)initWithBuffer:(uint8_t *)inBuffer fileObject:(DWRFFileObject *)inFileObject outBuffer:(uint8_t **)outBuffer; - (DWRFDebuggingInformationEntry *)entryWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer; @end @implementation DWRFDebuggingInformationCompilationUnit - (DWRFDebuggingInformationEntry *)entryWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer { if (inBuffer==nil) return nil; uint8_t * tAddress=inBuffer; DWRFDebuggingInformationEntry * tEntry=nil; uint64_t tAbbreviationCode=DWRF_readULEB128(inBuffer, &inBuffer); if (tAbbreviationCode==0) { if (outBuffer!=NULL) *outBuffer=inBuffer; return [DWRFDebuggingInformationEntry nilEntry]; } DWRFAbbreviationDeclaration * tAbbreviationDeclaration=_abbreviationDeclarations[tAbbreviationCode-1]; // Tag DW_TAG tTag=tAbbreviationDeclaration.tag; switch(tTag) { case DW_TAG_lexical_block: tEntry=[DWRFLexicalBlockEntry new]; break; case DW_TAG_compile_unit: tEntry=[DWRFCompileUnitEntry new]; break; case DW_TAG_subprogram: tEntry=[DWRFSubProgramEntry new]; break; default: tEntry=[DWRFDebuggingInformationEntry new]; break; } if (tEntry!=nil) { tEntry.address=tAddress; tEntry.abbreviationCode=tAbbreviationCode; tEntry.tag=tAbbreviationDeclaration.tag; // Code tEntry.abbreviationCode=tAbbreviationCode; NSMutableDictionary * tAttributesDictionary=[NSMutableDictionary dictionary]; // Attributes for(DWRFAttributeSpecification * tSpecification in tAbbreviationDeclaration.allAttributesSpecifications) { NSNumber * tKey=@(tSpecification.name); id tObject=nil; switch(tSpecification.form) { case DW_FORM_addr: { uint64_t tAddress; memcpy(&tAddress,inBuffer,_header.address_size*sizeof(uint8_t)); inBuffer+=_header.address_size*sizeof(uint8_t); tObject=@(tAddress); break; } case DW_FORM_block: { uint64_t tBlockLength=DWRF_readULEB128(inBuffer, &inBuffer); NSData * tData=[NSData dataWithBytes:inBuffer length:tBlockLength]; inBuffer+=tBlockLength; tObject=tData; break; } case DW_FORM_block1: { uint8_t tBlockLength=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); NSData * tData=[NSData dataWithBytes:inBuffer length:tBlockLength]; inBuffer+=tBlockLength; tObject=tData; break; } case DW_FORM_block2: { uint16_t tLength=*((uint16_t *)inBuffer); inBuffer+=sizeof(uint16_t); tObject=[NSData dataWithBytes:inBuffer length:tLength]; inBuffer+=tLength*sizeof(uint8_t); break; } case DW_FORM_block4: { uint32_t tLength=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); tObject=[NSData dataWithBytes:inBuffer length:tLength]; inBuffer+=tLength*sizeof(uint8_t); break; } case DW_FORM_data1: { uint8_t tConstant=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); tObject=@(tConstant); break; } case DW_FORM_data2: { uint16_t tConstant=*((uint16_t *)inBuffer); inBuffer+=sizeof(uint16_t); tObject=@(tConstant); break; } case DW_FORM_data4: { uint32_t tConstant=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); tObject=@(tConstant); break; } case DW_FORM_data8: { uint64_t tConstant=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); tObject=@(tConstant); break; } case DW_FORM_data16: { tObject=[NSData dataWithBytes:inBuffer length:16*sizeof(uint8_t)]; inBuffer+=16*sizeof(uint8_t); break; } case DW_FORM_implicit_const: { // A COMPLETER break; } /*case DW_FORM_string: { } break; */ case DW_FORM_flag: { uint8_t tPresent=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); tObject=[NSNumber numberWithBool:(tPresent!=0)]; break; } case DW_FORM_sdata: { int64_t tConstant=DWRF_readLEB128(inBuffer, &inBuffer); tObject=@(tConstant); break; } case DW_FORM_strp: { uint64_t tOffset=0; if (self.dwarfFormat==DWRF64Format) { tOffset=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); } else { tOffset=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); } tObject=[_fileObject.section_debug_str stringAtOffset:tOffset]; break; } case DW_FORM_udata: { uint64_t tConstant=DWRF_readULEB128(inBuffer, &inBuffer); tObject=@(tConstant); break; } case DW_FORM_ref_addr: { uint64_t tAddress=0; if (self.header.version>=3) { if (self.dwarfFormat==DWRF64Format) { tAddress=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); } else { tAddress=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); } } else { switch(self.header.address_size) { case 4: tAddress=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); break; case 8: tAddress=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); break; } } tObject=@(tAddress); break; } /*case DW_FORM_ref1: { } break; case DW_FORM_ref2: { } break;*/ case DW_FORM_ref4: { uint32_t tReference=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); tObject=@(tReference); break; } /*case DW_FORM_ref8: { } break; case DW_FORM_ref_udata: { } break; case DW_FORM_indirect: { } break;*/ case DW_FORM_sec_offset: { uint64_t tOffset=0; if (self.dwarfFormat==DWRF64Format) { tOffset=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); } else { tOffset=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); } tObject=@(tOffset); break; } case DW_FORM_exprloc: { uint64_t tLength=DWRF_readULEB128(inBuffer, &inBuffer); inBuffer+=tLength*sizeof(uint8_t); // A COMPLETER break; } case DW_FORM_flag_present: { // Implicitly indicated as present tObject=@(YES); break; } /*case DW_FORM_reg_sig8: { } break;*/ case DW_FORM_strx: { uint64_t tIndex=DWRF_readULEB128(inBuffer,&inBuffer); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_str_offsets_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_str_offsets_base"); } uint64_t tOffset=[_fileObject.section_debug_str_offsets offsetAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=[_fileObject.section_debug_str stringAtOffset:tOffset]; break; } case DW_FORM_addrx: { uint64_t tIndex=DWRF_readULEB128(inBuffer,&inBuffer); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_addr_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_addr_base"); } uint64_t tAddress=[_fileObject.section_debug_addr addressAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=@(tAddress); break; } case DW_FORM_strx1: { uint8_t tIndex=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_str_offsets_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_str_offsets_base"); } uint64_t tOffset=[_fileObject.section_debug_str_offsets offsetAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=[_fileObject.section_debug_str stringAtOffset:tOffset]; break; } case DW_FORM_strx2: { uint16_t tIndex=*((uint16_t *)inBuffer); inBuffer+=sizeof(uint16_t); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_str_offsets_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_str_offsets_base"); } uint64_t tOffset=[_fileObject.section_debug_str_offsets offsetAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=[_fileObject.section_debug_str stringAtOffset:tOffset]; break; } case DW_FORM_strx3: { uint16_t tIndex=*((uint32_t *)inBuffer); inBuffer+=3*sizeof(uint8_t); tIndex=(tIndex>>8); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_str_offsets_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_str_offsets_base"); } uint64_t tOffset=[_fileObject.section_debug_str_offsets offsetAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=[_fileObject.section_debug_str stringAtOffset:tOffset]; break; } case DW_FORM_strx4: { uint32_t tIndex=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_str_offsets_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_str_offsets_base"); } uint64_t tOffset=[_fileObject.section_debug_str_offsets offsetAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=[_fileObject.section_debug_str stringAtOffset:tOffset]; break; } case DW_FORM_addrx1: { uint8_t tIndex=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_addr_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_addr_base"); } uint64_t tAddress=[_fileObject.section_debug_addr addressAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=@(tAddress); break; } case DW_FORM_addrx2: { uint16_t tIndex=*((uint16_t *)inBuffer); inBuffer+=sizeof(uint16_t); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_addr_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_addr_base"); } uint64_t tAddress=[_fileObject.section_debug_addr addressAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=@(tAddress); break; } case DW_FORM_addrx3: { uint16_t tIndex=*((uint32_t *)inBuffer); inBuffer+=3*sizeof(uint8_t); tIndex=(tIndex>>8); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_addr_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_addr_base"); } uint64_t tAddress=[_fileObject.section_debug_addr addressAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=@(tAddress); break; } case DW_FORM_addrx4: { uint32_t tIndex=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); NSNumber * tNumber=tAttributesDictionary[@(DW_AT_addr_base)]; if (tNumber==nil) { NSLog(@"Missing DW_AT_addr_base"); } uint64_t tAddress=[_fileObject.section_debug_addr addressAtIndex:tIndex base:[tNumber unsignedIntegerValue] format:self.dwarfFormat]; tObject=@(tAddress); break; } default: NSLog(@"FORM not handled: %lX",(unsigned long)tSpecification.form); break; } if (tObject!=nil) { DWRFDIEAttribute * tNewAttribute=[DWRFDIEAttribute new]; tNewAttribute.form=tSpecification.form; tNewAttribute.object=tObject; tAttributesDictionary[tKey]=tNewAttribute; } } tEntry.attributes=tAttributesDictionary; if (tAbbreviationDeclaration.hasChildren) { NSMutableArray * tEntries=[NSMutableArray array]; while (1) { DWRFDebuggingInformationEntry * tChildEntry=[self entryWithBuffer:inBuffer outBuffer:&inBuffer]; if (tChildEntry==nil) { NSLog(@"Error when unarchiving Debugging Information Entry"); return nil; } if (tChildEntry.abbreviationCode==0) break; tChildEntry.parent=tEntry; [tEntries addObject:tChildEntry]; } tEntry.children=[tEntries copy]; } if (outBuffer!=NULL) *outBuffer=inBuffer; } return tEntry; } - (instancetype)initWithBuffer:(uint8_t *)inBuffer fileObject:(DWRFFileObject *)inFileObject outBuffer:(uint8_t **)outBuffer { if (inBuffer==nil) return nil; self=[super init]; if (self!=nil) { _address=inBuffer; _fileObject=inFileObject; _header=[[DWRFDebuggingInformationCompilationUnitHeader alloc] initWithBuffer:inBuffer outBuffer:&inBuffer]; self.dwarfFormat=_header.dwarfFormat; DWRFAbbreviationDeclarationsSet * tDeclarationsSet=[_fileObject.section_debug_abbrev abbreviationDeclarationsSetAtOffset:_header.debug_abbrev_offset]; if (tDeclarationsSet==nil) { // Aie aie aie return nil; } _abbreviationDeclarations=tDeclarationsSet.allAbbreviationDeclarations; // Retrieve Compile Unit entry and its children _compileUnitEntry=(DWRFCompileUnitEntry *)[self entryWithBuffer:inBuffer outBuffer:&inBuffer]; if (_compileUnitEntry==nil) { NSLog(@"Error when unarchiving Compile Unit Entry"); return nil; } if (_compileUnitEntry.abbreviationCode==0) { NSLog(@"Error when unarchiving Compile Unit Entry"); return nil; } } if (outBuffer!=NULL) *outBuffer=inBuffer; return self; } #pragma mark - -(DW_LANG)language { return _compileUnitEntry.language; } -(NSString *)compilationDirectory { return _compileUnitEntry.compilationDirectory; } - (DWRFDebuggingInformationEntry *)entryAtAddress:(uint8_t *)inAddress { return [_compileUnitEntry entryAtAddress:inAddress]; } - (DWRFLineNumberProgram *)lineNumberProgram { return [_fileObject.section_debug_line lineNumberProgramAtOffset:_compileUnitEntry.lineNumberProgramOffset]; } - (DWRFSubProgramEntry *)subProgramForMachineInstructionAddress:(uint64_t)inMachineInstructionAddress { if (_allSubProgramEntities==nil) { _allSubProgramEntities=[NSMutableArray array]; __block __weak void (^_weakEnumerateNodesRecursively)(DWRFDebuggingInformationEntry *,NSMutableArray *); __block void(^_enumerateNodesRecursively)(DWRFDebuggingInformationEntry *,NSMutableArray *); _enumerateNodesRecursively = ^void(DWRFDebuggingInformationEntry * bEntry,NSMutableArray * bMutableArray) { if (bEntry.tag==DW_TAG_subprogram && [bEntry isKindOfClass:[DWRFSubProgramEntry class]]==YES) { [bMutableArray addObject:(DWRFSubProgramEntry *)bEntry]; } for(DWRFDebuggingInformationEntry * bChildEntry in bEntry.children) { _weakEnumerateNodesRecursively(bChildEntry,bMutableArray); } }; _weakEnumerateNodesRecursively = _enumerateNodesRecursively; _enumerateNodesRecursively(_compileUnitEntry,_allSubProgramEntities); } for(DWRFSubProgramEntry * tEntry in _allSubProgramEntities) { if (tEntry.tag==DW_TAG_subprogram) { if ([tEntry isKindOfClass:[DWRFSubProgramEntry class]]==YES) { DWRFSubProgramEntry * tSubProgramEntry=(DWRFSubProgramEntry *)tEntry; if ([tSubProgramEntry pcRangeContainsMachineInstructionAddress:inMachineInstructionAddress]==NO) continue; // Look for inlined subroutines for(DWRFDebuggingInformationEntry * tChild in tSubProgramEntry.children) { if (tChild.tag==DW_TAG_inlined_subroutine) { if ([tChild pcRangeContainsMachineInstructionAddress:inMachineInstructionAddress]==YES) { NSNumber * tNumber=[tChild objectForAttribute:DW_AT_abstract_origin]; if (tNumber!=nil) { uint64_t tOffset=[tNumber unsignedIntegerValue]; DWRFDebuggingInformationEntry * tEntry=[_compileUnitEntry entryAtAddress:_address+tOffset]; if ([tEntry isKindOfClass:[DWRFSubProgramEntry class]]==YES) { tSubProgramEntry=(DWRFSubProgramEntry *)tEntry; } } break; } } } if (tSubProgramEntry.name==nil) { NSNumber * tReference=[tSubProgramEntry objectForAttribute:DW_AT_specification]; if (tReference!=nil) { DWRFDebuggingInformationEntry * tReferencedEntry=[self entryAtAddress:_address+[tReference unsignedIntegerValue]]; if ([tReferencedEntry isKindOfClass:[DWRFSubProgramEntry class]]==YES) { tSubProgramEntry.referencedEntry=tReferencedEntry; } } } return tSubProgramEntry; } } } return nil; } @end @interface DWRFSection_debug_info () { NSData * _cachedData; NSMutableDictionary * _compilationUnits; } @property DWRFFileObject * fileObject; @end @implementation DWRFSection_debug_info - (instancetype)initWithData:(NSData *)inData fileObject:(DWRFFileObject *)inFileObject { if (inData==nil || [inData isKindOfClass:[NSData class]]==NO) return nil; self=[super init]; if (self!=nil) { _fileObject=inFileObject; _cachedData=inData; _compilationUnits=[NSMutableDictionary dictionary]; } return self; } #pragma mark - - (DWRFDebuggingInformationCompilationUnit *)compilationUnitAtOffset:(uint64_t)inOffset { DWRFDebuggingInformationCompilationUnit * tCompilationUnit=_compilationUnits[@(inOffset)]; if (tCompilationUnit!=nil) return tCompilationUnit; uint8_t * tBufferPtr=(uint8_t *)_cachedData.bytes; tBufferPtr=tBufferPtr+inOffset; tCompilationUnit=[[DWRFDebuggingInformationCompilationUnit alloc] initWithBuffer:tBufferPtr fileObject:self.fileObject outBuffer:&tBufferPtr]; if (tCompilationUnit!=nil) _compilationUnits[@(inOffset)]=tCompilationUnit; return tCompilationUnit; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_line.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface DWRFLineNumberProgramLocation : NSObject @property (readonly) uint64_t machineInstructionAddress; @property (readonly,copy) NSString * fileName; @property (readonly) uint64_t lineNumber; @property (readonly) uint64_t columnNumber; @end @interface DWRFLineNumberProgram : NSObject - (NSString *)fileNameAtIndex:(NSUInteger)inIndex; - (DWRFLineNumberProgramLocation *)locationForMachineInstructionAddress:(uint64_t)inMachineInstructionAddress; @end @interface DWRFSection_debug_line : NSObject - (instancetype)initWithData:(NSData *)inData; - (DWRFLineNumberProgram *)lineNumberProgramAtOffset:(uint64_t)inOffset; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_line.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFSection_debug_line.h" #include "LEB128.h" #import "DWRFObject.h" typedef NS_ENUM(uint8_t, DW_LNS) { DW_LNS_extended_op = 0x00, DW_LNS_copy = 0x01, DW_LNS_advance_pc = 0x02, DW_LNS_advance_line = 0x03, DW_LNS_set_file = 0x04, DW_LNS_set_column = 0x05, DW_LNS_negate_stmt = 0x06, DW_LNS_set_basic_block = 0x07, DW_LNS_const_add_pc = 0x08, DW_LNS_fixed_advance_pc = 0x09, DW_LNS_set_prologue_end = 0x0a, DW_LNS_set_epilogue_begin = 0x0b, DW_LNS_set_isa = 0x0c }; typedef NS_ENUM(NSUInteger, DW_LNE) { DW_LNE_end_sequence = 0x01, DW_LNE_set_address = 0x02, DW_LNE_define_file = 0x03, DW_LNE_set_discriminator = 0x04, DW_LNE_lo_user = 0x80, DW_LNE_hi_user = 0xff }; @interface DWRFLineNumberProgramLocation () @property uint64_t machineInstructionAddress; @property (copy) NSString * fileName; @property uint64_t lineNumber; @property uint64_t columnNumber; @end @implementation DWRFLineNumberProgramLocation @end @interface DWRFLineNumberProgramStateMachine : NSObject @property uint64_t address; @property uint64_t op_index; @property uint64_t file; @property uint64_t line; @property uint64_t column; @property BOOL is_stmt; @property BOOL basic_block; @property BOOL end_sequence; @property BOOL prologue_end; @property BOOL epilogue_begin; @property uint64_t xisa; @property uint64_t discriminator; @end @implementation DWRFLineNumberProgramStateMachine - (instancetype)initWithStmt:(BOOL)inStmt; { self=[super init]; if (self!=nil) { _address=0; _op_index=0; _file=1; _line=1; _column=0; _is_stmt=inStmt; _basic_block=NO; _end_sequence=NO; _prologue_end=NO; _epilogue_begin=NO; _xisa=0; _discriminator=0; } return self; } @end @interface DWRFLineNumberProgramHeaderFileNameEntry : NSObject @property NSString * filePath; @property uint64_t directoryIndex; @property uint64_t lastModificationDate; @property uint64_t fileSize; @end @implementation DWRFLineNumberProgramHeaderFileNameEntry @end @interface DWRFLineNumberProgramHeader : DWRFObject @property uint64_t unitLength; // 4 bytes DWARF-32 / 12 bytes DWARF-64 @property uint16_t version; @property uint64_t headerLength; // 4 bytes DWARF-32 / 8 bytes DWARF-64 @property uint8_t minimumInstructionLength; @property uint8_t maximumOperationsPerInstruction; @property uint8_t defaultIsStmt; @property int8_t lineBase; @property uint8_t lineRange; @property int8_t opcodeBase; @property uint8_t * standardOpcodeLengths; // opcodeBase count @property NSMutableArray * includeDirectories; @property NSMutableArray * fileEntries; - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer; @end @implementation DWRFLineNumberProgramHeader - (instancetype)initWithBuffer:(uint8_t *)inBuffer outBuffer:(uint8_t **)outBuffer { if (inBuffer==NULL) return nil; self=[super init]; if (self!=nil) { uint32_t tUnsignedInteger; tUnsignedInteger=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); if (tUnsignedInteger==0xffffffff) { self.dwarfFormat=DWRF64Format; _unitLength=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); } else { _unitLength=tUnsignedInteger; } _version=*((uint16_t *)inBuffer); inBuffer+=sizeof(uint16_t); if (self.dwarfFormat==DWRF64Format) { _headerLength=*((uint64_t *)inBuffer); inBuffer+=sizeof(uint64_t); _headerLength+=18; } else { _headerLength=*((uint32_t *)inBuffer); inBuffer+=sizeof(uint32_t); _headerLength+=10; } _minimumInstructionLength=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); if (_version>=4) { _maximumOperationsPerInstruction=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); } else { _maximumOperationsPerInstruction=1; } _defaultIsStmt=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); _lineBase=*((int8_t *)inBuffer); inBuffer+=sizeof(int8_t); _lineRange=*((uint8_t *)inBuffer); inBuffer+=sizeof(uint8_t); _opcodeBase=*((int8_t *)inBuffer); inBuffer+=sizeof(int8_t); _standardOpcodeLengths=malloc(_opcodeBase*sizeof(uint8_t)); for(size_t tIndex=0;tIndex<(_opcodeBase-1);tIndex++) _standardOpcodeLengths[tIndex]=DWRF_readLEB128(inBuffer, &inBuffer); _includeDirectories=[NSMutableArray array]; while((*inBuffer)!=0) { size_t tLength=strlen((char *)inBuffer); NSString * tString=[NSString stringWithCString:(char *)inBuffer encoding:NSUTF8StringEncoding]; if (tString!=nil) [_includeDirectories addObject:tString]; inBuffer+=(tLength+1); } inBuffer++; _fileEntries=[NSMutableArray array]; while((*inBuffer)!=0) { DWRFLineNumberProgramHeaderFileNameEntry * tEntry=[DWRFLineNumberProgramHeaderFileNameEntry new]; size_t tLength=strlen((char *)inBuffer); NSString * tString=[NSString stringWithCString:(char *)inBuffer encoding:NSUTF8StringEncoding]; if (tString==nil) return nil; inBuffer+=(tLength+1); tEntry.filePath=tString; tEntry.directoryIndex=DWRF_readULEB128(inBuffer, &inBuffer); tEntry.lastModificationDate=DWRF_readULEB128(inBuffer, &inBuffer); tEntry.fileSize=DWRF_readULEB128(inBuffer, &inBuffer); [_fileEntries addObject:tEntry]; } inBuffer++; } if (outBuffer!=NULL) *outBuffer=inBuffer; return self; } @end @interface DWRFLineNumberProgram () { DWRFLineNumberProgramHeader * _header; uint8_t * _programBufferStart; uint8_t * _programBufferEnd; NSMutableArray * _locationsAddresses; NSMutableDictionary * _locationsRegistry; } - (instancetype)initWithBuffer:(uint8_t *)inBuffer; - (DWRFLineNumberProgramLocation *)locationFromStateMachine:(DWRFLineNumberProgramStateMachine *)inStateMachine; @end @implementation DWRFLineNumberProgram - (instancetype)initWithBuffer:(uint8_t *)inBuffer { if (inBuffer==NULL) return nil; self=[super init]; if (self!=nil) { uint8_t * tBuffer=inBuffer; _header=[[DWRFLineNumberProgramHeader alloc] initWithBuffer:tBuffer outBuffer:&tBuffer]; if (_header==nil) { NSLog(@"Error unarchiving Line Number Program Header"); return nil; } _programBufferStart=inBuffer+_header.headerLength; _programBufferEnd=inBuffer+_header.unitLength; } return self; } #pragma mark - - (NSString *)fileNameAtIndex:(NSUInteger)inIndex { if (inIndex>_header.fileEntries.count) return nil; DWRFLineNumberProgramHeaderFileNameEntry * tEntry=_header.fileEntries[inIndex-1]; return tEntry.filePath; } - (BOOL)runProgram { _locationsAddresses=[NSMutableArray array]; _locationsRegistry=[NSMutableDictionary dictionary]; DWRFLineNumberProgramStateMachine * tStateMachine=[[DWRFLineNumberProgramStateMachine alloc] initWithStmt:_header.defaultIsStmt]; BOOL tDone=NO; uint8_t * tBuffer=_programBufferStart; while (tBuffer<_programBufferEnd && tDone==NO) { uint8_t tOpcode=*tBuffer; tBuffer+=sizeof(uint8_t); if (tOpcode>=_header.opcodeBase) { // Special Opcode tOpcode-=_header.opcodeBase; uint8_t tOperationAdvance=tOpcode/_header.lineRange; tStateMachine.line+=_header.lineBase+ (tOpcode % _header.lineRange); tStateMachine.address+=_header.minimumInstructionLength*((tStateMachine.op_index+tOperationAdvance)/_header.maximumOperationsPerInstruction); tStateMachine.op_index=(tStateMachine.op_index+tOperationAdvance)%_header.maximumOperationsPerInstruction; tStateMachine.basic_block=NO; tStateMachine.prologue_end=NO; tStateMachine.epilogue_begin=NO; tStateMachine.discriminator=0; // Add a row to the matrix DWRFLineNumberProgramLocation * tLocation=[self locationFromStateMachine:tStateMachine]; NSNumber * tKey=@(tStateMachine.address); [_locationsAddresses addObject:tKey]; _locationsRegistry[tKey]=tLocation; continue; } if (tOpcode!=DW_LNS_extended_op) { // Standard Opcode switch(tOpcode) { case DW_LNS_copy: { DWRFLineNumberProgramLocation * tLocation=[self locationFromStateMachine:tStateMachine]; NSNumber * tKey=@(tStateMachine.address); [_locationsAddresses addObject:tKey]; _locationsRegistry[tKey]=tLocation; tStateMachine.discriminator=0; tStateMachine.basic_block=NO; tStateMachine.prologue_end=NO; tStateMachine.epilogue_begin=NO; break; } case DW_LNS_advance_pc: { uint64_t tOperationAdvance=DWRF_readULEB128(tBuffer, &tBuffer); tStateMachine.address+=_header.minimumInstructionLength*((tStateMachine.op_index+tOperationAdvance)/_header.maximumOperationsPerInstruction); tStateMachine.op_index=(tStateMachine.op_index+tOperationAdvance)%_header.maximumOperationsPerInstruction; break; } case DW_LNS_advance_line: tStateMachine.line+=DWRF_readLEB128(tBuffer, &tBuffer); break; case DW_LNS_set_file: tStateMachine.file=DWRF_readULEB128(tBuffer, &tBuffer); break; case DW_LNS_set_column: tStateMachine.column=DWRF_readULEB128(tBuffer, &tBuffer); break; case DW_LNS_negate_stmt: tStateMachine.is_stmt=!tStateMachine.is_stmt; break; case DW_LNS_set_basic_block: tStateMachine.basic_block=YES; break; case DW_LNS_const_add_pc: { uint64_t tOperationAdvance=(255 - _header.opcodeBase) / _header.lineRange; tStateMachine.address+=_header.minimumInstructionLength*((tStateMachine.op_index+tOperationAdvance)/_header.maximumOperationsPerInstruction); tStateMachine.op_index=(tStateMachine.op_index+tOperationAdvance)%_header.maximumOperationsPerInstruction; break; } case DW_LNS_fixed_advance_pc: { uint16_t tAdvance=*((uint16_t *)tBuffer); tBuffer+=sizeof(uint16_t); tStateMachine.address+=tAdvance; tStateMachine.op_index=0; break; } case DW_LNS_set_prologue_end: tStateMachine.prologue_end=YES; break; case DW_LNS_set_epilogue_begin: tStateMachine.epilogue_begin=YES; break; case DW_LNS_set_isa: tStateMachine.xisa=DWRF_readULEB128(tBuffer, &tBuffer); break; default: { // Unsupported standard opcode uint8_t tArgumentsCount=_header.standardOpcodeLengths[tOpcode-1]; while(tArgumentsCount>0) { DWRF_readULEB128(tBuffer, &tBuffer); tArgumentsCount--; } break; } } continue; } // Extended Opcode uint64_t tLength=DWRF_readULEB128(tBuffer, &tBuffer); if (tLength==0) { NSLog(@"Unexpected 0 value for extended opcode length"); } uint8_t tExtendedOpcode=*tBuffer; tBuffer+=sizeof(uint8_t); tLength-=1; switch(tExtendedOpcode) { case DW_LNE_end_sequence: { tStateMachine.end_sequence=YES; // Add a row to the matrix DWRFLineNumberProgramLocation * tLocation=[self locationFromStateMachine:tStateMachine]; NSNumber * tKey=@(tStateMachine.address); [_locationsAddresses addObject:tKey]; _locationsRegistry[tKey]=tLocation; tStateMachine=[[DWRFLineNumberProgramStateMachine alloc] initWithStmt:_header.defaultIsStmt]; break; } case DW_LNE_set_address: { if (tLength==4) // 32 bits { tStateMachine.address=*((uint32_t *)tBuffer); tBuffer+=sizeof(uint32_t); } else // 64 bits { tStateMachine.address=*((uint64_t *)tBuffer); tBuffer+=sizeof(uint64_t); } tStateMachine.op_index=0; break; } case DW_LNE_define_file: { DWRFLineNumberProgramHeaderFileNameEntry * tFileNameEntry=[DWRFLineNumberProgramHeaderFileNameEntry new]; tFileNameEntry.filePath=[NSString stringWithUTF8String:(const char *)tBuffer]; tFileNameEntry.directoryIndex=DWRF_readULEB128(tBuffer, &tBuffer); tFileNameEntry.lastModificationDate=DWRF_readULEB128(tBuffer, &tBuffer); tFileNameEntry.fileSize=DWRF_readULEB128(tBuffer, &tBuffer); [_header.fileEntries addObject:tFileNameEntry]; break; } case DW_LNE_set_discriminator: tStateMachine.discriminator=DWRF_readULEB128(tBuffer, &tBuffer); break; default: // Unsupported Extended opcode tBuffer+=tLength; break; } } return YES; } - (DWRFLineNumberProgramLocation *)locationForMachineInstructionAddress:(uint64_t)inMachineInstructionAddress { if (_locationsAddresses==nil) { // We need to build the list of addresses first if ([self runProgram]==NO) return nil; } if (_locationsAddresses.count==0) return nil; NSNumber * tKey=_locationsAddresses.firstObject; if (inMachineInstructionAddress<[tKey unsignedLongValue]) return nil; for(NSNumber * tLocationAddressNumber in _locationsAddresses) { uint64_t tLocationAddress=[tLocationAddressNumber unsignedLongValue]; if (inMachineInstructionAddress * _cachedLineNumberPrograms; } @end @implementation DWRFSection_debug_line - (instancetype)initWithData:(NSData *)inData { if (inData==nil) return nil; self=[super init]; if (self!=nil) { _cachedData=inData; _cachedLineNumberPrograms=[NSMutableDictionary dictionary]; } return self; } #pragma mark - - (DWRFLineNumberProgram *)lineNumberProgramAtOffset:(uint64_t)inOffset { DWRFLineNumberProgram * tLineNumberProgram=_cachedLineNumberPrograms[@(inOffset)]; if (tLineNumberProgram!=nil) return tLineNumberProgram; uint8_t * tBufferPtr=(uint8_t *)_cachedData.bytes; tLineNumberProgram=[[DWRFLineNumberProgram alloc] initWithBuffer:tBufferPtr+inOffset /*fileObject:self.fileObject outBuffer:&tBufferPtr*/]; if (tLineNumberProgram!=nil) _cachedLineNumberPrograms[@(inOffset)]=tLineNumberProgram; return tLineNumberProgram; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_str.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface DWRFSection_debug_str : NSObject - (instancetype)initWithData:(NSData *)inData; - (NSString *)stringAtOffset:(uint64_t)inOffset; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_str.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFSection_debug_str.h" @interface DWRFSection_debug_str () { NSMutableDictionary * _cachedStrings; NSData * _cachedData; } @end @implementation DWRFSection_debug_str - (instancetype)initWithData:(NSData *)inData { self=[super init]; if (self!=nil) { _cachedData=inData; _cachedStrings=[NSMutableDictionary dictionary]; } return self; } #pragma mark - - (NSString *)stringAtOffset:(uint64_t)inOffset { NSString * tString=_cachedStrings[@(inOffset)]; if (tString!=nil) return tString; uint8_t * tBufferPtr=(uint8_t *)_cachedData.bytes; tString=[NSString stringWithCString:(const char *)tBufferPtr+inOffset encoding:NSASCIIStringEncoding]; if (tString!=nil) _cachedStrings[@(inOffset)]=tString; return tString; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_str_offsets.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "DWRFObject.h" @interface DWRFSection_debug_str_offsets : NSObject - (instancetype)initWithData:(NSData *)inData; - (uint64_t)offsetAtIndex:(uint64_t)inIndex base:(uint64_t)inBase format:(DWRFFormat)inFormat; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/DWRFSection_debug_str_offsets.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "DWRFSection_debug_str_offsets.h" @interface DWRFSection_debug_str_offsets () { NSData * _cachedData; } @end @implementation DWRFSection_debug_str_offsets - (instancetype)initWithData:(NSData *)inData { self=[super init]; if (self!=nil) { _cachedData=inData; } return self; } #pragma mark - - (uint64_t)offsetAtIndex:(uint64_t)inIndex base:(uint64_t)inBase format:(DWRFFormat)inFormat { uint8_t * tBytes=(uint8_t *)_cachedData.bytes; tBytes+=inBase; uint64_t tOffset=0; if (inFormat==DWRF64Format) { tBytes+=(inIndex*sizeof(uint64_t)); tOffset=*((uint64_t *)tBytes); } else { tBytes+=(inIndex*sizeof(uint32_t)); tOffset=*((uint32_t *)tBytes); } return tOffset; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/LEB128.c ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "LEB128.h" uint64_t DWRF_readULEB128(uint8_t * inBufferPtr,uint8_t ** outBufferPtr) { uint64_t tResult=0; int64_t tShift=0; while(1) { uint8_t tByte=*inBufferPtr; inBufferPtr++; if (tByte < 0x80) { tResult += (uint64_t)tByte << tShift; break; } tResult += (tByte & 0x7f) << tShift; tShift += 7; } if (outBufferPtr!=NULL) *outBufferPtr=inBufferPtr; return tResult; } int64_t DWRF_readLEB128(uint8_t * inBufferPtr,uint8_t ** outBufferPtr) { int64_t tResult=0; int64_t tShift=0; while(1) { uint8_t tByte=*inBufferPtr; inBufferPtr++; if (tByte < 0x80) { if (tByte & 0x40) tResult -= (0x80 - tByte) << tShift; else tResult += (tByte & 0x3f) << tShift; break; } tResult += (tByte & 0x7f) << tShift; tShift += 7; } if (outBufferPtr!=NULL) *outBufferPtr=inBufferPtr; return tResult; } ================================================ FILE: app_unexpectedly/app_unexpectedly/DWARF/LEB128.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LEB128_h #define LEB128_h #include #include uint64_t DWRF_readULEB128(uint8_t * inBufferPtr,uint8_t ** outBufferPtr); int64_t DWRF_readLEB128(uint8_t * inBufferPtr,uint8_t ** outBufferPtr); #endif ================================================ FILE: app_unexpectedly/app_unexpectedly/Demangling/CUICXXDemangler.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUICXXDemangler : NSObject + (NSString *)demangle:(NSString *)inMangledName; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Demangling/CUICXXDemangler.mm ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUICXXDemangler.h" #include @implementation CUICXXDemangler + (NSString *)demangle:(NSString *)inMangledName { if (inMangledName==nil) return nil; int tStatus=0; char * tBuffer=abi::__cxa_demangle(inMangledName.UTF8String,NULL,0,&tStatus); if (tBuffer==NULL) return nil; NSString * tDemangledName=[NSString stringWithUTF8String:tBuffer]; free(tBuffer); return tDemangledName; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Demangling/CUISwiftDemangler.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface CUISwiftDemangler : NSObject + (NSString *)demangle:(NSString *)inMangledName; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Demangling/CUISwiftDemangler.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUISwiftDemangler.h" #include /*size_t (*swift_demangle_getDemangledName)(const char *MangledName, char *OutputBuffer, size_t Length);*/ size_t (*swift_demangle_getSimplifiedDemangledName)(const char *MangledName, char *OutputBuffer, size_t Length); /*size_t (*swift_demangle_getModuleName)(const char *MangledName, char *OutputBuffer, size_t Length);*/ /*int (*swift_demangle_hasSwiftCallingConvention)(const char *MangledName);*/ @implementation CUISwiftDemangler + (NSString *)demangle:(NSString *)inMangledName { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ void * tFileHandle= dlopen("/usr/lib/swift/libswiftDemangle.dylib", RTLD_LAZY); if (tFileHandle==NULL) { tFileHandle= dlopen("/System/Library/PrivateFrameworks/Swift/libswiftDemangle.dylib", RTLD_LAZY); if (tFileHandle==NULL) { } } swift_demangle_getSimplifiedDemangledName=dlsym(tFileHandle,"swift_demangle_getSimplifiedDemangledName"); }); char tBuffer[2048]; if (swift_demangle_getSimplifiedDemangledName(inMangledName.UTF8String,tBuffer,2048)==0) return nil; NSString * tDemangledName=[NSString stringWithUTF8String:tBuffer]; return tDemangledName; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Controller.h ================================================ // // Controller.h // Line View Test // // Created by Paul Kim on 9/28/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // #import @class NoodleLineNumberView; @interface Controller : NSObject { IBOutlet NSScrollView *scrollView; IBOutlet NSTextView *scriptView; NoodleLineNumberView *lineNumberView; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Controller.m ================================================ // // Controller.m // Line View Test // // Created by Paul Kim on 9/28/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // #import "Controller.h" #import "NoodleLineNumberView.h" #import "NoodleLineNumberMarker.h" #import "MarkerLineNumberView.h" @implementation Controller - (void)awakeFromNib { lineNumberView = [[MarkerLineNumberView alloc] initWithScrollView:scrollView]; [scrollView setVerticalRulerView:lineNumberView]; [scrollView setHasHorizontalRuler:NO]; [scrollView setHasVerticalRuler:YES]; [scrollView setRulersVisible:YES]; [scriptView setFont:[NSFont userFixedPitchFontOfSize:[NSFont smallSystemFontSize]]]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/English.lproj/MainMenu.nib/designable.nib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Info.plist ================================================ CFBundleDevelopmentRegion English CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier com.yourcompany.${PRODUCT_NAME:identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 0.4.1 NSMainNibFile MainMenu NSPrincipalClass NSApplication NSHumanReadableCopyright Copyright © 2008, Noodlesoft, LLC. All rights reserved. ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Line View Test.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 44; objects = { /* Begin PBXBuildFile section */ 324EF09D0E996FBC00E81846 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 324EF0950E996FBC00E81846 /* Controller.m */; }; 324EF09E0E996FBC00E81846 /* MarkerLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 324EF0980E996FBC00E81846 /* MarkerLineNumberView.m */; }; 324EF09F0E996FBC00E81846 /* NoodleLineNumberMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 324EF09A0E996FBC00E81846 /* NoodleLineNumberMarker.m */; }; 324EF0A00E996FBC00E81846 /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 324EF09C0E996FBC00E81846 /* NoodleLineNumberView.m */; }; 324EF0A30E996FD100E81846 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 324EF0A10E996FD100E81846 /* MainMenu.nib */; }; 324EF0AA0E99700D00E81846 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 324EF0A90E99700D00E81846 /* Credits.rtf */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 324EF0950E996FBC00E81846 /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = ""; }; 324EF0960E996FBC00E81846 /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = ""; }; 324EF0970E996FBC00E81846 /* MarkerLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkerLineNumberView.h; sourceTree = ""; }; 324EF0980E996FBC00E81846 /* MarkerLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MarkerLineNumberView.m; sourceTree = ""; }; 324EF0990E996FBC00E81846 /* NoodleLineNumberMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleLineNumberMarker.h; sourceTree = ""; }; 324EF09A0E996FBC00E81846 /* NoodleLineNumberMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleLineNumberMarker.m; sourceTree = ""; }; 324EF09B0E996FBC00E81846 /* NoodleLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleLineNumberView.h; sourceTree = ""; }; 324EF09C0E996FBC00E81846 /* NoodleLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleLineNumberView.m; sourceTree = ""; }; 324EF0A20E996FD100E81846 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = ""; }; 324EF0A90E99700D00E81846 /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = ""; }; 32CA4F630368D1EE00C91783 /* Line View Test_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Line View Test_Prefix.pch"; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8D1107320486CEB800E47090 /* Line View Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Line View Test.app"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8D11072E0486CEB800E47090 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( 324EF0960E996FBC00E81846 /* Controller.h */, 324EF0950E996FBC00E81846 /* Controller.m */, 324EF0970E996FBC00E81846 /* MarkerLineNumberView.h */, 324EF0980E996FBC00E81846 /* MarkerLineNumberView.m */, 324EF0990E996FBC00E81846 /* NoodleLineNumberMarker.h */, 324EF09A0E996FBC00E81846 /* NoodleLineNumberMarker.m */, 324EF09B0E996FBC00E81846 /* NoodleLineNumberView.h */, 324EF09C0E996FBC00E81846 /* NoodleLineNumberView.m */, ); name = Classes; sourceTree = ""; }; 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { isa = PBXGroup; children = ( 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, ); name = "Linked Frameworks"; sourceTree = ""; }; 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { isa = PBXGroup; children = ( 29B97324FDCFA39411CA2CEA /* AppKit.framework */, 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, 29B97325FDCFA39411CA2CEA /* Foundation.framework */, ); name = "Other Frameworks"; sourceTree = ""; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( 8D1107320486CEB800E47090 /* Line View Test.app */, ); name = Products; sourceTree = ""; }; 29B97314FDCFA39411CA2CEA /* Line View Test */ = { isa = PBXGroup; children = ( 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, ); name = "Line View Test"; sourceTree = ""; }; 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( 32CA4F630368D1EE00C91783 /* Line View Test_Prefix.pch */, 29B97316FDCFA39411CA2CEA /* main.m */, ); name = "Other Sources"; sourceTree = ""; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( 324EF0A90E99700D00E81846 /* Credits.rtf */, 8D1107310486CEB800E47090 /* Info.plist */, 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, 324EF0A10E996FD100E81846 /* MainMenu.nib */, ); name = Resources; sourceTree = ""; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 8D1107260486CEB800E47090 /* Line View Test */ = { isa = PBXNativeTarget; buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Line View Test" */; buildPhases = ( 8D1107290486CEB800E47090 /* Resources */, 8D11072C0486CEB800E47090 /* Sources */, 8D11072E0486CEB800E47090 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = "Line View Test"; productInstallPath = "$(HOME)/Applications"; productName = "Line View Test"; productReference = 8D1107320486CEB800E47090 /* Line View Test.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Line View Test" */; compatibilityVersion = "Xcode 3.0"; developmentRegion = en; hasScannedForEncodings = 1; knownRegions = ( en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* Line View Test */; projectDirPath = ""; projectRoot = ""; targets = ( 8D1107260486CEB800E47090 /* Line View Test */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 8D1107290486CEB800E47090 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, 324EF0A30E996FD100E81846 /* MainMenu.nib in Resources */, 324EF0AA0E99700D00E81846 /* Credits.rtf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 8D11072C0486CEB800E47090 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8D11072D0486CEB800E47090 /* main.m in Sources */, 324EF09D0E996FBC00E81846 /* Controller.m in Sources */, 324EF09E0E996FBC00E81846 /* MarkerLineNumberView.m in Sources */, 324EF09F0E996FBC00E81846 /* NoodleLineNumberMarker.m in Sources */, 324EF0A00E996FBC00E81846 /* NoodleLineNumberView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 089C165DFE840E0CC02AAC07 /* English */, ); name = InfoPlist.strings; sourceTree = ""; }; 324EF0A10E996FD100E81846 /* MainMenu.nib */ = { isa = PBXVariantGroup; children = ( 324EF0A20E996FD100E81846 /* English */, ); name = MainMenu.nib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Line View Test_Prefix.pch"; INFOPLIST_FILE = Info.plist; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = "Line View Test"; }; name = Debug; }; C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Line View Test_Prefix.pch"; INFOPLIST_FILE = Info.plist; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = "Line View Test"; }; name = Release; }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(NATIVE_ARCH_ACTUAL)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; SDKROOT = macosx; WARNING_CFLAGS = "-Wall"; }; name = Debug; }; C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(NATIVE_ARCH_ACTUAL)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; PREBINDING = NO; SDKROOT = macosx; WARNING_CFLAGS = "-Wall"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Line View Test" */ = { isa = XCConfigurationList; buildConfigurations = ( C01FCF4B08A954540054247B /* Debug */, C01FCF4C08A954540054247B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Line View Test" */ = { isa = XCConfigurationList; buildConfigurations = ( C01FCF4F08A954540054247B /* Debug */, C01FCF5008A954540054247B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; } ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Line View Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Line View Test.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Line View Test_Prefix.pch ================================================ // // Prefix header for all source files of the 'Line View Test' target in the 'Line View Test' project // #ifdef __OBJC__ #import #endif ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/MarkerLineNumberView.h ================================================ // // MarkerTextView.h // Line View Test // // Created by Paul Kim on 10/4/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // #import #import "NoodleLineNumberView.h" @interface MarkerLineNumberView : NoodleLineNumberView { NSImage *markerImage; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/MarkerLineNumberView.m ================================================ // // MarkerTextView.m // Line View Test // // Created by Paul Kim on 10/4/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // #import "MarkerLineNumberView.h" #import "NoodleLineNumberMarker.h" #define CORNER_RADIUS 3.0 #define MARKER_HEIGHT 13.0 @implementation MarkerLineNumberView - (void)dealloc { [markerImage release]; [super dealloc]; } - (void)setRuleThickness:(float)thickness { [super setRuleThickness:thickness]; // Overridden to reset the size of the marker image forcing it to redraw with the new width. // If doing this in a non-subclass of NoodleLineNumberView, you can set it to post frame // notifications and listen for them. [markerImage setSize:NSMakeSize(thickness, MARKER_HEIGHT)]; } - (void)drawMarkerImageIntoRep:(id)rep { NSBezierPath *path; NSRect rect; rect = NSMakeRect(1.0, 2.0, [rep size].width - 2.0, [rep size].height - 3.0); path = [NSBezierPath bezierPath]; [path moveToPoint:NSMakePoint(NSMaxX(rect), NSMinY(rect) + NSHeight(rect) / 2)]; [path lineToPoint:NSMakePoint(NSMaxX(rect) - 5.0, NSMaxY(rect))]; [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect) + CORNER_RADIUS, NSMaxY(rect) - CORNER_RADIUS) radius:CORNER_RADIUS startAngle:90 endAngle:180]; [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect) + CORNER_RADIUS, NSMinY(rect) + CORNER_RADIUS) radius:CORNER_RADIUS startAngle:180 endAngle:270]; [path lineToPoint:NSMakePoint(NSMaxX(rect) - 5.0, NSMinY(rect))]; [path closePath]; [[NSColor colorWithCalibratedRed:0.003 green:0.56 blue:0.85 alpha:1.0] set]; [path fill]; [[NSColor colorWithCalibratedRed:0 green:0.44 blue:0.8 alpha:1.0] set]; [path setLineWidth:2.0]; [path stroke]; } - (NSImage *)markerImageWithSize:(NSSize)size { if (markerImage == nil) { NSCustomImageRep *rep; markerImage = [[NSImage alloc] initWithSize:size]; rep = [[NSCustomImageRep alloc] initWithDrawSelector:@selector(drawMarkerImageIntoRep:) delegate:self]; [rep setSize:size]; [markerImage addRepresentation:rep]; [rep release]; } return markerImage; } - (void)mouseDown:(NSEvent *)theEvent { NSPoint location; unsigned line; location = [self convertPoint:[theEvent locationInWindow] fromView:nil]; line = [self lineNumberForLocation:location.y]; if (line != NSNotFound) { NoodleLineNumberMarker *marker; marker = [self markerAtLine:line]; if (marker != nil) { [self removeMarker:marker]; } else { marker = [[NoodleLineNumberMarker alloc] initWithRulerView:self lineNumber:line image:[self markerImageWithSize:NSMakeSize([self ruleThickness], MARKER_HEIGHT)] imageOrigin:NSMakePoint(0, MARKER_HEIGHT / 2)]; [self addMarker:marker]; [marker release]; } [self setNeedsDisplay:YES]; } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/NoodleLineNumberMarker.h ================================================ // // NoodleLineNumberMarker.h // Line View Test // // Created by Paul Kim on 9/30/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Converted to Objective-C 2.x by Stephane Sudre #import @interface NoodleLineNumberMarker : NSRulerMarker @property NSUInteger lineNumber; - (instancetype)initWithRulerView:(NSRulerView *)inRulerView lineNumber:(NSUInteger)inLineNumber image:(NSImage *)inImage imageOrigin:(NSPoint)inImageOrigin; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/NoodleLineNumberMarker.m ================================================ // // NoodleLineNumberMarker.m // Line View Test // // Created by Paul Kim on 9/30/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Converted to Objective-C 2.x by Stephane Sudre #import "NoodleLineNumberMarker.h" NSString * const NOODLE_LINE_CODING_KEY=@"line"; @implementation NoodleLineNumberMarker - (instancetype)initWithRulerView:(NSRulerView *)inRulerView lineNumber:(NSUInteger)inLineNumber image:(NSImage *)inImage imageOrigin:(NSPoint)inImageOrigin { self = [super initWithRulerView:inRulerView markerLocation:0.0 image:inImage imageOrigin:inImageOrigin]; if (self != nil) { _lineNumber = inLineNumber; } return self; } #pragma mark - NSCoding - (id)initWithCoder:(NSCoder *)decoder { self = [super initWithCoder:decoder]; if (self != nil) { if ([decoder allowsKeyedCoding]==YES) { _lineNumber = [[decoder decodeObjectForKey:NOODLE_LINE_CODING_KEY] unsignedIntegerValue]; } else { _lineNumber = [[decoder decodeObject] unsignedIntegerValue]; } } return self; } - (void)encodeWithCoder:(NSCoder *)encoder { [super encodeWithCoder:encoder]; if ([encoder allowsKeyedCoding]==YES) { [encoder encodeObject:@(self.lineNumber) forKey:NOODLE_LINE_CODING_KEY]; } else { [encoder encodeObject:@(self.lineNumber)]; } } #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { NoodleLineNumberMarker * nMarker=[super copyWithZone:zone]; nMarker.lineNumber=self.lineNumber; return nMarker; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/NoodleLineNumberView.h ================================================ // // NoodleLineNumberView.h // Line View Test // // Created by Paul Kim on 9/28/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Converted to Objective-C 2.x by Stephane Sudre #import @class NoodleLineNumberMarker; @interface NoodleLineNumberView : NSRulerView @property (nonatomic) CGFloat fontSizeDelta; @property (nonatomic) NSFont * font; @property (nonatomic) NSColor * textColor; @property (nonatomic) NSColor * alternateTextColor; @property (nonatomic) NSColor * backgroundColor; - (instancetype)initWithScrollView:(NSScrollView *)inScrollView; - (NSUInteger)lineNumberForLocation:(CGFloat)inLocation; - (NoodleLineNumberMarker *)markerAtLine:(NSUInteger)inLineNumber; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/NoodleLineNumberView.m ================================================ // // NoodleLineNumberView.m // Line View Test // // Created by Paul Kim on 9/28/08. // Copyright (c) 2008 Noodlesoft, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Converted to Objective-C 2.x by Stephane Sudre #import "NoodleLineNumberView.h" #import "NoodleLineNumberMarker.h" #define DEFAULT_THICKNESS 22.0 #define RULER_MARGIN 5.0 @interface NoodleLineNumberView () { NSMutableArray * lineIndices; // Array of character indices for the beginning of each line NSMutableDictionary * _linesToMarkers; // Maps line numbers to markers } - (NSMutableArray *)lineIndices; - (void)invalidateLineIndices; - (void)calculateLines; - (NSUInteger)lineNumberForCharacterIndex:(NSUInteger)index inText:(NSString *)text; - (NSDictionary *)textAttributes; - (NSDictionary *)markerTextAttributes; @end @implementation NoodleLineNumberView - (id)initWithScrollView:(NSScrollView *)inScrollView { self = [super initWithScrollView:inScrollView orientation:NSVerticalRuler]; if (self != nil) { _linesToMarkers = [NSMutableDictionary dictionary]; [self setClientView:inScrollView.documentView]; } return self; } - (void)awakeFromNib { _linesToMarkers = [NSMutableDictionary dictionary]; [self setClientView:self.scrollView.documentView]; } - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } #pragma mark - - (void)setFontSizeDelta:(CGFloat)inFontSizeDelta { if (inFontSizeDelta>0) { _fontSizeDelta=0; } else { if (_fontSizeDelta>-5) { _fontSizeDelta=inFontSizeDelta; } } } - (NSFont *)font { if (_font == nil) return [NSFont labelFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeMini]]; return _font; } - (NSColor *)textColor { if (_textColor == nil) return [NSColor colorWithCalibratedWhite:0.42 alpha:1.0]; return _textColor; } - (NSColor *)alternateTextColor { if (_alternateTextColor == nil) return [NSColor whiteColor]; return _alternateTextColor; } - (BOOL)clipsToBounds { return YES; } - (BOOL)isOpaque { return YES; } #pragma mark - - (void)setClientView:(NSView *)inClientView { NSNotificationCenter *tNotificationCenter = NSNotificationCenter.defaultCenter; [tNotificationCenter removeObserver:self name:NSTextStorageDidProcessEditingNotification object:nil]; super.clientView = inClientView; if ([inClientView isKindOfClass:[NSTextView class]]==YES) { NSTextStorage *textStorage = ((NSTextView *)inClientView).textStorage; [tNotificationCenter addObserver:self selector:@selector(clientTextStorageDidProcessEditing:) name:NSTextStorageDidProcessEditingNotification object:textStorage]; [self invalidateLineIndices]; } } - (NSMutableArray *)lineIndices { if (lineIndices == nil) [self calculateLines]; return lineIndices; } - (void)invalidateLineIndices { lineIndices = nil; } - (NSUInteger)lineNumberForLocation:(CGFloat)inLocation { NSTextView * tTextView = (NSTextView *)self.clientView; if ([tTextView isKindOfClass:[NSTextView class]]==NO) return NSNotFound; NSRect tVisibleRect = [self scrollView].contentView.bounds; inLocation += NSMinY(tVisibleRect); NSRange nullRange = NSMakeRange(NSNotFound, 0); NSLayoutManager * tLayoutManager = tTextView.layoutManager; NSTextContainer * tTextContainter = tTextView.textContainer; NSMutableArray * tLineIndices = [self lineIndices]; NSUInteger tCount = tLineIndices.count; for (NSUInteger tLine = 0; tLine < tCount; tLine++) { NSUInteger index = [tLineIndices[tLine] unsignedIntValue]; NSUInteger tRectCount; NSRectArray tRects = [tLayoutManager rectArrayForCharacterRange:NSMakeRange(index, 0) withinSelectedCharacterRange:nullRange inTextContainer:tTextContainter rectCount:&tRectCount]; for (NSUInteger tIndex = 0; tIndex < tRectCount; tIndex++) { NSRect tRect=tRects[tIndex]; if ((inLocation >= NSMinY(tRect)) && (inLocation < NSMaxY(tRect))) return tLine + 1; } } return NSNotFound; } - (NoodleLineNumberMarker *)markerAtLine:(NSUInteger)inLine { return _linesToMarkers[@(inLine - 1)]; } - (void)calculateLines { NSTextView * tTextView=(NSTextView *)[self clientView]; if ([tTextView isKindOfClass:[NSTextView class]]==NO) return; NSUInteger lineEnd, contentEnd; NSString *text = tTextView.string; NSUInteger stringLength = text.length; lineIndices = [NSMutableArray array]; NSUInteger index = 0; NSUInteger numberOfLines = 0; do { [lineIndices addObject:@(index)]; index = NSMaxRange([text lineRangeForRange:NSMakeRange(index, 0)]); numberOfLines++; } while (index < stringLength); // Check if text ends with a new line. [text getLineStart:NULL end:&lineEnd contentsEnd:&contentEnd forRange:NSMakeRange([lineIndices.lastObject unsignedIntValue], 0)]; if (contentEnd < lineEnd) { [lineIndices addObject:@(index)]; } CGFloat oldThickness = self.ruleThickness; CGFloat newThickness = self.requiredThickness; if (fabs(oldThickness - newThickness) > 1) { /*// Not a good idea to resize the view during calculations (which can happen during // display). Do a delayed perform (using NSInvocation since arg is a float). dispatch_async(dispatch_get_main_queue(), ^{*/ self.ruleThickness=newThickness; /*});*/ } } - (NSUInteger)lineNumberForCharacterIndex:(NSUInteger)index inText:(NSString *)text { NSMutableArray * tLineIndices = [self lineIndices]; // Binary search NSUInteger left = 0; NSUInteger right = tLineIndices.count; while ((right - left) > 1) { NSUInteger mid = (right + left) / 2; NSUInteger lineStart = [tLineIndices[mid] unsignedIntValue]; if (index < lineStart) { right = mid; } else if (index > lineStart) { left = mid; } else { return mid; } } return left; } - (NSDictionary *)textAttributes { NSFont * tFont=self.font; NSFont * tAdjustedFont=nil; if (_fontSizeDelta<0) { tAdjustedFont=[[NSFontManager sharedFontManager] convertFont:tFont toSize:tFont.pointSize + _fontSizeDelta]; } if (tAdjustedFont==nil) tAdjustedFont=tFont; static NSParagraphStyle * sLeftAlignedStyle=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSMutableParagraphStyle *mutableStyle=[[NSParagraphStyle defaultParagraphStyle] mutableCopy]; mutableStyle.alignment=NSTextAlignmentLeft; sLeftAlignedStyle = [mutableStyle copy]; }); return @{ NSFontAttributeName:tAdjustedFont, NSForegroundColorAttributeName:self.textColor, NSWritingDirectionAttributeName:@[@(NSWritingDirectionLeftToRight)], NSParagraphStyleAttributeName:sLeftAlignedStyle }; } - (NSDictionary *)markerTextAttributes { return @{ NSFontAttributeName:self.font, NSForegroundColorAttributeName:self.alternateTextColor }; } - (CGFloat)requiredThickness { NSUInteger lineCount = [self lineIndices].count; NSUInteger digits = (NSUInteger)log10(lineCount) + 1; if (digits<4) digits=4; NSMutableString * sampleString = [NSMutableString string]; for (NSUInteger i = 0; i < digits; i++) { // Use "8" since it is one of the fatter numbers. Anything but "1" // will probably be ok here. I could be pedantic and actually find the fattest // number for the current font but nah. [sampleString appendString:@"8"]; } NSDictionary * tAttributes=@{NSFontAttributeName:self.font}; NSSize stringSize = [sampleString sizeWithAttributes:tAttributes]; // Round up the value. There is a bug on 10.4 where the display gets all wonky when scrolling if you don't // return an integral value here. return ceilf(MAX(DEFAULT_THICKNESS, stringSize.width + RULER_MARGIN * 2)); } #pragma mark - Drawing - (void)viewWillDraw { [super viewWillDraw]; if (lineIndices == nil) [self calculateLines]; } - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; } - (void)drawSeparatorInRect:(NSRect)inRect { } - (void)drawHashMarksAndLabelsInRect:(NSRect)aRect { NSRect bounds = [self bounds]; if (self.backgroundColor != nil) { [self.backgroundColor set]; NSRectFill(aRect); } NSTextView * tTextView =(NSTextView *) self.clientView; if ([tTextView isKindOfClass:[NSTextView class]]==NO) return; NSRect markerRect; NSString *labelText; NSUInteger line; CGFloat ypos; NSDictionary *currentTextAttributes; NSLayoutManager *layoutManager = tTextView.layoutManager; NSTextContainer *container = tTextView.textContainer; NSString * text = tTextView.string; NSRange nullRange = NSMakeRange(NSNotFound, 0); CGFloat yinset = 6;//[tTextView textContainerInset].height; NSRect visibleRect = [self scrollView].contentView.bounds; NSDictionary * textAttributes = [self textAttributes]; NSMutableArray * lines = [self lineIndices]; // Find the characters that are currently visible NSRange glyphRange = [layoutManager glyphRangeForBoundingRect:visibleRect inTextContainer:container]; NSRange range = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; // Fudge the range a tad in case there is an extra new line at end. // It doesn't show up in the glyphs so would not be accounted for. range.length++; NSUInteger count = lines.count; NSUInteger index = 0; for (line = [self lineNumberForCharacterIndex:range.location inText:text]; line < count; line++) { index = [lines[line] unsignedIntValue]; if (NSLocationInRange(index, range)) { NSUInteger rectCount; NSRectArray rects = [layoutManager rectArrayForCharacterRange:NSMakeRange(index, 0) withinSelectedCharacterRange:nullRange inTextContainer:container rectCount:&rectCount]; if (rectCount > 0) { // Note that the ruler view is only as tall as the visible // portion. Need to compensate for the clipview's coordinates. ypos = yinset + NSMinY(rects[0]) - NSMinY(visibleRect); NoodleLineNumberMarker * tMarker = _linesToMarkers[@(line)]; if (tMarker != nil) { NSImage * markerImage = tMarker.image; NSSize markerSize = markerImage.size; markerRect = NSMakeRect(0.0, 0.0, markerSize.width, markerSize.height); // Marker is flush right and centered vertically within the line. markerRect.origin.x = NSWidth(bounds) - markerSize.width - 1.0; markerRect.origin.y = ypos + NSHeight(rects[0]) / 2.0 - tMarker.imageOrigin.y; [markerImage drawInRect:markerRect fromRect:NSMakeRect(0, 0, markerSize.width, markerSize.height) operation:NSCompositingOperationSourceOver fraction:1.0]; } // Line numbers are internally stored starting at 0 labelText = [NSString stringWithFormat:@"%lu", line + 1]; NSSize stringSize = [labelText sizeWithAttributes:textAttributes]; if (tMarker == nil) { currentTextAttributes = textAttributes; } else { currentTextAttributes = [self markerTextAttributes]; } // Draw string flush right, centered vertically within the line [labelText drawInRect:NSMakeRect(NSWidth(bounds) - stringSize.width - RULER_MARGIN,ypos + (NSHeight(rects[0]) - stringSize.height) / 2.0,NSWidth(bounds) - RULER_MARGIN * 2.0, NSHeight(rects[0])) withAttributes:currentTextAttributes]; } } if (index > NSMaxRange(range)) break; } } #pragma mark - Markers - (void)setMarkers:(NSArray *)inMarkers { [_linesToMarkers removeAllObjects]; [super setMarkers:nil]; for(NSRulerMarker * tMarker in inMarkers) [self addMarker:tMarker]; } - (void)addMarker:(NSRulerMarker *)inMarker { if ([inMarker isKindOfClass:[NoodleLineNumberMarker class]]==YES) { _linesToMarkers[@([(NoodleLineNumberMarker *)inMarker lineNumber] - 1)]=inMarker; } else { [super addMarker:inMarker]; } } - (void)removeMarker:(NSRulerMarker *)aMarker { if ([aMarker isKindOfClass:[NoodleLineNumberMarker class]]) { [_linesToMarkers removeObjectForKey:@([(NoodleLineNumberMarker *)aMarker lineNumber] - 1)]; } else { [super removeMarker:aMarker]; } } #pragma mark - NSCoding #define NOODLE_FONT_CODING_KEY @"font" #define NOODLE_TEXT_COLOR_CODING_KEY @"textColor" #define NOODLE_ALT_TEXT_COLOR_CODING_KEY @"alternateTextColor" #define NOODLE_BACKGROUND_COLOR_CODING_KEY @"backgroundColor" - (id)initWithCoder:(NSCoder *)decoder { if ((self = [super initWithCoder:decoder]) != nil) { if ([decoder allowsKeyedCoding]) { self.font = [decoder decodeObjectForKey:NOODLE_FONT_CODING_KEY]; self.textColor = [decoder decodeObjectForKey:NOODLE_TEXT_COLOR_CODING_KEY]; self.alternateTextColor = [decoder decodeObjectForKey:NOODLE_ALT_TEXT_COLOR_CODING_KEY]; _backgroundColor = [decoder decodeObjectForKey:NOODLE_BACKGROUND_COLOR_CODING_KEY]; } else { self.font = [decoder decodeObject]; self.textColor = [decoder decodeObject]; self.alternateTextColor = [decoder decodeObject]; _backgroundColor = [decoder decodeObject]; } _linesToMarkers = [NSMutableDictionary dictionary]; } return self; } - (void)encodeWithCoder:(NSCoder *)encoder { [super encodeWithCoder:encoder]; if ([encoder allowsKeyedCoding]) { [encoder encodeObject:self.font forKey:NOODLE_FONT_CODING_KEY]; [encoder encodeObject:self.textColor forKey:NOODLE_TEXT_COLOR_CODING_KEY]; [encoder encodeObject:self.alternateTextColor forKey:NOODLE_ALT_TEXT_COLOR_CODING_KEY]; [encoder encodeObject:self.backgroundColor forKey:NOODLE_BACKGROUND_COLOR_CODING_KEY]; } else { [encoder encodeObject:self.font]; [encoder encodeObject:self.textColor]; [encoder encodeObject:self.alternateTextColor]; [encoder encodeObject:self.backgroundColor]; } } #pragma mark - Notifications - (void)clientTextStorageDidProcessEditing:(NSNotification *)notification { // Invalidate the line indices. They will be recalculated and recached on demand. [self invalidateLineIndices]; [self setNeedsDisplay:YES]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/Read Me.rtf ================================================ {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Monaco;} {\colortbl;\red255\green255\blue255;} {\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid1} {\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid2} {\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid3} {\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid4} {\list\listtemplateid5\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid5} {\list\listtemplateid6\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid6} {\list\listtemplateid7\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid7}} {\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}{\listoverride\listid5\listoverridecount0\ls5}{\listoverride\listid6\listoverridecount0\ls6}{\listoverride\listid7\listoverridecount0\ls7}} \vieww16040\viewh15820\viewkind0 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural \f0\b\fs24 \cf0 Line View Test \b0 \ version 0.4.1\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ This is a sample project and test harness for NoodleLineNumberView.\ \ NoodleLineNumberView is an NSRulerView subclass that will show line numbers when the document view of the scrollview is an NSTextView. It numbers logical lines, not visual ones. NoodleLineNumberMarker works in tandem with NoodleLineNumberView to display markers at specific lines.\ \ A discussion of this project can be found at: {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/"}}{\fldrslt http://www.noodlesoft.com/blog/2008/10/05/displaying-line-numbers-with-nstextview/}}\ \ Notes:\ \ \pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural \ls1\ilvl0\cf0 {\listtext \'95 }The view will expand it's width to accommodate the widths of the labels as needed.\ {\listtext \'95 }The included subclass (MarkerLineNumberView) shows how to deal with markers. It also shows how to use an NSCustomImageRep to do the drawing. This allows you to reset the size of the image and have the drawing adjust as needed (this happens if the line number view changes width because the line numbers gained or lost a digit). If you decide to implement most of this stuff in an external class (not a subclass), you can set the line number view to post frame changed notifications and listen for them.\ {\listtext \'95 }Note that markers are tied to numerical lines, not semantic ones. So, if you have a marker at line 50 and insert a new line at line 49, the marker will not shift to line 51 to point at the same line of text but will stay at line 50 pointing at whatever text is there now. Contrast with XCode where the markers move with insertions and deletions of lines (at least as best as it can). This is logic that you'll have to supply yourself.\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ To integrate NoodleLineNumberView, just create one and set it as the vertical ruler of the scrollview. Depending on the order of operations, you may need to set the client view of the NoodleLineNumberView to the NSTextView manually.\ \ This project actually uses a subclass of NoodleLineNumberView called MarkerLineNumberView. This class shows how one can integrate adding markers. Just click in the line number view to toggle a marker. It's more of an example than a reusable class since your markers may look different and you may have a different UI for adding them. Nonetheless, it shows the basics of how to do it.\ \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \b \cf0 Possible Performance Improvements\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \b0 \cf0 \ For performance, NoodleLineView keeps an array of the character indices for the start of each line. This gets recalculated whenever the text changes but at least it's cached for redisplays (such as scrolling around). It also only redraw the labels for the lines that are showing.\ \ It seems peppy enough for me, testing on a Powerbook 12" (G4) on Leopard. If you feel the need to optimize it further (I advise you Shark it first instead of making assumptions, though), here are some areas that could be improved:\ \ \pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural \ls2\ilvl0\cf0 {\listtext \'95 }Right now, the character indices are recalculated every time the text changes. I only listen for a \f1 NSTextDidChangeNotification \f0 which is pretty coarse as there's no notion of what changed. You need to hook in deeper to get finer grained details of what characters were affected and see if the line indices need to be recalculated at all (check for whether a line ending was added or removed) or what particular lines should be recalculated (if a line was changed, only recalculate the lines after it).\ {\listtext \'95 }The layout coordinates of each line can also be cached. If you tie into NSLayoutManager's delegate methods, you can find out when the layout has been invalidated. This would be helpful for cases where the view is scrolled or otherwise redisplayed without having the layout changed. Invalidations would happen in cases like when the view is resized in which case, you recalculate and recache. I have my doubts about whether this will save much but Shark it and find out.\ {\listtext \'95 }It is a tad pokey on Tiger. It seems like NSString's drawing methods are much improved in Leopard. On Tiger, you can experiment with using the field editor or a cell to draw the labels.\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ The first two were not done because I wanted this subclass to be self-contained and not interfere with any delegates that may already be in place.\ \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \b \cf0 Contact \b0 \ \ Just go {\field{\*\fldinst{HYPERLINK "http://www.noodlesoft.com/about.php"}}{\fldrslt www.noodlesoft.com}} and shoot me an email. Or visit the blog article linked above and leave a comment. Bugs, suggestions and other feedback appreciated.\ \ \ \b License \b0 \ \ I am releasing this under the MIT license.\ \ ____________________________________\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \f1 \cf0 Copyright (c) 2008 Noodlesoft, LLC. All Rights Reserved.\ \ Permission is hereby granted, free of charge, to any person\ obtaining a copy of this software and associated documentation\ files (the "Software"), to deal in the Software without\ restriction, including without limitation the rights to use,\ copy, modify, merge, publish, distribute, sublicense, and/or sell\ copies of the Software, and to permit persons to whom the\ Software is furnished to do so, subject to the following\ conditions:\ \ The above copyright notice and this permission notice shall be\ included in all copies or substantial portions of the Software.\ \ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\ OTHER DEALINGS IN THE SOFTWARE.\ \pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural \ls3\ilvl0 \f0\b \cf0 \ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ Changelog \b0 \ \ 0.4.1:\ \pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural \ls4\ilvl0\cf0 {\listtext \'95 }Fixed display glitch when scrolling after the line number view resizes when linked against/running on 10.4. Apparently, NSRulerView's \f1 setRuleThickness: \f0 does not like non-integral values.\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ 0.4:\ \pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural \ls5\ilvl0\cf0 {\listtext \'95 }Changed default font to use label font. Not sure if semantically, that's what XCode uses but it matches for the time being.\ {\listtext \'95 }Fixed display bugs introduced in 0.3 when line number view resizes itself.\ {\listtext \'95 }Added methods for setting various colors. The alternate text color is the color used by the line number label when a marker is drawn under it.\ {\listtext \'95 }Miscellaneous tweaks.\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ 0.3:\ \pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural \ls6\ilvl0\cf0 {\listtext \'95 }Now listens for NSTextStorage's NSTextStorageDidProcessEditingNotification instead of NSTextDidChangeNotification. The former includes programmatic changes to the text.\ {\listtext \'95 }Was not taking text storage's inset into account when lining up labels. OSAScriptView, for one, had a non-zero inset. Should be fixed now.\ {\listtext \'95 }Calculates lines lazily allowing multiple programmatic text changes to be batched up.\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ 0.2:\ \pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural \ls7\ilvl0\cf0 {\listtext \'95 }Initial public release\ \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural \cf0 \ } ================================================ FILE: app_unexpectedly/app_unexpectedly/Extemal/Line View Test/main.m ================================================ // // main.m // Line View Test // // Created by Paul Kim on 10/5/08. // Copyright Noodlesoft, LLC 2008. All rights reserved. // #import int main(int argc, char *argv[]) { return NSApplicationMain(argc, (const char **) argv); } ================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/ENDPOINTSECURITY_2.html ================================================ Summary

An ENDPOINTSECURITY termination reason with code 2 indicates that an Endpoint Security client took too long to respond to an event.

Discussion

An Endpoint Security client can be killed if it fails to respond to an authorization event before the deadline defined in the message for that event.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_BAD_ACCESS_SIGBUS.html ================================================ Summary

The EXC_BAD_ACCESS (SIGBUS) type indicates a process uses memory in an unexpected way.

Discussion

The exception can happen when the process tries to access unmapped memory (KERN_INVALID_ADDRESS), misaligned memory (EXC_ARM_DA_ALIGN) or unavailable memory (KERN_MEMORY_ERROR). This can also happen when the process tries to write on read-only or protected memory (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_BAD_ACCESS_SIGSEGV.html ================================================ Summary

The EXC_BAD_ACCESS (SIGSEGV) type indicates a process uses memory in an unexpected way.

Discussion

The exception can happen when the process tries to access unmapped memory (KERN_INVALID_ADDRESS), misaligned memory (EXC_ARM_DA_ALIGN) or unavailable memory (KERN_MEMORY_ERROR). This can also happen when the process tries to write on read-only or protected memory (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_BAD_INSTRUCTION_SIGILL.html ================================================ Summary

The EXC_BAD_INSTRUCTION (SIGILL) type indicates the process executed an illegal instruction (usually inserted by the compiler).

Discussion

The execution of this illegal instruction usually means that one of the compiler’s safety checks failed (e.g. when your code unwraps a nil optional in Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_BREAKPOINT_SIGTRAP.html ================================================ Summary

The EXC_BREAKPOINT (SIGTRAP) type indicates the process executed an illegal instruction (usually inserted by the compiler).

Discussion

The execution of this illegal instruction usually means that one of the compiler’s safety checks failed (e.g. when your code unwraps a nil optional in Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_CRASH_Code Signature Invalid.html ================================================ Summary

The EXC_CRASH (Code Signature Invalid) type indicates the operating system terminated the process because of problems related to code signing.

Discussion

The crash could have occurred because the application is using invalid entitlements or the code signing identity is incompatible with the running environment.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_CRASH_SIGABRT.html ================================================ Summary

The EXC_CRASH (SIGABRT) type indicates the process terminated because it received the SIGABRT signal.

Discussion

Typically, this signal is sent because a function in the process called abort(), such as when an app encounters an uncaught Objective-C or C++ exception.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_CRASH_SIGKILL.html ================================================ Summary

The EXC_CRASH (SIGKILL) type indicates the operating system terminated the process.

Discussion

The crash report contains a Termination Reason field with a code that explains the reason for the crash.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_CRASH_SIGQUIT.html ================================================ Summary

The EXC_CRASH (SIGQUIT) type indicates the process terminated at the request of another process with privileges to manage its lifetime.

Discussion

This does not mean that the process crashed, but it likely misbehaved in a detectable manner.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_CRASH_SIGSEGV.html ================================================ Summary

The EXC_CRASH (SIGSEGV) type indicates a process uses memory in an unexpected way.

Discussion

The exception can happen when the process tries to access unmapped memory, misaligned memory or unavailable memory. This can also happen when the process tries to write on read-only or protected memory.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/EXC_GUARD.html ================================================ Summary

The EXC_GUARD type indicates the process violated a system-enforced rule while using a guarded resource.

Discussion

Typically, this exception is raised when a process tries to use normal file descriptor APIs on guarded file descriptors.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/unknown_exception_type.html ================================================

No Quick Help


Search Documentation

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/en.lproj/unknown_termination_reason.html ================================================

No Quick Help



================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/ENDPOINTSECURITY_2.html ================================================ Resumen

Un motivo de terminación ENDPOINTSECURITY con el código 2 indica que un cliente de Endpoint Security tardó demasiado en responder a un evento.

Discusión

Un cliente de Endpoint Security puede terminarse si no responde a un evento de autorización antes de la fecha límite definida en el mensaje para ese evento.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_BAD_ACCESS_SIGBUS.html ================================================ Resumen

El tipo EXC_BAD_ACCESS (SIGBUS) indica que un proceso utiliza la memoria de forma inesperada.

Discusión

La excepción puede ocurrir cuando el proceso intenta acceder a memoria no asignada (KERN_INVALID_ADDRESS), memoria desalineada (EXC_ARM_DA_ALIGN) o memoria no disponible (KERN_MEMORY_ERROR). Esto también puede ocurrir cuando el proceso intenta escribir en una memoria protegida o de solo lectura (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_BAD_ACCESS_SIGSEGV.html ================================================ Resumen

El tipo EXC_BAD_ACCESS (SIGSEGV) indica que un proceso utiliza la memoria de forma inesperada.

Discusión

La excepción puede ocurrir cuando el proceso intenta acceder a memoria no asignada (KERN_INVALID_ADDRESS), memoria desalineada (EXC_ARM_DA_ALIGN) o memoria no disponible (KERN_MEMORY_ERROR). Esto también puede ocurrir cuando el proceso intenta escribir en una memoria protegida o de solo lectura (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_BAD_INSTRUCTION_SIGILL.html ================================================ Resumen

The EXC_BAD_INSTRUCTION (SIGILL) type indicates the process executed an illegal instruction (usually inserted by the compiler).

Discusión

La ejecución de esta instrucción ilegal generalmente significa que una de las comprobaciones de seguridad del compilador falló (por ejemplo, cuando su código desenvuelve un nil opcional en Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_BREAKPOINT_SIGTRAP.html ================================================ Resumen

El tipo EXC_BREAKPOINT (SIGTRAP) indica que el proceso ejecutó una instrucción ilegal (generalmente insertada por el compilador).

Discusión

La ejecución de esta instrucción ilegal generalmente significa que una de las comprobaciones de seguridad del compilador falló (por ejemplo, cuando su código desenvuelve un nil opcional en Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_CRASH_Code Signature Invalid.html ================================================ Resumen

EXC_CRASH (Code Signature Invalid) indica que el sistema operativo terminó el proceso debido a problemas relacionados con la firma del código.

Discusión

El bloqueo podría haber ocurrido porque la aplicación utiliza derechos no válidos o la identidad de firma de código es incompatible con el entorno en ejecución.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_CRASH_SIGABRT.html ================================================ Resumen

EXC_CRASH (SIGABRT) indica que el proceso terminó porque recibió la señal SIGABRT.

Discusión

Por lo general, esta señal se envía debido a una función en el proceso llamada abort(), como cuando una aplicación encuentra una excepción de Objective-C o C ++ no detectada.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_CRASH_SIGKILL.html ================================================ Resumen

EXC_CRASH (SIGKILL) indica que el sistema operativo terminó el proceso.

Discusión

El informe contiene un campo Termination Reason con un código que explica la razón de la falla.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_CRASH_SIGQUIT.html ================================================ Resumen

EXC_CRASH (SIGQUIT) indicates the process terminated at the request of another process with privileges to manage its lifetime.

Discusión

Esto no significa que el proceso haya fallado, pero probablemente se haya comportado mal de una manera detectable.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_CRASH_SIGSEGV.html ================================================ Resumen

El tipo EXC_CRASH (SIGSEGV) indica que un proceso utiliza la memoria de forma inesperada.

Discusión

La excepción puede ocurrir cuando el proceso intenta acceder a memoria no asignada, memoria desalineada o memoria no disponible. Esto también puede ocurrir cuando el proceso intenta escribir en una memoria protegida o de solo lectura.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/EXC_GUARD.html ================================================ Resumen

El tipo EXC_GUARD indica que el proceso violó una regla impuesta por el sistema mientras usaba un recurso protegido.

Discusión

Normalmente, esta excepción se genera cuando un proceso intenta utilizar las API de descriptores de archivos normales en descriptores de archivos protegidos.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/unknown_exception_type.html ================================================

Ayuda rápida no disponible


Buscar documentación

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/es.lproj/unknown_termination_reason.html ================================================

Ayuda rápida no disponible



================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/ENDPOINTSECURITY_2.html ================================================ Résumé

Une raison de terminaison ENDPOINTSECURITY avec un code 2 indique qu'un client Endpoint Security a mis trop de temps à répondre à un événement.

Discussion

Un client Endpoint Security peut être tué s'il échoue à répondre à un événement d'autorisation avant l'échéance définie dans le message pour cet événement.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_BAD_ACCESS_SIGBUS.html ================================================ Résumé

Le type d'exception EXC_BAD_ACCESS (SIGBUS) indique que le processus a utilisé la mémoire d'une façon inattendue.

Discussion

Cette exception peut survenir lorsque le processus essaye d'accèder à de la mémoire non mappée (KERN_INVALID_ADDRESS), de la mémoire non alignée (EXC_ARM_DA_ALIGN) ou de la mémoire non disponible (KERN_MEMORY_ERROR). Cela peut aussi survenir lorsque le processus tente d'écrire sur de la mémoire protégée ou en lecture seule (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_BAD_ACCESS_SIGSEGV.html ================================================ Résumé

Le type d'exception EXC_BAD_ACCESS (SIGSEGV) indique que le processus a utilisé la mémoire d'une façon inattendue.

Discussion

Cette exception peut survenir lorsque le processus essaye d'accèder à de la mémoire non mappée (KERN_INVALID_ADDRESS), de la mémoire non alignée (EXC_ARM_DA_ALIGN) ou de la mémoire non disponible (KERN_MEMORY_ERROR). Cela peut aussi survenir lorsque le processus tente d'écrire sur de la mémoire protégée ou en lecture seule (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_BAD_INSTRUCTION_SIGILL.html ================================================ Résumé

Le type d'exception EXC_BAD_INSTRUCTION (SIGILL) indique qu'une instruction illégale (probablement insérée par le compilateur) a interrompu l'opération.

Discussion

L'exécution d'une telle instruction indique généralement qu'une des procédures de vérifications insérées par le compilateur a détecté une erreur (e.g. quand votre code déballe un nil optionnel en Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_BREAKPOINT_SIGTRAP.html ================================================ Résumé

Le type d'exception EXC_BREAKPOINT (SIGTRAP) indice qu'une instruction illégale (probablement insérée par le compilateur) a interrompu le processus.

Discussion

L'exécution d'une telle instruction indique généralement qu'une des procédures de vérifications insérées par le compilateur a détecté une erreur (e.g. quand votre code déballe un nil optionnel en Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_CRASH_Code Signature Invalid.html ================================================ Résumé

Le type d'exception EXC_CRASH (Code Signature Invalid) indique que le système d'exploitation a interrompu le processus en raison de problèmes liés à la signature du code.

Discussion

Le crash peut être survenu parce que l'application utilise des droits invalides ou que l'identité de la signature du code est incompatible avec l'environnement d'exécution.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_CRASH_SIGABRT.html ================================================ Résumé

Le type d'exception EXC_CRASH (SIGABRT) indique que le processus s'est interrompu parce qu'il a reçu le signal SIGABRT.

Discussion

Typiquement, ce signal est envoyé parce qu'une fonction du processus a appelé abort(), comme lorsqu'une application est confrontée à une exception Objective-C ou C++ non interceptée.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_CRASH_SIGKILL.html ================================================ Résumé

Le type d'exception EXC_CRASH (SIGKILL) indique que le système d'exploitation a interrompu le processus.

Discussion

Le rapport de crash contient un champ "Termination Reason" (Raison de l'interruption) avec un code qui explique la raison du crash.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_CRASH_SIGQUIT.html ================================================ Résumé

Le type d'exception EXC_CRASH (SIGQUIT) indique que le processus a été arrêté par un autre processus disposant de droits sur la durée de vie du processus.

Discussion

Cela ne signifie pas que le processus a planté mais plutôt qu'il a été repéré qu'il se comportait de manière incorrecte.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_CRASH_SIGSEGV.html ================================================ Résumé

Le type d'exception EXC_CRASH (SIGSEGV) indique que le processus a utilisé la mémoire d'une façon inattendue.

Discussion

Cette exception peut survenir lorsque le processus essaye d'accèder à de la mémoire non mappée, de la mémoire non alignée ou de la mémoire non disponible. Cela peut aussi survenir lorsque le processus tente d'écrire sur de la mémoire protégée ou en lecture seule.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/EXC_GUARD.html ================================================ Résumé

Le type d'exception EXC_GUARD indique que le processus a enfreint une règle imposée par le système lors de l’utilisation d’une ressource protégée.

Discussion

En général, cette exception est soulevée lorsqu’un processus tente d’utiliser les API classiques de descripteurs de fichiers sur des descripteurs protégés.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/unknown_exception_type.html ================================================

Aide rapide indisponible


Rechercher dans la documentation

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/fr.lproj/unknown_termination_reason.html ================================================

Aide rapide indisponible



================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/ENDPOINTSECURITY_2.html ================================================ תַקצִיר

סיבת סיום שלסיבת סיום של ENDPOINTSECURITY עם קוד 2 מציינת שלקוח Endpoint Security לקח זמן רב מדי להגיב לאירוע.

דיון

לקוח Endpoint Security עלול להיסגר אם הוא לא מגיב לאירוע אישור לפני המועד האחרון שהוגדר בהודעה עבור אירוע זה.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_BAD_ACCESS_SIGBUS.html ================================================ תַקצִיר

הסוג EXC_BAD_ACCESS (SIGBUS) מציין שתהליך משתמש בזיכרון באופן בלתי צפוי.

דיון

החריג יכול להתרחש כאשר התהליך מנסה לגשת לזיכרון לא ממופה (KERN_INVALID_ADDRESS), לזיכרון לא מיושר (EXC_ARM_DA_ALIGN) או לזיכרון לא זמין (KERN_MEMORY_ERROR). זה יכול לקרות גם כאשר התהליך מנסה לכתוב על זיכרון לקריאה בלבד או מוגן (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_BAD_ACCESS_SIGSEGV.html ================================================ תַקצִיר

הסוג EXC_BAD_ACCESS (SIGSEGV) מציין שתהליך משתמש בזיכרון בצורה בלתי צפויה.

דיון

החריג יכול להתרחש כאשר התהליך מנסה לגשת לזיכרון לא ממופה (KERN_INVALID_ADDRESS), לזיכרון לא מיושר (EXC_ARM_DA_ALIGN) או לזיכרון לא זמין (KERN_MEMORY_ERROR). זה יכול לקרות גם כאשר התהליך מנסה לכתוב על זיכרון לקריאה בלבד או מוגן (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_BAD_INSTRUCTION_SIGILL.html ================================================ תַקצִיר

הסוג EXC_BAD_INSTRUCTION (SIGILL) מציין שהתהליך ביצע הוראה לא חוקית (בדרך כלל מוכנסת על ידי המהדר).

דיון

ביצוע הוראה לא חוקית זו בדרך כלל פירושו שאחת מבדיקות הבטיחות של המהדר נכשלה (למשל, כאשר הקוד שלך פותח ערך nil אופציונלי ב-Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_BREAKPOINT_SIGTRAP.html ================================================ תַקצִיר

הסוג EXC_BREAKPOINT (SIGTRAP) מציין שהתהליך ביצע הוראה לא חוקית (שבדרך כלל הוכנסה על ידי המהדר).

דיון

ביצוע הוראה לא חוקית זו בדרך כלל פירושו שאחת מבדיקות הבטיחות של המהדר נכשלה (למשל, כאשר הקוד שלך פותח ערך nil אופציונלי ב-Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_CRASH_Code Signature Invalid.html ================================================ תַקצִיר

הסוג EXC_CRASH (Code Signature Invalid) מציין שמערכת ההפעלה סיימה את התהליך עקב בעיות הקשורות לחתימת קוד.

דיון

ייתכן שהקריסה התרחשה מכיוון שהיישום משתמש בהרשאות לא חוקיות או שזהות חתימת הקוד אינה תואמת לסביבת ההפעלה.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_CRASH_SIGABRT.html ================================================ תַקצִיר

הסוג EXC_CRASH (SIGABRT) מציין שהתהליך הסתיים משום שקיבל את אות SIGABRT.

דיון

בדרך כלל, אות זה נשלח עקב פונקציה בתהליך הנקראת abort(), כגון כאשר אפליקציה נתקלת בחריג שלא נתפס ב-Objective-C או C++.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_CRASH_SIGKILL.html ================================================ תַקצִיר

הסוג EXC_CRASH (SIGKILL) מציין שמערכת ההפעלה סיימה את התהליך.

דיון

דוח הקריסה מכיל שדה Termination Reason עם קוד המסביר את סיבת הקריסה.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_CRASH_SIGQUIT.html ================================================ תַקצִיר

הסוג EXC_CRASH (SIGQUIT) מציין שהתהליך הסתיים לבקשת תהליך אחר בעל הרשאות לניהול חייו.

דיון

זה לא אומר שהתהליך קרס, אבל סביר להניח שהוא התנהג בצורה לא תקינה באופן שניתן לזיהוי.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_CRASH_SIGSEGV.html ================================================ תַקצִיר

הסוג EXC_CRASH (SIGSEGV) מציין שתהליך משתמש בזיכרון בצורה בלתי צפויה.

דיון

החריג יכול להתרחש כאשר התהליך מנסה לגשת לזיכרון לא ממופה, זיכרון לא מיושר או זיכרון לא זמין. זה יכול לקרות גם כאשר התהליך מנסה לכתוב על זיכרון לקריאה בלבד או זיכרון מוגן.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/EXC_GUARD.html ================================================ תַקצִיר

הסוג EXC_GUARD מציין שהתהליך הפר כלל שנאכף על ידי המערכת בעת שימוש במשאב מוגן.

דיון

בדרך כלל, חריג זה מופעל כאשר תהליך מנסה להשתמש בממשקי API רגילים של תיאורי קבצים על גבי תיאורי קבצים מוגנים.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/unknown_exception_type.html ================================================

אין עזרה מהירה


Search Documentation

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/he.lproj/unknown_termination_reason.html ================================================

אין עזרה מהירה



================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/ENDPOINTSECURITY_2.html ================================================ 要旨

An ENDPOINTSECURITY termination reason with code 2 indicates that an Endpoint Security client took too long to respond to an event.

討論

An Endpoint Security client can be killed if it fails to respond to an authorization event before the deadline defined in the message for that event.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_BAD_ACCESS_SIGBUS.html ================================================ 要旨

The EXC_BAD_ACCESS (SIGBUS) type indicates a process uses memory in an unexpected way.

討論

The exception can happen when the process tries to access unmapped memory (KERN_INVALID_ADDRESS), misaligned memory (EXC_ARM_DA_ALIGN) or unavailable memory (KERN_MEMORY_ERROR). This can also happen when the process tries to write on read-only or protected memory (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_BAD_ACCESS_SIGSEGV.html ================================================ 要旨

The EXC_BAD_ACCESS (SIGSEGV) type indicates a process uses memory in an unexpected way.

討論

The exception can happen when the process tries to access unmapped memory (KERN_INVALID_ADDRESS), misaligned memory (EXC_ARM_DA_ALIGN) or unavailable memory (KERN_MEMORY_ERROR). This can also happen when the process tries to write on read-only or protected memory (KERN_PROTECTION_FAILURE).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_BAD_INSTRUCTION_SIGILL.html ================================================ 要旨

The EXC_BAD_INSTRUCTION (SIGILL) type indicates the process executed an illegal instruction (usually inserted by the compiler).

討論

The execution of this illegal instruction usually means that one of the compiler’s safety checks failed (e.g. when your code unwraps a nil optional in Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_BREAKPOINT_SIGTRAP.html ================================================ 要旨

The EXC_BREAKPOINT (SIGTRAP) type indicates the process executed an illegal instruction (usually inserted by the compiler).

討論

The execution of this illegal instruction usually means that one of the compiler’s safety checks failed (e.g. when your code unwraps a nil optional in Swift).

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_CRASH_Code Signature Invalid.html ================================================ 要旨

EXC_CRASH (Code Signature Invalid) indicates the operating system terminated the process because of problems related to code signing.

討論

The crash could have occurred because the application is using invalid entitlements or the code signing identity is incompatible with the running environment.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_CRASH_SIGABRT.html ================================================ 要旨

EXC_CRASH (SIGABRT) indicates the process terminated because it received the SIGABRT signal.

討論

Typically, this signal is sent because a function in the process called abort(), such as when an app encounters an uncaught Objective-C or C++ exception.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_CRASH_SIGKILL.html ================================================ 要旨

EXC_CRASH (SIGKILL) indicates the operating system terminated the process.

討論

The crash report contains a Termination Reason field with a code that explains the reason for the crash.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_CRASH_SIGQUIT.html ================================================ 要旨

EXC_CRASH (SIGQUIT) indicates the process terminated at the request of another process with privileges to manage its lifetime.

討論

This does not mean that the process crashed, but it likely misbehaved in a detectable manner.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_CRASH_SIGSEGV.html ================================================ 要旨

The EXC_CRASH (SIGSEGV) type indicates a process uses memory in an unexpected way.

討論

The exception can happen when the process tries to access unmapped memory, misaligned memory or unavailable memory. This can also happen when the process tries to write on read-only or protected memory.

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/EXC_GUARD.html ================================================ 要旨

EXC_GUARD タイプは、保護されたリソースを使用しているときにプロセスがシステムによって強制されたルールに違反したことを示します。

討論

通常、この例外は、プロセスが保護されたファイル記述子で通常のファイル記述子 API を使用しようとしたときに発生します。

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/unknown_exception_type.html ================================================

No Quick Help


ドキュメントを検索する

================================================ FILE: app_unexpectedly/app_unexpectedly/Help/ja.lproj/unknown_termination_reason.html ================================================

No Quick Help



================================================ FILE: app_unexpectedly/app_unexpectedly/Help/known_exceptions.css ================================================ body { margin-left: 16px; margin-right: 16px; margin-top: 12px; margin-bottom: 10px; font-family: -apple-system, Helvetica; font-size:11; } a:link { text-decoration: none; color: #0055FF; } a:visited { text-decoration: none; } a:hover { text-decoration: underline; } a:active { text-decoration: underline; } div.external_link { text-align: right; } @media (prefers-color-scheme: dark) { body { margin-left: 16px; margin-right: 16px; margin-top: 12px; margin-bottom: 10px; font-family: -apple-system, Helvetica; font-size:11; color: #ddd; background: #262626; } a:link { text-decoration: none; color: #3f87d6 } a:visited { text-decoration: none; } a:hover { text-decoration: underline; } a:active { text-decoration: underline; } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Help/known_termination_reasons.css ================================================ body { margin-left: 16px; margin-right: 16px; margin-top: 12px; margin-bottom: 10px; font-family: -apple-system, Helvetica; font-size:11; } a:link { text-decoration: none; color: #0055FF; } a:visited { text-decoration: none; } a:hover { text-decoration: underline; } a:active { text-decoration: underline; } div.external_link { text-align: right; } @media (prefers-color-scheme: dark) { body { margin-left: 16px; margin-right: 16px; margin-top: 12px; margin-bottom: 10px; font-family: -apple-system, Helvetica; font-size:11; color: #ddd; background: #262626; } a:link { text-decoration: none; color: #3f87d6 } a:visited { text-decoration: none; } a:hover { text-decoration: underline; } a:active { text-decoration: underline; } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "size" : "16x16", "idiom" : "mac", "filename" : "applicationIcon_16.png", "scale" : "1x" }, { "size" : "16x16", "idiom" : "mac", "filename" : "applicationIcon_32-1.png", "scale" : "2x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "applicationIcon_32.png", "scale" : "1x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "applicationIcon_64.png", "scale" : "2x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "applicationIcon_128.png", "scale" : "1x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "applicationIcon_256-1.png", "scale" : "2x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "applicationIcon_256.png", "scale" : "1x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "applicationIcon_512-1.png", "scale" : "2x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "applicationIcon_512.png", "scale" : "1x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "applicationIcon_1024.png", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/FontPanelButton.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "FontPanelButton.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "FontPanelButton@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/TextMode.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "TextMode.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "TextMode@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/binaryImage_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "binary.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "binary@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/bottom_disclose_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "bottom_disclose_Template.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "bottom_disclose@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/bottom_hide_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "bottom_hide_Template.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "bottom_hide@2x copy.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/bytesOffset_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "bytesOffset.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "bytesOffset@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-appkit.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-appkit.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-appkit@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-audiospeech.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-audiospeech.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-audiospeech@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-database.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-database.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-database@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-foundation.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-foundation.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-foundation@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-framework.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-framework.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-framework@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-generic.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-generic.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-generic@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-graphics.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-graphics.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-graphics@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-languages.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-languages.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-languages@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-network.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-network.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-network@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-security.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-security.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-security@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-system.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-system.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-system@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-usercode.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-usercode.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-usercode@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/call-webinternet.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "call-webinternet.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "call-webinternet@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/crashedThread_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "crashedThread_Template.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "crashedThread_Template@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/crashreporter.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "crashreporter.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "crashreporter@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/filter_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "filter.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "filter@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/left_switch_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "left_switch.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "left_switch@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuBacktraces.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuBacktraces.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuBacktraces@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuBinaryImage.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuBinaryImage.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuBinaryImage@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuDiagnostic.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuDiagnostic.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuDiagnostic@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuException.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuException.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuException@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuHeader.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuHeader.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuHeader@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuThread.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuThread.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuThread@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuThreadCrashed.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuThreadCrashed.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuThreadCrashed@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/menuThreadState.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "menuThreadState.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "menuThreadState@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/middle_switch_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "middle_switch.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "middle_switch@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/presentation_structured_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "presentation_structured.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "presentation_structured@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/presentation_text_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "presentation_text.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "presentation_text@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/quote_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "quote.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "quote@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/right_switch_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "right_switch.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "right_switch@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/sidebar_recents_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "recents.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "recents@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/smallColumn_RTL_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "smallColumn_RTL_Template.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "smallColumn_RTL_Template@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/smallColumn_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "smallColumn_Template.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "smallColumn_Template@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/smallCrashedThread_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "smallCrashedThread_Template.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "smallCrashedThread_Template@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/smallLightTable_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "smallLightTable_Template.png", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/symbolication_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "symbolication.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "symbolication@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/templateBlue.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "templateBlue.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "templateBlue@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Images.xcassets/thread_Template.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "thread_Template.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "thread_Template@2x.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: app_unexpectedly/app_unexpectedly/Info.plist ================================================ CFBundleDevelopmentRegion en UIDesignRequiresCompatibility CFBundleDocumentTypes CFBundleTypeIconFile UnexpectedlyTheme CFBundleTypeName Unexpectedly Theme Name CFBundleTypeRole Editor LSItemContentTypes fr.whitebox.unexpectedly.theme LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions smartsource CFBundleTypeIconFile UnexpectedlySmartSource CFBundleTypeName Unexpectedly Smart Source CFBundleTypeRole Editor LSItemContentTypes fr.whitebox.unexpectedly.smartSource LSTypeIsPackage NSPersistentStoreTypeKey XML CFBundleTypeExtensions crash CFBundleTypeIconFile CFBundleTypeMIMETypes text/plain CFBundleTypeName Crash Report CFBundleTypeRole Viewer LSItemContentTypes com.apple.crashreport LSTypeIsPackage NSPersistentStoreTypeKey Binary LSHandlerRank Alternate CFBundleTypeExtensions ips CFBundleTypeIconFile CFBundleTypeMIMETypes text/plain CFBundleTypeName Analytics Report CFBundleTypeRole Viewer LSItemContentTypes com.apple.ips LSTypeIsPackage NSPersistentStoreTypeKey Binary LSHandlerRank Alternate CFBundleTypeExtensions dsym dSYM CFBundleTypeIconFile CFBundleTypeName Archived Debug Symbols CFBundleTypeRole Viewer LSItemContentTypes com.apple.xcode.dsym LSTypeIsPackage CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile AppIcon.icns CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleURLTypes CFBundleTypeExtensions dsym dSYM CFBundleTypeRole Viewer CFBundleTypeExtensions crash CFBundleTypeRole Viewer CFBundleTypeExtensions ips CFBundleTypeRole Viewer CFBundleVersion 78 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright Copyright © 2020-2026 Stéphane Sudre. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication NSAppleEventsUsageDescription To interact with other applications, Unexpectedly needs to be able to send Apple Events. UTExportedTypeDeclarations UTTypeConformsTo public.xml UTTypeDescription Unexpectedly Theme File UTTypeIconName UnexpectedlyTheme UTTypeIdentifier fr.whitebox.unexpectedly.theme UTTypeTagSpecification public.filename-extension unexpectedly-theme UTTypeConformsTo public.xml UTTypeDescription Unexpectedly Smart Source File UTTypeIconName UnexpectedlySmartSource UTTypeIdentifier fr.whitebox.unexpectedly.smartSource UTTypeTagSpecification public.filename-extension smartsource NSAppTransportSecurity NSExceptionDomains s.sudre.free.fr NSExceptionAllowsInsecureHTTPLoads WBVersionCheckURL http://s.sudre.free.fr/Software/Unexpectedly/RemoteVersion.plist ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHLoadCommand.h ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHMemoryBufferWrapper.h" @class MCHObjectFile; @interface MCHLoadCommand : MCHMemoryBufferWrapper @property (readonly) uint32_t type; + (uint32_t)typeFromLoadCommandBuffer:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap; - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture objectFile:(MCHObjectFile *)inObjectFile; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHLoadCommand.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHLoadCommand.h" #import "MCHObjectFile.h" #import "MCHUUIDLoadCommand.h" #import "MCHSegmentLoadCommand.h" /*#import "MTBCRpathLoadCommand.h" #import "MTBCLinkEditDataLoadCommand.h" #import "MTBCMinimumVersionLoadCommand.h" #import "MTBCSourceVersionLoadCommand.h" #import "MTBCEncryptionLoadCommand.h" #import "MTBCDynamicLinkerLoadCommand.h" #import "MTBCDynamicLinkedSharedLibraryLoadCommand.h" #import "MTBCPreboundDynamicLibraryCommand.h"*/ #include @interface MCHLoadCommand () @property uint32_t type; @end @implementation MCHLoadCommand + (uint32_t)typeFromLoadCommandBuffer:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap { if (inBytes==NULL || inLength<(sizeof(uint32_t))) return 0; uint32_t tCommandType=*((uint32_t *) inBytes); if (inSwap==YES) tCommandType=OSSwapBigToHostInt32(tCommandType); return tCommandType; } - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture objectFile:(MCHObjectFile *)inObjectFile { if (inBytes==NULL || inLength<=(sizeof(uint32_t))) return nil; uint32_t tCommandType=[MCHLoadCommand typeFromLoadCommandBuffer:inBytes length:inLength swap:inSwap]; uint32_t tCommandSize=*(((uint32_t *) inBytes)+1); if (inSwap==YES) tCommandSize=OSSwapBigToHostInt32(tCommandSize); switch(tCommandType) { case LC_SEGMENT: self=[[MCHSegmentLoadCommand alloc] initWithBytes:inBytes length:tCommandSize swap:inSwap architecture:MCHArchitecture32 objectFile:inObjectFile]; break; case LC_SEGMENT_64: self=[[MCHSegmentLoadCommand alloc] initWithBytes:inBytes length:tCommandSize swap:inSwap architecture:MCHArchitecture64 objectFile:inObjectFile]; break; case LC_SYMTAB: // A COMPLETER break; case LC_DYSYMTAB: // A COMPLETER break; case LC_ID_DYLIB: case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: case LC_REEXPORT_DYLIB: break; case LC_LOAD_DYLINKER: break; case LC_PREBOUND_DYLIB: break; case LC_UUID: self=[[MCHUUIDLoadCommand alloc] initWithBytes:inBytes length:tCommandSize swap:inSwap architecture:inArchitecture objectFile:inObjectFile]; break; case LC_RPATH: break; case LC_CODE_SIGNATURE: case LC_SEGMENT_SPLIT_INFO: case LC_FUNCTION_STARTS: case LC_DATA_IN_CODE: case LC_DYLIB_CODE_SIGN_DRS: case LC_LINKER_OPTIMIZATION_HINT: break; case LC_VERSION_MIN_MACOSX: case LC_VERSION_MIN_IPHONEOS: break; case LC_SOURCE_VERSION: break; case LC_ENCRYPTION_INFO: break; case LC_ENCRYPTION_INFO_64: break; case LC_DYLD_INFO: case LC_DYLD_INFO_ONLY: break; case LC_BUILD_VERSION: break; default: NSLog(@"Unknow load command type: %d",tCommandType); return nil; } if (self!=nil) { _type=tCommandType; } return self; } #pragma mark - - (NSString *)description { NSMutableString * tMutableString=[NSMutableString string]; [tMutableString appendFormat:@"0x%04x command:\n",self.type]; [tMutableString appendFormat:@" size: %u\n",(uint32_t)self.bufferSize]; return [tMutableString copy]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHMachBinary.h ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHMemoryBufferWrapper.h" #import "MCHObjectFile.h" @interface MCHMachBinary : MCHMemoryBufferWrapper - (instancetype)initWithContentsOfFile:(NSString *)inPath; - (instancetype)initWithContentsOfURL:(NSURL *)inURL; @property (readonly,nonatomic,getter=isFatBinary) BOOL fatBinary; @property (readonly,nonatomic) NSArray * allObjectFiles; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHMachBinary.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHMachBinary.h" #include #include @interface MCHMachBinary () { NSMutableArray * _objectFilesArray; NSData * _cachedData; NSUInteger bufferSize; const char * buffer; } @end @implementation MCHMachBinary - (instancetype)initWithContentsOfFile:(NSString *)inPath { if (inPath!=nil) { _cachedData=[NSData dataWithContentsOfFile:inPath]; if (_cachedData!=nil) return [self initWithBytes:_cachedData.bytes length:_cachedData.length swap:NO]; } return nil; } - (instancetype)initWithContentsOfURL:(NSURL *)inURL { if (inURL!=nil) { NSData * _cachedData=[NSData dataWithContentsOfURL:inURL]; if (_cachedData!=nil) return [self initWithBytes:_cachedData.bytes length:_cachedData.length swap:NO]; } return nil; } - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap { self=[super initWithBytes:inBytes length:inLength swap:inSwap]; if (self!=nil) { NSUInteger tFutureBufferOffset=0; tFutureBufferOffset+=sizeof(uint32_t); if (tFutureBufferOffset>=self.bufferSize) { // Buffer too small // A COMPLETER goto init_bail; } // Determine the architecture uint32_t tMagicNumber=*((uint32_t *)self.buffer); BOOL tSwap=YES; switch(tMagicNumber) { case MH_MAGIC: case MH_CIGAM: case MH_MAGIC_64: case MH_CIGAM_64: { MCHObjectFile * tObjectFile=[[MCHObjectFile alloc] initWithBytes:self.buffer length:self.bufferSize]; if (tObjectFile==nil) { goto init_bail; } _objectFilesArray=[NSMutableArray arrayWithObject:tObjectFile]; break; } case FAT_MAGIC_64: tSwap=NO; case FAT_CIGAM_64: // FAT { tFutureBufferOffset+=sizeof(uint32_t); if (tFutureBufferOffset>=self.bufferSize) { // A COMPLETER goto init_bail; } _objectFilesArray=[NSMutableArray array]; struct fat_header * tFatHeaderPtr=(struct fat_header *)self.buffer; uint32_t tArchitecturesCount=tFatHeaderPtr->nfat_arch; if (tSwap==YES) tArchitecturesCount=OSSwapBigToHostInt32(tArchitecturesCount); const char * tReadBuffer=self.buffer+tFutureBufferOffset; for(uint32_t tIndex=0;tIndex=self.bufferSize) { // A COMPLETER goto init_bail; } struct fat_arch_64 * tFatArchPtr=(struct fat_arch_64 *)tReadBuffer; MCHObjectFile * tObjectFile; if (tSwap==YES) tObjectFile=[[MCHObjectFile alloc] initWithBytes:self.buffer+OSSwapBigToHostInt64(tFatArchPtr->offset) length:OSSwapBigToHostInt64(tFatArchPtr->size)]; else tObjectFile=[[MCHObjectFile alloc] initWithBytes:self.buffer+tFatArchPtr->offset length:tFatArchPtr->size]; if (tObjectFile==nil) { goto init_bail; } [_objectFilesArray addObject:tObjectFile]; tReadBuffer+=sizeof(struct fat_arch_64); } break; } case FAT_MAGIC: tSwap=NO; case FAT_CIGAM: // FAT { tFutureBufferOffset+=sizeof(uint32_t); if (tFutureBufferOffset>=self.bufferSize) { // A COMPLETER goto init_bail; } _objectFilesArray=[NSMutableArray array]; struct fat_header * tFatHeaderPtr=(struct fat_header *)self.buffer; uint32_t tArchitecturesCount=tFatHeaderPtr->nfat_arch; if (tSwap==YES) tArchitecturesCount=OSSwapBigToHostInt32(tArchitecturesCount); const char * tReadBuffer=self.buffer+tFutureBufferOffset; for(uint32_t tIndex=0;tIndex=self.bufferSize) { // A COMPLETER goto init_bail; } struct fat_arch * tFatArchPtr=(struct fat_arch *)tReadBuffer; MCHObjectFile * tObjectFile; if (tSwap==YES) tObjectFile=[[MCHObjectFile alloc] initWithBytes:self.buffer+OSSwapBigToHostInt32(tFatArchPtr->offset) length:OSSwapBigToHostInt32(tFatArchPtr->size)]; else tObjectFile=[[MCHObjectFile alloc] initWithBytes:self.buffer+tFatArchPtr->offset length:tFatArchPtr->size]; if (tObjectFile==nil) { goto init_bail; } [_objectFilesArray addObject:tObjectFile]; tReadBuffer+=sizeof(struct fat_arch); } break; } default: NSLog(@"Unknown Mach Binary format"); // A COMPLETER goto init_bail; } return self; } init_bail: return nil; } #pragma mark - - (NSString *)description { NSMutableString * tMutableString=[NSMutableString string]; if (self.isFatBinary==YES) [tMutableString appendFormat:@"FAT binary (%d object files)\n",(int)[self allObjectFiles].count]; [[self allObjectFiles] enumerateObjectsUsingBlock:^(MCHObjectFile * bObjectFile,NSUInteger bIndex,BOOL * bOutStop){ [tMutableString appendString:[bObjectFile description]]; }]; return [tMutableString copy]; } #pragma mark - - (BOOL)isFatBinary { return (_objectFilesArray.count>1); } #pragma mark - - (NSArray *)allObjectFiles { return _objectFilesArray; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHMemoryBufferWrapper.h ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_ENUM(NSUInteger, MCHArchitecture) { MCHArchitectureUnknown=0, MCHArchitecture32, MCHArchitecture64 }; @interface MCHMemoryBufferWrapper : NSObject @property (readonly) const char * buffer; @property (readonly) NSUInteger bufferSize; @property (readonly, getter=shouldSwap) BOOL swap; @property (readonly) MCHArchitecture architecture; - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture; - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap; - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHMemoryBufferWrapper.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHMemoryBufferWrapper.h" @implementation MCHMemoryBufferWrapper - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture; { if (inBytes!=nil) { self=[super init]; if (self!=nil) { _buffer=inBytes; _bufferSize=inLength; _swap=inSwap; _architecture=inArchitecture; return self; } } return nil; } - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap { return [self initWithBytes:inBytes length:inLength swap:inSwap architecture:MCHArchitectureUnknown]; } - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength { return [self initWithBytes:inBytes length:inLength swap:NO]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHObjectFile.h ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHMemoryBufferWrapper.h" #import "MCHLoadCommand.h" #import "MCHSegment.h" #include @interface MCHObjectFile : MCHMemoryBufferWrapper @property (readonly) cpu_type_t cpuType; @property (readonly) cpu_subtype_t cpuSubType; @property (readonly) uint32_t fileType; @property (readonly) uint32_t flags; @property (nonatomic,readonly) NSArray * allLoadCommands; - (NSArray *)loadCommandsOfType:(uint32_t)inType; @property (nonatomic,readonly) NSArray * allSegments; - (MCHSegment *)segmentNamed:(NSString *)inName; //- (MTBCSegment *)segmentAtAddress:(uint64_t)inAddress; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHObjectFile.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHObjectFile.h" #import "MCHSegmentLoadCommand.h" @interface MCHObjectFile () { NSMutableArray *_loadCommandsArray; NSMutableArray *_segmentsArray; NSMutableDictionary * _segmentsIndex; } @property cpu_type_t cpuType; @property cpu_subtype_t cpuSubType; @property uint32_t fileType; @property uint32_t flags; @end @implementation MCHObjectFile - (instancetype)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture { self=[super initWithBytes:inBytes length:inLength swap:inSwap architecture:inArchitecture]; if (self!=nil) { NSUInteger tFutureBufferOffset=0; uint32_t tLoadCommandsNumber; //uint32_t tLoadCommandsTotalSize; if (inArchitecture==MCHArchitecture32) { if (self.bufferSizecputype; if (self.shouldSwap==YES) _cpuType=OSSwapBigToHostInt32(_cpuType); _cpuSubType=tMach32HeaderPtr->cpusubtype; if (self.shouldSwap==YES) _cpuSubType=OSSwapBigToHostInt32(_cpuSubType); _fileType=tMach32HeaderPtr->filetype; if (self.shouldSwap==YES) _fileType=OSSwapBigToHostInt32(_fileType); _flags=tMach32HeaderPtr->flags; if (self.shouldSwap==YES) _flags=OSSwapBigToHostInt32(_flags); tLoadCommandsNumber=tMach32HeaderPtr->ncmds; if (self.shouldSwap==YES) tLoadCommandsNumber=OSSwapBigToHostInt32(tLoadCommandsNumber); /*tLoadCommandsTotalSize=tMach32HeaderPtr->sizeofcmds; if (self.shouldSwap==YES) tLoadCommandsTotalSize=OSSwapBigToHostInt32(tLoadCommandsTotalSize);*/ tFutureBufferOffset=sizeof(struct mach_header); } else if (inArchitecture==MCHArchitecture64) { if (self.bufferSizecputype; if (self.shouldSwap==YES) _cpuType=OSSwapBigToHostInt32(_cpuType); _cpuSubType=tMach64HeaderPtr->cpusubtype; if (self.shouldSwap==YES) _cpuSubType=OSSwapBigToHostInt32(_cpuSubType); _fileType=tMach64HeaderPtr->filetype; if (self.shouldSwap==YES) _fileType=OSSwapBigToHostInt32(_fileType); _flags=tMach64HeaderPtr->flags; if (self.shouldSwap==YES) _flags=OSSwapBigToHostInt32(_flags); tLoadCommandsNumber=tMach64HeaderPtr->ncmds; if (self.shouldSwap==YES) tLoadCommandsNumber=OSSwapBigToHostInt32(tLoadCommandsNumber); /*tLoadCommandsTotalSize=tMach64HeaderPtr->sizeofcmds; if (self.shouldSwap==YES) tLoadCommandsTotalSize=OSSwapBigToHostInt32(tLoadCommandsTotalSize);*/ tFutureBufferOffset=sizeof(struct mach_header_64); } else { // Unknow architecture return nil; } if (tLoadCommandsNumber>0) { _loadCommandsArray=[NSMutableArray array]; _segmentsArray=[NSMutableArray array]; _segmentsIndex=[NSMutableDictionary dictionary]; for(uint32_t tLoadCommandIndex=0;tLoadCommandIndex=self.bufferSize) { // Buffer too small return nil; } tFutureBufferOffset-=sizeof(struct load_command); struct load_command * tLoadCommandPtr=(struct load_command *)(self.buffer+tFutureBufferOffset); uint32_t tLoadCommandType=tLoadCommandPtr->cmd; if (self.shouldSwap==YES) tLoadCommandType=OSSwapBigToHostInt32(tLoadCommandType); uint32_t tLoadCommandSize=tLoadCommandPtr->cmdsize; if (self.shouldSwap==YES) tLoadCommandSize=OSSwapBigToHostInt32(tLoadCommandSize); switch(tLoadCommandType) { case LC_SEGMENT: case LC_SYMTAB: case LC_SYMSEG: case LC_THREAD: case LC_UNIXTHREAD: case LC_LOADFVMLIB: case LC_IDFVMLIB: case LC_IDENT: case LC_FVMFILE: case LC_PREPAGE: case LC_DYSYMTAB: case LC_LOAD_DYLIB: case LC_ID_DYLIB: case LC_LOAD_DYLINKER: case LC_ID_DYLINKER: case LC_PREBOUND_DYLIB: case LC_ROUTINES: case LC_SUB_FRAMEWORK: case LC_SUB_UMBRELLA: case LC_SUB_CLIENT: case LC_SUB_LIBRARY: case LC_TWOLEVEL_HINTS: case LC_PREBIND_CKSUM: case LC_LOAD_WEAK_DYLIB: case LC_SEGMENT_64: case LC_ROUTINES_64: case LC_UUID: case LC_RPATH: case LC_CODE_SIGNATURE: case LC_SEGMENT_SPLIT_INFO: case LC_REEXPORT_DYLIB: case LC_LAZY_LOAD_DYLIB: case LC_ENCRYPTION_INFO: case LC_DYLD_INFO: case LC_DYLD_INFO_ONLY: case LC_LOAD_UPWARD_DYLIB: case LC_VERSION_MIN_MACOSX: case LC_VERSION_MIN_IPHONEOS: case LC_FUNCTION_STARTS: case LC_DYLD_ENVIRONMENT: case LC_MAIN: case LC_DATA_IN_CODE: case LC_SOURCE_VERSION: case LC_DYLIB_CODE_SIGN_DRS: case LC_ENCRYPTION_INFO_64: case LC_LINKER_OPTION: case LC_LINKER_OPTIMIZATION_HINT: case LC_BUILD_VERSION: { MCHLoadCommand * tLoadCommand=[[MCHLoadCommand alloc] initWithBytes:self.buffer+tFutureBufferOffset length:tLoadCommandSize swap:self.shouldSwap architecture:self.architecture objectFile:self]; if (tLoadCommand!=nil) { [_loadCommandsArray addObject:tLoadCommand]; if (tLoadCommandType==LC_SEGMENT || tLoadCommandType==LC_SEGMENT_64) { MCHSegmentLoadCommand * tSegmentLoadCommand=(MCHSegmentLoadCommand *)tLoadCommand; MCHSegment * tSegment=tSegmentLoadCommand.segment; if (tSegment!=nil) { [_segmentsArray addObject:tSegment]; if (tSegment.name!=nil) [_segmentsIndex setObject:tSegment forKey:tSegment.name]; } } } else { NSLog(@"Error initialization load command 0x%04x (0x%08x,%u)",tLoadCommandType,(uint32_t)tFutureBufferOffset,(uint32_t)tLoadCommandSize); } tFutureBufferOffset+=tLoadCommandSize; break; } default: // Unknown load command NSLog(@"Unknow load command: %d",tLoadCommandType); tFutureBufferOffset+=tLoadCommandSize; break; } } } } return self; } - (instancetype)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength { if (inBytes!=nil && inLength>sizeof(uint32_t)) { uint32_t tMagicNumber=*((uint32_t *)inBytes); switch(tMagicNumber) { case MH_MAGIC: return [self initWithBytes:inBytes length:inLength swap:NO architecture:MCHArchitecture32]; case MH_CIGAM: return [self initWithBytes:inBytes length:inLength swap:YES architecture:MCHArchitecture32]; case MH_MAGIC_64: return [self initWithBytes:inBytes length:inLength swap:NO architecture:MCHArchitecture64]; case MH_CIGAM_64: return [self initWithBytes:inBytes length:inLength swap:NO architecture:MCHArchitecture64]; default: // Unknown architecture break; } } return nil; } #pragma mark - - (NSString *)description { NSMutableString * tMutableString=[NSMutableString string]; [tMutableString appendFormat:@"mach-o file (%@)\n",(self.architecture==MCHArchitecture32)? @"32-bit" : @"64-bit"]; NSString * tFileType=nil; switch(self.fileType) { case MH_OBJECT: tFileType=@"Object File"; break; case MH_EXECUTE: tFileType=@"Executable"; break; case MH_FVMLIB: tFileType=@"VM Shared Library File"; break; case MH_CORE: tFileType=@"Core File"; break; case MH_PRELOAD: tFileType=@"Preloaded Executable"; break; case MH_DYLIB: tFileType=@"Dynamic Shared Library"; break; case MH_BUNDLE: tFileType=@"Dynamically Bound Bundle File"; break; case MH_DSYM: tFileType=@"Companion file with only debug sections"; break; default: tFileType=@"Description forthcoming"; break; } [tMutableString appendFormat:@"type: %@\n",tFileType]; NSString * tCPUType=nil; switch(self.cpuType) { case CPU_TYPE_I386: tCPUType=@"i386"; break; case CPU_TYPE_X86_64: tCPUType=@"x86_64"; break; case CPU_TYPE_POWERPC: tCPUType=@"ppc"; break; case CPU_TYPE_POWERPC64: tCPUType=@"ppc64"; break; case CPU_TYPE_ARM: tCPUType=@"arm"; break; case CPU_TYPE_ARM64: tCPUType=@"arm64"; break; default: tCPUType=@"Unknown"; break; } [tMutableString appendFormat:@"CPU: %@\n",tCPUType]; [tMutableString appendFormat:@"%d load commands:\n",(int) self.allLoadCommands.count]; [self.allLoadCommands enumerateObjectsUsingBlock:^(MCHLoadCommand * bLoadCommand, NSUInteger bIndex, BOOL * bOutStop){ [tMutableString appendString:[bLoadCommand description]]; [tMutableString appendString:@"\n"]; }]; [tMutableString appendString:@"\n"]; return [tMutableString copy]; } #pragma mark - - (NSArray *)allLoadCommands { return _loadCommandsArray; } - (NSArray *)loadCommandsOfType:(uint32_t)inType { NSMutableArray * tMutableArray=[NSMutableArray array]; for( MCHLoadCommand * tLoadCommand in self.allLoadCommands) { if (tLoadCommand.type==inType) [tMutableArray addObject:tLoadCommand]; } return [tMutableArray copy]; } #pragma mark - - (NSArray *)allSegments { return _segmentsArray; } - (MCHSegment *)segmentNamed:(NSString *)inName { if (inName!=nil) return [_segmentsIndex objectForKey:inName]; return nil; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHSection.h ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHMemoryBufferWrapper.h" @class MCHObjectFile; @interface MCHSection : MCHMemoryBufferWrapper @property (readonly) MCHObjectFile * objectFile; @property (readonly) NSString *name; @property (readonly) NSString *segmentName; @property (readonly) uint64_t address; - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture objectFile:(MCHObjectFile *)inObjectFile; - (const char *)bytesAtAddress:(uint64_t)inAddress; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHSection.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHSection.h" #import "MCHObjectFile.h" #include @implementation MCHSection - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture objectFile:( MCHObjectFile *)inObjectFile; { if (inBytes==NULL) return nil; NSString * tSectionName=nil; NSString * tSegmentName=nil; uint32_t tOffset=0; uint64_t tSize=0; uint32_t tFlags=0; uint64_t tAddress=0; if (inArchitecture==MCHArchitecture32) { struct section * tSection32Ptr=(struct section *)inBytes; char cStringBuffer[17]; memset(cStringBuffer,0,17); memcpy(cStringBuffer,tSection32Ptr->sectname,16); tSectionName=[[NSString alloc] initWithCString:cStringBuffer encoding:NSASCIIStringEncoding]; memset(cStringBuffer,0,17); memcpy(cStringBuffer,tSection32Ptr->segname,16); tSegmentName=[[NSString alloc] initWithCString:cStringBuffer encoding:NSASCIIStringEncoding]; uint32_t tAddress32=tSection32Ptr->addr; if (inSwap==YES) tAddress32=OSSwapBigToHostInt32(tAddress32); tAddress=tAddress32; uint32_t tSize32=tSection32Ptr->size; if (inSwap==YES) tSize32=OSSwapBigToHostInt32(tSize32); tSize=tSize32; tOffset=tSection32Ptr->offset; if (inSwap==YES) tOffset=OSSwapBigToHostInt32(tOffset); tFlags=tSection32Ptr->flags; if (inSwap==YES) tFlags=OSSwapBigToHostInt32(tFlags); } else if (inArchitecture==MCHArchitecture64) { struct section_64 * tSection64Ptr=(struct section_64 *)inBytes; char cStringBuffer[17]; memset(cStringBuffer,0,17); memcpy(cStringBuffer,tSection64Ptr->sectname,16); tSectionName=[[NSString alloc] initWithCString:cStringBuffer encoding:NSASCIIStringEncoding]; memset(cStringBuffer,0,17); memcpy(cStringBuffer,tSection64Ptr->segname,16); tSegmentName=[[NSString alloc] initWithCString:cStringBuffer encoding:NSASCIIStringEncoding]; uint64_t tAddress64=tSection64Ptr->addr; if (inSwap==YES) tAddress64=OSSwapBigToHostInt64(tAddress64); tAddress=tAddress64; uint64_t tSize64=tSection64Ptr->size; if (inSwap==YES) tSize64=OSSwapBigToHostInt64(tSize64); tSize=tSize64; tOffset=tSection64Ptr->offset; if (inSwap==YES) tOffset=OSSwapBigToHostInt32(tOffset); tFlags=tSection64Ptr->flags; if (inSwap==YES) tFlags=OSSwapBigToHostInt32(tFlags); } else { // Unknown architecture return nil; } uint32_t tType=tFlags&SECTION_TYPE; id tSection=nil; switch (tType) { case S_CSTRING_LITERALS: break; case S_ZEROFILL: break; default: if (tSection==nil) tSection=[super initWithBytes:inObjectFile.buffer+tOffset length:(NSUInteger)tSize swap:inSwap architecture:inArchitecture]; break; } self=tSection; if (self!=nil) { _objectFile=inObjectFile; _name=tSectionName; _segmentName=tSegmentName; _address=tAddress; } return self; } - (void)dealloc { _objectFile=nil; } #pragma mark - - (NSUInteger)hash { return self.name.hash; } - (NSString *)description { return [NSString stringWithFormat:@" <0x%08llx> (%@,%@)\n",_address,_segmentName,_name]; } #pragma mark - - (const char *)bytesAtAddress:(uint64_t)inAddress { return self.buffer+(inAddress-self.address); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHSegment.h ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHMemoryBufferWrapper.h" #import "MCHSection.h" @interface MCHSegment : MCHMemoryBufferWrapper @property (readonly) NSString * name; - (id)initWithName:(NSString *)inName sections:(NSArray *)inSections memoryBufferWrapper:(MCHMemoryBufferWrapper *)inMemoryBufferWrapper; @property (nonatomic,readonly) NSArray * allSections; - (MCHSection *)sectionNamed:(NSString *)inName; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHSegment.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHSegment.h" @interface MCHSegment () { NSArray * _sections; NSDictionary *_sectionsIndex; } @end @implementation MCHSegment - (id)initWithName:(NSString *)inName sections:(NSArray *)inSections memoryBufferWrapper:(MCHMemoryBufferWrapper *)inMemoryBufferWrapper { self=[super initWithBytes:inMemoryBufferWrapper.buffer length:inMemoryBufferWrapper.bufferSize swap:inMemoryBufferWrapper.shouldSwap architecture:inMemoryBufferWrapper.architecture]; if (self!=nil) { _name=inName; _sections=inSections; NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; [_sections enumerateObjectsUsingBlock:^(MCHSection * bSection, NSUInteger bIndex, BOOL * bOutStop){ if (bSection.name!=nil) tMutableDictionary[bSection.name]=bSection; }]; _sectionsIndex=[tMutableDictionary copy]; } return self; } #pragma mark - - (NSUInteger)hash { return self.name.hash; } - (NSString *)description { return @"Description forthcoming"; } #pragma mark - - (NSArray *)allSections { return _sections; } - (MCHSection *)sectionNamed:(NSString *)inName { return _sectionsIndex[inName]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHSegmentLoadCommand.h ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHLoadCommand.h" #import "MCHSegment.h" @interface MCHSegmentLoadCommand : MCHLoadCommand @property (readonly) MCHSegment * segment; @property (readonly) uint32_t flags; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/Mach-o/MCHSegmentLoadCommand.m ================================================ /* Copyright (c) 2020-2023, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "MCHSegmentLoadCommand.h" #include #import "MCHObjectFile.h" @interface MCHSegmentLoadCommand () { NSMutableArray *_sectionsArray; } @end @implementation MCHSegmentLoadCommand - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture objectFile:(MCHObjectFile *)inObjectFile { if (inLength>=sizeof(struct segment_command)) { self=[super initWithBytes:inBytes length:inLength swap:inSwap architecture:inArchitecture]; if (self!=nil) { NSString * tSegmentName=nil; MCHMemoryBufferWrapper * tMemoryBufferWrapper=nil; uint32_t tFlags=0; uint32_t tNumberOfSections=0; const char * tReadBuffer=NULL; if (inArchitecture==MCHArchitecture32) { struct segment_command * tSegmentCommand32Ptr=(struct segment_command *)inBytes; tSegmentName=[[NSString alloc] initWithCString:tSegmentCommand32Ptr->segname encoding:NSASCIIStringEncoding]; uint32_t tOffset=tSegmentCommand32Ptr->fileoff; if (self.shouldSwap==YES) tOffset=OSSwapBigToHostInt32(tOffset); uint32_t tSize=tSegmentCommand32Ptr->filesize; if (self.shouldSwap==YES) tSize=OSSwapBigToHostInt32(tSize); tFlags=tSegmentCommand32Ptr->flags; if (self.shouldSwap==YES) tFlags=OSSwapBigToHostInt32(tFlags); tNumberOfSections=tSegmentCommand32Ptr->nsects; if (self.shouldSwap==YES) tNumberOfSections=OSSwapBigToHostInt32(tNumberOfSections); tReadBuffer=inBytes+sizeof(struct segment_command); tMemoryBufferWrapper=[[MCHMemoryBufferWrapper alloc] initWithBytes:inObjectFile.buffer+tOffset length:tSize swap:inSwap architecture:inArchitecture]; } else if (inArchitecture==MCHArchitecture64) { struct segment_command_64 * tSegmentCommand64Ptr=(struct segment_command_64 *)inBytes; tSegmentName=[[NSString alloc] initWithCString:tSegmentCommand64Ptr->segname encoding:NSASCIIStringEncoding]; uint64_t tOffset=tSegmentCommand64Ptr->fileoff; if (self.shouldSwap==YES) tOffset=OSSwapBigToHostInt64(tOffset); uint64_t tSize=tSegmentCommand64Ptr->filesize; if (self.shouldSwap==YES) tSize=OSSwapBigToHostInt64(tSize); tFlags=tSegmentCommand64Ptr->flags; if (self.shouldSwap==YES) tFlags=OSSwapBigToHostInt32(tFlags); tNumberOfSections=tSegmentCommand64Ptr->nsects; if (self.shouldSwap==YES) tNumberOfSections=OSSwapBigToHostInt32(tNumberOfSections); tMemoryBufferWrapper=[[MCHMemoryBufferWrapper alloc] initWithBytes:inObjectFile.buffer+tOffset length:tSize swap:inSwap architecture:inArchitecture]; tReadBuffer=inBytes+sizeof(struct segment_command_64); } else { // Unknown architecture return nil; } _flags=tFlags; NSMutableArray * tMutableArray=[NSMutableArray array]; if (tNumberOfSections>0) { for(uint32_t tSectionIndex=0;tSectionIndex @implementation MCHUUIDLoadCommand - (id)initWithBytes:(const char *)inBytes length:(NSUInteger)inLength swap:(BOOL)inSwap architecture:(MCHArchitecture)inArchitecture objectFile:(MCHObjectFile *)inObjectFile { if (inLengthuuid]; } return self; } #pragma mark - - (NSString *)description { NSMutableString * tMutableString=[NSMutableString string]; [tMutableString appendString:@"LC_UUID command:\n"]; [tMutableString appendFormat:@" uuid: %@\n",_uuid.UUIDString]; return [tMutableString copy]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/NSBundle+dSYM.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSBundle (dSYM) @property (readonly,getter=isDSYMBundle) BOOL dSYMBundle; @property (readonly) NSArray * binaryUUIDs; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/NSBundle+dSYM.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSBundle+dSYM.h" #import "MCHMachBinary.h" #import "MCHUUIDLoadCommand.h" #import "MCHSegmentLoadCommand.h" #include #include @interface NSBundle (dSYM_Private) - (NSString *)symbolsFilePath; @end @implementation NSBundle (dSYM) - (NSString *)symbolsFilePath { NSString * tDWARFFolderPath=[self pathForResource:@"DWARF" ofType:nil]; if (tDWARFFolderPath==nil) return nil; NSArray * tArray=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:tDWARFFolderPath error:NULL]; if (tArray.count!=1) return nil; return [tDWARFFolderPath stringByAppendingPathComponent:tArray.firstObject]; } #pragma mark - - (BOOL)isDSYMBundle { NSString * tPath=self.bundlePath; if ([tPath.pathExtension isEqualToString:@"dSYM"]==NO) return NO; NSString * tPackageType=[self objectForInfoDictionaryKey:@"CFBundlePackageType"]; if ([tPackageType isKindOfClass:NSString.class]==NO) return NO; if ([tPackageType isEqualToString:@"dSYM"]==NO) return NO; NSString * tDWARFFilePath=[self symbolsFilePath]; if (tDWARFFilePath==nil) return NO; // Check that this is a mach-o file NSFileHandle * tFileHandle= [NSFileHandle fileHandleForReadingAtPath:tDWARFFilePath]; NSData * tData = [tFileHandle readDataOfLength:sizeof(uint32_t)]; [tFileHandle closeFile]; uint32_t tMagicHeader=0; [tData getBytes:&tMagicHeader length:sizeof(uint32_t)]; switch(tMagicHeader) { case MH_MAGIC: case MH_CIGAM: case MH_MAGIC_64: case MH_CIGAM_64: return YES; case FAT_MAGIC: case FAT_CIGAM: return YES; default: break; } return NO; } - (NSArray *)binaryUUIDs { NSMutableArray * tMutableArray=[NSMutableArray array]; NSString * tPath=[self symbolsFilePath]; MCHMachBinary * tMachBinary=[[MCHMachBinary alloc] initWithContentsOfFile:tPath]; //NSLog(@"%@",[tMachBinary description]); [[tMachBinary allObjectFiles] enumerateObjectsUsingBlock:^(MCHObjectFile * bObjectFile, NSUInteger bIndex, BOOL * bOutStop) { if (bObjectFile.fileType!=MH_DSYM) return; NSArray * tUUIDLoadCommands=[bObjectFile loadCommandsOfType:LC_UUID]; MCHUUIDLoadCommand * tUUIDLoadCommand=tUUIDLoadCommands.firstObject; NSString * tUUIDString=tUUIDLoadCommand.uuid.UUIDString; if (tUUIDString!=nil) [tMutableArray addObject:tUUIDString]; }]; return [tMutableArray copy]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/NSCrashLogTextScrollView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSCrashLogTextScrollView : NSScrollView @end ================================================ FILE: app_unexpectedly/app_unexpectedly/NSCrashLogTextScrollView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSCrashLogTextScrollView.h" @implementation NSCrashLogTextScrollView - (void)tile { [super tile]; if (self.rulersVisible==YES) { NSRect tBounds=self.bounds; NSScroller * tHorizontalScroller=self.horizontalScroller; NSRect tScrollerFrame=tHorizontalScroller.frame; if (tHorizontalScroller.hidden==NO && self.scrollerStyle==NSScrollerStyleLegacy) { NSRulerView * tRulerView=self.verticalRulerView; NSRect tRulerFrame=tRulerView.frame; tRulerFrame.origin.y=0; tRulerFrame.size.height=NSMaxY(tBounds)-NSHeight(tScrollerFrame); tRulerView.frame=tRulerFrame; self.scrollerInsets=NSEdgeInsetsMake(0,-NSWidth(tRulerView.frame), 0, 0); } } else { if (fabs(self.scrollerInsets.left)>1) self.scrollerInsets=NSEdgeInsetsMake(0,0,0,0); } } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/NSFileManager+ExtendedAttributes.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSFileManager (ExtendedAttributes) - (NSDictionary *)WB_extendedAttributesOfItemAtURL:(NSURL *)inURL error:(NSError *__autoreleasing *)outError; - (NSDictionary *)WB_extendedAttributesOfItemAtPath:(NSString *)inPath error:(NSError *__autoreleasing *)outError; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/NSFileManager+ExtendedAttributes.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "NSFileManager+ExtendedAttributes.h" //#include //#include #include @implementation NSFileManager (ExtendedAttributes) + (id)WB_objectFromData:(NSData *)inData extendedAttributeName:(NSString *)inAttributeName { // A COMPLETER return inData; } - (NSDictionary *)WB_extendedAttributesOfItemAtURL:(NSURL *)inURL error:(NSError *__autoreleasing *)outError { if (inURL==nil || inURL.isFileURL==NO) return nil; return [self WB_extendedAttributesOfItemAtPath:inURL.path error:outError]; } - (NSDictionary *)WB_extendedAttributesOfItemAtPath:(NSString *)inPath error:(NSError *__autoreleasing *)outError { if (inPath==nil) return nil; const char * tCPath=[inPath fileSystemRepresentation]; if (tCPath==NULL) { NSLog(@"Unable to get file system representation for path: %@",inPath); return nil; } int tFileDescriptor=open(tCPath,O_RDONLY|O_NOFOLLOW); if (tFileDescriptor==-1) { if (errno==ELOOP) // Symbolic link return [NSDictionary dictionary]; if (outError!=NULL) { NSError * tUnderlyingError; switch(errno) { case EACCES: *outError=[NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadNoPermissionError userInfo:nil]; return nil; case ENOENT: tUnderlyingError=[NSError errorWithDomain:NSPOSIXErrorDomain code:ENOENT userInfo:nil]; *outError=[NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadNoSuchFileError userInfo:@{NSFilePathErrorKey:inPath, NSUnderlyingErrorKey:tUnderlyingError}]; return nil; default: *outError=[NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadUnknownError userInfo:nil]; return nil; } } return nil; } ssize_t tBufferSize=flistxattr(tFileDescriptor,NULL,0,0); if (tBufferSize==-1) { if (errno==ENOTSUP) return [NSDictionary dictionary]; if (outError!=NULL) *outError=[NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadUnknownError userInfo:nil]; close(tFileDescriptor); return nil; } if (tBufferSize==0) return [NSDictionary dictionary]; char * tBuffer=(char *)malloc(tBufferSize*sizeof(char)); if (tBuffer==NULL) { if (outError!=NULL) *outError=[NSError errorWithDomain:NSPOSIXErrorDomain code:ENOMEM userInfo:nil]; close(tFileDescriptor); return nil; } ssize_t tReadBufferSize=flistxattr(tFileDescriptor, tBuffer, tBufferSize, 0); if (tReadBufferSize==-1) { if (errno==ENOTSUP) { free(tBuffer); close(tFileDescriptor); return [NSDictionary dictionary]; } if (outError!=NULL) *outError=[NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadUnknownError userInfo:nil]; free(tBuffer); close(tFileDescriptor); return nil; } char * tBufferEnd=tBuffer+tReadBufferSize; NSMutableDictionary * tExtendedAttributes=[NSMutableDictionary dictionary]; for(char * tAttributeNamePtr=tBuffer;tAttributeNamePtr @interface WBRemoteVersionChecker : NSObject @property (nonatomic,getter=isCheckEnabled) BOOL checkEnabled; + (WBRemoteVersionChecker *)sharedChecker; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/WBRemoteVersionChecker.m ================================================ /* Copyright (c) 2012-2024 Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "WBRemoteVersionChecker.h" #define WBREMOTEVERSIONREMINDER_PERIOD (24*3600) // Every day #define WBREMOTEVERSIONCHECK_PERIOD (3*24*3600) // Every 3 days NSString * const WBRemoteCheckEnabledKey=@"WBRemoteCheckEnabled"; NSString * const WBRemoteLastCheckDateKey=@"WBRemoteLastCheckDate"; NSString * const WBLastReminderDateKey=@"WBLastReminderDate"; NSString * const WBRemoteAvailableVersionKey=@"WBRemoteAvailableVersion"; NSString * const WBRemoteAvailableVersionURLKey=@"WBRemoteAvailableVersionURL"; NSString * const WBSkipRemoteAvailableVersionKey=@"WBSkipRemoteAvailableVersion"; NSString * const WBVersionCheckURL=@"WBVersionCheckURL"; @interface WBRemoteVersionChecker () { NSString * _productName; NSString * _productLocalVersion; NSString * _productCheckURL; NSUserDefaults * _defaults; } @end @implementation WBRemoteVersionChecker + (void)initialize { [[NSUserDefaults standardUserDefaults] registerDefaults:@{ WBRemoteCheckEnabledKey:@(YES), }]; } + (WBRemoteVersionChecker *)sharedChecker { static dispatch_once_t onceToken; static WBRemoteVersionChecker * sRemoteVersionChecker=nil; dispatch_once(&onceToken, ^{ sRemoteVersionChecker=[WBRemoteVersionChecker new]; }); return sRemoteVersionChecker; } #pragma mark - - (instancetype)init { self=[super init]; if (self!=nil) { NSBundle * tBundle=[NSBundle mainBundle]; _productName=[tBundle objectForInfoDictionaryKey:@"CFBundleName"]; _productLocalVersion=[tBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; _productCheckURL=[tBundle objectForInfoDictionaryKey:WBVersionCheckURL]; _defaults=[NSUserDefaults standardUserDefaults]; if (_productLocalVersion.length>0) { NSDate * tCurrentDate=[NSDate date]; if ([_defaults boolForKey:WBSkipRemoteAvailableVersionKey]==NO) { NSString * tRemoteVersion=[_defaults objectForKey:WBRemoteAvailableVersionKey]; if (tRemoteVersion!=nil) { if ([tRemoteVersion compare:_productLocalVersion options:NSNumericSearch]==NSOrderedDescending) { NSDate * tLastReminderDate=[_defaults objectForKey:WBLastReminderDateKey]; if (tLastReminderDate==nil || [tCurrentDate timeIntervalSinceDate:tLastReminderDate]>WBREMOTEVERSIONREMINDER_PERIOD) { NSString * tDownloadURL=[_defaults objectForKey:WBRemoteAvailableVersionURLKey]; if (tDownloadURL!=nil) { // Display dialog NSAlert * tAlert=[NSAlert new]; tAlert.messageText=[NSString stringWithFormat:NSLocalizedStringFromTable(@"A new version of %@ is available.",@"RemoteCheck",@""),_productName]; tAlert.informativeText=[NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ %@ is now available - you have %@. Would you like to download it now?",@"RemoteCheck",@""),_productName,tRemoteVersion,_productLocalVersion]; [tAlert addButtonWithTitle:NSLocalizedStringFromTable(@"Download",@"RemoteCheck",@"")]; [tAlert addButtonWithTitle:NSLocalizedStringFromTable(@"Skip This Version",@"RemoteCheck",@"")]; [tAlert addButtonWithTitle:NSLocalizedStringFromTable(@"Remind Me Later",@"RemoteCheck",@"")]; NSModalResponse tResponse=[tAlert runModal]; switch(tResponse) { case NSAlertFirstButtonReturn: // Download [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:tDownloadURL]]; [_defaults setObject:[NSDate date] forKey:WBLastReminderDateKey]; break; case NSAlertSecondButtonReturn: // Skip [_defaults setBool:YES forKey:WBSkipRemoteAvailableVersionKey]; break; case NSAlertThirdButtonReturn: // Remind me later [_defaults setObject:[NSDate date] forKey:WBLastReminderDateKey]; break; default: break; } } } } } } if (_productCheckURL.length>0) { NSUserDefaults *defaults = _defaults; // Check whether it's time to check for a newer version BOOL tCheckEnabled=[defaults boolForKey:WBRemoteCheckEnabledKey]; if (tCheckEnabled==YES) { NSDate * tLastCheckDate=[defaults objectForKey:WBRemoteLastCheckDateKey]; if (tLastCheckDate!=nil && ([tCurrentDate timeIntervalSinceDate:tLastCheckDate]<=WBREMOTEVERSIONCHECK_PERIOD)) return self; // Perform Remote Check NSURLSessionConfiguration * tURLSessionConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; NSURLSession * tURLSession = [NSURLSession sessionWithConfiguration:tURLSessionConfiguration]; NSURLSessionDataTask * tDataTask = [tURLSession dataTaskWithURL:[NSURL URLWithString:_productCheckURL] completionHandler:^(NSData *bData, NSURLResponse *bResponse, NSError *bError) { if (bData==nil) { NSLog(@"Unable to retrieve last available remove version: %@.", bError); return; } if (bResponse!=nil) { NSHTTPURLResponse * tHTTPResponse=(NSHTTPURLResponse *)bResponse; switch (tHTTPResponse.statusCode) { case 200: break; default: NSLog(@"HTTP Response status: %ld", tHTTPResponse.statusCode); break; } } [defaults setObject:[NSDate date] forKey:WBRemoteLastCheckDateKey]; NSPropertyListFormat tPropertyListFormat; NSDictionary * tDictionary=[NSPropertyListSerialization propertyListWithData:bData options:NSPropertyListImmutable format:&tPropertyListFormat error:NULL]; if (tDictionary==nil) { NSLog(@"Unable to deserialize downloaded data into a property list."); return; } NSString * tRemoteVersion=tDictionary[WBRemoteAvailableVersionKey]; NSString * tLocalRemoteVersion=[defaults objectForKey:WBRemoteAvailableVersionKey]; if (tLocalRemoteVersion!=nil && [tRemoteVersion compare:tLocalRemoteVersion options:NSNumericSearch]!=NSOrderedDescending) { return; } if (self->_productLocalVersion!=nil) { if ([tRemoteVersion compare:self->_productLocalVersion options:NSNumericSearch]==NSOrderedDescending) { NSString * tRemoteURL=[tDictionary objectForKey:WBRemoteAvailableVersionURLKey]; if (tRemoteURL!=nil) { [defaults setObject:tRemoteURL forKey:WBRemoteAvailableVersionURLKey]; [defaults setObject:tRemoteVersion forKey:WBRemoteAvailableVersionKey]; [defaults setBool:NO forKey:WBSkipRemoteAvailableVersionKey]; } } } }]; if (tDataTask==nil) { NSLog(@"Could not allocate NSURLSessionDataTask"); } else { [tDataTask resume]; } } } } } return self; } #pragma mark - - (BOOL)isCheckEnabled { id tObject=[_defaults objectForKey:WBRemoteCheckEnabledKey]; if (tObject==nil || [_defaults boolForKey:WBRemoteCheckEnabledKey]==YES) return YES; return NO; } - (void)setCheckEnabled:(BOOL)inBool { [_defaults setBool:inBool forKey:WBRemoteCheckEnabledKey]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/app_unexpectedly_Prefix.pch ================================================ /* Copyright (c) 2020-2024, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __OBJC__ #import #define CUIAppkitMinimumPushButtonWidth 82.0 // Foundation Extensions #import "NSArray+WBExtensions.h" // AppKit Extensions #import "NSResponder+Appearance.h" #import "NSColor+LabelColor.h" #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 #define WBControlStateValueOn NSControlStateValueOn #define WBControlStateValueOff NSControlStateValueOff #define WBPasteboardTypeString NSPasteboardTypeString #else #define WBControlStateValueOn NSOnState #define WBControlStateValueOff NSOffState #define WBPasteboardTypeString NSStringPboardType @protocol NSFontChanging @end @protocol NSMenuItemValidation @end #endif #endif ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIApplicationIconView.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUIWatchPart.h" @interface CUIApplicationIconView : NSView @property (nonatomic) CUIWatchRenderingMode renderingMode; - (NSData *)PNGData; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIApplicationIconView.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIApplicationIconView.h" #import "CUIWatchGear.h" #import "CUIWatchBridge.h" #import "CUIWatchJewel.h" #import "CUIWatchScrew.h" #import "CUIWatchAxis.h" static void CGPathToBezierPathApplierFunction(void *info, const CGPathElement *element) { NSBezierPath *bezierPath = (__bridge NSBezierPath *)info; CGPoint *points = element->points; switch(element->type) { case kCGPathElementMoveToPoint: [bezierPath moveToPoint:points[0]]; break; case kCGPathElementAddLineToPoint: [bezierPath lineToPoint:points[0]]; break; case kCGPathElementAddQuadCurveToPoint: { NSPoint qp0 = bezierPath.currentPoint, qp1 = points[0], qp2 = points[1], cp1, cp2; CGFloat m = (2.0 / 3.0); cp1.x = (qp0.x + ((qp1.x - qp0.x) * m)); cp1.y = (qp0.y + ((qp1.y - qp0.y) * m)); cp2.x = (qp2.x + ((qp1.x - qp2.x) * m)); cp2.y = (qp2.y + ((qp1.y - qp2.y) * m)); [bezierPath curveToPoint:qp2 controlPoint1:cp1 controlPoint2:cp2]; break; } case kCGPathElementAddCurveToPoint: [bezierPath curveToPoint:points[2] controlPoint1:points[0] controlPoint2:points[1]]; break; case kCGPathElementCloseSubpath: [bezierPath closePath]; break; } } @interface NSBezierPath (BezierPathWithCGPath) + (NSBezierPath *)JNS_bezierPathWithCGPath:(CGPathRef)cgPath; //prefixed as Apple may add bezierPathWithCGPath: method someday @end @implementation NSBezierPath (BezierPathWithCGPath) + (NSBezierPath *)JNS_bezierPathWithCGPath:(CGPathRef)cgPath { NSBezierPath *bezierPath = [NSBezierPath bezierPath]; CGPathApply(cgPath, (__bridge void *)bezierPath, CGPathToBezierPathApplierFunction); return bezierPath; } @end @interface CUIApplicationIconView () { CGFloat _ratio; NSTimer * _timer; CGFloat _rotation; NSMutableArray * _parts; } @end @implementation CUIApplicationIconView - (void)awakeFromNib { } #pragma mark - - (NSBezierPath *)centerBridgePath { NSRect tBounds=self.bounds; NSPoint tCenter=NSMakePoint(NSMidX(tBounds),(0.6*NSHeight(tBounds))); NSBezierPath * tBezierPath=[NSBezierPath bezierPath]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*102, tCenter.y-_ratio*8) radius:_ratio*90 startAngle:10 endAngle:65 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*57, tCenter.y+_ratio*98) radius:_ratio*25 startAngle:250 endAngle:200 clockwise:YES]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*95, tCenter.y+_ratio*85) radius:_ratio*15 startAngle:12 endAngle:246 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*105, tCenter.y+_ratio*56) radius:_ratio*15 startAngle:70 endAngle:-43 clockwise:YES]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*62, tCenter.y+_ratio*25) radius:_ratio*38 startAngle:149 endAngle:180 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*136, tCenter.y+_ratio*25) radius:_ratio*36 startAngle:0 endAngle:-120 clockwise:YES]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x-_ratio*166, tCenter.y-_ratio*30)]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*156, tCenter.y-_ratio*75) radius:_ratio*36 startAngle:65 endAngle:-20 clockwise:YES]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*144, tCenter.y+_ratio*20) radius:_ratio*120 startAngle:-70 endAngle:-20 clockwise:NO]; [tBezierPath closePath]; NSBezierPath * tHolePath=[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(tCenter.x-_ratio*86, tCenter.y-_ratio*30,_ratio*60,_ratio*80)]; [tBezierPath appendBezierPath:tHolePath]; tBezierPath.windingRule=NSWindingRuleEvenOdd; return tBezierPath; } - (NSBezierPath *)leftBridge { NSRect tBounds=self.bounds; NSPoint tCenter=NSMakePoint(NSMidX(tBounds),(0.6*NSHeight(tBounds))); NSBezierPath * tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(tCenter.x-_ratio*320,tCenter.y-_ratio*230)]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*53, tCenter.y-_ratio*96) radius:_ratio*210 startAngle:220 endAngle:150 clockwise:YES]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*136, tCenter.y+_ratio*25) radius:_ratio*15 startAngle:320 endAngle:160 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*237, tCenter.y+_ratio*80) radius:_ratio*100 startAngle:-30 endAngle:180 clockwise:YES]; [tBezierPath closePath]; return tBezierPath; } - (NSBezierPath *)topBridgePath { NSRect tBounds=self.bounds; NSPoint tCenter=NSMakePoint(NSMidX(tBounds),(0.6*NSHeight(tBounds))); NSBezierPath * tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(tCenter.x+_ratio*170,tCenter.y+_ratio*80)]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x+_ratio*155,tCenter.y+_ratio*45)]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*40, tCenter.y+_ratio*55) radius:_ratio*70 startAngle:20 endAngle:65 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x, tCenter.y+_ratio*120) radius:_ratio*70 startAngle:0 endAngle:120 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*78, tCenter.y+_ratio*126) radius:_ratio*70 startAngle:55 endAngle:120 clockwise:NO]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x-_ratio*40,tCenter.y+_ratio*310)]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x+_ratio*40,tCenter.y+_ratio*310)]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x+_ratio*180,tCenter.y+_ratio*85)]; [tBezierPath closePath]; return tBezierPath; } - (NSBezierPath *)rightBridgePath { NSRect tBounds=self.bounds; NSPoint tCenter=NSMakePoint(NSMidX(tBounds),(0.6*NSHeight(tBounds))); NSBezierPath * tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(tCenter.x+_ratio*230,tCenter.y-_ratio*50)]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x+_ratio*180,tCenter.y+_ratio*100)]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*165,tCenter.y) radius:_ratio*124 startAngle:90 endAngle:166 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*28,tCenter.y+_ratio*38) radius:_ratio*18 startAngle:340 endAngle:240 clockwise:YES]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x,tCenter.y) radius:_ratio*29 startAngle:50 endAngle:170 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*126, tCenter.y+_ratio*25) radius:_ratio*100 startAngle:350 endAngle:268 clockwise:YES]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*137, tCenter.y-_ratio*86) radius:_ratio*10 startAngle:90 endAngle:180 clockwise:NO]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*53, tCenter.y-_ratio*86) radius:_ratio*200 startAngle:180 endAngle:280 clockwise:NO]; [tBezierPath closePath]; NSBezierPath * tHolePath=[NSBezierPath bezierPath]; [tHolePath moveToPoint:NSMakePoint(tCenter.x+_ratio*168,tCenter.y+_ratio*30)]; [tHolePath lineToPoint:NSMakePoint(tCenter.x+_ratio*158,tCenter.y+_ratio*30)]; [tHolePath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*112,tCenter.y) radius:_ratio*51 startAngle:60 endAngle:194 clockwise:NO]; [tHolePath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*38, tCenter.y-_ratio*110) radius:_ratio*100 startAngle:77 endAngle:35 clockwise:NO]; [tHolePath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x+_ratio*112,tCenter.y) radius:_ratio*51 startAngle:278 endAngle:330 clockwise:NO]; [tHolePath lineToPoint:NSMakePoint(tCenter.x+_ratio*168,tCenter.y-_ratio*25)]; [tHolePath closePath]; [tHolePath appendBezierPathWithOvalInRect:NSMakeRect(tCenter.x-_ratio*9,tCenter.y-_ratio*8,_ratio*18.0,_ratio*18.0)]; [tBezierPath appendBezierPath:tHolePath]; tBezierPath.windingRule=NSWindingRuleEvenOdd; return tBezierPath; } - (void)viewDidMoveToWindow { if (self.window==nil) { [_timer invalidate]; _timer=nil; return; } NSRect tBounds=self.bounds; CGFloat tIconSize=NSWidth(tBounds); _ratio=NSWidth(tBounds)/1024.0; NSPoint tCenter=NSMakePoint(NSMidX(tBounds),(0.6*NSHeight(tBounds))); _parts=[NSMutableArray array]; CUIWatchGear * tGear5_60_Template=[CUIWatchGear new]; // 5 branches / 60 teeth tGear5_60_Template.outsideRadius=_ratio*59; tGear5_60_Template.axisRadius=_ratio*3; tGear5_60_Template.innerRadius=_ratio*20; tGear5_60_Template.innerBranchesCount=5; tGear5_60_Template.innerBranchThickness=_ratio*7.0; tGear5_60_Template.bezelRadius=_ratio*50; tGear5_60_Template.numberOfTeeth=60; tGear5_60_Template.wholeDepth=_ratio*6; tGear5_60_Template.addendum=_ratio*2; tGear5_60_Template.circularToothThickness=_ratio*4; tGear5_60_Template.toothTop=_ratio*2; tGear5_60_Template.rotation=10.0; tGear5_60_Template.gradient=[[NSGradient alloc] initWithColors:@[[NSColor colorWithDeviceRed:255/255.0 green:249/255.0 blue:231/255.0 alpha:1.0], [NSColor colorWithDeviceRed:245/255.0 green:242/255.0 blue:217/255.0 alpha:1.0], ]]; tGear5_60_Template.borderColor=[NSColor colorWithDeviceWhite:0.0 alpha:0.25]; // 3 branches / 0 teeth CUIWatchGear * tGear3_0=[CUIWatchGear new]; tGear3_0.outsideRadius=_ratio*95; tGear3_0.axisRadius=_ratio*8; tGear3_0.innerRadius=_ratio*20; tGear3_0.innerBranchesCount=3; if (tIconSize>64.0) { tGear3_0.innerBranchThickness=_ratio*10.0; } else { tGear3_0.innerBranchThickness=_ratio*30.0; } tGear3_0.gradient=[[NSGradient alloc] initWithColors:@[[NSColor colorWithDeviceRed:227/255.0 green:173/255.0 blue:102/255.0 alpha:1.0], [NSColor colorWithDeviceRed:246/255.0 green:187/255.0 blue:59/255.0 alpha:1.0], ]]; // 0 branches / 8 teeth CUIWatchGear * tGear0_8=[CUIWatchGear new]; tGear0_8.outsideRadius=_ratio*10; tGear0_8.axisRadius=_ratio*2; tGear0_8.innerBranchesCount=0; tGear0_8.numberOfTeeth=8; tGear0_8.wholeDepth=_ratio*5; tGear0_8.circularToothThickness=_ratio*3; tGear0_8.toothTop=_ratio*2; tGear0_8.addendum=_ratio*4; tGear0_8.gradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.8 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.5 alpha:1.0]]; tGear0_8.borderColor=[NSColor colorWithDeviceWhite:0.6 alpha:0.5]; // 0 branches / 30 teeth CUIWatchGear * tGear0_30=[CUIWatchGear new]; tGear0_30.outsideRadius=_ratio*46; tGear0_30.axisRadius=_ratio*13; tGear0_30.innerBranchesCount=0; if (tIconSize>128.0) { tGear0_30.bezelRadius=_ratio*32; tGear0_30.numberOfTeeth=30; } tGear0_30.wholeDepth=_ratio*9.0; tGear0_30.addendum=_ratio*5.0; tGear0_30.toothTop=_ratio*3; tGear0_30.circularToothThickness=_ratio*5.0; tGear0_30.gradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.8 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.5 alpha:1.0]]; // 0 branches / 60 teeth CUIWatchGear * tGear0_60=[CUIWatchGear new]; tGear0_60.outsideRadius=_ratio*94; tGear0_60.axisRadius=_ratio*13; tGear0_60.innerBranchesCount=0; if (tIconSize>128.0) { tGear0_60.numberOfTeeth=60; } tGear0_60.circularToothThickness=_ratio*5; tGear0_60.wholeDepth=_ratio*10; tGear0_60.addendum=_ratio*4; tGear0_60.toothTop=_ratio*3; tGear0_60.gradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.8 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.3 alpha:1.0]]; // 4 branches / 0 teeth CUIWatchGear * tGear4_0=[CUIWatchGear new]; tGear4_0.outsideRadius=_ratio*45; tGear4_0.axisRadius=_ratio*3; tGear4_0.innerRadius=_ratio*10; tGear4_0.innerBranchesCount=4; if (tIconSize>128.0) { tGear4_0.innerBranchThickness=7*_ratio; } else { tGear4_0.innerBranchThickness=14*_ratio; } tGear4_0.numberOfTeeth=0; tGear4_0.gradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.8 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.3 alpha:1.0]]; // Screw CUIWatchScrew * tWatchScrew_Template=[CUIWatchScrew new]; tWatchScrew_Template.radius=_ratio*14; // Place gears if (tIconSize>32.0) { tGear4_0.center=NSMakePoint(tCenter.x-_ratio*75, tCenter.y+_ratio*140); [_parts addObject:tGear4_0]; } CUIWatchAxis * tAxis1=[CUIWatchAxis new]; tAxis1.center=NSMakePoint(tCenter.x-_ratio*75, tCenter.y+_ratio*140); tAxis1.radius=_ratio*6.0; [_parts addObject:tAxis1]; // Center bridge if (tIconSize>64) { CUIWatchBridge * tCenterBridge=[CUIWatchBridge new]; tCenterBridge.bezierPath=[self centerBridgePath]; [_parts addObject:tCenterBridge]; CUIWatchScrew * tCenterBridgeScrew1=[tWatchScrew_Template copy]; tCenterBridgeScrew1.radius=_ratio*10; tCenterBridgeScrew1.rotation=-40; tCenterBridgeScrew1.center=NSMakePoint(tCenter.x-_ratio*105, tCenter.y-_ratio*30); [_parts addObject:tCenterBridgeScrew1]; } if (tIconSize>128.0) { CUIWatchJewel * tCenterJewel=[CUIWatchJewel new]; tCenterJewel.center=NSMakePoint(tCenter.x-_ratio*95, tCenter.y+_ratio*85); tCenterJewel.radius=_ratio*4.0; [_parts addObject:tCenterJewel]; } if (tIconSize>64.0) { CUIWatchGear * tGearYellow1=[tGear5_60_Template copy]; tGearYellow1.center=NSMakePoint(tCenter.x+_ratio*28, tCenter.y+_ratio*60); tGearYellow1.ticker = ^CGFloat{ return 1.0/60; }; [_parts addObject:tGearYellow1]; } tGear0_8.center=NSMakePoint(tCenter.x+_ratio*28, tCenter.y+_ratio*60); tGear0_8.ticker = ^CGFloat{ return 1.0/60; }; [_parts addObject:tGear0_8]; CUIWatchGear * tGearOrange=tGear3_0; tGearOrange.center=NSMakePoint(tCenter.x-_ratio*136, tCenter.y+_ratio*25); tGearOrange.ticker = ^CGFloat{ return 0.1; }; [_parts addObject:tGearOrange]; CUIWatchGear * tGearYellow2=[tGear5_60_Template copy]; tGearYellow2.center=NSMakePoint(tCenter.x, tCenter.y); tGearYellow2.ticker = ^CGFloat{ return -1.0/3600; }; [_parts addObject:tGearYellow2]; CUIWatchGear * tGearYellow3=[tGear5_60_Template copy]; tGearYellow3.center=NSMakePoint(tCenter.x, tCenter.y+_ratio*120); tGearYellow3.ticker = ^CGFloat{ return -1.0/3600; }; [_parts addObject:tGearYellow3]; CUIWatchAxis * tAxix3=[CUIWatchAxis new]; tAxix3.center=NSMakePoint(tCenter.x, tCenter.y+_ratio*120); tAxix3.radius=_ratio*4.0; [_parts addObject:tAxix3]; tGear0_8.center=NSMakePoint(tCenter.x+_ratio*28, tCenter.y+_ratio*60); [_parts addObject:tGear0_8]; // Top Bridge CUIWatchBridge * tTopBridge=[CUIWatchBridge new]; tTopBridge.bezierPath=[self topBridgePath]; [_parts addObject:tTopBridge]; CUIWatchScrew * tTopBridgeScrew1=[tWatchScrew_Template copy]; tTopBridgeScrew1.center=NSMakePoint(tCenter.x+_ratio, tCenter.y+_ratio*230); tTopBridgeScrew1.rotation=12.0; [_parts addObject:tTopBridgeScrew1]; // Left Bridge CUIWatchBridge * tLeftBridge=[CUIWatchBridge new]; tLeftBridge.bezierPath=[self leftBridge]; [_parts addObject:tLeftBridge]; CUIWatchScrew * tLeftBridgeScrew1=[tWatchScrew_Template copy]; tLeftBridgeScrew1.center=NSMakePoint(tCenter.x-_ratio*210, tCenter.y-_ratio*80); [_parts addObject:tLeftBridgeScrew1]; if (tIconSize>128.0) { CUIWatchJewel * tLeftJewel=[CUIWatchJewel new]; tLeftJewel.center=NSMakePoint(tCenter.x-_ratio*136, tCenter.y+_ratio*25); tLeftJewel.radius=_ratio*5.0; [_parts addObject:tLeftJewel]; } // Right bridge CUIWatchBridge * tRightBridge=[CUIWatchBridge new]; tRightBridge.bezierPath=[self rightBridgePath]; [_parts addObject:tRightBridge]; CUIWatchScrew * tRightBridgeScrew1=[tWatchScrew_Template copy]; tRightBridgeScrew1.center=NSMakePoint(tCenter.x+_ratio*140, tCenter.y+_ratio*80); tRightBridgeScrew1.rotation=95; [_parts addObject:tRightBridgeScrew1]; CUIWatchScrew * tRightBridgeScrew2=[tWatchScrew_Template copy]; tRightBridgeScrew2.center=NSMakePoint(tCenter.x-_ratio*115, tCenter.y-_ratio*105); tRightBridgeScrew2.rotation=15; [_parts addObject:tRightBridgeScrew2]; CUIWatchGear * tGearGray60=tGear0_60; tGearGray60.center=NSMakePoint(tCenter.x+_ratio*38, tCenter.y-_ratio*110); tGearGray60.ticker = ^CGFloat{ return 0.25; }; [_parts addObject:tGearGray60]; CUIWatchScrew * tRightBridgeScrew3=[tWatchScrew_Template copy]; tRightBridgeScrew3.center=NSMakePoint(tCenter.x+_ratio*38, tCenter.y-_ratio*110); tRightBridgeScrew3.rotation=-35; [_parts addObject:tRightBridgeScrew3]; CUIWatchGear * tGearGray30=tGear0_30; tGearGray30.center=NSMakePoint(tCenter.x+_ratio*112, tCenter.y); tGearGray30.rotation=6; tGearGray30.ticker = ^CGFloat{ return -0.5; }; [_parts addObject:tGearGray30]; CUIWatchScrew * tRightBridgeScrew4=[tWatchScrew_Template copy]; tRightBridgeScrew4.center=NSMakePoint(tCenter.x+_ratio*112, tCenter.y); tRightBridgeScrew4.rotation=-35; [_parts addObject:tRightBridgeScrew4]; CUIWatchAxis * tAxix2=[CUIWatchAxis new]; tAxix2.center=NSMakePoint(tCenter.x, tCenter.y); tAxix2.radius=_ratio*6.0; [_parts addObject:tAxix2]; _timer=[NSTimer scheduledTimerWithTimeInterval:0.05 repeats:YES block:^(NSTimer * _Nonnull timer) { /*_rotation+=2.0; if (_rotation>360.0) _rotation-=360.0; */ [self setNeedsDisplay:YES]; }]; //self.renderingMode=CUIWatchRenderingModeWireframe; } - (NSBezierPath *)roundedTrianglePathCenteredAt:(NSPoint)inCenter withBaseLength:(CGFloat)inLength radius:(CGFloat)inRadius { CGFloat width=inLength,height=0.866025*inLength; CGFloat tThirdOfHeight=height/3; CGPoint point1=CGPointMake(inCenter.x-width / 2, inCenter.y-tThirdOfHeight); CGPoint point2=CGPointMake(inCenter.x, inCenter.y+2*tThirdOfHeight); CGPoint point3=CGPointMake(inCenter.x+width / 2, inCenter.y-tThirdOfHeight); CGMutablePathRef tMutablePathRef=CGPathCreateMutable(); CGPathMoveToPoint(tMutablePathRef, NULL, inCenter.x, inCenter.y-tThirdOfHeight); CGPathAddArcToPoint(tMutablePathRef,NULL, point1.x,point1.y,point2.x,point2.y,inRadius); CGPathAddArcToPoint(tMutablePathRef,NULL, point2.x,point2.y,point3.x,point3.y,inRadius); CGPathAddArcToPoint(tMutablePathRef,NULL, point3.x,point3.y,point1.x,point1.y,inRadius); CGPathCloseSubpath(tMutablePathRef); return [NSBezierPath JNS_bezierPathWithCGPath:tMutablePathRef]; } #pragma mark - - (void)setRenderingMode:(CUIWatchRenderingMode)inRenderingMode { _renderingMode=inRenderingMode; for(CUIWatchPart * tPart in _parts) tPart.renderingMode=inRenderingMode; [self setNeedsDisplay:YES]; } - (void)drawRect:(NSRect)dirtyRect { NSRect tBounds=self.bounds; CGFloat tIconSize=NSWidth(tBounds); /*[[NSColor windowBackgroundColor] set]; NSRectFill(tBounds); [[NSColor lightGrayColor] set]; NSFrameRect(tBounds);*/ NSShadow *shadow=nil; NSPoint tCenter=NSMakePoint(NSMidX(tBounds),(0.41*NSHeight(tBounds))); NSBezierPath * tBezierPath=[self roundedTrianglePathCenteredAt:tCenter withBaseLength:_ratio*1096 radius:_ratio*100]; tBezierPath.lineWidth=1.0; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; } else { shadow = [NSShadow new]; shadow.shadowOffset = NSMakeSize(0, -10*_ratio); shadow.shadowBlurRadius = _ratio*20; shadow.shadowColor = [NSColor colorWithWhite:0 alpha:0.2]; [NSGraphicsContext saveGraphicsState]; [shadow set]; [[NSColor whiteColor] set]; [tBezierPath fill]; [NSGraphicsContext restoreGraphicsState]; [[NSColor colorWithWhite:0.0 alpha:0.1] set]; [tBezierPath stroke]; } tBezierPath=[self roundedTrianglePathCenteredAt:tCenter withBaseLength:_ratio*940 radius:_ratio*54]; NSGradient * tGradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.35 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.30 alpha:1.0]]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; } else { [tGradient drawInBezierPath:tBezierPath angle:90]; } /*[[NSColor blackColor] set]; [tBezierPath fill];*/ /*tBezierPath.lineWidth=_ratio*12.0; [[NSColor colorWithWhite:0.35 alpha:0.9] set]; [tBezierPath stroke];*/ //[tBezierPath fill]; /*shadow = [NSShadow new]; shadow.shadowOffset = NSMakeSize(0, 10); shadow.shadowBlurRadius =40; shadow.shadowColor = [NSColor redColor]; [NSGraphicsContext saveGraphicsState]; [shadow set]; */ [NSGraphicsContext saveGraphicsState]; tBezierPath=[self roundedTrianglePathCenteredAt:tCenter withBaseLength:_ratio*920 radius:_ratio*54]; [tBezierPath setClip]; for(CUIWatchPart * tPart in _parts) { if ([tPart isKindOfClass:CUIWatchGear.class]==YES) { [(CUIWatchGear *)tPart tick]; } [tPart draw]; } [NSGraphicsContext restoreGraphicsState]; NSBezierPath * tClipPath=[NSBezierPath bezierPath]; [tClipPath moveToPoint:NSMakePoint(NSMinX(tBounds),NSMinY(tBounds))]; [tClipPath lineToPoint:NSMakePoint(NSMaxX(tBounds),NSMinY(tBounds))]; [tClipPath lineToPoint:NSMakePoint(NSMaxX(tBounds),0.65*NSMaxY(tBounds))]; [tClipPath lineToPoint:NSMakePoint(NSMinX(tBounds),0.35*NSMaxY(tBounds))]; [tClipPath closePath]; [NSGraphicsContext saveGraphicsState]; [tClipPath addClip]; tBezierPath=[self roundedTrianglePathCenteredAt:tCenter withBaseLength:_ratio*940 radius:_ratio*54]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [NSGraphicsContext restoreGraphicsState]; tBezierPath.lineWidth=_ratio*12.0; [[NSColor textColor] setStroke]; [tBezierPath stroke]; tBezierPath.lineWidth=_ratio*1.0; [[NSColor textColor] setStroke]; [tBezierPath stroke]; } else { tGradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:254/255.0 green:227.0/255.0 blue:101.0/255.0 alpha:1.0] endingColor:[NSColor colorWithDeviceRed:255.0/255.0 green:212.0/255.0 blue:59.0/255.0 alpha:1.0]]; [tGradient drawInBezierPath:tBezierPath angle:270]; [NSGraphicsContext restoreGraphicsState]; tBezierPath.lineWidth=_ratio*12.0; [[NSColor colorWithWhite:0.35 alpha:0.9] setStroke]; [tBezierPath stroke]; tBezierPath.lineWidth=_ratio*1.0; [[NSColor colorWithWhite:0.0 alpha:0.1] setStroke]; [tBezierPath stroke]; } // ! tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(tCenter.x-_ratio*29,tCenter.y+_ratio*83)]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x-_ratio*15,tCenter.y-_ratio*21)]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x,tCenter.y-_ratio*20) radius:_ratio*15 startAngle:192 endAngle:348 clockwise:NO]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x+_ratio*31,tCenter.y+_ratio*101)]; [tBezierPath closePath]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; } else { shadow = [NSShadow new]; shadow.shadowOffset = NSMakeSize(0, -5*_ratio); shadow.shadowBlurRadius =_ratio*5; shadow.shadowColor = [NSColor colorWithDeviceWhite:0.2 alpha:0.6]; [NSGraphicsContext saveGraphicsState]; [shadow set]; [[NSColor colorWithDeviceWhite:0.35 alpha:1.0] setFill]; [tBezierPath fill]; [NSGraphicsContext restoreGraphicsState]; [[NSColor blackColor] set]; [tBezierPath stroke]; tGradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.40 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.20 alpha:1.0]]; [tGradient drawInBezierPath:tBezierPath angle:270]; } CGFloat tDiskRadius=_ratio*51.0; tBezierPath=[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(tCenter.x-tDiskRadius,tCenter.y-tDiskRadius-_ratio*130,2*tDiskRadius,2*tDiskRadius)]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; } else { [NSGraphicsContext saveGraphicsState]; [shadow set]; [[NSColor colorWithDeviceWhite:0.35 alpha:1.0] setFill]; [tBezierPath fill]; [NSGraphicsContext restoreGraphicsState]; tGradient=[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.35 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.15 alpha:1.0]]; [tGradient drawInBezierPath:tBezierPath angle:270]; [[NSColor colorWithDeviceWhite:0.2 alpha:0.8] setFill]; [tBezierPath fill]; } // Universal Key if (tIconSize>16.0) { NSBezierPath * tHandlePath=[NSBezierPath bezierPath]; [tHandlePath moveToPoint:NSMakePoint(0, 20)]; [tHandlePath lineToPoint:NSMakePoint(711,20)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(711, 0) radius:20 startAngle:90 endAngle:0 clockwise:YES]; [tHandlePath lineToPoint:NSMakePoint(731,-120)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(736, -120) radius:5 startAngle:180 endAngle:270 clockwise:NO]; [tHandlePath lineToPoint:NSMakePoint(786,-125)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(786, -120) radius:5 startAngle:270 endAngle:0 clockwise:NO]; [tHandlePath lineToPoint:NSMakePoint(791,135)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(786, 135) radius:5 startAngle:0 endAngle:90 clockwise:NO]; [tHandlePath lineToPoint:NSMakePoint(736,140)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(736, 135) radius:5 startAngle:90 endAngle:180 clockwise:NO]; [tHandlePath lineToPoint:NSMakePoint(731,30)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(728, 30) radius:3 startAngle:0 endAngle:225 clockwise:YES]; [tHandlePath lineToPoint:NSMakePoint(711,40)]; [tHandlePath lineToPoint:NSMakePoint(711,140)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(731, 140) radius:20 startAngle:180 endAngle:90 clockwise:YES]; [tHandlePath lineToPoint:NSMakePoint(791,160)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(791, 140) radius:20 startAngle:90 endAngle:0 clockwise:YES]; [tHandlePath lineToPoint:NSMakePoint(811,-125)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(791, -125) radius:20 startAngle:0 endAngle:270 clockwise:YES]; [tHandlePath lineToPoint:NSMakePoint(731,-145)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(731, -125) radius:20 startAngle:270 endAngle:180 clockwise:YES]; [tHandlePath lineToPoint:NSMakePoint(711,-5)]; [tHandlePath appendBezierPathWithArcWithCenter:NSMakePoint(706, -5) radius:5 startAngle:0 endAngle:90 clockwise:NO]; [tHandlePath lineToPoint:NSMakePoint(0,0)]; [tHandlePath closePath]; NSAffineTransform * tAffineTransform=[NSAffineTransform transform]; [tAffineTransform scaleBy:_ratio]; [tAffineTransform translateXBy:180 yBy:352]; [tAffineTransform rotateByDegrees:17.0]; [tHandlePath transformUsingAffineTransform:tAffineTransform]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] set]; [tHandlePath stroke]; } else { shadow = [NSShadow new]; shadow.shadowOffset = NSMakeSize(0, -8*_ratio); shadow.shadowBlurRadius =_ratio*10; shadow.shadowColor = [NSColor colorWithDeviceWhite:0.3 alpha:0.65]; [NSGraphicsContext saveGraphicsState]; [shadow set]; [[NSColor colorWithDeviceWhite:0.5 alpha:1.0] set]; [tHandlePath fill]; [NSGraphicsContext restoreGraphicsState]; /*tGradient=[[NSGradient alloc] initWithColorsAndLocations:[NSColor colorWithDeviceWhite:0.55 alpha:0.5],0.0, [NSColor colorWithDeviceWhite:0.6 alpha:1.0],0.45, [NSColor colorWithDeviceWhite:0.90 alpha:1.0],0.5, [NSColor colorWithDeviceWhite:0.6 alpha:1.0],0.55, [NSColor colorWithDeviceWhite:0.75 alpha:1.0],1.0,nil];*/ tHandlePath.lineWidth=1.0; [[NSColor colorWithDeviceWhite:0.40 alpha:1.0] set]; [tHandlePath stroke]; //[[NSColor colorWithDeviceWhite:0.4 alpha:1.0] setFill]; //[tHandlePath fill]; //[tGradient drawInBezierPath:tHandlePath angle:286.5]; } // Metal effect if (self.renderingMode!=CUIWatchRenderingModeWireframe) { [NSGraphicsContext saveGraphicsState]; [tHandlePath addClip]; NSBezierPath * tWhiteGlare=[NSBezierPath bezierPath]; [tWhiteGlare moveToPoint:NSMakePoint(2, 10)]; [tWhiteGlare lineToPoint:NSMakePoint(711,10)]; [tWhiteGlare appendBezierPathWithArcWithCenter:NSMakePoint(711, 0) radius:10 startAngle:90 endAngle:0 clockwise:YES]; [tWhiteGlare lineToPoint:NSMakePoint(721,-125)]; [tWhiteGlare appendBezierPathWithArcWithCenter:NSMakePoint(731, -125) radius:10 startAngle:180 endAngle:270 clockwise:NO]; [tWhiteGlare lineToPoint:NSMakePoint(791,-135)]; [tWhiteGlare appendBezierPathWithArcWithCenter:NSMakePoint(791, -125) radius:10 startAngle:270 endAngle:0 clockwise:NO]; [tWhiteGlare lineToPoint:NSMakePoint(801,140)]; [tWhiteGlare appendBezierPathWithArcWithCenter:NSMakePoint(791, 140) radius:10 startAngle:0 endAngle:90 clockwise:NO]; [tWhiteGlare lineToPoint:NSMakePoint(731,150)]; [tWhiteGlare appendBezierPathWithArcWithCenter:NSMakePoint(731, 140) radius:10 startAngle:90 endAngle:180 clockwise:NO]; [tWhiteGlare lineToPoint:NSMakePoint(721,25)]; [tWhiteGlare transformUsingAffineTransform:tAffineTransform]; [tWhiteGlare setLineWidth:18*_ratio]; [[NSColor colorWithDeviceWhite:0.56 alpha:1.0] set]; [tWhiteGlare stroke]; [tWhiteGlare setLineWidth:16*_ratio]; [[NSColor colorWithDeviceWhite:0.60 alpha:1.0] set]; [tWhiteGlare stroke]; [tWhiteGlare setLineWidth:14*_ratio]; [[NSColor colorWithDeviceWhite:0.65 alpha:1.0] set]; [tWhiteGlare stroke]; [tWhiteGlare setLineWidth:11*_ratio]; [[NSColor colorWithDeviceWhite:0.72 alpha:1.0] set]; [tWhiteGlare stroke]; [tWhiteGlare setLineWidth:5*_ratio]; [[NSColor colorWithDeviceWhite:0.81 alpha:1.0] set]; [tWhiteGlare stroke]; [tWhiteGlare setLineWidth:3*_ratio]; [[NSColor colorWithDeviceWhite:0.9 alpha:1.0] set]; [tWhiteGlare stroke]; [tWhiteGlare setLineWidth:1]; [[NSColor colorWithDeviceWhite:1.0 alpha:1.0] set]; [tWhiteGlare stroke]; [NSGraphicsContext restoreGraphicsState]; // Encoche tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(0+_ratio*590,10)]; [tBezierPath lineToPoint:NSMakePoint(0+_ratio*605,10)]; [tBezierPath transformUsingAffineTransform:tAffineTransform]; tBezierPath.lineWidth=4.0*_ratio; [[NSColor colorWithDeviceWhite:0.0 alpha:0.55] setStroke]; [tBezierPath stroke]; } } // Curl tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(tCenter.x-_ratio*310,tCenter.y+_ratio*1)]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*455,tCenter.y-_ratio*204) radius:250*_ratio startAngle:55 endAngle:30.5 clockwise:YES]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x+_ratio*240,tCenter.y+_ratio*65)]; [tBezierPath lineToPoint:NSMakePoint(tCenter.x+_ratio*220,tCenter.y+_ratio*160)]; [tBezierPath closePath]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; } else { shadow = [NSShadow new]; shadow.shadowOffset = NSMakeSize(0, 0); shadow.shadowBlurRadius =_ratio*10; shadow.shadowColor = [NSColor colorWithDeviceWhite:0.2 alpha:1.0]; [NSGraphicsContext saveGraphicsState]; [shadow set]; [[NSColor colorWithDeviceWhite:0.5 alpha:1.0] setFill]; [tBezierPath fill]; [NSGraphicsContext restoreGraphicsState]; tGradient=[[NSGradient alloc] initWithColorsAndLocations:[NSColor colorWithDeviceWhite:0.25 alpha:1.0],0.0, [NSColor colorWithDeviceWhite:0.5 alpha:1.0],0.25, [NSColor colorWithDeviceWhite:0.90 alpha:1.0],0.5, [NSColor colorWithDeviceWhite:0.5 alpha:1.0],0.75, [NSColor colorWithDeviceRed:67/255.0 green:66.0/255.0 blue:11.0/255.0 alpha:1.0],1.0,nil]; [tGradient drawInBezierPath:tBezierPath angle:287]; [[NSColor colorWithDeviceWhite:0.0 alpha:0.2] setStroke]; [tBezierPath stroke]; [[NSColor colorWithDeviceWhite:0.2 alpha:0.08] setStroke]; } tBezierPath=[NSBezierPath bezierPath]; [tBezierPath appendBezierPathWithArcWithCenter:NSMakePoint(tCenter.x-_ratio*450,tCenter.y-_ratio*202) radius:250*_ratio startAngle:54 endAngle:30.5 clockwise:YES]; [tBezierPath stroke]; if (tIconSize>128.0) { [NSBezierPath strokeLineFromPoint:NSMakePoint(tCenter.x-_ratio*28,tCenter.y+_ratio*85) toPoint:NSMakePoint(tCenter.x-_ratio*3,tCenter.y-_ratio*8)]; [NSBezierPath strokeLineFromPoint:NSMakePoint(tCenter.x+_ratio*28,tCenter.y+_ratio*101) toPoint:NSMakePoint(tCenter.x+_ratio*62,tCenter.y+_ratio*12)]; [NSBezierPath strokeLineFromPoint:NSMakePoint(tCenter.x+_ratio*233,tCenter.y+_ratio*64) toPoint:NSMakePoint(tCenter.x+_ratio*215,tCenter.y+_ratio*157)]; } } - (NSData *)PNGData { NSBitmapImageRep * tBitmapImageRep=[self bitmapImageRepForCachingDisplayInRect:self.bounds]; [self cacheDisplayInRect:self.bounds toBitmapImageRep:tBitmapImageRep]; NSData * tData = [tBitmapImageRep representationUsingType:NSBitmapImageFileTypePNG properties:@{}]; return tData; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchAxis.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchPart.h" @interface CUIWatchAxis : CUIWatchPart @property NSPoint center; @property CGFloat radius; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchAxis.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchAxis.h" @implementation CUIWatchAxis - (NSGradient *)gradient { return [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:1.0 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.2 alpha:1.0]]; } - (void)draw { NSBezierPath * tBezierPath=[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(self.center.x-self.radius, self.center.y-self.radius, self.radius*2.0, self.radius*2.0)]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; return; } [self.gradient drawInBezierPath:tBezierPath relativeCenterPosition:NSMakePoint(0.0,0.75)]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchBridge.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchPart.h" @interface CUIWatchBridge : CUIWatchPart @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchBridge.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchBridge.h" @implementation CUIWatchBridge - (NSGradient *)gradient { return [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.60 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.50 alpha:1.0]]; return [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.75 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.65 alpha:1.0]]; } + (NSImage *)brushedMetalTransparentTexture { return [NSImage imageNamed:@"brushed-alum"]; } - (void)draw { NSBezierPath * tBezierPath=self.bezierPath; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; return; } NSShadow * tShadow = [NSShadow new]; tShadow.shadowOffset = NSMakeSize(0, 2); tShadow.shadowBlurRadius = 20; tShadow.shadowColor = [NSColor colorWithDeviceWhite:0.1 alpha:0.75]; [NSGraphicsContext saveGraphicsState]; [tShadow set]; [[NSColor blackColor] set]; [tBezierPath fill]; [NSGraphicsContext restoreGraphicsState]; [self.gradient drawInBezierPath:tBezierPath angle:270]; [NSGraphicsContext saveGraphicsState]; NSImage * tImage=[CUIWatchBridge brushedMetalTransparentTexture]; [tBezierPath addClip]; [tImage drawAtPoint:tBezierPath.bounds.origin fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0]; [NSGraphicsContext restoreGraphicsState]; tBezierPath.lineWidth=1.0; [[NSColor colorWithDeviceWhite:0.0 alpha:0.3] setStroke]; [tBezierPath stroke]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchDrawablePart.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @protocol CUIWatchDrawablePart - (NSBezierPath *)bezierPath; - (NSGradient *)gradient; @optional - (void)draw; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchGear.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchPart.h" @interface CUIWatchGear : CUIWatchPart @property NSPoint center; @property CGFloat outsideRadius; @property (nonatomic,readonly) CGFloat rootRadius; @property NSUInteger numberOfTeeth; @property CGFloat circularToothThickness; @property CGFloat wholeDepth; @property CGFloat addendum; @property (nonatomic,readonly) CGFloat dedendum; @property CGFloat toothTop; @property CGFloat axisRadius; @property CGFloat innerRadius; @property CGFloat bezelRadius; @property NSUInteger innerBranchesCount; @property CGFloat innerBranchThickness; @property CGFloat rotation; @property (nonatomic, copy) CGFloat (^ticker)(void); - (void)tick; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchGear.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchGear.h" @implementation CUIWatchGear - (CGFloat)rootRadius { return self.outsideRadius-self.wholeDepth; } - (CGFloat)dedendum { return self.wholeDepth-self.addendum; } - (NSBezierPath *)bezierPath { #define RADTODEG(a) (((a)*180.0)/M_PI) #define DEGTORAD(a) (((a)*M_PI)/180.0) CGFloat tNumberOfTeeth=self.numberOfTeeth; CGFloat tRotationRad=DEGTORAD(self.rotation); CGFloat tOutsideRadius=self.outsideRadius; CGFloat tToothWidth=self.circularToothThickness; CGFloat tWholeDepth=self.wholeDepth; NSRect tOuterRect=NSMakeRect(self.center.x-tOutsideRadius,self.center.y-tOutsideRadius,2*tOutsideRadius,2*tOutsideRadius); NSBezierPath * tBezierPath=nil; if (self.numberOfTeeth==0) { tBezierPath=[NSBezierPath bezierPathWithOvalInRect:tOuterRect]; } else { if (self.toothTop>self.circularToothThickness) self.toothTop=self.circularToothThickness; if (self.toothTop<0) self.toothTop=0; CGFloat tRootRadius=self.rootRadius; CGFloat tBottomToothAngle=2.0*asin(tToothWidth*0.5/(tOutsideRadius-tWholeDepth)); CGFloat tTopToothAngle=2.0*asin((tToothWidth*0.5-self.toothTop*0.5)/(tOutsideRadius)); CGFloat tTopInterTeethAngle=(2.0*M_PI-tNumberOfTeeth*tTopToothAngle)/tNumberOfTeeth; CGFloat tBottomInterTeethAngle=(2.0*M_PI-tNumberOfTeeth*tBottomToothAngle)/tNumberOfTeeth; CGFloat tInvoluteAngle=atan(tToothWidth*0.5/(tOutsideRadius-self.addendum)); CGFloat tInvoluteInterTeethAngle=(2.0*M_PI-tNumberOfTeeth*2.0*tInvoluteAngle)/tNumberOfTeeth; CGFloat tInvoluteRadius=sqrt((tOutsideRadius-self.addendum)*(tOutsideRadius-self.addendum)-(tToothWidth*tToothWidth*0.25)); tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(self.center.x+tOutsideRadius*cos(tRotationRad-tTopToothAngle*0.5),self.center.y+tOutsideRadius*sin(tRotationRad-tTopToothAngle*0.5))]; for(NSUInteger tIndex=0;tIndex0.1) { tBezierPath=[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(self.center.x-self.bezelRadius,self.center.y-self.bezelRadius,2.0*self.bezelRadius,2.0*self.bezelRadius)]; [tBezierPath stroke]; } return; } [self.gradient drawInBezierPath:tBezierPath angle:270]; tBezierPath.lineWidth=1.0; if (self.borderColor!=nil) { [self.borderColor setStroke]; [tBezierPath stroke]; } if (self.bezelRadius>0.1) { [[NSColor colorWithDeviceWhite:0.1 alpha:0.2] setStroke]; tBezierPath=[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(self.center.x-self.bezelRadius,self.center.y-self.bezelRadius,2.0*self.bezelRadius,2.0*self.bezelRadius)]; [tBezierPath stroke]; } } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { CUIWatchGear * nGear=[CUIWatchGear new]; nGear.center=self.center; nGear.outsideRadius=self.outsideRadius; nGear.axisRadius=self.axisRadius; nGear.innerRadius=self.innerRadius; nGear.bezelRadius=self.bezelRadius; nGear.innerBranchesCount=self.innerBranchesCount; nGear.innerBranchThickness=self.innerBranchThickness; nGear.numberOfTeeth=self.numberOfTeeth; nGear.circularToothThickness=self.circularToothThickness; nGear.toothTop=self.toothTop; nGear.wholeDepth=self.wholeDepth; nGear.addendum=self.addendum; nGear.rotation=self.rotation; nGear.borderColor=self.borderColor; nGear.gradient=self.gradient; nGear.ticker=self.ticker; return nGear; } #pragma mark - - (void)tick { if (self.ticker==nil) { self.rotation+=1.0; return; } self.rotation+=self.ticker(); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchJewel.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchPart.h" @interface CUIWatchJewel : CUIWatchPart @property NSPoint center; @property CGFloat radius; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchJewel.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchJewel.h" @implementation CUIWatchJewel - (NSGradient *)gradient { return [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:49.0/255.0 green:28.0/255.0 blue:44.0/255.0 alpha:1.0] endingColor:[NSColor colorWithDeviceRed:49.0/255.0 green:28.0/255.0 blue:44.0/255.0 alpha:1.0]]; } - (void)draw { NSBezierPath * tBezierPath=[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(self.center.x-self.radius, self.center.y-self.radius, self.radius*2.0, self.radius*2.0)]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; return; } [self.gradient drawInBezierPath:tBezierPath relativeCenterPosition:NSMakePoint(0.0,-1.0)]; tBezierPath=[NSBezierPath bezierPath]; [tBezierPath appendBezierPathWithArcWithCenter:self.center radius:self.radius startAngle:180.0 endAngle:0.0 clockwise:NO]; [[NSColor colorWithDeviceRed:253.0/255.0 green:56.0/255.0 blue:212.0/255.0 alpha:0.8] setStroke]; [tBezierPath stroke]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchPart.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import typedef NS_ENUM(NSUInteger, CUIWatchRenderingMode) { CUIWatchRenderingModeFull=0, // default CUIWatchRenderingModeWireframe }; @interface CUIWatchPart : NSObject @property CUIWatchRenderingMode renderingMode; @property NSBezierPath * bezierPath; @property NSColor * borderColor; @property NSGradient * gradient; - (void)draw; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchPart.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchPart.h" @implementation CUIWatchPart - (instancetype)init { self=[super init]; if (self!=nil) { _borderColor=[NSColor colorWithDeviceWhite:0.0 alpha:0.5]; } return self; } #pragma mark - - (void)draw { NSBezierPath * tBezierPath=self.bezierPath; if (tBezierPath==nil) return; [self.gradient drawInBezierPath:tBezierPath angle:270]; tBezierPath.lineWidth=1.0; //[[NSColor redColor] set]; /*if ([tPart isKindOfClass:CUIWatchGear.class]==NO) { [[NSColor greenColor] set]; }*/ if (self.borderColor!=nil) { [self.borderColor setStroke]; [tBezierPath stroke]; } } #pragma mark - @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchScrew.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchPart.h" @interface CUIWatchScrew : CUIWatchPart @property NSPoint center; @property CGFloat radius; @property CGFloat rotation; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/clock/CUIWatchScrew.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIWatchScrew.h" @implementation CUIWatchScrew - (NSBezierPath *)bezierPath { NSRect tRect=NSMakeRect(self.center.x-self.radius,self.center.y-self.radius,2*self.radius,2*self.radius); NSBezierPath * tBezierPath=[NSBezierPath bezierPathWithOvalInRect:tRect]; return tBezierPath; } #pragma mark - - (NSGradient *)gradient { return [[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceWhite:0.8 alpha:1.0] endingColor:[NSColor colorWithDeviceWhite:0.7 alpha:1.0]]; } #pragma mark - - (void)draw { NSAffineTransform * tAffineTransform=[NSAffineTransform transform]; [tAffineTransform translateXBy:self.center.x yBy:self.center.y]; NSRect tRect=NSMakeRect(-self.radius,-self.radius,2*self.radius,2*self.radius); NSBezierPath * tBezierPath=[NSBezierPath bezierPathWithOvalInRect:tRect]; [tBezierPath transformUsingAffineTransform:tAffineTransform]; if (self.renderingMode==CUIWatchRenderingModeWireframe) { [[NSColor textColor] setStroke]; [tBezierPath stroke]; [tAffineTransform rotateByDegrees:self.rotation]; tBezierPath=[NSBezierPath bezierPath]; tBezierPath.lineWidth=1.5; [tBezierPath moveToPoint:NSMakePoint(-self.radius+1,0)]; [tBezierPath lineToPoint:NSMakePoint(self.radius,0)]; [tBezierPath transformUsingAffineTransform:tAffineTransform]; [tBezierPath stroke]; return; } [self.gradient drawInBezierPath:tBezierPath angle:270]; tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(-self.radius,0)]; [tBezierPath appendBezierPathWithArcWithCenter:NSZeroPoint radius:self.radius-1 startAngle:180 endAngle:360 clockwise:NO]; tBezierPath.lineWidth=1.0; [[NSColor colorWithWhite:1.0 alpha:0.4] setStroke]; [tBezierPath transformUsingAffineTransform:tAffineTransform]; [tBezierPath stroke]; tBezierPath=[NSBezierPath bezierPath]; [tBezierPath moveToPoint:NSMakePoint(self.radius,0)]; [tBezierPath appendBezierPathWithArcWithCenter:NSZeroPoint radius:self.radius startAngle:0 endAngle:180 clockwise:NO]; tBezierPath.lineWidth=1.0; [[NSColor colorWithWhite:0.3 alpha:0.4] setStroke]; //[[NSColor redColor] set]; [tBezierPath transformUsingAffineTransform:tAffineTransform]; [tBezierPath stroke]; [tAffineTransform rotateByDegrees:self.rotation]; tBezierPath=[NSBezierPath bezierPath]; tBezierPath.lineWidth=1.5; [tBezierPath moveToPoint:NSMakePoint(-self.radius+1,0)]; [tBezierPath lineToPoint:NSMakePoint(self.radius,0)]; [tBezierPath transformUsingAffineTransform:tAffineTransform]; [tBezierPath stroke]; } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { CUIWatchScrew * nScrew=[CUIWatchScrew new]; nScrew.center=self.center; nScrew.radius=self.radius; return nScrew; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/dSYM/CUIdSYMBundle+UI.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIdSYMBundle.h" @interface CUIdSYMBundle (UI) - (NSComparisonResult)compareNameAndVersion:(CUIdSYMBundle *)inOtherBundle; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/dSYM/CUIdSYMBundle+UI.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIdSYMBundle+UI.h" @implementation CUIdSYMBundle (UI) - (NSComparisonResult)compareNameAndVersion:(CUIdSYMBundle *)inOtherBundle { NSComparisonResult tResult=[self.displayName compare:inOtherBundle.displayName]; if (tResult!=NSOrderedSame) return tResult; return [self.displayVersion compare:inOtherBundle.displayVersion options:NSNumericSearch]; } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/dSYM/CUIdSYMBundle.h ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #import "CUISymbolicationData.h" @interface CUIdSYMBundle : NSBundle @property (nonatomic,readonly) NSString * displayName; @property (nonatomic,readonly) NSString * displayVersion; @property (readonly,getter=isDSYMBundle) BOOL dSYMBundle; @property (nonatomic,readonly) NSArray * binaryUUIDs; - (void)lookUpSymbolicationDataForMachineInstructionAddress:(NSUInteger)inAddress binaryUUID:(NSString *)inBinaryUUID completionHandler:(void (^)(CUISymbolicationDataLookUpResult bLookUpResult,CUISymbolicationData * bSymbolicationData))handler; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/dSYM/CUIdSYMBundle.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUIdSYMBundle.h" #import "MCHMachBinary.h" #import "MCHUUIDLoadCommand.h" #import "MCHSegmentLoadCommand.h" #include #include #import "DWRFFileObject.h" #import "CUISymbolicationDataCache.h" @interface CUIdSYMBundle () { NSArray * _cachedBinaryUUIDs; NSDictionary * _machObjectFilesRegistry; NSMutableDictionary * _cachedWARFFileObjectsRegistry; } @property (nonatomic) NSString * displayName; @property (nonatomic) NSString * displayVersion; @property (nonatomic) MCHMachBinary * machBinary; @property (nonatomic,copy) NSString * symbolsFilePath; - (void)lookUpSymbolicationDataForMachineInstructionAddress:(NSUInteger)inAddress binaryUUID:(NSString *)inBinaryUUID queue:(dispatch_queue_t)inQueue completionHandler:(void (^)(CUISymbolicationDataLookUpResult bLookUpResult,CUISymbolicationData * bSymbolicationData))handler; @end @implementation CUIdSYMBundle - (NSString *)displayName { if (_displayName==nil) { _displayName=self.bundlePath.lastPathComponent; } return _displayName; } - (NSString *)displayVersion { if (_displayVersion==nil) { NSString * tBundleShortVersionString=[self objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; if (tBundleShortVersionString==nil) tBundleShortVersionString=@"-"; NSString * tBundleVersionString=[self objectForInfoDictionaryKey:@"CFBundleVersion"]; if (tBundleVersionString==nil) tBundleVersionString=@"-"; _displayVersion=[NSString stringWithFormat:NSLocalizedString(@"%@ (%@)",@""), tBundleShortVersionString, tBundleVersionString ]; } return _displayVersion; } #pragma mark - - (NSString *)symbolsFilePath { NSString * tDWARFFolderPath=[self pathForResource:@"DWARF" ofType:nil]; if (tDWARFFolderPath==nil) return nil; NSArray * tArray=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:tDWARFFolderPath error:NULL]; if (tArray.count!=1) return nil; return [tDWARFFolderPath stringByAppendingPathComponent:tArray.firstObject]; } #pragma mark - - (MCHMachBinary *)machBinary { if (_machBinary==nil) { NSString * tPath=[self symbolsFilePath]; _machBinary=[[MCHMachBinary alloc] initWithContentsOfFile:tPath]; if (_machBinary==nil) { NSLog(@"Error unarchiving mach-o file at path: %@",tPath); } } return _machBinary; } - (BOOL)isDSYMBundle { NSString * tPath=self.bundlePath; if ([tPath.pathExtension isEqualToString:@"dSYM"]==NO) return NO; NSString * tPackageType=[self objectForInfoDictionaryKey:@"CFBundlePackageType"]; if ([tPackageType isKindOfClass:NSString.class]==NO) return NO; if ([tPackageType isEqualToString:@"dSYM"]==NO) return NO; NSString * tDWARFFilePath=[self symbolsFilePath]; if (tDWARFFilePath==nil) return NO; // Check that this is a mach-o file NSFileHandle * tFileHandle= [NSFileHandle fileHandleForReadingAtPath:tDWARFFilePath]; NSData * tData = [tFileHandle readDataOfLength:sizeof(uint32_t)]; [tFileHandle closeFile]; uint32_t tMagicHeader=0; [tData getBytes:&tMagicHeader length:sizeof(uint32_t)]; switch(tMagicHeader) { case MH_MAGIC: case MH_CIGAM: case MH_MAGIC_64: case MH_CIGAM_64: return YES; case FAT_MAGIC: case FAT_CIGAM: return YES; default: break; } return NO; } - (NSArray *)binaryUUIDs { if (_cachedBinaryUUIDs!=nil) return _cachedBinaryUUIDs; NSMutableArray * tMutableArray=[NSMutableArray array]; NSMutableDictionary * tMutableDictionary=[NSMutableDictionary dictionary]; MCHMachBinary * tBinary=self.machBinary; if (tBinary==nil) return nil; [[tBinary allObjectFiles] enumerateObjectsUsingBlock:^(MCHObjectFile * bObjectFile, NSUInteger bIndex, BOOL * bOutStop) { if (bObjectFile.fileType!=MH_DSYM) return; NSArray * tUUIDLoadCommands=[bObjectFile loadCommandsOfType:LC_UUID]; MCHUUIDLoadCommand * tUUIDLoadCommand=tUUIDLoadCommands.firstObject; NSString * tUUIDString=tUUIDLoadCommand.uuid.UUIDString; if (tUUIDString!=nil) { [tMutableArray addObject:tUUIDString]; tMutableDictionary[tUUIDString]=bObjectFile; } }]; _cachedBinaryUUIDs=[tMutableArray copy]; _machObjectFilesRegistry=[tMutableDictionary copy]; return _cachedBinaryUUIDs; } #pragma mark - - (void)lookUpSymbolicationDataForMachineInstructionAddress:(NSUInteger)inAddress binaryUUID:(NSString *)inBinaryUUID completionHandler:(void (^)(CUISymbolicationDataLookUpResult bLookUpResult,CUISymbolicationData * bSymbolicationData))handler; { [self lookUpSymbolicationDataForMachineInstructionAddress:inAddress binaryUUID:inBinaryUUID queue:dispatch_get_main_queue() completionHandler:handler]; } - (void)lookUpSymbolicationDataForMachineInstructionAddress:(NSUInteger)inAddress binaryUUID:(NSString *)inBinaryUUID queue:(dispatch_queue_t)inQueue completionHandler:(void (^)(CUISymbolicationDataLookUpResult bLookUpResult,CUISymbolicationData * bSymbolicationData))handler; { if (handler==nil) { // A COMPLETER return; } if (inBinaryUUID==nil) { handler(CUISymbolicationDataLookUpResultError,nil); return; } // Try to find it as it was the first time if (_machObjectFilesRegistry==nil) { [self binaryUUIDs]; if (_machObjectFilesRegistry.count==0) { handler(CUISymbolicationDataLookUpResultError,nil); return; } } DWRFFileObject * tFileObject=_cachedWARFFileObjectsRegistry[inBinaryUUID]; if (tFileObject==nil) { MCHObjectFile * tMachObjectFile=_machObjectFilesRegistry[inBinaryUUID]; if (tMachObjectFile==nil) { handler(CUISymbolicationDataLookUpResultError,nil); return; } if (_cachedWARFFileObjectsRegistry==nil) _cachedWARFFileObjectsRegistry=[NSMutableDictionary dictionary]; tFileObject=[[DWRFFileObject alloc] initWithMachObjectFile:tMachObjectFile]; if (tFileObject==nil) { handler(CUISymbolicationDataLookUpResultError,nil); return; } _cachedWARFFileObjectsRegistry[inBinaryUUID]=tFileObject; } static dispatch_queue_t sSearchSerialQueue=nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sSearchSerialQueue=dispatch_queue_create("fr.whitebox.unexpectedly.searchqueue", DISPATCH_QUEUE_SERIAL); }); dispatch_async(sSearchSerialQueue, ^{ [tFileObject lookUpSymbolicationDataForMachineInstructionAddress:inAddress completionHandler:^(BOOL bFound, CUISymbolicationData * bSymbolicationData) { dispatch_async(inQueue, ^{ if (bFound==NO) { handler(CUISymbolicationDataLookUpResultNotFound,nil); return; } // Update Cache [[CUISymbolicationDataCache sharedCache] setSymbolicationData:bSymbolicationData forAddress:inAddress binary:inBinaryUUID]; handler(CUISymbolicationDataLookUpResultFound,bSymbolicationData); }); }]; }); } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/default_themes.plist ================================================ UUID UUID2 groups attributes OSCode color 0.700000|0.700000|0.700000 font Menlo-Regular::11.0 background color 0.121569|0.119910|0.140239 font .AppleSystemUIFont::11.0 crashedThreadLabel color 0.989539|0.441258|0.1867240 font Menlo-Bold::11.0 executableCode color 1.000000|1.000000|1.000000 font Menlo-Bold::11.0 key color 0.900000|0.900000|0.900000 font Menlo-Italic::11.0 lineNumber color 0.42|0.42|0.42 font Menlo-Regular::11.0 memoryAddress color 0.589786|0.767791|0.999091 font Menlo-Regular::11.0 path color 0.991982|0.636635|0.991244 font Menlo-Italic::11.0 plaintext color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 registerValue color 0.997655|0.882916|0.443044 font Menlo-Regular::11.0 selection-background color 0.171197|0.532568|0.998515 font .AppleSystemUIFont::11.0 selection-text color 1.000000|1.000000|1.000000 font .AppleSystemUIFont::11.0 threadLabel color 0.668288|1.000000|0.433854 font Menlo-Regular::11.0 uuid color 0.400000|0.400000|0.400000 font Menlo-Regular::11.0 version color 0.848609|0.555776|0.191952 font Menlo-Regular::11.0 identifier Text items background selection-background selection-text plaintext key threadLabel crashedThreadLabel executableCode OSCode memoryAddress registerValue path version uuid name Default (Dark) UUID UUID1 groups attributes OSCode color 0.300000|0.300000|0.300000 font Menlo-Regular::11.0 background color 1.000000|1.000000|1.000000 font .AppleSystemUIFont::11.0 crashedThreadLabel color 0.957716|0.059633|0.075242 font Menlo-Bold::11.0 executableCode color 0.000000|0.000000|0.000000 font Menlo-Bold::11.0 key color 0.157741|0.157741|0.157741 font Menlo-Italic::11.0 lineNumber color 0.42|0.42|0.42 font Menlo-Regular::11.0 memoryAddress color 0.137678|0.193874|0.694335 font Menlo-Regular::11.0 path color 0.595377|0.057079|0.998607 font Menlo-Italic::11.0 plaintext color 0.000000|0.000000|0.000000 font Menlo-Regular::11.0 registerValue color 0.000000|0.000000|0.000000 font Menlo-Regular::11.0 selection-background color 0.817178|0.979453|0.999665 font .AppleSystemUIFont::11.0 selection-text color 0.000000|0.000000|0.000000 font .AppleSystemUIFont::11.0 threadLabel color 0.000000|0.000000|0.000000 font Menlo-Bold::11.0 uuid color 0.500000|0.500000|0.500000 font Menlo-Regular::11.0 version color 0.756722|0.413476|0.180156 font Menlo-Regular::11.0 identifier Text items background selection-background selection-text plaintext key threadLabel crashedThreadLabel executableCode OSCode memoryAddress registerValue path version uuid name Default (Light) UUID 93CC4486-C80B-43A0-BDB2-C05006230798 groups attributes OSCode color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 background color 0.121569|0.119910|0.140239 font .AppleSystemUIFont::11.0 crashedThreadLabel color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 executableCode color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 key color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 lineNumber color 0.42|0.42|0.42 font Menlo-Regular::11.0 memoryAddress color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 path color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 plaintext color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 registerValue color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 selection-background color 0.949198|0.949198|0.949198 font .AppleSystemUIFont::11.0 selection-text color 0.052241|0.052241|0.052241 font .AppleSystemUIFont::11.0 threadLabel color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 uuid color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 version color 1.000000|1.000000|1.000000 font Menlo-Regular::11.0 identifier Text items background selection-background selection-text plaintext key threadLabel crashedThreadLabel executableCode OSCode memoryAddress registerValue path version uuid name Monochrome (Dark) monochrome UUID DEA1A282-4860-4CBD-85F5-70CAC95742CB groups attributes OSCode color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 background color 0.994426|0.994426|0.994426 font .AppleSystemUIFont::11.0 crashedThreadLabel color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 executableCode color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 key color 0.047095|0.047095|0.047095 font Menlo-Regular::11.0 lineNumber color 0.42|0.42|0.42 font Menlo-Regular::11.0 memoryAddress color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 path color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 plaintext color 0.054302|0.054302|0.054302 font Menlo-Regular::11.0 registerValue color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 selection-background color 0.884986|0.884986|0.884986 font .AppleSystemUIFont::11.0 selection-text color 0.000000|0.000000|0.000000 font .AppleSystemUIFont::11.0 threadLabel color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 uuid color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 version color 0.048801|0.048801|0.048801 font Menlo-Regular::11.0 identifier Text items background selection-background selection-text plaintext key threadLabel crashedThreadLabel executableCode OSCode memoryAddress registerValue path version uuid monochrome name Monochrome (Light) UUID 59DEA3E4-BF17-4C09-84D3-B97E531574EF groups attributes OSCode color 0.700000|0.700000|0.700000 font Menlo-Italic::14.0 background color 0.121569|0.119910|0.140239 font .AppleSystemUIFont::11.0 crashedThreadLabel color 1.000000|0.000000|0.000000 font Menlo-Italic::14.0 executableCode color 1.000000|1.000000|1.000000 font Menlo-Italic::14.0 key color 0.900000|0.900000|0.900000 font Menlo-Italic::14.0 lineNumber color 0.42|0.42|0.42 font Menlo-Regular::11.0 memoryAddress color 0.589786|0.767791|0.999091 font Menlo-Italic::14.0 path color 0.991982|0.636635|0.991244 font Menlo-Italic::14.0 plaintext color 1.000000|1.000000|1.000000 font Menlo-Regular::14.0 registerValue color 0.997655|0.882916|0.443044 font Menlo-Italic::14.0 selection-background color 0.171197|0.532568|0.998515 font .AppleSystemUIFont::11.0 selection-text color 1.000000|1.000000|1.000000 font .AppleSystemUIFont::11.0 threadLabel color 0.668288|1.000000|0.433854 font Menlo-Italic::14.0 uuid color 0.400000|0.400000|0.400000 font Menlo-Italic::14.0 version color 0.848609|0.555776|0.191952 font Menlo-Italic::14.0 identifier Text items background selection-background selection-text plaintext key threadLabel crashedThreadLabel executableCode OSCode memoryAddress registerValue path version uuid name Presentation (Dark) UUID EAB59E67-4070-4A69-A7BB-08DA065918C9 groups attributes OSCode color 0.300000|0.300000|0.300000 font Menlo-Regular::14.0 background color 1.000000|1.000000|1.000000 font .AppleSystemUIFont::11.0 crashedThreadLabel color 0.957716|0.059633|0.075242 font Menlo-Regular::14.0 executableCode color 0.000000|0.000000|0.000000 font Menlo-Regular::14.0 key color 0.157741|0.157741|0.157741 font Menlo-Regular::14.0 lineNumber color 0.42|0.42|0.42 font Menlo-Regular::11.0 memoryAddress color 0.137678|0.193874|0.694335 font Menlo-Regular::14.0 path color 0.595377|0.057079|0.998607 font Menlo-Regular::14.0 plaintext color 0.000000|0.000000|0.000000 font Menlo-Regular::14.0 registerValue color 0.000000|0.000000|0.000000 font Menlo-Regular::14.0 selection-background color 0.817178|0.979453|0.999665 font .AppleSystemUIFont::11.0 selection-text color 0.000000|0.000000|0.000000 font .AppleSystemUIFont::11.0 threadLabel color 0.000000|0.000000|0.000000 font Menlo-Regular::14.0 uuid color 0.500000|0.500000|0.500000 font Menlo-Regular::14.0 version color 0.756722|0.413476|0.180156 font Menlo-Regular::14.0 identifier Text items background selection-background selection-text plaintext key threadLabel crashedThreadLabel executableCode OSCode memoryAddress registerValue path version uuid name Presentation (Light) ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIAboutBoxWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIBinaryImagesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUICodeSigningInformationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUICollectionViewRegisterItem.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUICrashLogPresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUICrashLogPresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUICrashLogsListViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUICrashLogsSourceSmartEditorWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUICrashLogsSourcesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIExportAccessoryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIInspectorExecutableViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIInspectorGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIInspectorProcessesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIInspectorUserViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUILineJumperWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIMainWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePaneAdvancedViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePaneCrashreporterViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePaneFontscolorsViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePaneGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePanePresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePanePresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePanePresentationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencePaneSymbolicationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUIPreferencesWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CUISymbolsFilesLibraryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/CodeSigning.strings ================================================ "TestFlight" = "TestFlight"; "Development" = "Development"; "AppStore" = "AppStore"; "Enterprise" = "Enterprise"; "Developer ID" = "Developer ID"; "None" = "None"; ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/MainMenu.xib ================================================ CA CA ================================================ FILE: app_unexpectedly/app_unexpectedly/en.lproj/Predicates.strings ================================================ /* Predicate Editor */ "%[All]@ of the following are true" = "%1$[All]@ of the following are true"; "%[Any]@ of the following are true" = "%1$[Any]@ of the following are true"; "%[processName]@ %[is]@ %@" = "%1$[Process Name]@ %2$[is]@ %3$@"; "%[processName]@ %[is not]@ %@" = "%1$[Process Name]@ %2$[is not]@ %3$@"; "%[processName]@ %[begins with]@ %@" = "%1$[Process Name]@ %2$[begins with]@ %3$@"; "%[processName]@ %[ends with]@ %@" = "%1$[Process Name]@ %2$[ends with]@ %3$@"; "%[processName]@ %[contains]@ %@" = "%1$[Process Name]@ %2$[contains]@ %3$@"; "%[header.bundleIdentifier]@ %[is]@ %@" = "%1$[Identifier]@ %2$[is]@ %3$@"; "%[header.bundleIdentifier]@ %[is not]@ %@" = "%1$[Identifier]@ %2$[is not]@ %3$@"; "%[header.bundleIdentifier]@ %[begins with]@ %@" = "%1$[Identifier]@ %2$[begins with]@ %3$@"; "%[header.bundleIdentifier]@ %[ends with]@ %@" = "%1$[Identifier]@ %2$[ends with]@ %3$@"; "%[header.bundleIdentifier]@ %[contains]@ %@" = "%1$[Identifier]@ %2$[contains]@ %3$@"; "%[header.executablePath]@ %[is]@ %@" = "%1$[Executable Path]@ %2$[is]@ %3$@"; "%[header.executablePath]@ %[is not]@ %@" = "%1$[Executable Path]@ %2$[is not]@ %3$@"; "%[header.executablePath]@ %[begins with]@ %@" = "%1$[Executable Path]@ %2$[begins with]@ %3$@"; "%[header.executablePath]@ %[ends with]@ %@" = "%1$[Executable Path]@ %2$[ends with]@ %3$@"; "%[header.executablePath]@ %[contains]@ %@" = "%1$[Executable Path]@ %2$[contains]@ %3$@"; "%[header.executableVersion]@ %[is]@ %@" = "%1$[Executable Version]@ %2$[is]@ %3$@"; "%[header.executableVersion]@ %[is not]@ %@" = "%1$[Executable Version]@ %2$[is not]@ %3$@"; "%[header.executableVersion]@ %[begins with]@ %@" = "%1$[Executable Version]@ %2$[begins with]@ %3$@"; "%[header.executableVersion]@ %[ends with]@ %@" = "%1$[Executable Version]@ %2$[ends with]@ %3$@"; "%[header.executableVersion]@ %[contains]@ %@" = "%1$[Executable Version]@ %2$[contains]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is]@ %@" = "%1$[Crashed Thread Name]@ %2$[is]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is not]@ %@" = "%1$[Crashed Thread Name]@ %2$[is not]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[begins with]@ %@" = "%1$[Crashed Thread Name]@ %2$[begins with]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[ends with]@ %@" = "%1$[Crashed Thread Name]@ %2$[ends with]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[contains]@ %@" = "%1$[Crashed Thread Name]@ %2$[contains]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is]@ %@" = "%1$[Operating System Version]@ %2$[is]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is not]@ %@" = "%1$[Operating System Version]@ %2$[is not]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[begins with]@ %@" = "%1$[Operating System Version]@ %2$[begins with]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[ends with]@ %@" = "%1$[Operating System Version]@ %2$[ends with]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[contains]@ %@" = "%1$[Operating System Version]@ %2$[contains]@ %3$@"; "%[dateTime]@ %[is less than or equal to]@ %@" = "%1$[Date]@ %2$[is before or the same as]@ %3$@"; "%[dateTime]@ %[is greater than or equal to]@ %@" = "%1$[Date]@ %2$[is on or after]@ %3$@"; "%[exceptionType]@ is %[EXC_ARITHMETIC]@" = "%1$[Exception Type]@ is %2$[EXC_ARITHMETIC]@"; "%[exceptionType]@ is %[EXC_BAD_ACCESS]@" = "%1$[Exception Type]@ is %2$[EXC_BAD_ACCESS]@"; "%[exceptionType]@ is %[EXC_BAD_INSTRUCTION]@" = "%1$[Exception Type]@ is %2$[EXC_BAD_INSTRUCTION]@"; "%[exceptionType]@ is %[EXC_BREAKPOINT]@" = "%1$[Exception Type]@ is %2$[EXC_BREAKPOINT]@"; "%[exceptionType]@ is %[EXC_CORPSE_NOTIFY]@" = "%1$[Exception Type]@ is %2$[EXC_CORPSE_NOTIFY]@"; "%[exceptionType]@ is %[EXC_CRASH]@" = "%1$[Exception Type]@ is %2$[EXC_CRASH]@"; "%[exceptionType]@ is %[EXC_EMULATION]@" = "%1$[Exception Type]@ is %2$[EXC_EMULATION]@"; "%[exceptionType]@ is %[EXC_GUARD]@" = "%1$[Exception Type]@ is %2$[EXC_GUARD]@"; "%[exceptionType]@ is %[EXC_MACH_SYSCALL]@" = "%1$[Exception Type]@ is %2$[EXC_MACH_SYSCALL]@"; "%[exceptionType]@ is %[EXC_RESOURCE]@" = "%1$[Exception Type]@ is %2$[EXC_RESOURCE]@"; "%[exceptionType]@ is %[EXC_RPC_ALERT]@" = "%1$[Exception Type]@ is %2$[EXC_RPC_ALERT]@"; "%[exceptionType]@ is %[EXC_SOFTWARE]@" = "%1$[Exception Type]@ is %2$[EXC_SOFTWARE]@"; "%[exceptionType]@ is %[EXC_SYSCALL]@" = "%1$[Exception Type]@ is %2$[EXC_SYSCALL]@"; "%[exceptionSignal]@ is %[SIGABRT]@" = "%1$[Exception Signal]@ is %2$[SIGABRT]@"; "%[exceptionSignal]@ is %[SIGBUS]@" = "%1$[Exception Signal]@ is %2$[SIGBUS]@"; "%[exceptionSignal]@ is %[SIGILL]@" = "%1$[Exception Signal]@ is %2$[SIGILL]@"; "%[exceptionSignal]@ is %[SIGKILL]@" = "%1$[Exception Signal]@ is %2$[SIGKILL]@"; "%[exceptionSignal]@ is %[SIGQUIT]@" = "%1$[Exception Signal]@ is %2$[SIGQUIT]@"; "%[exceptionSignal]@ is %[SIGSEGV]@" = "%1$[Exception Signal]@ is %2$[SIGSEGV]@"; "%[exceptionSignal]@ is %[SIGTRAP]@" = "%1$[Exception Signal]@ is %2$[SIGTRAP]@"; "%[exceptionSignal]@ is %[Code Signature Invalid]@" = "%1$[Exception Signal]@ is %2$[Code Signature Invalid]@"; "%[crashLogFileName]@ %[is]@ %@" = "%1$[Report File Name]@ %2$[is]@ %3$@"; "%[crashLogFileName]@ %[is not]@ %@" = "%1$[Report File Name]@ %2$[is not]@ %3$@"; "%[crashLogFileName]@ %[begins with]@ %@" = "%1$[Report File Name]@ %2$[begins with]@ %3$@"; "%[crashLogFileName]@ %[ends with]@ %@" = "%1$[Report File Name]@ %2$[ends with]@ %3$@"; "%[crashLogFileName]@ %[contains]@ %@" = "%1$[Report File Name]@ %2$[contains]@ %3$@"; "%[reportSourceTypeNumber]@ is %[0]@" = "%1$[Source]@ is %2$[System Reports]@"; "%[reportSourceTypeNumber]@ is %[1]@" = "%1$[Source]@ is %2$[User Reports]@"; "%[reportSourceTypeNumber]@ is %[2]@" = "%1$[Source]@ is %2$[Another Source]@"; ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIAboutBoxWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIBinaryImagesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUICodeSigningInformationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUICollectionViewRegisterItem.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUICrashLogPresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUICrashLogPresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUICrashLogsListViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUICrashLogsSourceSmartEditorWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUICrashLogsSourcesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIExportAccessoryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIInspectorExecutableViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIInspectorGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIInspectorProcessesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIInspectorUserViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUILineJumperWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIMainWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePaneAdvancedViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePaneCrashreporterViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePaneFontscolorsViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePaneGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePanePresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePanePresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePanePresentationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencePaneSymbolicationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUIPreferencesWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CUISymbolsFilesLibraryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/CodeSigning.strings ================================================ "TestFlight" = "TestFlight"; "Development" = "Desarrollo"; "AppStore" = "AppStore"; "Enterprise" = "Empresa"; "Developer ID" = "Developer ID"; "None" = "Ninguna"; ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/MainMenu.xib ================================================ CA CA ================================================ FILE: app_unexpectedly/app_unexpectedly/es.lproj/Predicates.strings ================================================ /* Predicate Editor */ "%[All]@ of the following are true" = "%1$[Todas]@ las siguientes son verdaderas"; "%[Any]@ of the following are true" = "%1$[Alguna]@ de las siguientes es verdadera"; "%[processName]@ %[is]@ %@" = "%1$[Nombre del proceso]@ %2$[es]@ %3$@"; "%[processName]@ %[is not]@ %@" = "%1$[Nombre del proceso]@ %2$[no es]@ %3$@"; "%[processName]@ %[begins with]@ %@" = "%1$[Nombre del proceso]@ %2$[empieza por]@ %3$@"; "%[processName]@ %[ends with]@ %@" = "%1$[Nombre del proceso]@ %2$[acaba en]@ %3$@"; "%[processName]@ %[contains]@ %@" = "%1$[Nombre del proceso]@ %2$[contiene]@ %3$@"; "%[header.bundleIdentifier]@ %[is]@ %@" = "%1$[Identifier]@ %2$[es]@ %3$@"; "%[header.bundleIdentifier]@ %[is not]@ %@" = "%1$[Identifier]@ %2$[no es]@ %3$@"; "%[header.bundleIdentifier]@ %[begins with]@ %@" = "%1$[Identifier]@ %2$[empieza por]@ %3$@"; "%[header.bundleIdentifier]@ %[ends with]@ %@" = "%1$[Identifier]@ %2$[ends with]@ %3$@"; "%[header.bundleIdentifier]@ %[contains]@ %@" = "%1$[Identifier]@ %2$[contiene]@ %3$@"; "%[header.executablePath]@ %[is]@ %@" = "%1$[Ruta del ejecutable]@ %2$[es]@ %3$@"; "%[header.executablePath]@ %[is not]@ %@" = "%1$[Ruta del ejecutable]@ %2$[no es]@ %3$@"; "%[header.executablePath]@ %[begins with]@ %@" = "%1$[Ruta del ejecutable]@ %2$[empieza por]@ %3$@"; "%[header.executablePath]@ %[ends with]@ %@" = "%1$[Ruta del ejecutable]@ %2$[acaba en]@ %3$@"; "%[header.executablePath]@ %[contains]@ %@" = "%1$[Ruta del ejecutable]@ %2$[contiene]@ %3$@"; "%[header.executableVersion]@ %[is]@ %@" = "%1$[Versión del ejectuable]@ %2$[es]@ %3$@"; "%[header.executableVersion]@ %[is not]@ %@" = "%1$[Versión del ejectuable]@ %2$[no es]@ %3$@"; "%[header.executableVersion]@ %[begins with]@ %@" = "%1$[Versión del ejectuable]@ %2$[empieza por]@ %3$@"; "%[header.executableVersion]@ %[ends with]@ %@" = "%1$[Versión del ejectuable]@ %2$[acaba en]@ %3$@"; "%[header.executableVersion]@ %[contains]@ %@" = "%1$[Versión del ejectuable]@ %2$[contiene]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is]@ %@" = "%1$[Nombre del thread fallado]@ %2$[es]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is not]@ %@" = "%1$[Nombre del thread fallado]@ %2$[no es]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[begins with]@ %@" = "%1$[Nombre del thread fallado]@ %2$[empieza por]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[ends with]@ %@" = "%1$[Nombre del thread fallado]@ %2$[acaba en]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[contains]@ %@" = "%1$[Nombre del thread fallado]@ %2$[contiene]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is]@ %@" = "%1$[Versión del sistema operativo]@ %2$[es]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is not]@ %@" = "%1$[Versión del sistema operativo]@ %2$[no es]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[begins with]@ %@" = "%1$[Versión del sistema operativo]@ %2$[empieza por]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[ends with]@ %@" = "%1$[Versión del sistema operativo]@ %2$[acaba en]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[contains]@ %@" = "%1$[Versión del sistema operativo]@ %2$[contiene]@ %3$@"; "%[dateTime]@ %[is less than or equal to]@ %@" = "%1$[Fecha]@ %2$[es anterior a]@ %3$@"; "%[dateTime]@ %[is greater than or equal to]@ %@" = "%1$[Fecha]@ %2$[es posterior a]@ %3$@"; "%[exceptionType]@ is %[EXC_ARITHMETIC]@" = "%1$[Tipo de excepción]@ es %2$[EXC_ARITHMETIC]@"; "%[exceptionType]@ is %[EXC_BAD_ACCESS]@" = "%1$[Tipo de excepción]@ es %2$[EXC_BAD_ACCESS]@"; "%[exceptionType]@ is %[EXC_BAD_INSTRUCTION]@" = "%1$[Tipo de excepción]@ es %2$[EXC_BAD_INSTRUCTION]@"; "%[exceptionType]@ is %[EXC_BREAKPOINT]@" = "%1$[Tipo de excepción]@ es %2$[EXC_BREAKPOINT]@"; "%[exceptionType]@ is %[EXC_CORPSE_NOTIFY]@" = "%1$[Tipo de excepción]@ es %2$[EXC_CORPSE_NOTIFY]@"; "%[exceptionType]@ is %[EXC_CRASH]@" = "%1$[Tipo de excepción]@ es %2$[EXC_CRASH]@"; "%[exceptionType]@ is %[EXC_EMULATION]@" = "%1$[Tipo de excepción]@ es %2$[EXC_EMULATION]@"; "%[exceptionType]@ is %[EXC_GUARD]@" = "%1$[Tipo de excepción]@ es %2$[EXC_GUARD]@"; "%[exceptionType]@ is %[EXC_MACH_SYSCALL]@" = "%1$[Tipo de excepción]@ es %2$[EXC_MACH_SYSCALL]@"; "%[exceptionType]@ is %[EXC_RESOURCE]@" = "%1$[Tipo de excepción]@ is %2$[EXC_RESOURCE]@"; "%[exceptionType]@ is %[EXC_RPC_ALERT]@" = "%1$[Tipo de excepción]@ es %2$[EXC_RPC_ALERT]@"; "%[exceptionType]@ is %[EXC_SOFTWARE]@" = "%1$[Tipo de excepción]@ es %2$[EXC_SOFTWARE]@"; "%[exceptionType]@ is %[EXC_SYSCALL]@" = "%1$[Tipo de excepción]@ es %2$[EXC_SYSCALL]@"; "%[exceptionSignal]@ is %[SIGABRT]@" = "%1$[Señal de excepción]@ es %2$[SIGABRT]@"; "%[exceptionSignal]@ is %[SIGBUS]@" = "%1$[Señal de excepción]@ es %2$[SIGBUS]@"; "%[exceptionSignal]@ is %[SIGILL]@" = "%1$[Señal de excepción]@ es %2$[SIGILL]@"; "%[exceptionSignal]@ is %[SIGKILL]@" = "%1$[Señal de excepción]@ es %2$[SIGKILL]@"; "%[exceptionSignal]@ is %[SIGQUIT]@" = "%1$[Señal de excepción]@ es %2$[SIGQUIT]@"; "%[exceptionSignal]@ is %[SIGSEGV]@" = "%1$[Señal de excepción]@ es %2$[SIGSEGV]@"; "%[exceptionSignal]@ is %[SIGTRAP]@" = "%1$[Señal de excepción]@ es %2$[SIGTRAP]@"; "%[exceptionSignal]@ is %[Code Signature Invalid]@" = "%1$[Señal de excepción]@ es %2$[Code Signature Invalid]@"; "%[crashLogFileName]@ %[is]@ %@" = "%1$[Nombre de archivo de informe]@ %2$[es]@ %3$@"; "%[crashLogFileName]@ %[is not]@ %@" = "%1$[Nombre de archivo de informe]@ %2$[no es]@ %3$@"; "%[crashLogFileName]@ %[begins with]@ %@" = "%1$[Nombre de archivo de informe]@ %2$[empieza por]@ %3$@"; "%[crashLogFileName]@ %[ends with]@ %@" = "%1$[Nombre de archivo de informe]@ %2$[acaba en]@ %3$@"; "%[crashLogFileName]@ %[contains]@ %@" = "%1$[Nombre de archivo de informe]@ %2$[contiene]@ %3$@"; "%[reportSourceTypeNumber]@ is %[0]@" = "%1$[Fuente]@ es %2$[Informes del sistema]@"; "%[reportSourceTypeNumber]@ is %[1]@" = "%1$[Fuente]@ es %2$[Informes del usuario]@"; "%[reportSourceTypeNumber]@ is %[2]@" = "%1$[Fuente]@ es %2$[Otra fuente]@"; ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIAboutBoxWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIBinaryImagesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUICodeSigningInformationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUICollectionViewRegisterItem.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUICrashLogPresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUICrashLogPresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUICrashLogsListViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUICrashLogsSourceSmartEditorWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUICrashLogsSourcesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIExportAccessoryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIInspectorExecutableViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIInspectorGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIInspectorProcessesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIInspectorUserViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUILineJumperWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIMainWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePaneAdvancedViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePaneCrashreporterViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePaneFontscolorsViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePaneGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePanePresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePanePresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePanePresentationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencePaneSymbolicationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUIPreferencesWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CUISymbolsFilesLibraryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/CodeSigning.strings ================================================ "TestFlight" = "TestFlight"; "Development" = "Developpement"; "AppStore" = "AppStore"; "Enterprise" = "Enterprise"; "Developer ID" = "Developer ID"; "None" = "Aucune"; ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/MainMenu.xib ================================================ CA CA ================================================ FILE: app_unexpectedly/app_unexpectedly/fr.lproj/Predicates.strings ================================================ /* Predicate Editor */ "%[All]@ of the following are true" = "%1$[Toutes les]@ conditions suivantes sont vraies"; "%[Any]@ of the following are true" = "%1$[Certaines des]@ conditions suivantes sont vraies"; "%[processName]@ %[is]@ %@" = "%1$[Le nom de l'opération]@ %2$[est]@ %3$@"; "%[processName]@ %[is not]@ %@" = "%1$[Le nom de l'opération]@ %2$[n'est pas]@ %3$@"; "%[processName]@ %[begins with]@ %@" = "%1$[Le nom de l'opération]@ %2$[commence par]@ %3$@"; "%[processName]@ %[ends with]@ %@" = "%1$[Le nom de l'opération]@ %2$[se termine par]@ %3$@"; "%[processName]@ %[contains]@ %@" = "%1$[Le nom de l'opération]@ %2$[contient]@ %3$@"; "%[header.bundleIdentifier]@ %[is]@ %@" = "%1$[L'identifiant]@ %2$[est]@ %3$@"; "%[header.bundleIdentifier]@ %[is not]@ %@" = "%1$[L'identifiant]@ %2$[n'est pas]@ %3$@"; "%[header.bundleIdentifier]@ %[begins with]@ %@" = "%1$[L'identifiant]@ %2$[commence par]@ %3$@"; "%[header.bundleIdentifier]@ %[ends with]@ %@" = "%1$[L'identifiant]@ %2$[se termine par]@ %3$@"; "%[header.bundleIdentifier]@ %[contains]@ %@" = "%1$[L'identifiant]@ %2$[contient]@ %3$@"; "%[header.executablePath]@ %[is]@ %@" = "%1$[Le chemin de l'exécutable]@ %2$[est]@ %3$@"; "%[header.executablePath]@ %[is not]@ %@" = "%1$[Le chemin de l'exécutable]@ %2$[n'est pas]@ %3$@"; "%[header.executablePath]@ %[begins with]@ %@" = "%1$[Le chemin de l'exécutable]@ %2$[commence par]@ %3$@"; "%[header.executablePath]@ %[ends with]@ %@" = "%1$[Le chemin de l'exécutable]@ %2$[se termine par]@ %3$@"; "%[header.executablePath]@ %[contains]@ %@" = "%1$[Le chemin de l'exécutable]@ %2$[contient]@ %3$@"; "%[header.executableVersion]@ %[is]@ %@" = "%1$[La version de l'exécutable]@ %2$[est]@ %3$@"; "%[header.executableVersion]@ %[is not]@ %@" = "%1$[La version de l'exécutable]@ %2$[n'est pas]@ %3$@"; "%[header.executableVersion]@ %[begins with]@ %@" = "%1$[La version de l'exécutable]@ %2$[commence par]@ %3$@"; "%[header.executableVersion]@ %[ends with]@ %@" = "%1$[La version de l'exécutable]@ %2$[se termine par]@ %3$@"; "%[header.executableVersion]@ %[contains]@ %@" = "%1$[La version de l'exécutable]@ %2$[contient]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is]@ %@" = "%1$[Le nom du thread planté]@ %2$[est]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is not]@ %@" = "%1$[Le nom du thread planté]@ %2$[n'est pas]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[begins with]@ %@" = "%1$[Le nom du thread planté]@ %2$[commence par]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[ends with]@ %@" = "%1$[Le nom du thread planté]@ %2$[se termine par]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[contains]@ %@" = "%1$[Le nom du thread planté]@ %2$[contient]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is]@ %@" = "%1$[La version de l'OS]@ %2$[est]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is not]@ %@" = "%1$[La version de l'OS]@ %2$[n'est pas]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[begins with]@ %@" = "%1$[La version de l'OS]@ %2$[commence par]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[ends with]@ %@" = "%1$[La version de l'OS]@ %2$[se termine par]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[contains]@ %@" = "%1$[La version de l'OS]@ %2$[contient]@ %3$@"; "%[dateTime]@ %[is less than or equal to]@ %@" = "%1$[La date]@ %2$[est antérieure ou égale à]@ %3$@"; "%[dateTime]@ %[is greater than or equal to]@ %@" = "%1$[La date]@ %2$[est postérieure ou égale à]@ %3$@"; "%[exceptionType]@ is %[EXC_ARITHMETIC]@" = "%1$[Le type de l'exception]@ est %2$[EXC_ARITHMETIC]@"; "%[exceptionType]@ is %[EXC_BAD_ACCESS]@" = "%1$[Le type de l'exception]@ est %2$[EXC_BAD_ACCESS]@"; "%[exceptionType]@ is %[EXC_BAD_INSTRUCTION]@" = "%1$[Le type de l'exception]@ est %2$[EXC_BAD_INSTRUCTION]@"; "%[exceptionType]@ is %[EXC_BREAKPOINT]@" = "%1$[Le type de l'exception]@ est %2$[EXC_BREAKPOINT]@"; "%[exceptionType]@ is %[EXC_CORPSE_NOTIFY]@" = "%1$[Le type de l'exception]@ est %2$[EXC_CORPSE_NOTIFY]@"; "%[exceptionType]@ is %[EXC_CRASH]@" = "%1$[Le type de l'exception]@ est %2$[EXC_CRASH]@"; "%[exceptionType]@ is %[EXC_EMULATION]@" = "%1$[Le type de l'exception]@ est %2$[EXC_EMULATION]@"; "%[exceptionType]@ is %[EXC_GUARD]@" = "%1$[Le type de l'exception]@ est %2$[EXC_GUARD]@"; "%[exceptionType]@ is %[EXC_MACH_SYSCALL]@" = "%1$[Le type de l'exception]@ est %2$[EXC_MACH_SYSCALL]@"; "%[exceptionType]@ is %[EXC_RESOURCE]@" = "%1$[Le type de l'exception]@ est %2$[EXC_RESOURCE]@"; "%[exceptionType]@ is %[EXC_RPC_ALERT]@" = "%1$[Le type de l'exception]@ est %2$[EXC_RPC_ALERT]@"; "%[exceptionType]@ is %[EXC_SOFTWARE]@" = "%1$[Le type de l'exception]@ est %2$[EXC_SOFTWARE]@"; "%[exceptionType]@ is %[EXC_SYSCALL]@" = "%1$[Le type de l'exception]@ est %2$[EXC_SYSCALL]@"; "%[exceptionSignal]@ is %[SIGABRT]@" = "%1$[Le signal de l'exception]@ est %2$[SIGABRT]@"; "%[exceptionSignal]@ is %[SIGBUS]@" = "%1$[Le signal de l'exception]@ est %2$[SIGBUS]@"; "%[exceptionSignal]@ is %[SIGILL]@" = "%1$[Le signal de l'exception]@ est %2$[SIGILL]@"; "%[exceptionSignal]@ is %[SIGKILL]@" = "%1$[Le signal de l'exception]@ est %2$[SIGKILL]@"; "%[exceptionSignal]@ is %[SIGQUIT]@" = "%1$[Le signal de l'exception]@ est %2$[SIGQUIT]@"; "%[exceptionSignal]@ is %[SIGSEGV]@" = "%1$[Le signal de l'exception]@ est %2$[SIGSEGV]@"; "%[exceptionSignal]@ is %[SIGTRAP]@" = "%1$[Le signal de l'exception]@ est %2$[SIGTRAP]@"; "%[exceptionSignal]@ is %[Code Signature Invalid]@" = "%1$[Le signal de l'exception]@ est %2$[Code Signature Invalid]@"; "%[crashLogFileName]@ %[is]@ %@" = "%1$[Le nom du fichier du rapport]@ %2$[est]@ %3$@"; "%[crashLogFileName]@ %[is not]@ %@" = "%1$[Le nom du fichier du rapport]@ %2$[n'est pas]@ %3$@"; "%[crashLogFileName]@ %[begins with]@ %@" = "%1$[Le nom du fichier du rapport]@ %2$[commence par]@ %3$@"; "%[crashLogFileName]@ %[ends with]@ %@" = "%1$[Le nom du fichier du rapport]@ %2$[se termine par]@ %3$@"; "%[crashLogFileName]@ %[contains]@ %@" = "%1$[Le nom du fichier du rapport]@ %2$[contient]@ %3$@"; "%[reportSourceTypeNumber]@ is %[0]@" = "%1$[La source]@ est %2$[les rapports système]@"; "%[reportSourceTypeNumber]@ is %[1]@" = "%1$[La source]@ est %2$[les rapports utilisateurs]@"; "%[reportSourceTypeNumber]@ is %[2]@" = "%1$[La source]@ est %2$[une autre source]@"; ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIAboutBoxWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIBinaryImagesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUICodeSigningInformationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUICollectionViewRegisterItem.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUICrashLogPresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUICrashLogPresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUICrashLogsListViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUICrashLogsSourceSmartEditorWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUICrashLogsSourcesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIExportAccessoryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIInspectorExecutableViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIInspectorGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIInspectorProcessesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIInspectorUserViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUILineJumperWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIMainWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePaneAdvancedViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePaneCrashreporterViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePaneFontscolorsViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePaneGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePanePresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePanePresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePanePresentationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencePaneSymbolicationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUIPreferencesWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CUISymbolsFilesLibraryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/CodeSigning.strings ================================================ "TestFlight" = "TestFlight"; "Development" = "הִתפַּתְחוּת"; "AppStore" = "AppStore"; "Enterprise" = "מִפְעָל"; "Developer ID" = "Developer ID"; "None" = "אַף לֹא אֶחָד"; ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/MainMenu.xib ================================================ CA CA ================================================ FILE: app_unexpectedly/app_unexpectedly/he.lproj/Predicates.strings ================================================ /* Predicate Editor */ "%[All]@ of the following are true" = "%1$[כל]@ התנאים הבאים נכונים"; "%[Any]@ of the following are true" = "%1$[כל אחד]@ מהתנאים הבאים הוא נכון"; "%[processName]@ %[is]@ %@" = "%1$[השם תהליך]@ %2$[הוא]@ %3$@"; "%[processName]@ %[is not]@ %@" = "%1$[השם תהליך]@ %2$[אינו שווה ל-]@ %3$@"; "%[processName]@ %[begins with]@ %@" = "%1$[השם תהליך]@ %2$[מתחיל ב-]@ %3$@"; "%[processName]@ %[ends with]@ %@" = "%1$[השם תהליך]@ %2$[מסתיים ב-]@ %3$@"; "%[processName]@ %[contains]@ %@" = "%1$[השם תהליך]@ %2$[מכיל]@ %3$@"; "%[header.bundleIdentifier]@ %[is]@ %@" = "%1$[המזהה]@ %2$[הוא]@ %3$@"; "%[header.bundleIdentifier]@ %[is not]@ %@" = "%1$[המזהה]@ %2$[אינו שווה ל-]@ %3$@"; "%[header.bundleIdentifier]@ %[begins with]@ %@" = "%1$[המזהה]@ %2$[מתחיל ב-]@ %3$@"; "%[header.bundleIdentifier]@ %[ends with]@ %@" = "%1$[המזהה]@ %2$[מסתיים ב-]@ %3$@"; "%[header.bundleIdentifier]@ %[contains]@ %@" = "%1$[המזהה]@ %2$[מכיל]@ %3$@"; "%[header.executablePath]@ %[is]@ %@" = "%1$[הנתיב של קובץ הרצה]@ %2$[הוא]@ %3$@"; "%[header.executablePath]@ %[is not]@ %@" = "%1$[הנתיב של קובץ הרצה]@ %2$[אינו שווה ל-]@ %3$@"; "%[header.executablePath]@ %[begins with]@ %@" = "%1$[הנתיב של קובץ הרצה]@ %2$[מתחיל ב-]@ %3$@"; "%[header.executablePath]@ %[ends with]@ %@" = "%1$[הנתיב של קובץ הרצה]@ %2$[מסתיים ב-]@ %3$@"; "%[header.executablePath]@ %[contains]@ %@" = "%1$[הנתיב של קובץ הרצה]@ %2$[מכיל]@ %3$@"; "%[header.executableVersion]@ %[is]@ %@" = "%1$[גירסה של קובץ הרצה]@ %2$[היא]@ %3$@"; "%[header.executableVersion]@ %[is not]@ %@" = "%1$[גירסה של קובץ הרצה]@ %2$[אינו שווה ל-]@ %3$@"; "%[header.executableVersion]@ %[begins with]@ %@" = "%1$[גירסה של קובץ הרצה]@ %2$[מתחיל ב-]@ %3$@"; "%[header.executableVersion]@ %[ends with]@ %@" = "%1$[גירסה של קובץ הרצה]@ %2$[מסתיים ב-]@ %3$@"; "%[header.executableVersion]@ %[contains]@ %@" = "%1$[גירסה של קובץ הרצה]@ %2$[מכיל]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is]@ %@" = "%1$[שם שרשור שקרס]@ %2$[הוא]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[is not]@ %@" = "%1$[שם שרשור שקרס]@ %2$[אינו שווה ל-]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[begins with]@ %@" = "%1$[שם שרשור שקרס]@ %2$[מתחיל ב-]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[ends with]@ %@" = "%1$[שם שרשור שקרס]@ %2$[מסתיים ב-]@ %3$@"; "%[exceptionInformation.crashedThreadName]@ %[contains]@ %@" = "%1$[שם שרשור שקרס]@ %2$[מכיל]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is]@ %@" = "%1$[גירסה של מַעֲרֶכֶת הַפעָלָה]@ %2$[היא]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[is not]@ %@" = "%1$[גירסה של מַעֲרֶכֶת הַפעָלָה]@ %2$[אינו שווה ל-]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[begins with]@ %@" = "%1$[גירסה של מַעֲרֶכֶת הַפעָלָה]@ %2$[מתחיל ב-]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[ends with]@ %@" = "%1$[גירסה של מַעֲרֶכֶת הַפעָלָה]@ %2$[מסתיים ב-]@ %3$@"; "%[header.operatingSystemVersion.stringValue]@ %[contains]@ %@" = "%1$[גירסה של מַעֲרֶכֶת הַפעָלָה]@ %2$[מכיל]@ %3$@"; "%[dateTime]@ %[is less than or equal to]@ %@" = "%1$[תאריך]@ %2$[חל לפני]@ %3$@"; "%[dateTime]@ %[is greater than or equal to]@ %@" = "%1$[תאריך]@ %2$[חל לאחר]@ %3$@"; "%[exceptionType]@ is %[EXC_ARITHMETIC]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_ARITHMETIC]@"; "%[exceptionType]@ is %[EXC_BAD_ACCESS]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_BAD_ACCESS]@"; "%[exceptionType]@ is %[EXC_BAD_INSTRUCTION]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_BAD_INSTRUCTION]@"; "%[exceptionType]@ is %[EXC_BREAKPOINT]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_BREAKPOINT]@"; "%[exceptionType]@ is %[EXC_CORPSE_NOTIFY]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_CORPSE_NOTIFY]@"; "%[exceptionType]@ is %[EXC_CRASH]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_CRASH]@"; "%[exceptionType]@ is %[EXC_EMULATION]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_EMULATION]@"; "%[exceptionType]@ is %[EXC_GUARD]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_GUARD]@"; "%[exceptionType]@ is %[EXC_MACH_SYSCALL]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_MACH_SYSCALL]@"; "%[exceptionType]@ is %[EXC_RESOURCE]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_RESOURCE]@"; "%[exceptionType]@ is %[EXC_RPC_ALERT]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_RPC_ALERT]@"; "%[exceptionType]@ is %[EXC_SOFTWARE]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_SOFTWARE]@"; "%[exceptionType]@ is %[EXC_SYSCALL]@" = "‏%1$[Exception Type]@ הוא %2$[EXC_SYSCALL]@"; "%[exceptionSignal]@ is %[SIGABRT]@" = "‏%1$[Exception Signal]@ הוא %2$[SIGABRT]@"; "%[exceptionSignal]@ is %[SIGBUS]@" = "‏%1$[Exception Signal]@ הוא %2$[SIGBUS]@"; "%[exceptionSignal]@ is %[SIGILL]@" = "‏%1$[Exception Signal]@ הוא %2$[SIGILL]@"; "%[exceptionSignal]@ is %[SIGKILL]@" = "‏%1$[Exception Signal]@ הוא %2$[SIGKILL]@"; "%[exceptionSignal]@ is %[SIGQUIT]@" = "‏%1$[Exception Signal]@ הוא %2$[SIGQUIT]@"; "%[exceptionSignal]@ is %[SIGSEGV]@" = "‏%1$[Exception Signal]@ הוא %2$[SIGSEGV]@"; "%[exceptionSignal]@ is %[SIGTRAP]@" = "‏%1$[Exception Signal]@ הוא %2$[SIGTRAP]@"; "%[exceptionSignal]@ is %[Code Signature Invalid]@" = "‏%1$[Exception Signal]@ הוא %2$[Code Signature Invalid]@"; "%[crashLogFileName]@ %[is]@ %@" = "%1$[שם קובץ הדוח]@ %2$[הוא]@ %3$@"; "%[crashLogFileName]@ %[is not]@ %@" = "%1$[שם קובץ הדוח]@ %2$[אינו שווה ל-]@ %3$@"; "%[crashLogFileName]@ %[begins with]@ %@" = "%1$[שם קובץ הדוח]@ %2$[מתחיל ב-]@ %3$@"; "%[crashLogFileName]@ %[ends with]@ %@" = "%1$[שם קובץ הדוח]@ %2$[מסתיים ב-]@ %3$@"; "%[crashLogFileName]@ %[contains]@ %@" = "%1$[שם קובץ הדוח]@ %2$[מכיל]@ %3$@"; "%[reportSourceTypeNumber]@ is %[0]@" = "‏%1$[מקור]@ הוא %2$[דוחות המשתמש]@"; "%[reportSourceTypeNumber]@ is %[1]@" = "%1$[מקור]@ הוא %2$[דוחות המשתמש]@"; "%[reportSourceTypeNumber]@ is %[2]@" = "‏%1$[מקור]@ הוא %2$[מקור אחר]@"; ================================================ FILE: app_unexpectedly/app_unexpectedly/ips + Extensions/IPSImage+Offset.h ================================================ // // IPSImage+Offset.h // crashreport // // Created by stephane on 21/02/2022. // Copyright © 2022 Whitebox. All rights reserved. // #import "IPSImage.h" @interface IPSImage (Offset) @property (nonatomic,readonly) NSUInteger binaryImageOffset; @end ================================================ FILE: app_unexpectedly/app_unexpectedly/ips + Extensions/IPSImage+Offset.m ================================================ // // IPSImage+Offset.m // crashreport // // Created by stephane on 21/02/2022. // Copyright © 2022 Whitebox. All rights reserved. // #import "IPSImage+Offset.h" @implementation IPSImage (Offset) - (NSUInteger)binaryImageOffset { NSUInteger tLoadAddress=self.loadAddress; if (tLoadAddress>0x7fff00000000) // Won't happen on ARM-64 return tLoadAddress; if (tLoadAddress>=0x100000000) return (tLoadAddress-0x100000000); return tLoadAddress; // 32-bit } @end ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIAboutBoxWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIBinaryImagesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUICodeSigningInformationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUICollectionViewRegisterItem.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUICrashLogPresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUICrashLogPresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUICrashLogsListViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUICrashLogsSourceSmartEditorWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUICrashLogsSourcesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIExportAccessoryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIInspectorExecutableViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIInspectorGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIInspectorProcessesViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIInspectorUserViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUILineJumperWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIMainWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePaneAdvancedViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePaneCrashreporterViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePaneFontscolorsViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePaneGeneralViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePanePresentationOutlineViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePanePresentationTextViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePanePresentationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencePaneSymbolicationViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUIPreferencesWindowController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CUISymbolsFilesLibraryViewController.xib ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/CodeSigning.strings ================================================ "TestFlight" = "TestFlight"; "Development" = "発達"; "AppStore" = "AppStore"; "Enterprise" = "企業"; "Developer ID" = "Developer ID"; "None" = "なし"; ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/MainMenu.xib ================================================ CA CA ================================================ FILE: app_unexpectedly/app_unexpectedly/ja.lproj/Predicates.strings ================================================ /* Predicate Editor */ "%[All]@ of the following are true" = "以下の条件の%1$[すべてを満たす]@"; "%[Any]@ of the following are true" = "以下の条件の%1$[いずれかを満たす]@"; "%[processName]@ %[is]@ %@" = "%1$[プロセス名]@が%3$@%2$[である]@"; "%[processName]@ %[is not]@ %@" = "%1$[プロセス名]@が%3$@%2$[ではない]@"; "%[processName]@ %[begins with]@ %@" = "%1$[プロセス名]@が%3$@%2$[で始まる]@"; "%[processName]@ %[ends with]@ %@" = "%1$[プロセス名]@@が%3$@%2$[で終わる]@"; "%[processName]@ %[contains]@ %@" = "%1$[プロセス名]@が%3$@%2$[を含む]@"; "%[header.bundleIdentifier]@ %[is]@ %@" = "%1$[Identifier]@が%3$@%2$[である]@"; "%[header.bundleIdentifier]@ %[is not]@ %@" = "%1$[Identifier]@が%3$@%2$[ではない]@"; "%[header.bundleIdentifier]@ %[begins with]@ %@" = "%1$[Identifier]@が%3$@%2$[で始まる]@"; "%[header.bundleIdentifier]@ %[ends with]@ %@" = "%1$[Identifier]@@が%3$@%2$[で終わる]@"; "%[header.bundleIdentifier]@ %[contains]@ %@" = "%1$[Identifier]@が%3$@%2$[を含む]@"; "%[header.executablePath]@ %[is]@ %@" = "%1$[実行可能ファイルのパス]@が%3$@%2$[である]@"; "%[header.executablePath]@ %[is not]@ %@" = "%1$[実行可能ファイルのパス]@が%3$@%2$[ではない]@"; "%[header.executablePath]@ %[begins with]@ %@" = "%1$[実行可能ファイルのパス]@が%3$@%2$[で始まる]@"; "%[header.executablePath]@ %[ends with]@ %@" = "%1$[実行可能ファイルのパス]@@が%3$@%2$[で終わる]@"; "%[header.executablePath]@ %[contains]@ %@" = "%1$[実行可能ファイルのパス]@が%3$@%2$[を含む]@"; "%[header.executableVersion]@ %[is]@ %@" = "%1$[実行可能ファイルのバージョン]@が%3$@%2$[である]@"; "%[header.executableVersion]@ %[is not]@ %@" = "%1$[実行可能ファイルのバージョン]@が%3$@%2$[ではない]@"; "%[header.executableVersion]@ %[begins with]@ %@" = "%1$[実行可能ファイルのバージョン]@が%3$@%2$[で始まる]@"; "%[header.executableVersion]@ %[ends with]@ %@" = "%1$[実行可能ファイルのバージョン]@@が%3$@%2$[で終わる]@"; "%[header.executableVersion]@ %[contains]@ %@" = "%1$[実行可能ファイルのバージョン]@が%3$@%2$[を含む]@"; "%[exceptionInformation.crashedThreadName]@ %[is]@ %@" = "%1$[クラッシュしたスレッド名]@が%3$@%2$[である]@"; "%[exceptionInformation.crashedThreadName]@ %[is not]@ %@" = "%1$[クラッシュしたスレッド名]@が%3$@%2$[ではない]@"; "%[exceptionInformation.crashedThreadName]@ %[begins with]@ %@" = "%1$[クラッシュしたスレッド名]@が%3$@%2$[で始まる]@"; "%[exceptionInformation.crashedThreadName]@ %[ends with]@ %@" = "%1$[クラッシュしたスレッド名]@@が%3$@%2$[で終わる]@"; "%[exceptionInformation.crashedThreadName]@ %[contains]@ %@" = "%1$[クラッシュしたスレッド名]@が%3$@%2$[を含む]@"; "%[header.operatingSystemVersion.stringValue]@ %[is]@ %@" = "%1$[オペレーティング・システムのバージョン]@が%3$@%2$[である]@"; "%[header.operatingSystemVersion.stringValue]@ %[is not]@ %@" = "%1$[オペレーティング・システムのバージョン]@が%3$@%2$[ではない]@"; "%[header.operatingSystemVersion.stringValue]@ %[begins with]@ %@" = "%1$[オペレーティング・システムのバージョン]@が%3$@%2$[で始まる]@"; "%[header.operatingSystemVersion.stringValue]@ %[ends with]@ %@" = "%1$[オペレーティング・システムのバージョン]@@が%3$@%2$[で終わる]@"; "%[header.operatingSystemVersion.stringValue]@ %[contains]@ %@" = "%1$[オペレーティング・システムのバージョン]@が%3$@%2$[を含む]@"; "%[dateTime]@ %[is less than or equal to]@ %@" = "%1$[日付]@が%3$@%2$[より前]@"; "%[dateTime]@ %[is greater than or equal to]@ %@" = "%1$[日付]@が%3$@%2$[より後]@"; "%[exceptionType]@ is %[EXC_ARITHMETIC]@" = "%1$[例外の種類]@が%2$[EXC_ARITHMETIC]@である"; "%[exceptionType]@ is %[EXC_BAD_ACCESS]@" = "%1$[例外の種類]@が%2$[EXC_BAD_ACCESS]@である"; "%[exceptionType]@ is %[EXC_BAD_INSTRUCTION]@" = "%1$[例外の種類]@が%2$[EXC_BAD_INSTRUCTION]@である"; "%[exceptionType]@ is %[EXC_BREAKPOINT]@" = "%1$[例外の種類]@が%2$[EXC_BREAKPOINT]@である"; "%[exceptionType]@ is %[EXC_CORPSE_NOTIFY]@" = "%1$[例外の種類]@が%2$[EXC_CORPSE_NOTIFY]@である"; "%[exceptionType]@ is %[EXC_CRASH]@" = "%1$[例外の種類]@が%2$[EXC_CRASH]@である"; "%[exceptionType]@ is %[EXC_EMULATION]@" = "%1$[例外の種類]@が%2$[EXC_EMULATION]@である"; "%[exceptionType]@ is %[EXC_GUARD]@" = "%1$[例外の種類]@が%2$[EXC_GUARD]@である"; "%[exceptionType]@ is %[EXC_MACH_SYSCALL]@" = "%1$[例外の種類]@が%2$[EXC_MACH_SYSCALL]@である"; "%[exceptionType]@ is %[EXC_RESOURCE]@" = "%1$[例外の種類]@が%2$[EXC_RESOURCE]@である"; "%[exceptionType]@ is %[EXC_RPC_ALERT]@" = "%1$[例外の種類]@が%2$[EXC_RPC_ALERT]@である"; "%[exceptionType]@ is %[EXC_SOFTWARE]@" = "%1$[例外の種類]@が%2$[EXC_SOFTWARE]@である"; "%[exceptionType]@ is %[EXC_SYSCALL]@" = "%1$[例外の種類]@が%2$[EXC_SYSCALL]@である"; "%[exceptionSignal]@ is %[SIGABRT]@" = "%1$[例外信号]@が%2$[SIGABRT]@である"; "%[exceptionSignal]@ is %[SIGBUS]@" = "%1$[例外信号]@が%2$[SIGBUS]@である"; "%[exceptionSignal]@ is %[SIGILL]@" = "%1$[例外信号]@が%2$[SIGILL]@である"; "%[exceptionSignal]@ is %[SIGKILL]@" = "%1$[例外信号]@が%2$[SIGKILL]@である"; "%[exceptionSignal]@ is %[SIGQUIT]@" = "%1$[例外信号]@が%2$[SIGQUIT]@である"; "%[exceptionSignal]@ is %[SIGSEGV]@" = "%1$[例外信号]@が%2$[SIGSEGV]@である"; "%[exceptionSignal]@ is %[SIGTRAP]@" = "%1$[例外信号]@が%2$[SIGTRAP]@である"; "%[exceptionSignal]@ is %[Code Signature Invalid]@" = "%1$[例外信号]@が%2$[Code Signature Invalid]@である"; "%[crashLogFileName]@ %[is]@ %@" = "%1$[レポートのファイル名]@が%3$@%2$[である]@"; "%[crashLogFileName]@ %[is not]@ %@" = "%1$[レポートのファイル名]@が%3$@%2$[ではない]@"; "%[crashLogFileName]@ %[begins with]@ %@" = "%1$[レポートのファイル名]@が%3$@%2$[で始まる]@"; "%[crashLogFileName]@ %[ends with]@ %@" = "%1$[レポートのファイル名]@@が%3$@%2$[で終わる]@"; "%[crashLogFileName]@ %[contains]@ %@" = "%1$[レポートのファイル名]@が%3$@%2$[を含む]@"; "%[reportSourceTypeNumber]@ is %[0]@" = "%1$[ソース]@%2$[システムレポート]@である"; "%[reportSourceTypeNumber]@ is %[1]@" = "%1$[ソース]@%2$[ユーザレポート]@である"; "%[reportSourceTypeNumber]@ is %[2]@" = "%1$[ソース]@%2$[別の情報源]@である"; ================================================ FILE: app_unexpectedly/app_unexpectedly/main.m ================================================ /* Copyright (c) 2020-2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import int main(int argc, const char * argv[]) { return NSApplicationMain(argc, argv); } ================================================ FILE: app_unexpectedly/app_unexpectedly/template.source ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ D06294382E1DD8150008895D /* CUICodeSigningInformationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D06294362E1DD8150008895D /* CUICodeSigningInformationViewController.m */; }; D0790DBD2E00BACF00CD6A72 /* CUIThreadImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D0790DBC2E00BACF00CD6A72 /* CUIThreadImageView.m */; }; D0BA6A462E09FEB50010D630 /* EXC_GUARD.html in Resources */ = {isa = PBXBuildFile; fileRef = D0BA6A442E09FEB50010D630 /* EXC_GUARD.html */; }; D0BD223B2F3FC6810052AD8E /* NSMenuItem+RSCore.m in Sources */ = {isa = PBXBuildFile; fileRef = D0BD223A2F3FC6810052AD8E /* NSMenuItem+RSCore.m */; }; F4040A7624F5B9CE0072BF65 /* CUINavigationChevronView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4040A7524F5B9CE0072BF65 /* CUINavigationChevronView.m */; }; F4040A7924F5BC230072BF65 /* CUINavigationView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4040A7824F5BC230072BF65 /* CUINavigationView.m */; }; F4055C8125EEE37400DC6CCA /* CUIMainWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4055C8325EEE37400DC6CCA /* CUIMainWindowController.xib */; }; F405A96D255015D800AD2F24 /* CUICXXDemangler.mm in Sources */ = {isa = PBXBuildFile; fileRef = F405A96C255015D800AD2F24 /* CUICXXDemangler.mm */; }; F405A97025501A5F00AD2F24 /* CUIParsingErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = F405A96F25501A5F00AD2F24 /* CUIParsingErrors.m */; }; F406B4992687AB1400B90C7B /* CUIPreferencePaneAdvancedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F406B49B2687AB1400B90C7B /* CUIPreferencePaneAdvancedViewController.xib */; }; F40ACE2D255697A3006855E5 /* CUICrashLogBrowsingState.m in Sources */ = {isa = PBXBuildFile; fileRef = F40ACE2C255697A3006855E5 /* CUICrashLogBrowsingState.m */; }; F40ACE30255697CE006855E5 /* CUICrashLogBrowsingStateRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = F40ACE2F255697CE006855E5 /* CUICrashLogBrowsingStateRegistry.m */; }; F40B0D7E24D3558800663282 /* CUIPreferencesTabBox.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D7824D3558700663282 /* CUIPreferencesTabBox.m */; }; F40B0D7F24D3558800663282 /* CUIPreferencesTabHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D7924D3558800663282 /* CUIPreferencesTabHeaderView.m */; }; F40B0D8024D3558800663282 /* CUIPreferencesTabButton.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D7B24D3558800663282 /* CUIPreferencesTabButton.m */; }; F40B0D8724D3569800663282 /* NSColor+LabelColor.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D8424D3569800663282 /* NSColor+LabelColor.m */; }; F40B0D8824D3569800663282 /* NSResponder+Appearance.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D8524D3569800663282 /* NSResponder+Appearance.m */; }; F40B0D8D24D356A200663282 /* NSArray+WBExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D8924D356A200663282 /* NSArray+WBExtensions.m */; }; F40B0D8E24D356A200663282 /* NSIndexSet+Analysis.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D8B24D356A200663282 /* NSIndexSet+Analysis.m */; }; F40B0D9124D356F900663282 /* NSToolbar+Packages.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D9024D356F900663282 /* NSToolbar+Packages.m */; }; F40B0D9424D3571B00663282 /* NSTableView+Selection.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D9224D3571A00663282 /* NSTableView+Selection.m */; }; F40B0D9724D3572E00663282 /* NSColor+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D9524D3572E00663282 /* NSColor+String.m */; }; F40B0D9D24D370A200663282 /* NSDictionary+MutableDeepCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B0D9C24D370A200663282 /* NSDictionary+MutableDeepCopy.m */; }; F40B124924E89BBE005E82DD /* CUIPreferencesWindowController+Convenience.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B124824E89BBE005E82DD /* CUIPreferencesWindowController+Convenience.m */; }; F40B77D724AF0F5C001A8131 /* CUICrashLogsSourceStandardDirectory+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B77D624AF0F5C001A8131 /* CUICrashLogsSourceStandardDirectory+UI.m */; }; F40B77DA24AF1426001A8131 /* CUICrashLogsSourceAll+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F40B77D924AF1426001A8131 /* CUICrashLogsSourceAll+UI.m */; }; F40B832625FC0AEC0091D886 /* EXC_CRASH_SIGSEGV.html in Resources */ = {isa = PBXBuildFile; fileRef = F40B832825FC0AEC0091D886 /* EXC_CRASH_SIGSEGV.html */; }; F40BEAF124E9F754007A3F60 /* CUIThemeItemAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = F40BEAF024E9F754007A3F60 /* CUIThemeItemAttributes.m */; }; F40BEAFC24E9FEF8007A3F60 /* NSDictionary+WBExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = F40BEAFB24E9FEF8007A3F60 /* NSDictionary+WBExtensions.m */; }; F40ED76724E72A6E00557BB8 /* CUICategoriesClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = F40ED76624E72A6E00557BB8 /* CUICategoriesClipView.m */; }; F40FC81625EAF7B000DB4B27 /* CUISourceFileTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = F40FC81525EAF7B000DB4B27 /* CUISourceFileTableCellView.m */; }; F4132C8F24AA19F70086B99C /* CUICrashLogsSource.m in Sources */ = {isa = PBXBuildFile; fileRef = F4132C8E24AA19F70086B99C /* CUICrashLogsSource.m */; }; F414068824D5F1D20059FF21 /* CUIApplicationSpecificBacktraceRowView.m in Sources */ = {isa = PBXBuildFile; fileRef = F414068724D5F1D20059FF21 /* CUIApplicationSpecificBacktraceRowView.m */; }; F414068B24D6014D0059FF21 /* CUIFontAndColorsFramedView.m in Sources */ = {isa = PBXBuildFile; fileRef = F414068A24D6014D0059FF21 /* CUIFontAndColorsFramedView.m */; }; F414D08E24BFB57700A7095C /* CUICrashLogDianosticMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = F414D08D24BFB57700A7095C /* CUICrashLogDianosticMessages.m */; }; F414D09124BFBC3A00A7095C /* CUICrashLogBacktraces.m in Sources */ = {isa = PBXBuildFile; fileRef = F414D09024BFBC3A00A7095C /* CUICrashLogBacktraces.m */; }; F414D09424BFBC4A00A7095C /* CUICrashLogThreadState.m in Sources */ = {isa = PBXBuildFile; fileRef = F414D09324BFBC4A00A7095C /* CUICrashLogThreadState.m */; }; F414D09724BFBC6300A7095C /* CUICrashLogBinaryImages.m in Sources */ = {isa = PBXBuildFile; fileRef = F414D09624BFBC6300A7095C /* CUICrashLogBinaryImages.m */; }; F416686F24B0AEE800C2AB89 /* CUIContentsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F416686D24B0AEE800C2AB89 /* CUIContentsViewController.m */; }; F416687024B0AEE800C2AB89 /* CUIContentsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F416686E24B0AEE800C2AB89 /* CUIContentsViewController.xib */; }; F416687424B0AF4D00C2AB89 /* CUICenteredLabelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F416687224B0AF4D00C2AB89 /* CUICenteredLabelViewController.m */; }; F416687924B0BA5000C2AB89 /* CUICrashLogContentsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F416687724B0BA5000C2AB89 /* CUICrashLogContentsViewController.m */; }; F416687A24B0BA5000C2AB89 /* CUICrashLogContentsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F416687824B0BA5000C2AB89 /* CUICrashLogContentsViewController.xib */; }; F416687E24B0BBA300C2AB89 /* CUICrashLogPresentationTextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F416687C24B0BBA300C2AB89 /* CUICrashLogPresentationTextViewController.m */; }; F416688224B0BBFC00C2AB89 /* CUICrashLogPresentationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F416688124B0BBFC00C2AB89 /* CUICrashLogPresentationViewController.m */; }; F416688624B0BF2000C2AB89 /* CUISidebarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F416688424B0BF2000C2AB89 /* CUISidebarViewController.m */; }; F416688724B0BF2000C2AB89 /* CUISidebarViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F416688524B0BF2000C2AB89 /* CUISidebarViewController.xib */; }; F419376F2672B2BE00B796EB /* CUICrashLogsOpenErrorPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = F419376E2672B2BE00B796EB /* CUICrashLogsOpenErrorPanel.m */; }; F41D66B025921F3400C0D491 /* CUIPreferencePanePresentationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F41D66AE25921F3400C0D491 /* CUIPreferencePanePresentationViewController.m */; }; F41ECA5324AB689B00CE56C7 /* CUIInspectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F41ECA5124AB689B00CE56C7 /* CUIInspectorViewController.m */; }; F41ECA5424AB689B00CE56C7 /* CUIInspectorViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F41ECA5224AB689B00CE56C7 /* CUIInspectorViewController.xib */; }; F420C9B9254F30A100D24249 /* CUIFileDeadDropView.m in Sources */ = {isa = PBXBuildFile; fileRef = F420C9B8254F30A100D24249 /* CUIFileDeadDropView.m */; }; F420C9C1254F335000D24249 /* CUIdSYMDropView.m in Sources */ = {isa = PBXBuildFile; fileRef = F420C9C0254F335000D24249 /* CUIdSYMDropView.m */; }; F420C9C4254F5F4C00D24249 /* CUIdSYMHunter.m in Sources */ = {isa = PBXBuildFile; fileRef = F420C9C3254F5F4C00D24249 /* CUIdSYMHunter.m */; }; F420F35224E95E5F006C82CD /* CUITheme.m in Sources */ = {isa = PBXBuildFile; fileRef = F420F35124E95E5F006C82CD /* CUITheme.m */; }; F4214CB524B6534400852DDE /* CUICrashLogsSourcesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F4214CB424B6534400852DDE /* CUICrashLogsSourcesManager.m */; }; F423818C267D1D4A003837AC /* CUIPreferencePaneAdvancedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F423818A267D1D4A003837AC /* CUIPreferencePaneAdvancedViewController.m */; }; F4238191267D3522003837AC /* WBRemoteVersionChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = F4238190267D3522003837AC /* WBRemoteVersionChecker.m */; }; F428C0702724592D00FB8CAC /* IPSImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0412724592900FB8CAC /* IPSImage.m */; }; F428C0712724592D00FB8CAC /* IPSIncidentHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0422724592900FB8CAC /* IPSIncidentHeader.m */; }; F428C0722724592D00FB8CAC /* IPSIncidentExceptionInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0432724592900FB8CAC /* IPSIncidentExceptionInformation.m */; }; F428C0732724592D00FB8CAC /* IPSIncidentDiagnosticMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0442724592900FB8CAC /* IPSIncidentDiagnosticMessage.m */; }; F428C0742724592D00FB8CAC /* IPSReport.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0452724592900FB8CAC /* IPSReport.m */; }; F428C0752724592D00FB8CAC /* IPSThreadInstructionState.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0462724592900FB8CAC /* IPSThreadInstructionState.m */; }; F428C0762724592D00FB8CAC /* IPSThreadInstructionStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0472724592900FB8CAC /* IPSThreadInstructionStream.m */; }; F428C0772724592D00FB8CAC /* IPSRegisterState.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0492724592900FB8CAC /* IPSRegisterState.m */; }; F428C0782724592D00FB8CAC /* IPSDateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C04A2724592A00FB8CAC /* IPSDateFormatter.m */; }; F428C0792724592D00FB8CAC /* IPSApplicationSpecificInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C04B2724592A00FB8CAC /* IPSApplicationSpecificInformation.m */; }; F428C07A2724592D00FB8CAC /* IPSSummary.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C04C2724592A00FB8CAC /* IPSSummary.m */; }; F428C07B2724592D00FB8CAC /* IPSTermination.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C04D2724592A00FB8CAC /* IPSTermination.m */; }; F428C07C2724592D00FB8CAC /* IPSExternalModificationSummary.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C04E2724592A00FB8CAC /* IPSExternalModificationSummary.m */; }; F428C07D2724592D00FB8CAC /* IPSExternalModificationStatistics.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0502724592A00FB8CAC /* IPSExternalModificationStatistics.m */; }; F428C07E2724592D00FB8CAC /* IPSBundleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0532724592A00FB8CAC /* IPSBundleInfo.m */; }; F428C07F2724592D00FB8CAC /* IPSException.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0542724592A00FB8CAC /* IPSException.m */; }; F428C0802724592D00FB8CAC /* IPSThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0572724592A00FB8CAC /* IPSThread.m */; }; F428C0812724592D00FB8CAC /* IPSThreadFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0592724592B00FB8CAC /* IPSThreadFrame.m */; }; F428C0822724592D00FB8CAC /* IPSError.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C05B2724592B00FB8CAC /* IPSError.m */; }; F428C0832724592D00FB8CAC /* IPSOperatingSystemVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C05E2724592B00FB8CAC /* IPSOperatingSystemVersion.m */; }; F428C0842724592D00FB8CAC /* IPSThreadState.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0622724592B00FB8CAC /* IPSThreadState.m */; }; F428C0852724592D00FB8CAC /* IPSLegacyInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0682724592C00FB8CAC /* IPSLegacyInfo.m */; }; F428C0862724592D00FB8CAC /* IPSIncident.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C06A2724592C00FB8CAC /* IPSIncident.m */; }; F42B57E224ABEF6E00F77ED5 /* CUICallsSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = F42B57E124ABEF6E00F77ED5 /* CUICallsSelection.m */; }; F42D0BC425514B670021A551 /* template.source in Resources */ = {isa = PBXBuildFile; fileRef = F42D0BC225514B2E0021A551 /* template.source */; }; F42E50012724B7550092181A /* CUICrashDataTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F42E50002724B7550092181A /* CUICrashDataTransform.m */; }; F4301A6825EF0DE000ACDA3F /* CUIPreferencePanePresentationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4301A6A25EF0DE000ACDA3F /* CUIPreferencePanePresentationViewController.xib */; }; F4306D592577E168007E667F /* CUICrashLogThreadState+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4306D582577E168007E667F /* CUICrashLogThreadState+UI.m */; }; F432ACC824A95014000A3E7A /* CUIThreadsListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F432ACC624A95014000A3E7A /* CUIThreadsListViewController.m */; }; F432ACCC24A9502A000A3E7A /* CUIThreadsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F432ACCB24A9502A000A3E7A /* CUIThreadsViewController.m */; }; F432ACD024A95042000A3E7A /* CUIThreadsColumnViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F432ACCE24A95042000A3E7A /* CUIThreadsColumnViewController.m */; }; F43362FE25FCEFBA006E7894 /* CUIRawCrashLog+Path.m in Sources */ = {isa = PBXBuildFile; fileRef = F43362FD25FCEFBA006E7894 /* CUIRawCrashLog+Path.m */; }; F4341C6B258EB8FE001A5605 /* CUICrashReporterDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = F4341C6A258EB8FE001A5605 /* CUICrashReporterDefaults.m */; }; F4386B0F2849541C00B83525 /* CUICrashLogExceptionInformation+QuickHelp.m in Sources */ = {isa = PBXBuildFile; fileRef = F4386B0D2849541B00B83525 /* CUICrashLogExceptionInformation+QuickHelp.m */; }; F43A9A832591260C005AB2AA /* CUIOutlineModeDisplaySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = F43A9A822591260C005AB2AA /* CUIOutlineModeDisplaySettings.m */; }; F43AF0D1256FE2AE0066CA1B /* DWRFSection_debug_addr.m in Sources */ = {isa = PBXBuildFile; fileRef = F43AF0D0256FE2AE0066CA1B /* DWRFSection_debug_addr.m */; }; F43C828824D892620096F27B /* CUIPreferencePanePresentationTextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F43C828624D892620096F27B /* CUIPreferencePanePresentationTextViewController.m */; }; F43C828C24D8A39B0096F27B /* CUITextModeDisplaySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = F43C828B24D8A39B0096F27B /* CUITextModeDisplaySettings.m */; }; F43D8FF724A7FAD2008147F9 /* CUIMainWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F43D8FF524A7FAD2008147F9 /* CUIMainWindowController.m */; }; F440A3E324AA315800C23DA1 /* CUICrashLogsSourceStandardDirectory.m in Sources */ = {isa = PBXBuildFile; fileRef = F440A3E224AA315800C23DA1 /* CUICrashLogsSourceStandardDirectory.m */; }; F440A3E624AA31B500C23DA1 /* CUICrashLogsSourceFile.m in Sources */ = {isa = PBXBuildFile; fileRef = F440A3E524AA31B500C23DA1 /* CUICrashLogsSourceFile.m */; }; F440A3E924AA35AC00C23DA1 /* CUICrashLogsSourceDirectory.m in Sources */ = {isa = PBXBuildFile; fileRef = F440A3E824AA35AC00C23DA1 /* CUICrashLogsSourceDirectory.m */; }; F440A3EC24AA38E600C23DA1 /* CUICrashLogsSourceAll.m in Sources */ = {isa = PBXBuildFile; fileRef = F440A3EB24AA38E600C23DA1 /* CUICrashLogsSourceAll.m */; }; F442FCED24AB855C00E87B69 /* CUIBinaryImagesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F442FCEB24AB855C00E87B69 /* CUIBinaryImagesViewController.m */; }; F442FCF124AB8A8B00E87B69 /* CUIBinaryImageUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F442FCF024AB8A8B00E87B69 /* CUIBinaryImageUtility.m */; }; F44356F324A8A113001D3D35 /* CUICrashLogPresentationOutlineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F44356F124A8A113001D3D35 /* CUICrashLogPresentationOutlineViewController.m */; }; F44356FF24A8A8B5001D3D35 /* CUIThreadNamedTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = F44356FE24A8A8B5001D3D35 /* CUIThreadNamedTableCellView.m */; }; F4440FE0282C4104003C810B /* IPSSummarySerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4440FDC282C4103003C810B /* IPSSummarySerialization.m */; }; F4440FE1282C4104003C810B /* IPSCrashSummary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4440FDD282C4103003C810B /* IPSCrashSummary.m */; }; F44E7B7F255C83D500025C04 /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = F44E7B7C255C83D500025C04 /* NoodleLineNumberView.m */; }; F44E7B80255C83D500025C04 /* NoodleLineNumberMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = F44E7B7D255C83D500025C04 /* NoodleLineNumberMarker.m */; }; F45015C625FABCAC000C4B8D /* EXC_BAD_ACCESS_SIGSEGV.html in Resources */ = {isa = PBXBuildFile; fileRef = F45015C825FABCAC000C4B8D /* EXC_BAD_ACCESS_SIGSEGV.html */; }; F45015CA25FABE00000C4B8D /* EXC_BAD_INSTRUCTION_SIGILL.html in Resources */ = {isa = PBXBuildFile; fileRef = F45015CC25FABE00000C4B8D /* EXC_BAD_INSTRUCTION_SIGILL.html */; }; F45015CE25FAD279000C4B8D /* EXC_CRASH_SIGQUIT.html in Resources */ = {isa = PBXBuildFile; fileRef = F45015D025FAD279000C4B8D /* EXC_CRASH_SIGQUIT.html */; }; F453AE4925EE706F00B7BEF0 /* CUIExportAccessoryViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F453AE4B25EE706F00B7BEF0 /* CUIExportAccessoryViewController.xib */; }; F453AE4D25EE70E800B7BEF0 /* CUICrashLogPresentationTextViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F453AE4F25EE70E800B7BEF0 /* CUICrashLogPresentationTextViewController.xib */; }; F45442A924AF355700EE79E4 /* CUICaptionView.m in Sources */ = {isa = PBXBuildFile; fileRef = F45442A824AF355700EE79E4 /* CUICaptionView.m */; }; F4545C3C256C1AF900F62A39 /* CUIRegistersWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4545C3A256C1AF900F62A39 /* CUIRegistersWindowController.m */; }; F4545C3D256C1AF900F62A39 /* CUIRegistersWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4545C3B256C1AF900F62A39 /* CUIRegistersWindowController.xib */; }; F4545C41256C1B2400F62A39 /* CUIRegistersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4545C3F256C1B2400F62A39 /* CUIRegistersViewController.m */; }; F4559F3724AF232800B8EF41 /* CUICrashLogHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = F4559F3624AF232800B8EF41 /* CUICrashLogHeader.m */; }; F4577BEA2592848D009B2AD2 /* CUIPreferencePanePresentationOutlineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4577BE82592848D009B2AD2 /* CUIPreferencePanePresentationOutlineViewController.m */; }; F45854FA25C76591007A3A79 /* Unexpectedly_License.pdf in Resources */ = {isa = PBXBuildFile; fileRef = F45854F825C76590007A3A79 /* Unexpectedly_License.pdf */; }; F45854FB25C76591007A3A79 /* Unexpectedly_Acknowledgements.pdf in Resources */ = {isa = PBXBuildFile; fileRef = F45854F925C76591007A3A79 /* Unexpectedly_Acknowledgements.pdf */; }; F45A2D5D25EC5CA00007D50E /* CUIPreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F45A2D5F25EC5CA00007D50E /* CUIPreferencesWindowController.xib */; }; F45A2D6125EC5D130007D50E /* CUIPreferencePaneFontscolorsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F45A2D6325EC5D130007D50E /* CUIPreferencePaneFontscolorsViewController.xib */; }; F45A2D6525EC5F850007D50E /* CUIAboutBoxWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F45A2D6725EC5F850007D50E /* CUIAboutBoxWindowController.xib */; }; F45A2D6925EC602B0007D50E /* CUIBinaryImagesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F45A2D6B25EC602B0007D50E /* CUIBinaryImagesViewController.xib */; }; F45A2D6D25EC60920007D50E /* CUICrashLogsSourcesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F45A2D6F25EC60920007D50E /* CUICrashLogsSourcesViewController.xib */; }; F45A2D7125EC60D90007D50E /* CUICrashLogsListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F45A2D7325EC60D90007D50E /* CUICrashLogsListViewController.xib */; }; F45B518C24AFA04000E97B87 /* CUICrashLogsSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = F45B518B24AFA04000E97B87 /* CUICrashLogsSelection.m */; }; F45DED692E350F07008F4CE8 /* CUICodeSigningInformationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F45DED6B2E350F07008F4CE8 /* CUICodeSigningInformationViewController.xib */; }; F45DED6F2E3510D9008F4CE8 /* CodeSigning.strings in Resources */ = {isa = PBXBuildFile; fileRef = F45DED6D2E3510D9008F4CE8 /* CodeSigning.strings */; }; F45F2F5B2538EF3F0030A402 /* NSFileManager+ExtendedAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = F45F2F5A2538EF3F0030A402 /* NSFileManager+ExtendedAttributes.m */; }; F45F84DC266ABB7600F354F3 /* crashreport.qlgenerator in CopyFiles */ = {isa = PBXBuildFile; fileRef = F45F84D8266ABB5800F354F3 /* crashreport.qlgenerator */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; F46198E924CA390700FA9717 /* CUICrashLogBacktraces+Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F46198E824CA390700FA9717 /* CUICrashLogBacktraces+Utilities.m */; }; F46198EE24CA459700FA9717 /* CUIInspectorAlternateBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = F46198ED24CA459700FA9717 /* CUIInspectorAlternateBackgroundView.m */; }; F461CE8A25F6DD75007CFDE7 /* CUIApplicationItemAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = F461CE8925F6DD75007CFDE7 /* CUIApplicationItemAttributes.m */; }; F4627F1225704557007E5CD0 /* CUICollectionViewRegisterItem.m in Sources */ = {isa = PBXBuildFile; fileRef = F4627F1025704557007E5CD0 /* CUICollectionViewRegisterItem.m */; }; F462DD3124ADC5F900044AB1 /* CUICrashLogsSourceSmart.m in Sources */ = {isa = PBXBuildFile; fileRef = F462DD3024ADC5F900044AB1 /* CUICrashLogsSourceSmart.m */; }; F464F20C24ACF9CF007A3A96 /* CUICrashLogsMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F464F20A24ACF9CF007A3A96 /* CUICrashLogsMainViewController.m */; }; F464F20D24ACF9CF007A3A96 /* CUICrashLogsMainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F464F20B24ACF9CF007A3A96 /* CUICrashLogsMainViewController.xib */; }; F464F21024ACFBA1007A3A96 /* CUIRegister.m in Sources */ = {isa = PBXBuildFile; fileRef = F464F20F24ACFBA1007A3A96 /* CUIRegister.m */; }; F464FA1525D2DA2A00E024A3 /* NSSet+WBExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = F464FA1425D2DA2A00E024A3 /* NSSet+WBExtensions.m */; }; F4651F8624B297420090DF10 /* CUIOperatingSystemVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = F4651F8524B297420090DF10 /* CUIOperatingSystemVersion.m */; }; F469AB2524B3DDEA0053C824 /* CUICrashLogExceptionInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F469AB2424B3DDEA0053C824 /* CUICrashLogExceptionInformation.m */; }; F46BAF59250162C900991970 /* CUIPreferencesWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = F46BAF58250162C900991970 /* CUIPreferencesWindow.m */; }; F46D2A2624C33FA200652D50 /* Predicates.strings in Resources */ = {isa = PBXBuildFile; fileRef = F46D2A2824C33FA200652D50 /* Predicates.strings */; }; F46D779B25ED8D1800039663 /* CUIInspectorGeneralViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F46D779D25ED8D1800039663 /* CUIInspectorGeneralViewController.xib */; }; F46D779F25ED8D3600039663 /* CUIInspectorUserViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F46D77A125ED8D3600039663 /* CUIInspectorUserViewController.xib */; }; F46D77A325ED8D5700039663 /* CUIInspectorExecutableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F46D77A525ED8D5700039663 /* CUIInspectorExecutableViewController.xib */; }; F46D77A725ED8E3B00039663 /* CUIInspectorProcessesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F46D77A925ED8E3B00039663 /* CUIInspectorProcessesViewController.xib */; }; F46D77AB25ED9EAE00039663 /* CUICollectionViewRegisterItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = F46D77AD25ED9EAE00039663 /* CUICollectionViewRegisterItem.xib */; }; F472CC972550631A003F6338 /* CUISwiftDemangler.m in Sources */ = {isa = PBXBuildFile; fileRef = F472CC962550631A003F6338 /* CUISwiftDemangler.m */; }; F4754D7125F5678700B0D48F /* CUICrashLogPresentationOutlineViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4754D7325F5678700B0D48F /* CUICrashLogPresentationOutlineViewController.xib */; }; F475FB4026DBAC8200A113D8 /* CUITableViewNoSpace.m in Sources */ = {isa = PBXBuildFile; fileRef = F475FB3F26DBAC8200A113D8 /* CUITableViewNoSpace.m */; }; F476EEBE25686DEF00F40F87 /* CUIAboutBoxFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = F476EEBD25686DEF00F40F87 /* CUIAboutBoxFooterView.m */; }; F476EEC125686EC000F40F87 /* CUIContentBox.m in Sources */ = {isa = PBXBuildFile; fileRef = F476EEBF25686EC000F40F87 /* CUIContentBox.m */; }; F4775479255B0054006BA662 /* CUIThemesTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4775478255B0054006BA662 /* CUIThemesTableView.m */; }; F47AF8C0255DE61E0037E2D8 /* NSCrashLogTextScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = F47AF8BF255DE61E0037E2D8 /* NSCrashLogTextScrollView.m */; }; F47C381E2A422E880020D88F /* CUIThreadsListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F47C381C2A422E880020D88F /* CUIThreadsListViewController.xib */; }; F47C381F2A422E880020D88F /* CUIThreadsListViewController_RTL.xib in Resources */ = {isa = PBXBuildFile; fileRef = F47C381D2A422E880020D88F /* CUIThreadsListViewController_RTL.xib */; }; F47C38222A4230370020D88F /* CUIThreadsColumnViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F47C38202A4230370020D88F /* CUIThreadsColumnViewController.xib */; }; F47C38232A4230370020D88F /* CUIThreadsColumnViewController_RTL.xib in Resources */ = {isa = PBXBuildFile; fileRef = F47C38212A4230370020D88F /* CUIThreadsColumnViewController_RTL.xib */; }; F47F76622673542600A74905 /* CUICrashLogsOpenErrorRecord+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F47F76612673542600A74905 /* CUICrashLogsOpenErrorRecord+UI.m */; }; F47F76652673548600A74905 /* CUICrashLogsOpenErrorRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = F47F76642673548600A74905 /* CUICrashLogsOpenErrorRecord.m */; }; F47F7668267355EA00A74905 /* CUICrashLogErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = F47F7667267355EA00A74905 /* CUICrashLogErrors.m */; }; F480692E24AF7D83009665F2 /* CUICrashLogsListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F480692C24AF7D83009665F2 /* CUICrashLogsListViewController.m */; }; F483845124EB041B00FAEF5D /* CUIThemeItemsGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = F483845024EB041B00FAEF5D /* CUIThemeItemsGroup.m */; }; F483845324EB11F700FAEF5D /* default_themes.plist in Resources */ = {isa = PBXBuildFile; fileRef = F483845224EB11F700FAEF5D /* default_themes.plist */; }; F483845624EB1BEB00FAEF5D /* CUIApplicationPreferences+Themes.m in Sources */ = {isa = PBXBuildFile; fileRef = F483845524EB1BEB00FAEF5D /* CUIApplicationPreferences+Themes.m */; }; F483845924EB26DF00FAEF5D /* CUIThemeItemsGroup+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F483845824EB26DF00FAEF5D /* CUIThemeItemsGroup+UI.m */; }; F4871DC02543566E00580562 /* CUIdSYMBundle.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871DBF2543566E00580562 /* CUIdSYMBundle.m */; }; F4871E0325435AF400580562 /* DWRFSection_debug_info.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871DF225435AF300580562 /* DWRFSection_debug_info.m */; }; F4871E0425435AF400580562 /* DWRFSection_debug_str.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871DF325435AF300580562 /* DWRFSection_debug_str.m */; }; F4871E0525435AF400580562 /* DWRFSection_debug_line.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871DF725435AF300580562 /* DWRFSection_debug_line.m */; }; F4871E0625435AF400580562 /* DWRFSection_debug_abbrev.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871DF925435AF300580562 /* DWRFSection_debug_abbrev.m */; }; F4871E0725435AF400580562 /* DWRFFileObject.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871DFB25435AF300580562 /* DWRFFileObject.m */; }; F4871E0825435AF400580562 /* LEB128.c in Sources */ = {isa = PBXBuildFile; fileRef = F4871DFE25435AF400580562 /* LEB128.c */; }; F4871E0925435AF400580562 /* DWRFObject.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871E0125435AF400580562 /* DWRFObject.m */; }; F4871E0A25435AF400580562 /* DWRFSection_debug_aranges.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871E0225435AF400580562 /* DWRFSection_debug_aranges.m */; }; F4871E0D25437A6A00580562 /* CUISymbolicationDataCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871E0C25437A6A00580562 /* CUISymbolicationDataCache.m */; }; F4871E10254384E100580562 /* CUIdSYMBundlesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F4871E0F254384E100580562 /* CUIdSYMBundlesManager.m */; }; F48906AE25D2BA0C002D79A9 /* CUISelectedWhiteTextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F48906AD25D2BA0C002D79A9 /* CUISelectedWhiteTextFieldCell.m */; }; F48944222545836F00E3E360 /* CUISymbolsFilesLibraryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F48944202545836F00E3E360 /* CUISymbolsFilesLibraryViewController.m */; }; F4895F5727A72D1000D75369 /* CUILineJumperWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4895F5927A72D1000D75369 /* CUILineJumperWindowController.xib */; }; F48BAB3625D9D4140005F3E5 /* CUIThreadImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F48BAB3525D9D4140005F3E5 /* CUIThreadImageCell.m */; }; F48CF5FF24A96992002AD214 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4CC570B24A79EDA00150EC4 /* MainMenu.xib */; }; F49227C824A8D45000772411 /* CUIStackFrame+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F49227C724A8D45000772411 /* CUIStackFrame+UI.m */; }; F49282C325696BF900D255D8 /* known_exceptions.css in Resources */ = {isa = PBXBuildFile; fileRef = F49282C225696BF900D255D8 /* known_exceptions.css */; }; F493DB1C24F1CF30001AA8C0 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F493DB1A24F1CF2F001AA8C0 /* Localizable.strings */; }; F495AEBC25F029C2000D92E1 /* CUIPreferencePanePresentationTextViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F495AEBE25F029C2000D92E1 /* CUIPreferencePanePresentationTextViewController.xib */; }; F495AEC025F02F74000D92E1 /* CUIPreferencePanePresentationOutlineViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F495AEC225F02F74000D92E1 /* CUIPreferencePanePresentationOutlineViewController.xib */; }; F495AEC425F03141000D92E1 /* unknown_exception_type.html in Resources */ = {isa = PBXBuildFile; fileRef = F495AEC625F03141000D92E1 /* unknown_exception_type.html */; }; F495AEC825F0320D000D92E1 /* EXC_CRASH_SIGABRT.html in Resources */ = {isa = PBXBuildFile; fileRef = F495AECA25F0320D000D92E1 /* EXC_CRASH_SIGABRT.html */; }; F495AECC25F033CC000D92E1 /* EXC_CRASH_SIGKILL.html in Resources */ = {isa = PBXBuildFile; fileRef = F495AECE25F033CC000D92E1 /* EXC_CRASH_SIGKILL.html */; }; F495AED025F034C0000D92E1 /* EXC_BREAKPOINT_SIGTRAP.html in Resources */ = {isa = PBXBuildFile; fileRef = F495AED225F034C0000D92E1 /* EXC_BREAKPOINT_SIGTRAP.html */; }; F495AED425F03820000D92E1 /* EXC_CRASH_Code Signature Invalid.html in Resources */ = {isa = PBXBuildFile; fileRef = F495AED625F03820000D92E1 /* EXC_CRASH_Code Signature Invalid.html */; }; F49673FE24D0CF6400716289 /* CUIPreferencesWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F49673FC24D0CF6400716289 /* CUIPreferencesWindowController.m */; }; F496740324D0D05800716289 /* CUIPreferencePaneViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F496740224D0D05800716289 /* CUIPreferencePaneViewController.m */; }; F496740A24D0D2A300716289 /* CUIPreferencePaneFontscolorsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F496740824D0D2A300716289 /* CUIPreferencePaneFontscolorsViewController.m */; }; F496740E24D0D74A00716289 /* CUIApplicationPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = F496740D24D0D74A00716289 /* CUIApplicationPreferences.m */; }; F497303A25F796E6001D01FE /* CUIHopperDisassemblerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F497303925F796E6001D01FE /* CUIHopperDisassemblerManager.m */; }; F497303E25F7F74C001D01FE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F497303C25F7F74B001D01FE /* InfoPlist.strings */; }; F497AD5524B8FE88008517B7 /* CUICrashLogsSourceSmartEditorPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = F497AD5424B8FE88008517B7 /* CUICrashLogsSourceSmartEditorPanel.m */; }; F497F0162576E1A100BD1970 /* CUIRoundedRectBezelView.m in Sources */ = {isa = PBXBuildFile; fileRef = F497F0152576E1A100BD1970 /* CUIRoundedRectBezelView.m */; }; F49A55DE24C7A7F900D249DE /* CUICallTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = F49A55DD24C7A7F900D249DE /* CUICallTableCellView.m */; }; F49A6D7E25474F6E00466D15 /* CUIInactiveButton.m in Sources */ = {isa = PBXBuildFile; fileRef = F49A6D7D25474F6E00466D15 /* CUIInactiveButton.m */; }; F49A6D8125476F7B00466D15 /* CUISymbolicationDataFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F49A6D8025476F7B00466D15 /* CUISymbolicationDataFormatter.m */; }; F49C47CA24E9B48B003FC65C /* CUIThemesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F49C47C924E9B48B003FC65C /* CUIThemesManager.m */; }; F4A0BEF1261BC39700BADEED /* CUIWatchGear.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A0BEE2261BC39600BADEED /* CUIWatchGear.m */; }; F4A0BEF2261BC39700BADEED /* CUIWatchJewel.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A0BEE3261BC39600BADEED /* CUIWatchJewel.m */; }; F4A0BEF3261BC39700BADEED /* brushed-alum.png in Resources */ = {isa = PBXBuildFile; fileRef = F4A0BEE5261BC39600BADEED /* brushed-alum.png */; }; F4A0BEF4261BC39700BADEED /* CUIWatchAxis.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A0BEE6261BC39600BADEED /* CUIWatchAxis.m */; }; F4A0BEF6261BC39700BADEED /* CUIWatchPart.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A0BEEB261BC39700BADEED /* CUIWatchPart.m */; }; F4A0BEF7261BC39700BADEED /* CUIWatchBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A0BEED261BC39700BADEED /* CUIWatchBridge.m */; }; F4A0BEF8261BC39700BADEED /* CUIWatchScrew.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A0BEEF261BC39700BADEED /* CUIWatchScrew.m */; }; F4A3A6DF25ED7F450018053E /* CUICrashLogsSourceSmartEditorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4A3A6E125ED7F450018053E /* CUICrashLogsSourceSmartEditorWindowController.xib */; }; F4A3A6E325ED81260018053E /* CUIPreferencePaneGeneralViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4A3A6E525ED81260018053E /* CUIPreferencePaneGeneralViewController.xib */; }; F4A3A6E725ED817E0018053E /* CUIPreferencePaneCrashreporterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4A3A6E925ED817E0018053E /* CUIPreferencePaneCrashreporterViewController.xib */; }; F4A3A6EB25ED82F10018053E /* EXC_BAD_ACCESS_SIGBUS.html in Resources */ = {isa = PBXBuildFile; fileRef = F4A3A6ED25ED82F10018053E /* EXC_BAD_ACCESS_SIGBUS.html */; }; F4A58D1B24CA4B1500D98FDB /* CUICrashedThreadRowView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A58D1A24CA4B1500D98FDB /* CUICrashedThreadRowView.m */; }; F4A58D1E24CA4CDA00D98FDB /* CUICrashedThreadCallRowView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A58D1D24CA4CDA00D98FDB /* CUICrashedThreadCallRowView.m */; }; F4A7696A2555D9DE00F9D9D3 /* CUIRawCrashLog+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4A769692555D9DD00F9D9D3 /* CUIRawCrashLog+UI.m */; }; F4A9967C2675078B0001B40E /* CUICrashLogsOpenErrorWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4A9967B2675078A0001B40E /* CUICrashLogsOpenErrorWindowController.xib */; }; F4AA22B72561A233001A1315 /* CUIAboutBoxWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4AA22B52561A233001A1315 /* CUIAboutBoxWindowController.m */; }; F4AC864A2558A03B004F2637 /* CUIExportAccessoryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4AC86482558A03B004F2637 /* CUIExportAccessoryViewController.m */; }; F4B018372620FEC7009727F1 /* CUIApplicationIconView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B018352620FEC7009727F1 /* CUIApplicationIconView.m */; }; F4B138572522948700D9DE2F /* NSBundle+dSYM.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B138562522948700D9DE2F /* NSBundle+dSYM.m */; }; F4B52E212548B8B4007593FD /* CUIdSYMBundle+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B52E202548B8B4007593FD /* CUIdSYMBundle+UI.m */; }; F4B57C0C24AF5607000851FF /* CUICrashLogsSourceToday.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B57C0B24AF5607000851FF /* CUICrashLogsSourceToday.m */; }; F4B57C0F24AF5655000851FF /* CUICrashLogsSourceToday+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B57C0E24AF5655000851FF /* CUICrashLogsSourceToday+UI.m */; }; F4B5BE6E2848277400C33F6F /* CUIExceptionTypePopUpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B5BE6D2848277400C33F6F /* CUIExceptionTypePopUpViewController.m */; }; F4B5BE7128482A4300C33F6F /* CUITerminationReasonPopUpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B5BE7028482A4300C33F6F /* CUITerminationReasonPopUpViewController.m */; }; F4B649D324EDCD2300008C47 /* CUIInspectorExecutableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B649D124EDCD2300008C47 /* CUIInspectorExecutableViewController.m */; }; F4B649D724EDD09A00008C47 /* CUIInspectorStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B649D624EDD09A00008C47 /* CUIInspectorStackableViewController.m */; }; F4B649DB24EDD64900008C47 /* CUIInspectorProcessesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B649D924EDD64900008C47 /* CUIInspectorProcessesViewController.m */; }; F4B67838258F702E0047369E /* CUIPreferencePaneCrashreporterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B67836258F702E0047369E /* CUIPreferencePaneCrashreporterViewController.m */; }; F4B74C1924B233C900CD1E60 /* CUIRightViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B74C1724B233C900CD1E60 /* CUIRightViewController.m */; }; F4B74C1A24B233C900CD1E60 /* CUIRightViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4B74C1824B233C900CD1E60 /* CUIRightViewController.xib */; }; F4B9AD3225319A410083FA6C /* MCHMemoryBufferWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD2425319A400083FA6C /* MCHMemoryBufferWrapper.m */; }; F4B9AD3325319A410083FA6C /* MCHSegment.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD2625319A400083FA6C /* MCHSegment.m */; }; F4B9AD3425319A410083FA6C /* MCHObjectFile.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD2825319A400083FA6C /* MCHObjectFile.m */; }; F4B9AD3525319A410083FA6C /* MCHUUIDLoadCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD2B25319A400083FA6C /* MCHUUIDLoadCommand.m */; }; F4B9AD3625319A410083FA6C /* MCHLoadCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD2D25319A410083FA6C /* MCHLoadCommand.m */; }; F4B9AD3725319A410083FA6C /* MCHSection.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD2E25319A410083FA6C /* MCHSection.m */; }; F4B9AD3825319A410083FA6C /* MCHMachBinary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD3025319A410083FA6C /* MCHMachBinary.m */; }; F4B9AD3B25319D7C0083FA6C /* MCHSegmentLoadCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = F4B9AD3925319D7B0083FA6C /* MCHSegmentLoadCommand.m */; }; F4BBAC5D24AA7D37000511BE /* CUIBinaryImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BBAC5C24AA7D37000511BE /* CUIBinaryImage.m */; }; F4BC577124DF426200063545 /* CUIAATextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BC577024DF426200063545 /* CUIAATextFieldCell.m */; }; F4BD6A0025553E9000F98F3E /* CUICrashLogSectionsDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BD69FF25553E9000F98F3E /* CUICrashLogSectionsDetector.m */; }; F4BD8C6A2DF4DDCB00BD61A8 /* IPSExceptionReason.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BD8C692DF4DDCA00BD61A8 /* IPSExceptionReason.m */; }; F4C269CD2503BCC100C8F3B3 /* CUISymbolicationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C269CC2503BCC100C8F3B3 /* CUISymbolicationManager.m */; }; F4C269D02503BE6500C8F3B3 /* CUISymbolicationData.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C269CF2503BE6500C8F3B3 /* CUISymbolicationData.m */; }; F4C7498E24F84689004F38C0 /* CUIQuickHelpPopUpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C7498C24F84689004F38C0 /* CUIQuickHelpPopUpViewController.m */; }; F4C7498F24F84689004F38C0 /* CUIQuickHelpPopUpViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4C7498D24F84689004F38C0 /* CUIQuickHelpPopUpViewController.xib */; }; F4CC570624A79EDA00150EC4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CC570524A79EDA00150EC4 /* AppDelegate.m */; }; F4CC570824A79EDA00150EC4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CC570724A79EDA00150EC4 /* main.m */; }; F4CC570A24A79EDA00150EC4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4CC570924A79EDA00150EC4 /* Images.xcassets */; }; F4CC572424A7A1D100150EC4 /* CUICrashLogsProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CC572324A7A1D100150EC4 /* CUICrashLogsProvider.m */; }; F4CC572724A7A2B200150EC4 /* CUICrashLog.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CC572624A7A2B200150EC4 /* CUICrashLog.m */; }; F4CC572D24A7A5F000150EC4 /* CUICrashLog+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CC572C24A7A5F000150EC4 /* CUICrashLog+Transform.m */; }; F4CC573024A7A95A00150EC4 /* CUIThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CC572F24A7A95A00150EC4 /* CUIThread.m */; }; F4CC573324A7ABAF00150EC4 /* CUICallStackBacktrace.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CC573224A7ABAF00150EC4 /* CUICallStackBacktrace.m */; }; F4CCCC6124AE76780031BC27 /* CUICrashLogsSourcesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CCCC5F24AE76780031BC27 /* CUICrashLogsSourcesViewController.m */; }; F4CCCC6524AE810E0031BC27 /* CUICrashLogsSourcesSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CCCC6424AE810E0031BC27 /* CUICrashLogsSourcesSelection.m */; }; F4CCCC6B24AE95430031BC27 /* CUICrashLogsSourceFileSystemItem.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CCCC6A24AE95430031BC27 /* CUICrashLogsSourceFileSystemItem.m */; }; F4CCCC6E24AE9EDA0031BC27 /* CUICrashLogsSource+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CCCC6D24AE9EDA0031BC27 /* CUICrashLogsSource+UI.m */; }; F4CD32B6257D17B3008C71AA /* CUIPreferencePaneSymbolicationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CD32B4257D17B3008C71AA /* CUIPreferencePaneSymbolicationViewController.m */; }; F4CE83DE2554B97400A8BD87 /* CUICenteredLabelViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4CE83DD2554B97300A8BD87 /* CUICenteredLabelViewController.xib */; }; F4CF6CF62DF6111B0078458E /* IPSIncident+ApplicationSpecificInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CF6CF42DF6111B0078458E /* IPSIncident+ApplicationSpecificInformation.m */; }; F4D0EE95273DB8CD00CC9737 /* IPSThreadState+RegisterDisplayName.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D0EE93273DB8CC00CC9737 /* IPSThreadState+RegisterDisplayName.m */; }; F4D14D682745C0A9003698AD /* IPSImage+UserCode.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D14D662745C0A9003698AD /* IPSImage+UserCode.m */; }; F4D5C77C2571AF900029B051 /* CUIRegisterLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D5C77B2571AF900029B051 /* CUIRegisterLabel.m */; }; F4D6C56D2680028A00B78B3D /* RemoteCheck.strings in Resources */ = {isa = PBXBuildFile; fileRef = F4D6C56B2680028A00B78B3D /* RemoteCheck.strings */; }; F4D7F15B25F04A620024E9A5 /* CUISymbolsFilesLibraryViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4D7F15D25F04A620024E9A5 /* CUISymbolsFilesLibraryViewController.xib */; }; F4D7F15F25F04A9D0024E9A5 /* CUIPreferencePaneSymbolicationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4D7F16125F04A9D0024E9A5 /* CUIPreferencePaneSymbolicationViewController.xib */; }; F4DAF0B327C44AA800256EA4 /* IPSImage+Offset.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DAF0B227C44AA700256EA4 /* IPSImage+Offset.m */; }; F4DAFBEE2736B7B200FB50A6 /* CUIIPSTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DAFBED2736B7B200FB50A6 /* CUIIPSTransform.m */; }; F4DAFBF12736B7D500FB50A6 /* CUIDataTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DAFBF02736B7D500FB50A6 /* CUIDataTransform.m */; }; F4DF815A2893463E008EF1B3 /* IPSThreadState+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF813C2893463B008EF1B3 /* IPSThreadState+Obfuscating.m */; }; F4DF815B2893463E008EF1B3 /* IPSIncidentDiagnosticMessage+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF813D2893463B008EF1B3 /* IPSIncidentDiagnosticMessage+Obfuscating.m */; }; F4DF815C2893463E008EF1B3 /* IPSApplicationSpecificInformation+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81402893463B008EF1B3 /* IPSApplicationSpecificInformation+Obfuscating.m */; }; F4DF815D2893463E008EF1B3 /* IPSIncidentHeader+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81432893463C008EF1B3 /* IPSIncidentHeader+Obfuscating.m */; }; F4DF815E2893463E008EF1B3 /* IPSObfuscator.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81462893463C008EF1B3 /* IPSObfuscator.m */; }; F4DF815F2893463E008EF1B3 /* IPSCrashSummary+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81472893463C008EF1B3 /* IPSCrashSummary+Obfuscating.m */; }; F4DF81602893463E008EF1B3 /* IPSThread+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81492893463C008EF1B3 /* IPSThread+Obfuscating.m */; }; F4DF81612893463E008EF1B3 /* IPSThreadFrame+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF814A2893463C008EF1B3 /* IPSThreadFrame+Obfuscating.m */; }; F4DF81622893463E008EF1B3 /* IPSRegisterState+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF814B2893463C008EF1B3 /* IPSRegisterState+Obfuscating.m */; }; F4DF81632893463E008EF1B3 /* IPSImage+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF814F2893463D008EF1B3 /* IPSImage+Obfuscating.m */; }; F4DF81642893463E008EF1B3 /* IPSLegacyInfo+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81502893463D008EF1B3 /* IPSLegacyInfo+Obfuscating.m */; }; F4DF81652893463E008EF1B3 /* IPSReport+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81522893463D008EF1B3 /* IPSReport+Obfuscating.m */; }; F4DF81662893463E008EF1B3 /* IPSIncidentExceptionInformation+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81552893463D008EF1B3 /* IPSIncidentExceptionInformation+Obfuscating.m */; }; F4DF81672893463E008EF1B3 /* IPSBundleInfo+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81562893463D008EF1B3 /* IPSBundleInfo+Obfuscating.m */; }; F4DF81682893463E008EF1B3 /* IPSIncident+Obfuscating.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DF81572893463D008EF1B3 /* IPSIncident+Obfuscating.m */; }; F4E0BD25262078220048647C /* CUIAboutBoxWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E0BD24262078220048647C /* CUIAboutBoxWindow.m */; }; F4E671922E2C3B1600E5A064 /* CUICodeSigningFlagsTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E671912E2C3B1600E5A064 /* CUICodeSigningFlagsTableView.m */; }; F4E671952E2C405F00E5A064 /* CodeSigningFlags.plist in Resources */ = {isa = PBXBuildFile; fileRef = F4E671942E2C405F00E5A064 /* CodeSigningFlags.plist */; }; F4E6ED9C2849695200766F9A /* unknown_termination_reason.html in Resources */ = {isa = PBXBuildFile; fileRef = F4E6ED9A2849695100766F9A /* unknown_termination_reason.html */; }; F4E6EDA1284969DD00766F9A /* known_termination_reasons.css in Resources */ = {isa = PBXBuildFile; fileRef = F4E6EDA0284969DD00766F9A /* known_termination_reasons.css */; }; F4E6EDA4284969E500766F9A /* ENDPOINTSECURITY_2.html in Resources */ = {isa = PBXBuildFile; fileRef = F4E6EDA2284969E500766F9A /* ENDPOINTSECURITY_2.html */; }; F4E861BA255496310061E203 /* CUIRawCrashLog.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E861B9255496310061E203 /* CUIRawCrashLog.m */; }; F4E91ADD256A98050017C3EE /* CUIFontBoxView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E91ADC256A98050017C3EE /* CUIFontBoxView.m */; }; F4EAFA2C24FA6CD100C0B729 /* CUICrashLogTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4EAFA2B24FA6CD100C0B729 /* CUICrashLogTextView.m */; }; F4EBADB424A8F04F00DF4271 /* CUICrashLog+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4EBADB324A8F04F00DF4271 /* CUICrashLog+UI.m */; }; F4EBADB724A8F10000DF4271 /* CUICrashLogTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4EBADB624A8F10000DF4271 /* CUICrashLogTableCellView.m */; }; F4EBD24B24E01556007F0252 /* CUITableCustomSelectionColorRowView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4EBD24A24E01556007F0252 /* CUITableCustomSelectionColorRowView.m */; }; F4ED18A324EC77A300ED7EF2 /* NSArray+UniqueName.m in Sources */ = {isa = PBXBuildFile; fileRef = F4ED18A124EC77A300ED7EF2 /* NSArray+UniqueName.m */; }; F4ED758A2501A29700316E73 /* CUIStackFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = F4ED75892501A29700316E73 /* CUIStackFrame.m */; }; F4EFE75224BA48F500DB97AC /* CUIMainWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = F4EFE75124BA48F500DB97AC /* CUIMainWindow.m */; }; F4F2A9D024BB7E3600F912D4 /* CUICrashLogsSourceSeparator.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F2A9CF24BB7E3600F912D4 /* CUICrashLogsSourceSeparator.m */; }; F4F2A9D324BB809200F912D4 /* CUICrashLogsSourceTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F2A9D224BB809200F912D4 /* CUICrashLogsSourceTableCellView.m */; }; F4F5395924D21DB800D537BC /* CUIPreferencePaneGeneralViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F5395724D21DB800D537BC /* CUIPreferencePaneGeneralViewController.m */; }; F4F5821C256FC7B90032FC53 /* DWRFSection_debug_str_offsets.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F5821B256FC7B90032FC53 /* DWRFSection_debug_str_offsets.m */; }; F4F892F92575A6DC00BE4CE0 /* CUIRegistersViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4F892F82575A6DC00BE4CE0 /* CUIRegistersViewController.xib */; }; F4F892FD2575A70800BE4CE0 /* CUIRegistersMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F892FB2575A70800BE4CE0 /* CUIRegistersMainViewController.m */; }; F4F892FE2575A70800BE4CE0 /* CUIRegistersMainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4F892FC2575A70800BE4CE0 /* CUIRegistersMainViewController.xib */; }; F4F8D26924F29624007661D6 /* CUIPresentationTextNavigationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D26724F29624007661D6 /* CUIPresentationTextNavigationViewController.m */; }; F4F8D26A24F29624007661D6 /* CUIPresentationTextNavigationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4F8D26824F29624007661D6 /* CUIPresentationTextNavigationViewController.xib */; }; F4F9BAF224EF060E00D08FBD /* CUIInspectorUserViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F9BAF024EF060E00D08FBD /* CUIInspectorUserViewController.m */; }; F4F9BAF724EF06BC00D08FBD /* CUIInspectorGeneralViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F9BAF524EF06BC00D08FBD /* CUIInspectorGeneralViewController.m */; }; F4F9D3362556C7DB00D28E6E /* CUILineJumperWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F9D3342556C7DB00D28E6E /* CUILineJumperWindowController.m */; }; F4FA4323273EF2F30068EDB8 /* NSString+CPU.m in Sources */ = {isa = PBXBuildFile; fileRef = F4FA4322273EF2F30068EDB8 /* NSString+CPU.m */; }; F4FC8EA727C1A6EE00291875 /* CUIReportThemedTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4FC8EA627C1A6EE00291875 /* CUIReportThemedTransform.m */; }; F4FE2DEA25615CA800C1774A /* CUICrashLogExceptionInformation+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4FE2DE925615CA800C1774A /* CUICrashLogExceptionInformation+UI.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ F45F84D7266ABB5800F354F3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F45F84D3266ABB5800F354F3 /* crashreport.xcodeproj */; proxyType = 2; remoteGlobalIDString = F48DAE252661207800C93D40; remoteInfo = crashreport; }; F45F84D9266ABB6300F354F3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F45F84D3266ABB5800F354F3 /* crashreport.xcodeproj */; proxyType = 1; remoteGlobalIDString = F48DAE242661207700C93D40; remoteInfo = crashreport; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ F45F84DB266ABB7000F354F3 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = Contents/Library/QuickLook; dstSubfolderSpec = 1; files = ( F45F84DC266ABB7600F354F3 /* crashreport.qlgenerator in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ D000743B2E11F30900CC5121 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = Help/ja.lproj/EXC_GUARD.html; sourceTree = ""; }; D000743C2E11F30B00CC5121 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = Help/es.lproj/EXC_GUARD.html; sourceTree = ""; }; D00B152C2E0B52740098456B /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = Help/fr.lproj/EXC_GUARD.html; sourceTree = ""; }; D06294352E1DD8150008895D /* CUICodeSigningInformationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICodeSigningInformationViewController.h; sourceTree = ""; }; D06294362E1DD8150008895D /* CUICodeSigningInformationViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICodeSigningInformationViewController.m; sourceTree = ""; }; D0790DBB2E00BACF00CD6A72 /* CUIThreadImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIThreadImageView.h; sourceTree = ""; }; D0790DBC2E00BACF00CD6A72 /* CUIThreadImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIThreadImageView.m; sourceTree = ""; }; D0AECAE42E0F34830028246E /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = Help/he.lproj/EXC_GUARD.html; sourceTree = ""; }; D0BA6A452E09FEB50010D630 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = Help/en.lproj/EXC_GUARD.html; sourceTree = ""; }; D0BD22392F3FC6810052AD8E /* NSMenuItem+RSCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "NSMenuItem+RSCore.h"; path = "RSCore/NSMenuItem+RSCore.h"; sourceTree = ""; }; D0BD223A2F3FC6810052AD8E /* NSMenuItem+RSCore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "NSMenuItem+RSCore.m"; path = "RSCore/NSMenuItem+RSCore.m"; sourceTree = ""; }; F4040A7424F5B9CE0072BF65 /* CUINavigationChevronView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUINavigationChevronView.h; sourceTree = ""; }; F4040A7524F5B9CE0072BF65 /* CUINavigationChevronView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUINavigationChevronView.m; sourceTree = ""; }; F4040A7724F5BC230072BF65 /* CUINavigationView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUINavigationView.h; sourceTree = ""; }; F4040A7824F5BC230072BF65 /* CUINavigationView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUINavigationView.m; sourceTree = ""; }; F4055C8225EEE37400DC6CCA /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIMainWindowController.xib; sourceTree = ""; }; F4055C8425EEE37600DC6CCA /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIMainWindowController.xib; sourceTree = ""; }; F405A96B255015D800AD2F24 /* CUICXXDemangler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CUICXXDemangler.h; path = app_unexpectedly/Demangling/CUICXXDemangler.h; sourceTree = ""; }; F405A96C255015D800AD2F24 /* CUICXXDemangler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = CUICXXDemangler.mm; path = app_unexpectedly/Demangling/CUICXXDemangler.mm; sourceTree = ""; }; F405A96E25501A5F00AD2F24 /* CUIParsingErrors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIParsingErrors.h; sourceTree = ""; }; F405A96F25501A5F00AD2F24 /* CUIParsingErrors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIParsingErrors.m; sourceTree = ""; }; F406B49A2687AB1400B90C7B /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePaneAdvancedViewController.xib; sourceTree = ""; }; F406B49C2687AB1800B90C7B /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePaneAdvancedViewController.xib; sourceTree = ""; }; F406B49D2687AC1900B90C7B /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePaneAdvancedViewController.xib; sourceTree = ""; }; F40ACE2B255697A3006855E5 /* CUICrashLogBrowsingState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogBrowsingState.h; sourceTree = ""; }; F40ACE2C255697A3006855E5 /* CUICrashLogBrowsingState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogBrowsingState.m; sourceTree = ""; }; F40ACE2E255697CE006855E5 /* CUICrashLogBrowsingStateRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogBrowsingStateRegistry.h; sourceTree = ""; }; F40ACE2F255697CE006855E5 /* CUICrashLogBrowsingStateRegistry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogBrowsingStateRegistry.m; sourceTree = ""; }; F40B0D7824D3558700663282 /* CUIPreferencesTabBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencesTabBox.m; sourceTree = ""; }; F40B0D7924D3558800663282 /* CUIPreferencesTabHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencesTabHeaderView.m; sourceTree = ""; }; F40B0D7A24D3558800663282 /* CUIPreferencesTabBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIPreferencesTabBox.h; sourceTree = ""; }; F40B0D7B24D3558800663282 /* CUIPreferencesTabButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencesTabButton.m; sourceTree = ""; }; F40B0D7C24D3558800663282 /* CUIPreferencesTabButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIPreferencesTabButton.h; sourceTree = ""; }; F40B0D7D24D3558800663282 /* CUIPreferencesTabHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIPreferencesTabHeaderView.h; sourceTree = ""; }; F40B0D8324D3569800663282 /* NSColor+LabelColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSColor+LabelColor.h"; path = "AppKit + Extensions/NSColor+LabelColor.h"; sourceTree = ""; }; F40B0D8424D3569800663282 /* NSColor+LabelColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSColor+LabelColor.m"; path = "AppKit + Extensions/NSColor+LabelColor.m"; sourceTree = ""; }; F40B0D8524D3569800663282 /* NSResponder+Appearance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSResponder+Appearance.m"; path = "AppKit + Extensions/NSResponder+Appearance.m"; sourceTree = ""; }; F40B0D8624D3569800663282 /* NSResponder+Appearance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSResponder+Appearance.h"; path = "AppKit + Extensions/NSResponder+Appearance.h"; sourceTree = ""; }; F40B0D8924D356A200663282 /* NSArray+WBExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+WBExtensions.m"; path = "Foundation + Extensions/NSArray+WBExtensions.m"; sourceTree = ""; }; F40B0D8A24D356A200663282 /* NSIndexSet+Analysis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSIndexSet+Analysis.h"; path = "Foundation + Extensions/NSIndexSet+Analysis.h"; sourceTree = ""; }; F40B0D8B24D356A200663282 /* NSIndexSet+Analysis.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSIndexSet+Analysis.m"; path = "Foundation + Extensions/NSIndexSet+Analysis.m"; sourceTree = ""; }; F40B0D8C24D356A200663282 /* NSArray+WBExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+WBExtensions.h"; path = "Foundation + Extensions/NSArray+WBExtensions.h"; sourceTree = ""; }; F40B0D8F24D356F900663282 /* NSToolbar+Packages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSToolbar+Packages.h"; path = "AppKit + Extensions/NSToolbar+Packages.h"; sourceTree = ""; }; F40B0D9024D356F900663282 /* NSToolbar+Packages.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSToolbar+Packages.m"; path = "AppKit + Extensions/NSToolbar+Packages.m"; sourceTree = ""; }; F40B0D9224D3571A00663282 /* NSTableView+Selection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSTableView+Selection.m"; path = "AppKit + Extensions/NSTableView+Selection.m"; sourceTree = ""; }; F40B0D9324D3571B00663282 /* NSTableView+Selection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSTableView+Selection.h"; path = "AppKit + Extensions/NSTableView+Selection.h"; sourceTree = ""; }; F40B0D9524D3572E00663282 /* NSColor+String.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSColor+String.m"; path = "AppKit + Extensions/NSColor+String.m"; sourceTree = ""; }; F40B0D9624D3572E00663282 /* NSColor+String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSColor+String.h"; path = "AppKit + Extensions/NSColor+String.h"; sourceTree = ""; }; F40B0D9B24D370A200663282 /* NSDictionary+MutableDeepCopy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+MutableDeepCopy.h"; path = "Foundation + Extensions/NSDictionary+MutableDeepCopy.h"; sourceTree = ""; }; F40B0D9C24D370A200663282 /* NSDictionary+MutableDeepCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+MutableDeepCopy.m"; path = "Foundation + Extensions/NSDictionary+MutableDeepCopy.m"; sourceTree = ""; }; F40B124724E89BBE005E82DD /* CUIPreferencesWindowController+Convenience.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUIPreferencesWindowController+Convenience.h"; sourceTree = ""; }; F40B124824E89BBE005E82DD /* CUIPreferencesWindowController+Convenience.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUIPreferencesWindowController+Convenience.m"; sourceTree = ""; }; F40B77D524AF0F5C001A8131 /* CUICrashLogsSourceStandardDirectory+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogsSourceStandardDirectory+UI.h"; sourceTree = ""; }; F40B77D624AF0F5C001A8131 /* CUICrashLogsSourceStandardDirectory+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogsSourceStandardDirectory+UI.m"; sourceTree = ""; }; F40B77D824AF1426001A8131 /* CUICrashLogsSourceAll+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogsSourceAll+UI.h"; sourceTree = ""; }; F40B77D924AF1426001A8131 /* CUICrashLogsSourceAll+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogsSourceAll+UI.m"; sourceTree = ""; }; F40B832725FC0AEC0091D886 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_CRASH_SIGSEGV.html; sourceTree = ""; }; F40B832925FC0AEE0091D886 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_CRASH_SIGSEGV.html; sourceTree = ""; }; F40BEAEF24E9F754007A3F60 /* CUIThemeItemAttributes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIThemeItemAttributes.h; sourceTree = ""; }; F40BEAF024E9F754007A3F60 /* CUIThemeItemAttributes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIThemeItemAttributes.m; sourceTree = ""; }; F40BEAFA24E9FEF8007A3F60 /* NSDictionary+WBExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+WBExtensions.h"; path = "Foundation + Extensions/NSDictionary+WBExtensions.h"; sourceTree = ""; }; F40BEAFB24E9FEF8007A3F60 /* NSDictionary+WBExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+WBExtensions.m"; path = "Foundation + Extensions/NSDictionary+WBExtensions.m"; sourceTree = ""; }; F40ED76524E72A6E00557BB8 /* CUICategoriesClipView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICategoriesClipView.h; sourceTree = ""; }; F40ED76624E72A6E00557BB8 /* CUICategoriesClipView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICategoriesClipView.m; sourceTree = ""; }; F40FC81425EAF7B000DB4B27 /* CUISourceFileTableCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISourceFileTableCellView.h; sourceTree = ""; }; F40FC81525EAF7B000DB4B27 /* CUISourceFileTableCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISourceFileTableCellView.m; sourceTree = ""; }; F4111AC4265EE92200FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIAboutBoxWindowController.xib; sourceTree = ""; }; F4111AC5265EE92200FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePaneGeneralViewController.xib; sourceTree = ""; }; F4111AC6265EE92200FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePanePresentationTextViewController.xib; sourceTree = ""; }; F4111AC7265EE92200FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePanePresentationOutlineViewController.xib; sourceTree = ""; }; F4111AC8265EE92200FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePanePresentationViewController.xib; sourceTree = ""; }; F4111AC9265EE92200FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePaneFontscolorsViewController.xib; sourceTree = ""; }; F4111ACA265EE92200FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUISymbolsFilesLibraryViewController.xib; sourceTree = ""; }; F4111ACB265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePaneSymbolicationViewController.xib; sourceTree = ""; }; F4111ACC265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencePaneCrashreporterViewController.xib; sourceTree = ""; }; F4111ACD265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIPreferencesWindowController.xib; sourceTree = ""; }; F4111ACE265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUICrashLogsSourceSmartEditorWindowController.xib; sourceTree = ""; }; F4111ACF265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUICrashLogsSourcesViewController.xib; sourceTree = ""; }; F4111AD0265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUICrashLogsListViewController.xib; sourceTree = ""; }; F4111AD1265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIInspectorGeneralViewController.xib; sourceTree = ""; }; F4111AD2265EE92300FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIInspectorUserViewController.xib; sourceTree = ""; }; F4111AD3265EE92400FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIInspectorExecutableViewController.xib; sourceTree = ""; }; F4111AD4265EE92400FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIInspectorProcessesViewController.xib; sourceTree = ""; }; F4111AD5265EE92400FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/unknown_exception_type.html; sourceTree = ""; }; F4111AD6265EE92400FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_BAD_ACCESS_SIGBUS.html; sourceTree = ""; }; F4111AD7265EE92400FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_BAD_ACCESS_SIGSEGV.html; sourceTree = ""; }; F4111AD8265EE92400FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_BAD_INSTRUCTION_SIGILL.html; sourceTree = ""; }; F4111AD9265EE92400FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_BREAKPOINT_SIGTRAP.html; sourceTree = ""; }; F4111ADA265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_CRASH_SIGABRT.html; sourceTree = ""; }; F4111ADB265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_CRASH_SIGKILL.html; sourceTree = ""; }; F4111ADC265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_CRASH_SIGQUIT.html; sourceTree = ""; }; F4111ADD265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = es.lproj/EXC_CRASH_SIGSEGV.html; sourceTree = ""; }; F4111ADE265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = "es.lproj/EXC_CRASH_Code Signature Invalid.html"; sourceTree = ""; }; F4111ADF265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIExportAccessoryViewController.xib; sourceTree = ""; }; F4111AE0265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUICrashLogPresentationTextViewController.xib; sourceTree = ""; }; F4111AE1265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUICrashLogPresentationOutlineViewController.xib; sourceTree = ""; }; F4111AE2265EE92500FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUICollectionViewRegisterItem.xib; sourceTree = ""; }; F4111AE3265EE92600FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIBinaryImagesViewController.xib; sourceTree = ""; }; F4111AE4265EE92600FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUIMainWindowController.xib; sourceTree = ""; }; F4111AE5265EE92600FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; F4111AE6265EE92600FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Predicates.strings; sourceTree = ""; }; F4111AE7265EE92600FD8950 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/MainMenu.xib; sourceTree = ""; }; F4111AE8265EE92600FD8950 /* es */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; F4132C8D24AA19F70086B99C /* CUICrashLogsSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSource.h; sourceTree = ""; }; F4132C8E24AA19F70086B99C /* CUICrashLogsSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSource.m; sourceTree = ""; }; F414068624D5F1D20059FF21 /* CUIApplicationSpecificBacktraceRowView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIApplicationSpecificBacktraceRowView.h; sourceTree = ""; }; F414068724D5F1D20059FF21 /* CUIApplicationSpecificBacktraceRowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIApplicationSpecificBacktraceRowView.m; sourceTree = ""; }; F414068924D6014D0059FF21 /* CUIFontAndColorsFramedView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIFontAndColorsFramedView.h; sourceTree = ""; }; F414068A24D6014D0059FF21 /* CUIFontAndColorsFramedView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIFontAndColorsFramedView.m; sourceTree = ""; }; F414D08C24BFB57700A7095C /* CUICrashLogDianosticMessages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogDianosticMessages.h; sourceTree = ""; }; F414D08D24BFB57700A7095C /* CUICrashLogDianosticMessages.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogDianosticMessages.m; sourceTree = ""; }; F414D08F24BFBC3A00A7095C /* CUICrashLogBacktraces.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogBacktraces.h; sourceTree = ""; }; F414D09024BFBC3A00A7095C /* CUICrashLogBacktraces.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogBacktraces.m; sourceTree = ""; }; F414D09224BFBC4A00A7095C /* CUICrashLogThreadState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogThreadState.h; sourceTree = ""; }; F414D09324BFBC4A00A7095C /* CUICrashLogThreadState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogThreadState.m; sourceTree = ""; }; F414D09524BFBC6300A7095C /* CUICrashLogBinaryImages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogBinaryImages.h; sourceTree = ""; }; F414D09624BFBC6300A7095C /* CUICrashLogBinaryImages.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogBinaryImages.m; sourceTree = ""; }; F416686C24B0AEE800C2AB89 /* CUIContentsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIContentsViewController.h; sourceTree = ""; }; F416686D24B0AEE800C2AB89 /* CUIContentsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIContentsViewController.m; sourceTree = ""; }; F416686E24B0AEE800C2AB89 /* CUIContentsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUIContentsViewController.xib; sourceTree = ""; }; F416687124B0AF4D00C2AB89 /* CUICenteredLabelViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICenteredLabelViewController.h; sourceTree = ""; }; F416687224B0AF4D00C2AB89 /* CUICenteredLabelViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICenteredLabelViewController.m; sourceTree = ""; }; F416687624B0BA5000C2AB89 /* CUICrashLogContentsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogContentsViewController.h; sourceTree = ""; }; F416687724B0BA5000C2AB89 /* CUICrashLogContentsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogContentsViewController.m; sourceTree = ""; }; F416687824B0BA5000C2AB89 /* CUICrashLogContentsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUICrashLogContentsViewController.xib; sourceTree = ""; }; F416687B24B0BBA300C2AB89 /* CUICrashLogPresentationTextViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogPresentationTextViewController.h; sourceTree = ""; }; F416687C24B0BBA300C2AB89 /* CUICrashLogPresentationTextViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogPresentationTextViewController.m; sourceTree = ""; }; F416688024B0BBFC00C2AB89 /* CUICrashLogPresentationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogPresentationViewController.h; sourceTree = ""; }; F416688124B0BBFC00C2AB89 /* CUICrashLogPresentationViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogPresentationViewController.m; sourceTree = ""; }; F416688324B0BF2000C2AB89 /* CUISidebarViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISidebarViewController.h; sourceTree = ""; }; F416688424B0BF2000C2AB89 /* CUISidebarViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISidebarViewController.m; sourceTree = ""; }; F416688524B0BF2000C2AB89 /* CUISidebarViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUISidebarViewController.xib; sourceTree = ""; }; F419376D2672B2BE00B796EB /* CUICrashLogsOpenErrorPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsOpenErrorPanel.h; sourceTree = ""; }; F419376E2672B2BE00B796EB /* CUICrashLogsOpenErrorPanel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsOpenErrorPanel.m; sourceTree = ""; }; F41D66AD25921F3400C0D491 /* CUIPreferencePanePresentationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePanePresentationViewController.h; sourceTree = ""; }; F41D66AE25921F3400C0D491 /* CUIPreferencePanePresentationViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePanePresentationViewController.m; sourceTree = ""; }; F41ECA5024AB689B00CE56C7 /* CUIInspectorViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInspectorViewController.h; sourceTree = ""; }; F41ECA5124AB689B00CE56C7 /* CUIInspectorViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInspectorViewController.m; sourceTree = ""; }; F41ECA5224AB689B00CE56C7 /* CUIInspectorViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUIInspectorViewController.xib; sourceTree = ""; }; F420C9B7254F30A100D24249 /* CUIFileDeadDropView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIFileDeadDropView.h; sourceTree = ""; }; F420C9B8254F30A100D24249 /* CUIFileDeadDropView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIFileDeadDropView.m; sourceTree = ""; }; F420C9BF254F335000D24249 /* CUIdSYMDropView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIdSYMDropView.h; sourceTree = ""; }; F420C9C0254F335000D24249 /* CUIdSYMDropView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIdSYMDropView.m; sourceTree = ""; }; F420C9C2254F5F4C00D24249 /* CUIdSYMHunter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIdSYMHunter.h; sourceTree = ""; }; F420C9C3254F5F4C00D24249 /* CUIdSYMHunter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIdSYMHunter.m; sourceTree = ""; }; F420F35024E95E5F006C82CD /* CUITheme.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUITheme.h; sourceTree = ""; }; F420F35124E95E5F006C82CD /* CUITheme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUITheme.m; sourceTree = ""; }; F4214CB324B6534400852DDE /* CUICrashLogsSourcesManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourcesManager.h; sourceTree = ""; }; F4214CB424B6534400852DDE /* CUICrashLogsSourcesManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourcesManager.m; sourceTree = ""; }; F4238189267D1D4A003837AC /* CUIPreferencePaneAdvancedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePaneAdvancedViewController.h; sourceTree = ""; }; F423818A267D1D4A003837AC /* CUIPreferencePaneAdvancedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePaneAdvancedViewController.m; sourceTree = ""; }; F423818F267D3521003837AC /* WBRemoteVersionChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBRemoteVersionChecker.h; sourceTree = ""; }; F4238190267D3522003837AC /* WBRemoteVersionChecker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBRemoteVersionChecker.m; sourceTree = ""; }; F428C0412724592900FB8CAC /* IPSImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSImage.m; path = ../submodules/ips2crash/Model/IPSImage.m; sourceTree = ""; }; F428C0422724592900FB8CAC /* IPSIncidentHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncidentHeader.m; path = ../submodules/ips2crash/Model/IPSIncidentHeader.m; sourceTree = ""; }; F428C0432724592900FB8CAC /* IPSIncidentExceptionInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncidentExceptionInformation.m; path = ../submodules/ips2crash/Model/IPSIncidentExceptionInformation.m; sourceTree = ""; }; F428C0442724592900FB8CAC /* IPSIncidentDiagnosticMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncidentDiagnosticMessage.m; path = ../submodules/ips2crash/Model/IPSIncidentDiagnosticMessage.m; sourceTree = ""; }; F428C0452724592900FB8CAC /* IPSReport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSReport.m; path = ../submodules/ips2crash/Model/IPSReport.m; sourceTree = ""; }; F428C0462724592900FB8CAC /* IPSThreadInstructionState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadInstructionState.m; path = ../submodules/ips2crash/Model/IPSThreadInstructionState.m; sourceTree = ""; }; F428C0472724592900FB8CAC /* IPSThreadInstructionStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadInstructionStream.m; path = ../submodules/ips2crash/Model/IPSThreadInstructionStream.m; sourceTree = ""; }; F428C0482724592900FB8CAC /* IPSIncident.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncident.h; path = ../submodules/ips2crash/Model/IPSIncident.h; sourceTree = ""; }; F428C0492724592900FB8CAC /* IPSRegisterState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSRegisterState.m; path = ../submodules/ips2crash/Model/IPSRegisterState.m; sourceTree = ""; }; F428C04A2724592A00FB8CAC /* IPSDateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSDateFormatter.m; path = ../submodules/ips2crash/Model/IPSDateFormatter.m; sourceTree = ""; }; F428C04B2724592A00FB8CAC /* IPSApplicationSpecificInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSApplicationSpecificInformation.m; path = ../submodules/ips2crash/Model/IPSApplicationSpecificInformation.m; sourceTree = ""; }; F428C04C2724592A00FB8CAC /* IPSSummary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSSummary.m; path = ../submodules/ips2crash/Model/IPSSummary.m; sourceTree = ""; }; F428C04D2724592A00FB8CAC /* IPSTermination.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSTermination.m; path = ../submodules/ips2crash/Model/IPSTermination.m; sourceTree = ""; }; F428C04E2724592A00FB8CAC /* IPSExternalModificationSummary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSExternalModificationSummary.m; path = ../submodules/ips2crash/Model/IPSExternalModificationSummary.m; sourceTree = ""; }; F428C04F2724592A00FB8CAC /* IPSError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSError.h; path = ../submodules/ips2crash/Model/IPSError.h; sourceTree = ""; }; F428C0502724592A00FB8CAC /* IPSExternalModificationStatistics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSExternalModificationStatistics.m; path = ../submodules/ips2crash/Model/IPSExternalModificationStatistics.m; sourceTree = ""; }; F428C0512724592A00FB8CAC /* IPSReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSReport.h; path = ../submodules/ips2crash/Model/IPSReport.h; sourceTree = ""; }; F428C0522724592A00FB8CAC /* IPSTermination.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSTermination.h; path = ../submodules/ips2crash/Model/IPSTermination.h; sourceTree = ""; }; F428C0532724592A00FB8CAC /* IPSBundleInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSBundleInfo.m; path = ../submodules/ips2crash/Model/IPSBundleInfo.m; sourceTree = ""; }; F428C0542724592A00FB8CAC /* IPSException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSException.m; path = ../submodules/ips2crash/Model/IPSException.m; sourceTree = ""; }; F428C0552724592A00FB8CAC /* IPSObjectProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSObjectProtocol.h; path = ../submodules/ips2crash/Model/IPSObjectProtocol.h; sourceTree = ""; }; F428C0562724592A00FB8CAC /* IPSSummary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSSummary.h; path = ../submodules/ips2crash/Model/IPSSummary.h; sourceTree = ""; }; F428C0572724592A00FB8CAC /* IPSThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThread.m; path = ../submodules/ips2crash/Model/IPSThread.m; sourceTree = ""; }; F428C0582724592B00FB8CAC /* IPSIncidentExceptionInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncidentExceptionInformation.h; path = ../submodules/ips2crash/Model/IPSIncidentExceptionInformation.h; sourceTree = ""; }; F428C0592724592B00FB8CAC /* IPSThreadFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadFrame.m; path = ../submodules/ips2crash/Model/IPSThreadFrame.m; sourceTree = ""; }; F428C05A2724592B00FB8CAC /* IPSExternalModificationSummary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSExternalModificationSummary.h; path = ../submodules/ips2crash/Model/IPSExternalModificationSummary.h; sourceTree = ""; }; F428C05B2724592B00FB8CAC /* IPSError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSError.m; path = ../submodules/ips2crash/Model/IPSError.m; sourceTree = ""; }; F428C05C2724592B00FB8CAC /* IPSDateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSDateFormatter.h; path = ../submodules/ips2crash/Model/IPSDateFormatter.h; sourceTree = ""; }; F428C05D2724592B00FB8CAC /* IPSThreadFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadFrame.h; path = ../submodules/ips2crash/Model/IPSThreadFrame.h; sourceTree = ""; }; F428C05E2724592B00FB8CAC /* IPSOperatingSystemVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSOperatingSystemVersion.m; path = ../submodules/ips2crash/Model/IPSOperatingSystemVersion.m; sourceTree = ""; }; F428C05F2724592B00FB8CAC /* IPSThreadInstructionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadInstructionState.h; path = ../submodules/ips2crash/Model/IPSThreadInstructionState.h; sourceTree = ""; }; F428C0602724592B00FB8CAC /* IPSThreadInstructionStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadInstructionStream.h; path = ../submodules/ips2crash/Model/IPSThreadInstructionStream.h; sourceTree = ""; }; F428C0612724592B00FB8CAC /* IPSThreadState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadState.h; path = ../submodules/ips2crash/Model/IPSThreadState.h; sourceTree = ""; }; F428C0622724592B00FB8CAC /* IPSThreadState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadState.m; path = ../submodules/ips2crash/Model/IPSThreadState.m; sourceTree = ""; }; F428C0632724592B00FB8CAC /* IPSImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSImage.h; path = ../submodules/ips2crash/Model/IPSImage.h; sourceTree = ""; }; F428C0642724592C00FB8CAC /* IPSExternalModificationStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSExternalModificationStatistics.h; path = ../submodules/ips2crash/Model/IPSExternalModificationStatistics.h; sourceTree = ""; }; F428C0652724592C00FB8CAC /* IPSApplicationSpecificInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSApplicationSpecificInformation.h; path = ../submodules/ips2crash/Model/IPSApplicationSpecificInformation.h; sourceTree = ""; }; F428C0662724592C00FB8CAC /* IPSLegacyInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSLegacyInfo.h; path = ../submodules/ips2crash/Model/IPSLegacyInfo.h; sourceTree = ""; }; F428C0672724592C00FB8CAC /* IPSBundleInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSBundleInfo.h; path = ../submodules/ips2crash/Model/IPSBundleInfo.h; sourceTree = ""; }; F428C0682724592C00FB8CAC /* IPSLegacyInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSLegacyInfo.m; path = ../submodules/ips2crash/Model/IPSLegacyInfo.m; sourceTree = ""; }; F428C0692724592C00FB8CAC /* IPSThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThread.h; path = ../submodules/ips2crash/Model/IPSThread.h; sourceTree = ""; }; F428C06A2724592C00FB8CAC /* IPSIncident.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncident.m; path = ../submodules/ips2crash/Model/IPSIncident.m; sourceTree = ""; }; F428C06B2724592C00FB8CAC /* IPSIncidentDiagnosticMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncidentDiagnosticMessage.h; path = ../submodules/ips2crash/Model/IPSIncidentDiagnosticMessage.h; sourceTree = ""; }; F428C06C2724592C00FB8CAC /* IPSRegisterState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSRegisterState.h; path = ../submodules/ips2crash/Model/IPSRegisterState.h; sourceTree = ""; }; F428C06D2724592C00FB8CAC /* IPSIncidentHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncidentHeader.h; path = ../submodules/ips2crash/Model/IPSIncidentHeader.h; sourceTree = ""; }; F428C06E2724592D00FB8CAC /* IPSOperatingSystemVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSOperatingSystemVersion.h; path = ../submodules/ips2crash/Model/IPSOperatingSystemVersion.h; sourceTree = ""; }; F428C06F2724592D00FB8CAC /* IPSException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSException.h; path = ../submodules/ips2crash/Model/IPSException.h; sourceTree = ""; }; F42B57E024ABEF6E00F77ED5 /* CUICallsSelection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICallsSelection.h; sourceTree = ""; }; F42B57E124ABEF6E00F77ED5 /* CUICallsSelection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICallsSelection.m; sourceTree = ""; }; F42D0BC225514B2E0021A551 /* template.source */ = {isa = PBXFileReference; lastKnownFileType = text; path = template.source; sourceTree = ""; }; F42E4FFF2724B7550092181A /* CUICrashDataTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashDataTransform.h; sourceTree = ""; }; F42E50002724B7550092181A /* CUICrashDataTransform.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashDataTransform.m; sourceTree = ""; }; F4301A6925EF0DE000ACDA3F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePanePresentationViewController.xib; sourceTree = ""; }; F4301A6B25EF0DE200ACDA3F /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePanePresentationViewController.xib; sourceTree = ""; }; F43066C52A12EDE4002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/RemoteCheck.strings; sourceTree = ""; }; F43066C62A12EDE4002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIAboutBoxWindowController.xib; sourceTree = ""; }; F43066C72A12EDE5002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePaneGeneralViewController.xib; sourceTree = ""; }; F43066C82A12EDE5002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePanePresentationTextViewController.xib; sourceTree = ""; }; F43066C92A12EDE5002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePanePresentationOutlineViewController.xib; sourceTree = ""; }; F43066CA2A12EDE5002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePanePresentationViewController.xib; sourceTree = ""; }; F43066CB2A12EDE5002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePaneFontscolorsViewController.xib; sourceTree = ""; }; F43066CC2A12EDE5002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUISymbolsFilesLibraryViewController.xib; sourceTree = ""; }; F43066CD2A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePaneSymbolicationViewController.xib; sourceTree = ""; }; F43066CE2A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePaneCrashreporterViewController.xib; sourceTree = ""; }; F43066CF2A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencePaneAdvancedViewController.xib; sourceTree = ""; }; F43066D02A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIPreferencesWindowController.xib; sourceTree = ""; }; F43066D12A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUICrashLogsSourceSmartEditorWindowController.xib; sourceTree = ""; }; F43066D22A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUICrashLogsSourcesViewController.xib; sourceTree = ""; }; F43066D32A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUICrashLogsListViewController.xib; sourceTree = ""; }; F43066D42A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIInspectorGeneralViewController.xib; sourceTree = ""; }; F43066D52A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIInspectorUserViewController.xib; sourceTree = ""; }; F43066D62A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIInspectorExecutableViewController.xib; sourceTree = ""; }; F43066D72A12EDE6002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIInspectorProcessesViewController.xib; sourceTree = ""; }; F43066D82A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/unknown_exception_type.html; sourceTree = ""; }; F43066D92A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_BAD_ACCESS_SIGBUS.html; sourceTree = ""; }; F43066DA2A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_BAD_ACCESS_SIGSEGV.html; sourceTree = ""; }; F43066DB2A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_BAD_INSTRUCTION_SIGILL.html; sourceTree = ""; }; F43066DC2A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_BREAKPOINT_SIGTRAP.html; sourceTree = ""; }; F43066DD2A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_CRASH_SIGABRT.html; sourceTree = ""; }; F43066DE2A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_CRASH_SIGKILL.html; sourceTree = ""; }; F43066DF2A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_CRASH_SIGQUIT.html; sourceTree = ""; }; F43066E02A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = he.lproj/EXC_CRASH_SIGSEGV.html; sourceTree = ""; }; F43066E12A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = "he.lproj/EXC_CRASH_Code Signature Invalid.html"; sourceTree = ""; }; F43066E22A12EDE7002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = Help/he.lproj/unknown_termination_reason.html; sourceTree = ""; }; F43066E32A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = he; path = Help/he.lproj/ENDPOINTSECURITY_2.html; sourceTree = ""; }; F43066E42A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUILineJumperWindowController.xib; sourceTree = ""; }; F43066E52A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIExportAccessoryViewController.xib; sourceTree = ""; }; F43066E62A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUICrashLogPresentationTextViewController.xib; sourceTree = ""; }; F43066E72A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUICrashLogPresentationOutlineViewController.xib; sourceTree = ""; }; F43066E82A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUICollectionViewRegisterItem.xib; sourceTree = ""; }; F43066E92A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIBinaryImagesViewController.xib; sourceTree = ""; }; F43066EA2A12EDE8002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUIMainWindowController.xib; sourceTree = ""; }; F43066EB2A12EDE8002AB430 /* he */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = ""; }; F43066EC2A12EDE9002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Predicates.strings; sourceTree = ""; }; F43066ED2A12EDE9002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/MainMenu.xib; sourceTree = ""; }; F43066EE2A12EDE9002AB430 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/InfoPlist.strings; sourceTree = ""; }; F4306D572577E168007E667F /* CUICrashLogThreadState+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogThreadState+UI.h"; sourceTree = ""; }; F4306D582577E168007E667F /* CUICrashLogThreadState+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogThreadState+UI.m"; sourceTree = ""; }; F432ACC524A95014000A3E7A /* CUIThreadsListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIThreadsListViewController.h; sourceTree = ""; }; F432ACC624A95014000A3E7A /* CUIThreadsListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIThreadsListViewController.m; sourceTree = ""; }; F432ACCA24A9502A000A3E7A /* CUIThreadsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIThreadsViewController.h; sourceTree = ""; }; F432ACCB24A9502A000A3E7A /* CUIThreadsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIThreadsViewController.m; sourceTree = ""; }; F432ACCD24A95042000A3E7A /* CUIThreadsColumnViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIThreadsColumnViewController.h; sourceTree = ""; }; F432ACCE24A95042000A3E7A /* CUIThreadsColumnViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIThreadsColumnViewController.m; sourceTree = ""; }; F43362FC25FCEFBA006E7894 /* CUIRawCrashLog+Path.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUIRawCrashLog+Path.h"; sourceTree = ""; }; F43362FD25FCEFBA006E7894 /* CUIRawCrashLog+Path.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUIRawCrashLog+Path.m"; sourceTree = ""; }; F4341C69258EB8FE001A5605 /* CUICrashReporterDefaults.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashReporterDefaults.h; sourceTree = ""; }; F4341C6A258EB8FE001A5605 /* CUICrashReporterDefaults.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashReporterDefaults.m; sourceTree = ""; }; F4386B0D2849541B00B83525 /* CUICrashLogExceptionInformation+QuickHelp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogExceptionInformation+QuickHelp.m"; sourceTree = ""; }; F4386B0E2849541B00B83525 /* CUICrashLogExceptionInformation+QuickHelp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogExceptionInformation+QuickHelp.h"; sourceTree = ""; }; F43A9A812591260C005AB2AA /* CUIOutlineModeDisplaySettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIOutlineModeDisplaySettings.h; sourceTree = ""; }; F43A9A822591260C005AB2AA /* CUIOutlineModeDisplaySettings.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIOutlineModeDisplaySettings.m; sourceTree = ""; }; F43AF0CF256FE2AE0066CA1B /* DWRFSection_debug_addr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DWRFSection_debug_addr.h; path = app_unexpectedly/DWARF/DWRFSection_debug_addr.h; sourceTree = ""; }; F43AF0D0256FE2AE0066CA1B /* DWRFSection_debug_addr.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DWRFSection_debug_addr.m; path = app_unexpectedly/DWARF/DWRFSection_debug_addr.m; sourceTree = ""; }; F43BA4E425F2674100D8D68A /* SharedConfigurationSettings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = SharedConfigurationSettings.xcconfig; path = ../Configs/SharedConfigurationSettings.xcconfig; sourceTree = ""; }; F43C828524D892620096F27B /* CUIPreferencePanePresentationTextViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePanePresentationTextViewController.h; sourceTree = ""; }; F43C828624D892620096F27B /* CUIPreferencePanePresentationTextViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePanePresentationTextViewController.m; sourceTree = ""; }; F43C828A24D8A39B0096F27B /* CUITextModeDisplaySettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUITextModeDisplaySettings.h; sourceTree = ""; }; F43C828B24D8A39B0096F27B /* CUITextModeDisplaySettings.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUITextModeDisplaySettings.m; sourceTree = ""; }; F43C828D24D8AD850096F27B /* CUIStackFrameComponents.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CUIStackFrameComponents.h; path = app_unexpectedly/CUIStackFrameComponents.h; sourceTree = ""; }; F43D8FF424A7FAD2008147F9 /* CUIMainWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIMainWindowController.h; sourceTree = ""; }; F43D8FF524A7FAD2008147F9 /* CUIMainWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIMainWindowController.m; sourceTree = ""; }; F440A3E124AA315800C23DA1 /* CUICrashLogsSourceStandardDirectory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceStandardDirectory.h; sourceTree = ""; }; F440A3E224AA315800C23DA1 /* CUICrashLogsSourceStandardDirectory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceStandardDirectory.m; sourceTree = ""; }; F440A3E424AA31B500C23DA1 /* CUICrashLogsSourceFile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceFile.h; sourceTree = ""; }; F440A3E524AA31B500C23DA1 /* CUICrashLogsSourceFile.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceFile.m; sourceTree = ""; }; F440A3E724AA35AC00C23DA1 /* CUICrashLogsSourceDirectory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceDirectory.h; sourceTree = ""; }; F440A3E824AA35AC00C23DA1 /* CUICrashLogsSourceDirectory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceDirectory.m; sourceTree = ""; }; F440A3EA24AA38E600C23DA1 /* CUICrashLogsSourceAll.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceAll.h; sourceTree = ""; }; F440A3EB24AA38E600C23DA1 /* CUICrashLogsSourceAll.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceAll.m; sourceTree = ""; }; F442FCEA24AB855C00E87B69 /* CUIBinaryImagesViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIBinaryImagesViewController.h; sourceTree = ""; }; F442FCEB24AB855C00E87B69 /* CUIBinaryImagesViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIBinaryImagesViewController.m; sourceTree = ""; }; F442FCEF24AB8A8B00E87B69 /* CUIBinaryImageUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIBinaryImageUtility.h; sourceTree = ""; }; F442FCF024AB8A8B00E87B69 /* CUIBinaryImageUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIBinaryImageUtility.m; sourceTree = ""; }; F44356F024A8A113001D3D35 /* CUICrashLogPresentationOutlineViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUICrashLogPresentationOutlineViewController.h; sourceTree = ""; }; F44356F124A8A113001D3D35 /* CUICrashLogPresentationOutlineViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogPresentationOutlineViewController.m; sourceTree = ""; }; F44356FD24A8A8B5001D3D35 /* CUIThreadNamedTableCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIThreadNamedTableCellView.h; sourceTree = ""; }; F44356FE24A8A8B5001D3D35 /* CUIThreadNamedTableCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIThreadNamedTableCellView.m; sourceTree = ""; }; F4440FDC282C4103003C810B /* IPSSummarySerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSSummarySerialization.m; path = ../submodules/ips2crash/Model/IPSSummarySerialization.m; sourceTree = ""; }; F4440FDD282C4103003C810B /* IPSCrashSummary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSCrashSummary.m; path = ../submodules/ips2crash/Model/IPSCrashSummary.m; sourceTree = ""; }; F4440FDE282C4103003C810B /* IPSSummarySerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSSummarySerialization.h; path = ../submodules/ips2crash/Model/IPSSummarySerialization.h; sourceTree = ""; }; F4440FDF282C4103003C810B /* IPSCrashSummary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSCrashSummary.h; path = ../submodules/ips2crash/Model/IPSCrashSummary.h; sourceTree = ""; }; F44A5F2D24CCDCB1006B59B8 /* CUICollectionViewDockedThreadItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICollectionViewDockedThreadItem.h; sourceTree = ""; }; F44A5F2E24CCDCB1006B59B8 /* CUICollectionViewDockedThreadItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICollectionViewDockedThreadItem.m; sourceTree = ""; }; F44A5F2F24CCDCB1006B59B8 /* CUICollectionViewDockedThreadItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUICollectionViewDockedThreadItem.xib; sourceTree = ""; }; F44A5F3224CCDD00006B59B8 /* CUICollectionViewThreadItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICollectionViewThreadItem.h; sourceTree = ""; }; F44A5F3324CCDD00006B59B8 /* CUICollectionViewThreadItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICollectionViewThreadItem.m; sourceTree = ""; }; F44A5F3524CCDFD9006B59B8 /* CUICollectionViewDockedThreadsLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICollectionViewDockedThreadsLayout.h; sourceTree = ""; }; F44A5F3624CCDFD9006B59B8 /* CUICollectionViewDockedThreadsLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICollectionViewDockedThreadsLayout.m; sourceTree = ""; }; F44A5F3924CCE2B6006B59B8 /* CUILightTableDockedThreadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUILightTableDockedThreadView.h; sourceTree = ""; }; F44A5F3A24CCE2B6006B59B8 /* CUILightTableDockedThreadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUILightTableDockedThreadView.m; sourceTree = ""; }; F44A5F3C24CCE2D6006B59B8 /* CUILightTableThreadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUILightTableThreadView.h; sourceTree = ""; }; F44A5F3D24CCE2D6006B59B8 /* CUILightTableThreadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUILightTableThreadView.m; sourceTree = ""; }; F44E7B7B255C83D500025C04 /* NoodleLineNumberMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NoodleLineNumberMarker.h; path = "Extemal/Line View Test/NoodleLineNumberMarker.h"; sourceTree = ""; }; F44E7B7C255C83D500025C04 /* NoodleLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NoodleLineNumberView.m; path = "Extemal/Line View Test/NoodleLineNumberView.m"; sourceTree = ""; }; F44E7B7D255C83D500025C04 /* NoodleLineNumberMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NoodleLineNumberMarker.m; path = "Extemal/Line View Test/NoodleLineNumberMarker.m"; sourceTree = ""; }; F44E7B7E255C83D500025C04 /* NoodleLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NoodleLineNumberView.h; path = "Extemal/Line View Test/NoodleLineNumberView.h"; sourceTree = ""; }; F45015C725FABCAC000C4B8D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_BAD_ACCESS_SIGSEGV.html; sourceTree = ""; }; F45015C925FABCAF000C4B8D /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_BAD_ACCESS_SIGSEGV.html; sourceTree = ""; }; F45015CB25FABE00000C4B8D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_BAD_INSTRUCTION_SIGILL.html; sourceTree = ""; }; F45015CD25FABE02000C4B8D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_BAD_INSTRUCTION_SIGILL.html; sourceTree = ""; }; F45015CF25FAD279000C4B8D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_CRASH_SIGQUIT.html; sourceTree = ""; }; F45015D125FAD27B000C4B8D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_CRASH_SIGQUIT.html; sourceTree = ""; }; F453AE4A25EE706F00B7BEF0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIExportAccessoryViewController.xib; sourceTree = ""; }; F453AE4C25EE707000B7BEF0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIExportAccessoryViewController.xib; sourceTree = ""; }; F453AE4E25EE70E800B7BEF0 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUICrashLogPresentationTextViewController.xib; sourceTree = ""; }; F453AE5025EE70E900B7BEF0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUICrashLogPresentationTextViewController.xib; sourceTree = ""; }; F45442A724AF355700EE79E4 /* CUICaptionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICaptionView.h; sourceTree = ""; }; F45442A824AF355700EE79E4 /* CUICaptionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICaptionView.m; sourceTree = ""; }; F4545C39256C1AF900F62A39 /* CUIRegistersWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRegistersWindowController.h; sourceTree = ""; }; F4545C3A256C1AF900F62A39 /* CUIRegistersWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRegistersWindowController.m; sourceTree = ""; }; F4545C3B256C1AF900F62A39 /* CUIRegistersWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUIRegistersWindowController.xib; sourceTree = ""; }; F4545C3E256C1B2400F62A39 /* CUIRegistersViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRegistersViewController.h; sourceTree = ""; }; F4545C3F256C1B2400F62A39 /* CUIRegistersViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRegistersViewController.m; sourceTree = ""; }; F4559F3524AF232800B8EF41 /* CUICrashLogHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogHeader.h; sourceTree = ""; }; F4559F3624AF232800B8EF41 /* CUICrashLogHeader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogHeader.m; sourceTree = ""; }; F4577BE72592848D009B2AD2 /* CUIPreferencePanePresentationOutlineViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePanePresentationOutlineViewController.h; sourceTree = ""; }; F4577BE82592848D009B2AD2 /* CUIPreferencePanePresentationOutlineViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePanePresentationOutlineViewController.m; sourceTree = ""; }; F45854F825C76590007A3A79 /* Unexpectedly_License.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = Unexpectedly_License.pdf; path = "../../Documents Pages/Unexpectedly_License.pdf"; sourceTree = ""; }; F45854F925C76591007A3A79 /* Unexpectedly_Acknowledgements.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = Unexpectedly_Acknowledgements.pdf; path = "../../Documents Pages/Unexpectedly_Acknowledgements.pdf"; sourceTree = ""; }; F45A2D5525EC50960007D50E /* fr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; F45A2D5625EC50960007D50E /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Predicates.strings; sourceTree = ""; }; F45A2D5725EC50960007D50E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/MainMenu.xib; sourceTree = ""; }; F45A2D5E25EC5CA00007D50E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencesWindowController.xib; sourceTree = ""; }; F45A2D6025EC5CA30007D50E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencesWindowController.xib; sourceTree = ""; }; F45A2D6225EC5D130007D50E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePaneFontscolorsViewController.xib; sourceTree = ""; }; F45A2D6425EC5D140007D50E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePaneFontscolorsViewController.xib; sourceTree = ""; }; F45A2D6625EC5F850007D50E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIAboutBoxWindowController.xib; sourceTree = ""; }; F45A2D6825EC5F870007D50E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIAboutBoxWindowController.xib; sourceTree = ""; }; F45A2D6A25EC602B0007D50E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIBinaryImagesViewController.xib; sourceTree = ""; }; F45A2D6C25EC60310007D50E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIBinaryImagesViewController.xib; sourceTree = ""; }; F45A2D6E25EC60920007D50E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUICrashLogsSourcesViewController.xib; sourceTree = ""; }; F45A2D7025EC60930007D50E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUICrashLogsSourcesViewController.xib; sourceTree = ""; }; F45A2D7225EC60D90007D50E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUICrashLogsListViewController.xib; sourceTree = ""; }; F45A2D7425EC60DB0007D50E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUICrashLogsListViewController.xib; sourceTree = ""; }; F45B518A24AFA04000E97B87 /* CUICrashLogsSelection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSelection.h; sourceTree = ""; }; F45B518B24AFA04000E97B87 /* CUICrashLogsSelection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSelection.m; sourceTree = ""; }; F45DED6A2E350F07008F4CE8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUICodeSigningInformationViewController.xib; sourceTree = ""; }; F45DED6C2E350F0D008F4CE8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUICodeSigningInformationViewController.xib; sourceTree = ""; }; F45DED6E2E3510D9008F4CE8 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/CodeSigning.strings; sourceTree = ""; }; F45DED702E351134008F4CE8 /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/CodeSigning.strings; sourceTree = ""; }; F45DED712E3511B8008F4CE8 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/CodeSigning.strings; sourceTree = ""; }; F45DED722E3511BB008F4CE8 /* ja */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/CodeSigning.strings; sourceTree = ""; }; F45DED732E3511BC008F4CE8 /* he */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/CodeSigning.strings; sourceTree = ""; }; F45DED742E351277008F4CE8 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUICodeSigningInformationViewController.xib; sourceTree = ""; }; F45DED752E351279008F4CE8 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUICodeSigningInformationViewController.xib; sourceTree = ""; }; F45DED762E35127A008F4CE8 /* he */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = he; path = he.lproj/CUICodeSigningInformationViewController.xib; sourceTree = ""; }; F45F2F592538EF3F0030A402 /* NSFileManager+ExtendedAttributes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "NSFileManager+ExtendedAttributes.h"; path = "app_unexpectedly/NSFileManager+ExtendedAttributes.h"; sourceTree = ""; }; F45F2F5A2538EF3F0030A402 /* NSFileManager+ExtendedAttributes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "NSFileManager+ExtendedAttributes.m"; path = "app_unexpectedly/NSFileManager+ExtendedAttributes.m"; sourceTree = ""; }; F45F84D3266ABB5800F354F3 /* crashreport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = crashreport.xcodeproj; path = ../plugin_quicklook/crashreport.xcodeproj; sourceTree = ""; }; F46198E724CA390700FA9717 /* CUICrashLogBacktraces+Utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogBacktraces+Utilities.h"; sourceTree = ""; }; F46198E824CA390700FA9717 /* CUICrashLogBacktraces+Utilities.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogBacktraces+Utilities.m"; sourceTree = ""; }; F46198EC24CA459700FA9717 /* CUIInspectorAlternateBackgroundView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInspectorAlternateBackgroundView.h; sourceTree = ""; }; F46198ED24CA459700FA9717 /* CUIInspectorAlternateBackgroundView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInspectorAlternateBackgroundView.m; sourceTree = ""; }; F461CE8825F6DD75007CFDE7 /* CUIApplicationItemAttributes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIApplicationItemAttributes.h; sourceTree = ""; }; F461CE8925F6DD75007CFDE7 /* CUIApplicationItemAttributes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIApplicationItemAttributes.m; sourceTree = ""; }; F4627F0F25704557007E5CD0 /* CUICollectionViewRegisterItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICollectionViewRegisterItem.h; sourceTree = ""; }; F4627F1025704557007E5CD0 /* CUICollectionViewRegisterItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICollectionViewRegisterItem.m; sourceTree = ""; }; F462DD2F24ADC5F900044AB1 /* CUICrashLogsSourceSmart.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceSmart.h; sourceTree = ""; }; F462DD3024ADC5F900044AB1 /* CUICrashLogsSourceSmart.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceSmart.m; sourceTree = ""; }; F464F20924ACF9CF007A3A96 /* CUICrashLogsMainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsMainViewController.h; sourceTree = ""; }; F464F20A24ACF9CF007A3A96 /* CUICrashLogsMainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsMainViewController.m; sourceTree = ""; }; F464F20B24ACF9CF007A3A96 /* CUICrashLogsMainViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUICrashLogsMainViewController.xib; sourceTree = ""; }; F464F20E24ACFBA1007A3A96 /* CUIRegister.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRegister.h; sourceTree = ""; }; F464F20F24ACFBA1007A3A96 /* CUIRegister.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRegister.m; sourceTree = ""; }; F464FA1325D2DA2A00E024A3 /* NSSet+WBExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSSet+WBExtensions.h"; path = "Foundation + Extensions/NSSet+WBExtensions.h"; sourceTree = ""; }; F464FA1425D2DA2A00E024A3 /* NSSet+WBExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSSet+WBExtensions.m"; path = "Foundation + Extensions/NSSet+WBExtensions.m"; sourceTree = ""; }; F4651F8424B297420090DF10 /* CUIOperatingSystemVersion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIOperatingSystemVersion.h; sourceTree = ""; }; F4651F8524B297420090DF10 /* CUIOperatingSystemVersion.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIOperatingSystemVersion.m; sourceTree = ""; }; F469AB2324B3DDEA0053C824 /* CUICrashLogExceptionInformation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogExceptionInformation.h; sourceTree = ""; }; F469AB2424B3DDEA0053C824 /* CUICrashLogExceptionInformation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogExceptionInformation.m; sourceTree = ""; }; F46BAF57250162C900991970 /* CUIPreferencesWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencesWindow.h; sourceTree = ""; }; F46BAF58250162C900991970 /* CUIPreferencesWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencesWindow.m; sourceTree = ""; }; F46D2A2724C33FA200652D50 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Predicates.strings; sourceTree = ""; }; F46D779C25ED8D1800039663 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIInspectorGeneralViewController.xib; sourceTree = ""; }; F46D779E25ED8D1900039663 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIInspectorGeneralViewController.xib; sourceTree = ""; }; F46D77A025ED8D3600039663 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIInspectorUserViewController.xib; sourceTree = ""; }; F46D77A225ED8D3900039663 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIInspectorUserViewController.xib; sourceTree = ""; }; F46D77A425ED8D5700039663 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIInspectorExecutableViewController.xib; sourceTree = ""; }; F46D77A625ED8D5900039663 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIInspectorExecutableViewController.xib; sourceTree = ""; }; F46D77A825ED8E3B00039663 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIInspectorProcessesViewController.xib; sourceTree = ""; }; F46D77AA25ED8E3E00039663 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIInspectorProcessesViewController.xib; sourceTree = ""; }; F46D77AC25ED9EAE00039663 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUICollectionViewRegisterItem.xib; sourceTree = ""; }; F46D77AE25ED9EAF00039663 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUICollectionViewRegisterItem.xib; sourceTree = ""; }; F472CC952550631A003F6338 /* CUISwiftDemangler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUISwiftDemangler.h; path = app_unexpectedly/Demangling/CUISwiftDemangler.h; sourceTree = ""; }; F472CC962550631A003F6338 /* CUISwiftDemangler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUISwiftDemangler.m; path = app_unexpectedly/Demangling/CUISwiftDemangler.m; sourceTree = ""; }; F4754D7225F5678700B0D48F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUICrashLogPresentationOutlineViewController.xib; sourceTree = ""; }; F4754D7425F5678A00B0D48F /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUICrashLogPresentationOutlineViewController.xib; sourceTree = ""; }; F475FB3E26DBAC8200A113D8 /* CUITableViewNoSpace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUITableViewNoSpace.h; sourceTree = ""; }; F475FB3F26DBAC8200A113D8 /* CUITableViewNoSpace.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUITableViewNoSpace.m; sourceTree = ""; }; F476EEBC25686DEF00F40F87 /* CUIAboutBoxFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIAboutBoxFooterView.h; sourceTree = ""; }; F476EEBD25686DEF00F40F87 /* CUIAboutBoxFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIAboutBoxFooterView.m; sourceTree = ""; }; F476EEBF25686EC000F40F87 /* CUIContentBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIContentBox.m; sourceTree = ""; }; F476EEC025686EC000F40F87 /* CUIContentBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIContentBox.h; sourceTree = ""; }; F4775477255B0054006BA662 /* CUIThemesTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIThemesTableView.h; sourceTree = ""; }; F4775478255B0054006BA662 /* CUIThemesTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIThemesTableView.m; sourceTree = ""; }; F47AF8BE255DE61E0037E2D8 /* NSCrashLogTextScrollView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSCrashLogTextScrollView.h; sourceTree = ""; }; F47AF8BF255DE61E0037E2D8 /* NSCrashLogTextScrollView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSCrashLogTextScrollView.m; sourceTree = ""; }; F47C381C2A422E880020D88F /* CUIThreadsListViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CUIThreadsListViewController.xib; sourceTree = ""; }; F47C381D2A422E880020D88F /* CUIThreadsListViewController_RTL.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CUIThreadsListViewController_RTL.xib; sourceTree = ""; }; F47C38202A4230370020D88F /* CUIThreadsColumnViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CUIThreadsColumnViewController.xib; sourceTree = ""; }; F47C38212A4230370020D88F /* CUIThreadsColumnViewController_RTL.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CUIThreadsColumnViewController_RTL.xib; sourceTree = ""; }; F47F76602673542600A74905 /* CUICrashLogsOpenErrorRecord+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogsOpenErrorRecord+UI.h"; sourceTree = ""; }; F47F76612673542600A74905 /* CUICrashLogsOpenErrorRecord+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogsOpenErrorRecord+UI.m"; sourceTree = ""; }; F47F76632673548600A74905 /* CUICrashLogsOpenErrorRecord.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsOpenErrorRecord.h; sourceTree = ""; }; F47F76642673548600A74905 /* CUICrashLogsOpenErrorRecord.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsOpenErrorRecord.m; sourceTree = ""; }; F47F7666267355EA00A74905 /* CUICrashLogErrors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogErrors.h; sourceTree = ""; }; F47F7667267355EA00A74905 /* CUICrashLogErrors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogErrors.m; sourceTree = ""; }; F480692B24AF7D83009665F2 /* CUICrashLogsListViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsListViewController.h; sourceTree = ""; }; F480692C24AF7D83009665F2 /* CUICrashLogsListViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsListViewController.m; sourceTree = ""; }; F483844F24EB041B00FAEF5D /* CUIThemeItemsGroup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIThemeItemsGroup.h; sourceTree = ""; }; F483845024EB041B00FAEF5D /* CUIThemeItemsGroup.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIThemeItemsGroup.m; sourceTree = ""; }; F483845224EB11F700FAEF5D /* default_themes.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = default_themes.plist; sourceTree = ""; }; F483845424EB1BEB00FAEF5D /* CUIApplicationPreferences+Themes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUIApplicationPreferences+Themes.h"; sourceTree = ""; }; F483845524EB1BEB00FAEF5D /* CUIApplicationPreferences+Themes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUIApplicationPreferences+Themes.m"; sourceTree = ""; }; F483845724EB26DF00FAEF5D /* CUIThemeItemsGroup+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUIThemeItemsGroup+UI.h"; sourceTree = ""; }; F483845824EB26DF00FAEF5D /* CUIThemeItemsGroup+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUIThemeItemsGroup+UI.m"; sourceTree = ""; }; F4871DBE2543566E00580562 /* CUIdSYMBundle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CUIdSYMBundle.h; path = dSYM/CUIdSYMBundle.h; sourceTree = ""; }; F4871DBF2543566E00580562 /* CUIdSYMBundle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CUIdSYMBundle.m; path = dSYM/CUIdSYMBundle.m; sourceTree = ""; }; F4871DF225435AF300580562 /* DWRFSection_debug_info.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DWRFSection_debug_info.m; path = app_unexpectedly/DWARF/DWRFSection_debug_info.m; sourceTree = ""; }; F4871DF325435AF300580562 /* DWRFSection_debug_str.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DWRFSection_debug_str.m; path = app_unexpectedly/DWARF/DWRFSection_debug_str.m; sourceTree = ""; }; F4871DF425435AF300580562 /* DWRFFileObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFFileObject.h; path = app_unexpectedly/DWARF/DWRFFileObject.h; sourceTree = ""; }; F4871DF525435AF300580562 /* DWRFSection_debug_line.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFSection_debug_line.h; path = app_unexpectedly/DWARF/DWRFSection_debug_line.h; sourceTree = ""; }; F4871DF625435AF300580562 /* LEB128.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LEB128.h; path = app_unexpectedly/DWARF/LEB128.h; sourceTree = ""; }; F4871DF725435AF300580562 /* DWRFSection_debug_line.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DWRFSection_debug_line.m; path = app_unexpectedly/DWARF/DWRFSection_debug_line.m; sourceTree = ""; }; F4871DF825435AF300580562 /* DWRFSection_debug_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFSection_debug_info.h; path = app_unexpectedly/DWARF/DWRFSection_debug_info.h; sourceTree = ""; }; F4871DF925435AF300580562 /* DWRFSection_debug_abbrev.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DWRFSection_debug_abbrev.m; path = app_unexpectedly/DWARF/DWRFSection_debug_abbrev.m; sourceTree = ""; }; F4871DFA25435AF300580562 /* DWRFSection_debug_str.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFSection_debug_str.h; path = app_unexpectedly/DWARF/DWRFSection_debug_str.h; sourceTree = ""; }; F4871DFB25435AF300580562 /* DWRFFileObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DWRFFileObject.m; path = app_unexpectedly/DWARF/DWRFFileObject.m; sourceTree = ""; }; F4871DFC25435AF300580562 /* DWRFEnums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFEnums.h; path = app_unexpectedly/DWARF/DWRFEnums.h; sourceTree = ""; }; F4871DFD25435AF300580562 /* DWRFSection_debug_aranges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFSection_debug_aranges.h; path = app_unexpectedly/DWARF/DWRFSection_debug_aranges.h; sourceTree = ""; }; F4871DFE25435AF400580562 /* LEB128.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = LEB128.c; path = app_unexpectedly/DWARF/LEB128.c; sourceTree = ""; }; F4871DFF25435AF400580562 /* DWRFSection_debug_abbrev.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFSection_debug_abbrev.h; path = app_unexpectedly/DWARF/DWRFSection_debug_abbrev.h; sourceTree = ""; }; F4871E0025435AF400580562 /* DWRFObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWRFObject.h; path = app_unexpectedly/DWARF/DWRFObject.h; sourceTree = ""; }; F4871E0125435AF400580562 /* DWRFObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DWRFObject.m; path = app_unexpectedly/DWARF/DWRFObject.m; sourceTree = ""; }; F4871E0225435AF400580562 /* DWRFSection_debug_aranges.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DWRFSection_debug_aranges.m; path = app_unexpectedly/DWARF/DWRFSection_debug_aranges.m; sourceTree = ""; }; F4871E0B25437A6A00580562 /* CUISymbolicationDataCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISymbolicationDataCache.h; sourceTree = ""; }; F4871E0C25437A6A00580562 /* CUISymbolicationDataCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISymbolicationDataCache.m; sourceTree = ""; }; F4871E0E254384E100580562 /* CUIdSYMBundlesManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIdSYMBundlesManager.h; sourceTree = ""; }; F4871E0F254384E100580562 /* CUIdSYMBundlesManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIdSYMBundlesManager.m; sourceTree = ""; }; F48906AC25D2BA0C002D79A9 /* CUISelectedWhiteTextFieldCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISelectedWhiteTextFieldCell.h; sourceTree = ""; }; F48906AD25D2BA0C002D79A9 /* CUISelectedWhiteTextFieldCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISelectedWhiteTextFieldCell.m; sourceTree = ""; }; F489441F2545836F00E3E360 /* CUISymbolsFilesLibraryViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISymbolsFilesLibraryViewController.h; sourceTree = ""; }; F48944202545836F00E3E360 /* CUISymbolsFilesLibraryViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISymbolsFilesLibraryViewController.m; sourceTree = ""; }; F4895F5827A72D1000D75369 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUILineJumperWindowController.xib; sourceTree = ""; }; F4895F5A27A72D1300D75369 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUILineJumperWindowController.xib; sourceTree = ""; }; F4895F5B27A72D3300D75369 /* es */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = es; path = es.lproj/CUILineJumperWindowController.xib; sourceTree = ""; }; F4895F5C27A72D6300D75369 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUILineJumperWindowController.xib; sourceTree = ""; }; F48BAB3425D9D4140005F3E5 /* CUIThreadImageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIThreadImageCell.h; sourceTree = ""; }; F48BAB3525D9D4140005F3E5 /* CUIThreadImageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIThreadImageCell.m; sourceTree = ""; }; F48CF60024A969B5002AD214 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; F49227C624A8D45000772411 /* CUIStackFrame+UI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CUIStackFrame+UI.h"; sourceTree = ""; }; F49227C724A8D45000772411 /* CUIStackFrame+UI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CUIStackFrame+UI.m"; sourceTree = ""; }; F49282C225696BF900D255D8 /* known_exceptions.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = known_exceptions.css; path = Help/known_exceptions.css; sourceTree = ""; wrapsLines = 1; }; F493DB1B24F1CF2F001AA8C0 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; F495AEBD25F029C2000D92E1 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePanePresentationTextViewController.xib; sourceTree = ""; }; F495AEBF25F029CD000D92E1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePanePresentationTextViewController.xib; sourceTree = ""; }; F495AEC125F02F74000D92E1 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePanePresentationOutlineViewController.xib; sourceTree = ""; }; F495AEC325F02F76000D92E1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePanePresentationOutlineViewController.xib; sourceTree = ""; }; F495AEC525F03141000D92E1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/unknown_exception_type.html; sourceTree = ""; }; F495AEC725F0314A000D92E1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/unknown_exception_type.html; sourceTree = ""; }; F495AEC925F0320D000D92E1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_CRASH_SIGABRT.html; sourceTree = ""; }; F495AECB25F03213000D92E1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_CRASH_SIGABRT.html; sourceTree = ""; }; F495AECD25F033CC000D92E1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_CRASH_SIGKILL.html; sourceTree = ""; }; F495AECF25F033D0000D92E1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_CRASH_SIGKILL.html; sourceTree = ""; }; F495AED125F034C0000D92E1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_BREAKPOINT_SIGTRAP.html; sourceTree = ""; }; F495AED325F034C4000D92E1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_BREAKPOINT_SIGTRAP.html; sourceTree = ""; }; F495AED525F03820000D92E1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = "en.lproj/EXC_CRASH_Code Signature Invalid.html"; sourceTree = ""; }; F495AED725F03825000D92E1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = "fr.lproj/EXC_CRASH_Code Signature Invalid.html"; sourceTree = ""; }; F49673FB24D0CF6400716289 /* CUIPreferencesWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencesWindowController.h; sourceTree = ""; }; F49673FC24D0CF6400716289 /* CUIPreferencesWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencesWindowController.m; sourceTree = ""; }; F496740124D0D05800716289 /* CUIPreferencePaneViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePaneViewController.h; sourceTree = ""; }; F496740224D0D05800716289 /* CUIPreferencePaneViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePaneViewController.m; sourceTree = ""; }; F496740724D0D2A300716289 /* CUIPreferencePaneFontscolorsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePaneFontscolorsViewController.h; sourceTree = ""; }; F496740824D0D2A300716289 /* CUIPreferencePaneFontscolorsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePaneFontscolorsViewController.m; sourceTree = ""; }; F496740C24D0D74A00716289 /* CUIApplicationPreferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIApplicationPreferences.h; sourceTree = ""; }; F496740D24D0D74A00716289 /* CUIApplicationPreferences.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIApplicationPreferences.m; sourceTree = ""; }; F497303825F796E6001D01FE /* CUIHopperDisassemblerManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIHopperDisassemblerManager.h; sourceTree = ""; }; F497303925F796E6001D01FE /* CUIHopperDisassemblerManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIHopperDisassemblerManager.m; sourceTree = ""; }; F497303B25F7A121001D01FE /* CUICodeType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICodeType.h; sourceTree = ""; }; F497303D25F7F74B001D01FE /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; F497303F25F7F7A6001D01FE /* fr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; F497AD5324B8FE88008517B7 /* CUICrashLogsSourceSmartEditorPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceSmartEditorPanel.h; sourceTree = ""; }; F497AD5424B8FE88008517B7 /* CUICrashLogsSourceSmartEditorPanel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceSmartEditorPanel.m; sourceTree = ""; }; F497AD5B24B90481008517B7 /* app_unexpectedly_Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = app_unexpectedly_Prefix.pch; sourceTree = ""; }; F497F0142576E1A100BD1970 /* CUIRoundedRectBezelView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRoundedRectBezelView.h; sourceTree = ""; }; F497F0152576E1A100BD1970 /* CUIRoundedRectBezelView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRoundedRectBezelView.m; sourceTree = ""; }; F49A55DC24C7A7F900D249DE /* CUICallTableCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICallTableCellView.h; sourceTree = ""; }; F49A55DD24C7A7F900D249DE /* CUICallTableCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICallTableCellView.m; sourceTree = ""; }; F49A6D7C25474F6E00466D15 /* CUIInactiveButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInactiveButton.h; sourceTree = ""; }; F49A6D7D25474F6E00466D15 /* CUIInactiveButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInactiveButton.m; sourceTree = ""; }; F49A6D7F25476F7B00466D15 /* CUISymbolicationDataFormatter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISymbolicationDataFormatter.h; sourceTree = ""; }; F49A6D8025476F7B00466D15 /* CUISymbolicationDataFormatter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISymbolicationDataFormatter.m; sourceTree = ""; }; F49C47C824E9B48B003FC65C /* CUIThemesManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIThemesManager.h; sourceTree = ""; }; F49C47C924E9B48B003FC65C /* CUIThemesManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIThemesManager.m; sourceTree = ""; }; F4A0BEE1261BC39600BADEED /* CUIWatchScrew.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIWatchScrew.h; path = clock/CUIWatchScrew.h; sourceTree = ""; }; F4A0BEE2261BC39600BADEED /* CUIWatchGear.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIWatchGear.m; path = clock/CUIWatchGear.m; sourceTree = ""; }; F4A0BEE3261BC39600BADEED /* CUIWatchJewel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIWatchJewel.m; path = clock/CUIWatchJewel.m; sourceTree = ""; }; F4A0BEE4261BC39600BADEED /* CUIWatchGear.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIWatchGear.h; path = clock/CUIWatchGear.h; sourceTree = ""; }; F4A0BEE5261BC39600BADEED /* brushed-alum.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "brushed-alum.png"; path = "clock/brushed-alum.png"; sourceTree = ""; }; F4A0BEE6261BC39600BADEED /* CUIWatchAxis.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIWatchAxis.m; path = clock/CUIWatchAxis.m; sourceTree = ""; }; F4A0BEE8261BC39600BADEED /* CUIWatchPart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIWatchPart.h; path = clock/CUIWatchPart.h; sourceTree = ""; }; F4A0BEE9261BC39700BADEED /* CUIWatchDrawablePart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIWatchDrawablePart.h; path = clock/CUIWatchDrawablePart.h; sourceTree = ""; }; F4A0BEEB261BC39700BADEED /* CUIWatchPart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIWatchPart.m; path = clock/CUIWatchPart.m; sourceTree = ""; }; F4A0BEEC261BC39700BADEED /* CUIWatchAxis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIWatchAxis.h; path = clock/CUIWatchAxis.h; sourceTree = ""; }; F4A0BEED261BC39700BADEED /* CUIWatchBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIWatchBridge.m; path = clock/CUIWatchBridge.m; sourceTree = ""; }; F4A0BEEE261BC39700BADEED /* CUIWatchBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIWatchBridge.h; path = clock/CUIWatchBridge.h; sourceTree = ""; }; F4A0BEEF261BC39700BADEED /* CUIWatchScrew.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIWatchScrew.m; path = clock/CUIWatchScrew.m; sourceTree = ""; }; F4A0BEF0261BC39700BADEED /* CUIWatchJewel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIWatchJewel.h; path = clock/CUIWatchJewel.h; sourceTree = ""; }; F4A3A6E025ED7F450018053E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUICrashLogsSourceSmartEditorWindowController.xib; sourceTree = ""; }; F4A3A6E225ED7F460018053E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUICrashLogsSourceSmartEditorWindowController.xib; sourceTree = ""; }; F4A3A6E425ED81260018053E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePaneGeneralViewController.xib; sourceTree = ""; }; F4A3A6E625ED81290018053E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePaneGeneralViewController.xib; sourceTree = ""; }; F4A3A6E825ED817E0018053E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePaneCrashreporterViewController.xib; sourceTree = ""; }; F4A3A6EA25ED81800018053E /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePaneCrashreporterViewController.xib; sourceTree = ""; }; F4A3A6EC25ED82F10018053E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/EXC_BAD_ACCESS_SIGBUS.html; sourceTree = ""; }; F4A3A6EE25ED82F20018053E /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/EXC_BAD_ACCESS_SIGBUS.html; sourceTree = ""; }; F4A58D1924CA4B1500D98FDB /* CUICrashedThreadRowView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashedThreadRowView.h; sourceTree = ""; }; F4A58D1A24CA4B1500D98FDB /* CUICrashedThreadRowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashedThreadRowView.m; sourceTree = ""; }; F4A58D1C24CA4CDA00D98FDB /* CUICrashedThreadCallRowView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashedThreadCallRowView.h; sourceTree = ""; }; F4A58D1D24CA4CDA00D98FDB /* CUICrashedThreadCallRowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashedThreadCallRowView.m; sourceTree = ""; }; F4A769682555D9DD00F9D9D3 /* CUIRawCrashLog+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUIRawCrashLog+UI.h"; sourceTree = ""; }; F4A769692555D9DD00F9D9D3 /* CUIRawCrashLog+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUIRawCrashLog+UI.m"; sourceTree = ""; }; F4A9967B2675078A0001B40E /* CUICrashLogsOpenErrorWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CUICrashLogsOpenErrorWindowController.xib; sourceTree = ""; }; F4AA22B42561A233001A1315 /* CUIAboutBoxWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIAboutBoxWindowController.h; sourceTree = ""; }; F4AA22B52561A233001A1315 /* CUIAboutBoxWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIAboutBoxWindowController.m; sourceTree = ""; }; F4AC86472558A03B004F2637 /* CUIExportAccessoryViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIExportAccessoryViewController.h; sourceTree = ""; }; F4AC86482558A03B004F2637 /* CUIExportAccessoryViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIExportAccessoryViewController.m; sourceTree = ""; }; F4B018352620FEC7009727F1 /* CUIApplicationIconView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIApplicationIconView.m; path = clock/CUIApplicationIconView.m; sourceTree = ""; }; F4B018362620FEC7009727F1 /* CUIApplicationIconView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIApplicationIconView.h; path = clock/CUIApplicationIconView.h; sourceTree = ""; }; F4B138552522948700D9DE2F /* NSBundle+dSYM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSBundle+dSYM.h"; sourceTree = ""; }; F4B138562522948700D9DE2F /* NSBundle+dSYM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+dSYM.m"; sourceTree = ""; }; F4B52E1F2548B8B4007593FD /* CUIdSYMBundle+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "CUIdSYMBundle+UI.h"; path = "dSYM/CUIdSYMBundle+UI.h"; sourceTree = ""; }; F4B52E202548B8B4007593FD /* CUIdSYMBundle+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "CUIdSYMBundle+UI.m"; path = "dSYM/CUIdSYMBundle+UI.m"; sourceTree = ""; }; F4B57C0A24AF5607000851FF /* CUICrashLogsSourceToday.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceToday.h; sourceTree = ""; }; F4B57C0B24AF5607000851FF /* CUICrashLogsSourceToday.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceToday.m; sourceTree = ""; }; F4B57C0D24AF5655000851FF /* CUICrashLogsSourceToday+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogsSourceToday+UI.h"; sourceTree = ""; }; F4B57C0E24AF5655000851FF /* CUICrashLogsSourceToday+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogsSourceToday+UI.m"; sourceTree = ""; }; F4B5BE6C2848277400C33F6F /* CUIExceptionTypePopUpViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIExceptionTypePopUpViewController.h; sourceTree = ""; }; F4B5BE6D2848277400C33F6F /* CUIExceptionTypePopUpViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIExceptionTypePopUpViewController.m; sourceTree = ""; }; F4B5BE6F28482A4300C33F6F /* CUITerminationReasonPopUpViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUITerminationReasonPopUpViewController.h; sourceTree = ""; }; F4B5BE7028482A4300C33F6F /* CUITerminationReasonPopUpViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUITerminationReasonPopUpViewController.m; sourceTree = ""; }; F4B649D024EDCD2300008C47 /* CUIInspectorExecutableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInspectorExecutableViewController.h; sourceTree = ""; }; F4B649D124EDCD2300008C47 /* CUIInspectorExecutableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInspectorExecutableViewController.m; sourceTree = ""; }; F4B649D524EDD09A00008C47 /* CUIInspectorStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInspectorStackableViewController.h; sourceTree = ""; }; F4B649D624EDD09A00008C47 /* CUIInspectorStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInspectorStackableViewController.m; sourceTree = ""; }; F4B649D824EDD64900008C47 /* CUIInspectorProcessesViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInspectorProcessesViewController.h; sourceTree = ""; }; F4B649D924EDD64900008C47 /* CUIInspectorProcessesViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInspectorProcessesViewController.m; sourceTree = ""; }; F4B67835258F702E0047369E /* CUIPreferencePaneCrashreporterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePaneCrashreporterViewController.h; sourceTree = ""; }; F4B67836258F702E0047369E /* CUIPreferencePaneCrashreporterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePaneCrashreporterViewController.m; sourceTree = ""; }; F4B74C1624B233C900CD1E60 /* CUIRightViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRightViewController.h; sourceTree = ""; }; F4B74C1724B233C900CD1E60 /* CUIRightViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRightViewController.m; sourceTree = ""; }; F4B74C1824B233C900CD1E60 /* CUIRightViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUIRightViewController.xib; sourceTree = ""; }; F4B9AD2425319A400083FA6C /* MCHMemoryBufferWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHMemoryBufferWrapper.m; path = "app_unexpectedly/Mach-o/MCHMemoryBufferWrapper.m"; sourceTree = ""; }; F4B9AD2525319A400083FA6C /* MCHObjectFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHObjectFile.h; path = "app_unexpectedly/Mach-o/MCHObjectFile.h"; sourceTree = ""; }; F4B9AD2625319A400083FA6C /* MCHSegment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHSegment.m; path = "app_unexpectedly/Mach-o/MCHSegment.m"; sourceTree = ""; }; F4B9AD2725319A400083FA6C /* MCHMachBinary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHMachBinary.h; path = "app_unexpectedly/Mach-o/MCHMachBinary.h"; sourceTree = ""; }; F4B9AD2825319A400083FA6C /* MCHObjectFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHObjectFile.m; path = "app_unexpectedly/Mach-o/MCHObjectFile.m"; sourceTree = ""; }; F4B9AD2925319A400083FA6C /* MCHLoadCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHLoadCommand.h; path = "app_unexpectedly/Mach-o/MCHLoadCommand.h"; sourceTree = ""; }; F4B9AD2A25319A400083FA6C /* MCHMemoryBufferWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHMemoryBufferWrapper.h; path = "app_unexpectedly/Mach-o/MCHMemoryBufferWrapper.h"; sourceTree = ""; }; F4B9AD2B25319A400083FA6C /* MCHUUIDLoadCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHUUIDLoadCommand.m; path = "app_unexpectedly/Mach-o/MCHUUIDLoadCommand.m"; sourceTree = ""; }; F4B9AD2C25319A410083FA6C /* MCHSegment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHSegment.h; path = "app_unexpectedly/Mach-o/MCHSegment.h"; sourceTree = ""; }; F4B9AD2D25319A410083FA6C /* MCHLoadCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHLoadCommand.m; path = "app_unexpectedly/Mach-o/MCHLoadCommand.m"; sourceTree = ""; }; F4B9AD2E25319A410083FA6C /* MCHSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHSection.m; path = "app_unexpectedly/Mach-o/MCHSection.m"; sourceTree = ""; }; F4B9AD2F25319A410083FA6C /* MCHUUIDLoadCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHUUIDLoadCommand.h; path = "app_unexpectedly/Mach-o/MCHUUIDLoadCommand.h"; sourceTree = ""; }; F4B9AD3025319A410083FA6C /* MCHMachBinary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHMachBinary.m; path = "app_unexpectedly/Mach-o/MCHMachBinary.m"; sourceTree = ""; }; F4B9AD3125319A410083FA6C /* MCHSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHSection.h; path = "app_unexpectedly/Mach-o/MCHSection.h"; sourceTree = ""; }; F4B9AD3925319D7B0083FA6C /* MCHSegmentLoadCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MCHSegmentLoadCommand.m; path = "app_unexpectedly/Mach-o/MCHSegmentLoadCommand.m"; sourceTree = ""; }; F4B9AD3A25319D7C0083FA6C /* MCHSegmentLoadCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MCHSegmentLoadCommand.h; path = "app_unexpectedly/Mach-o/MCHSegmentLoadCommand.h"; sourceTree = ""; }; F4BBAC5B24AA7D37000511BE /* CUIBinaryImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIBinaryImage.h; sourceTree = ""; }; F4BBAC5C24AA7D37000511BE /* CUIBinaryImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIBinaryImage.m; sourceTree = ""; }; F4BC576F24DF426200063545 /* CUIAATextFieldCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIAATextFieldCell.h; sourceTree = ""; }; F4BC577024DF426200063545 /* CUIAATextFieldCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIAATextFieldCell.m; sourceTree = ""; }; F4BD69FE25553E8F00F98F3E /* CUICrashLogSectionsDetector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogSectionsDetector.h; sourceTree = ""; }; F4BD69FF25553E9000F98F3E /* CUICrashLogSectionsDetector.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogSectionsDetector.m; sourceTree = ""; }; F4BD8C682DF4DDCA00BD61A8 /* IPSExceptionReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSExceptionReason.h; path = ../submodules/ips2crash/Model/IPSExceptionReason.h; sourceTree = ""; }; F4BD8C692DF4DDCA00BD61A8 /* IPSExceptionReason.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSExceptionReason.m; path = ../submodules/ips2crash/Model/IPSExceptionReason.m; sourceTree = ""; }; F4C269CB2503BCC100C8F3B3 /* CUISymbolicationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISymbolicationManager.h; sourceTree = ""; }; F4C269CC2503BCC100C8F3B3 /* CUISymbolicationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISymbolicationManager.m; sourceTree = ""; }; F4C269CE2503BE6500C8F3B3 /* CUISymbolicationData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUISymbolicationData.h; sourceTree = ""; }; F4C269CF2503BE6500C8F3B3 /* CUISymbolicationData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUISymbolicationData.m; sourceTree = ""; }; F4C7498B24F84689004F38C0 /* CUIQuickHelpPopUpViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIQuickHelpPopUpViewController.h; sourceTree = ""; }; F4C7498C24F84689004F38C0 /* CUIQuickHelpPopUpViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIQuickHelpPopUpViewController.m; sourceTree = ""; }; F4C7498D24F84689004F38C0 /* CUIQuickHelpPopUpViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUIQuickHelpPopUpViewController.xib; sourceTree = ""; }; F4CC56FF24A79EDA00150EC4 /* Unexpectedly.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Unexpectedly.app; sourceTree = BUILT_PRODUCTS_DIR; }; F4CC570324A79EDA00150EC4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F4CC570424A79EDA00150EC4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; F4CC570524A79EDA00150EC4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; F4CC570724A79EDA00150EC4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; F4CC570924A79EDA00150EC4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; F4CC572224A7A1D100150EC4 /* CUICrashLogsProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsProvider.h; sourceTree = ""; }; F4CC572324A7A1D100150EC4 /* CUICrashLogsProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsProvider.m; sourceTree = ""; }; F4CC572524A7A2B200150EC4 /* CUICrashLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUICrashLog.h; sourceTree = ""; }; F4CC572624A7A2B200150EC4 /* CUICrashLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUICrashLog.m; sourceTree = ""; }; F4CC572B24A7A5F000150EC4 /* CUICrashLog+Transform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CUICrashLog+Transform.h"; sourceTree = ""; }; F4CC572C24A7A5F000150EC4 /* CUICrashLog+Transform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLog+Transform.m"; sourceTree = ""; }; F4CC572E24A7A95A00150EC4 /* CUIThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUIThread.h; sourceTree = ""; }; F4CC572F24A7A95A00150EC4 /* CUIThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUIThread.m; sourceTree = ""; }; F4CC573124A7ABAF00150EC4 /* CUICallStackBacktrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUICallStackBacktrace.h; sourceTree = ""; }; F4CC573224A7ABAF00150EC4 /* CUICallStackBacktrace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUICallStackBacktrace.m; sourceTree = ""; }; F4CCCC5E24AE76780031BC27 /* CUICrashLogsSourcesViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourcesViewController.h; sourceTree = ""; }; F4CCCC5F24AE76780031BC27 /* CUICrashLogsSourcesViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourcesViewController.m; sourceTree = ""; }; F4CCCC6324AE810E0031BC27 /* CUICrashLogsSourcesSelection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourcesSelection.h; sourceTree = ""; }; F4CCCC6424AE810E0031BC27 /* CUICrashLogsSourcesSelection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourcesSelection.m; sourceTree = ""; }; F4CCCC6924AE95430031BC27 /* CUICrashLogsSourceFileSystemItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceFileSystemItem.h; sourceTree = ""; }; F4CCCC6A24AE95430031BC27 /* CUICrashLogsSourceFileSystemItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceFileSystemItem.m; sourceTree = ""; }; F4CCCC6C24AE9EDA0031BC27 /* CUICrashLogsSource+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogsSource+UI.h"; sourceTree = ""; }; F4CCCC6D24AE9EDA0031BC27 /* CUICrashLogsSource+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogsSource+UI.m"; sourceTree = ""; }; F4CD32B3257D17B3008C71AA /* CUIPreferencePaneSymbolicationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePaneSymbolicationViewController.h; sourceTree = ""; }; F4CD32B4257D17B3008C71AA /* CUIPreferencePaneSymbolicationViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePaneSymbolicationViewController.m; sourceTree = ""; }; F4CE09A42A76E43300BACB71 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = Help/es.lproj/ENDPOINTSECURITY_2.html; sourceTree = ""; }; F4CE09A52A76E44D00BACB71 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = Help/ja.lproj/ENDPOINTSECURITY_2.html; sourceTree = ""; }; F4CE83DD2554B97300A8BD87 /* CUICenteredLabelViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CUICenteredLabelViewController.xib; sourceTree = ""; }; F4CF6CF42DF6111B0078458E /* IPSIncident+ApplicationSpecificInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSIncident+ApplicationSpecificInformation.m"; path = "../submodules/ips2crash/tool_ips2crash/ips2crash/IPSIncident+ApplicationSpecificInformation.m"; sourceTree = ""; }; F4CF6CF52DF6111B0078458E /* IPSIncident+ApplicationSpecificInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSIncident+ApplicationSpecificInformation.h"; path = "../submodules/ips2crash/tool_ips2crash/ips2crash/IPSIncident+ApplicationSpecificInformation.h"; sourceTree = ""; }; F4D0EE93273DB8CC00CC9737 /* IPSThreadState+RegisterDisplayName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSThreadState+RegisterDisplayName.m"; path = "../submodules/ips2crash/tool_ips2crash/ips2crash/IPSThreadState+RegisterDisplayName.m"; sourceTree = ""; }; F4D0EE94273DB8CC00CC9737 /* IPSThreadState+RegisterDisplayName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSThreadState+RegisterDisplayName.h"; path = "../submodules/ips2crash/tool_ips2crash/ips2crash/IPSThreadState+RegisterDisplayName.h"; sourceTree = ""; }; F4D14D662745C0A9003698AD /* IPSImage+UserCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSImage+UserCode.m"; path = "../submodules/ips2crash/tool_ips2crash/ips2crash/IPSImage+UserCode.m"; sourceTree = ""; }; F4D14D672745C0A9003698AD /* IPSImage+UserCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSImage+UserCode.h"; path = "../submodules/ips2crash/tool_ips2crash/ips2crash/IPSImage+UserCode.h"; sourceTree = ""; }; F4D5C77A2571AF900029B051 /* CUIRegisterLabel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRegisterLabel.h; sourceTree = ""; }; F4D5C77B2571AF900029B051 /* CUIRegisterLabel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRegisterLabel.m; sourceTree = ""; }; F4D6C56C2680028A00B78B3D /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/RemoteCheck.strings; sourceTree = ""; }; F4D6C56E268002DE00B78B3D /* fr */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/RemoteCheck.strings; sourceTree = ""; }; F4D6C56F2680031E00B78B3D /* es */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/RemoteCheck.strings; sourceTree = ""; }; F4D7F15C25F04A620024E9A5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUISymbolsFilesLibraryViewController.xib; sourceTree = ""; }; F4D7F15E25F04A630024E9A5 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUISymbolsFilesLibraryViewController.xib; sourceTree = ""; }; F4D7F16025F04A9D0024E9A5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/CUIPreferencePaneSymbolicationViewController.xib; sourceTree = ""; }; F4D7F16225F04A9E0024E9A5 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = fr; path = fr.lproj/CUIPreferencePaneSymbolicationViewController.xib; sourceTree = ""; }; F4DAF0B127C44AA700256EA4 /* IPSImage+Offset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSImage+Offset.h"; path = "app_unexpectedly/ips + Extensions/IPSImage+Offset.h"; sourceTree = ""; }; F4DAF0B227C44AA700256EA4 /* IPSImage+Offset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSImage+Offset.m"; path = "app_unexpectedly/ips + Extensions/IPSImage+Offset.m"; sourceTree = ""; }; F4DAFBEC2736B7B200FB50A6 /* CUIIPSTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIIPSTransform.h; sourceTree = ""; }; F4DAFBED2736B7B200FB50A6 /* CUIIPSTransform.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIIPSTransform.m; sourceTree = ""; }; F4DAFBEF2736B7D500FB50A6 /* CUIDataTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIDataTransform.h; sourceTree = ""; }; F4DAFBF02736B7D500FB50A6 /* CUIDataTransform.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIDataTransform.m; sourceTree = ""; }; F4DF813B2893463B008EF1B3 /* IPSIncidentDiagnosticMessage+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSIncidentDiagnosticMessage+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncidentDiagnosticMessage+Obfuscating.h"; sourceTree = ""; }; F4DF813C2893463B008EF1B3 /* IPSThreadState+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSThreadState+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSThreadState+Obfuscating.m"; sourceTree = ""; }; F4DF813D2893463B008EF1B3 /* IPSIncidentDiagnosticMessage+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSIncidentDiagnosticMessage+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncidentDiagnosticMessage+Obfuscating.m"; sourceTree = ""; }; F4DF813E2893463B008EF1B3 /* IPSObfuscator+Extended.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSObfuscator+Extended.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSObfuscator+Extended.h"; sourceTree = ""; }; F4DF813F2893463B008EF1B3 /* IPSThreadState+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSThreadState+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSThreadState+Obfuscating.h"; sourceTree = ""; }; F4DF81402893463B008EF1B3 /* IPSApplicationSpecificInformation+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSApplicationSpecificInformation+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSApplicationSpecificInformation+Obfuscating.m"; sourceTree = ""; }; F4DF81412893463B008EF1B3 /* IPSObfuscator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSObfuscator.h; path = "../submodules/ips2crash/Model + Obfuscating/IPSObfuscator.h"; sourceTree = ""; }; F4DF81422893463C008EF1B3 /* IPSBundleInfo+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSBundleInfo+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSBundleInfo+Obfuscating.h"; sourceTree = ""; }; F4DF81432893463C008EF1B3 /* IPSIncidentHeader+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSIncidentHeader+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncidentHeader+Obfuscating.m"; sourceTree = ""; }; F4DF81442893463C008EF1B3 /* IPSLegacyInfo+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSLegacyInfo+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSLegacyInfo+Obfuscating.h"; sourceTree = ""; }; F4DF81452893463C008EF1B3 /* IPSIncident+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSIncident+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncident+Obfuscating.h"; sourceTree = ""; }; F4DF81462893463C008EF1B3 /* IPSObfuscator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSObfuscator.m; path = "../submodules/ips2crash/Model + Obfuscating/IPSObfuscator.m"; sourceTree = ""; }; F4DF81472893463C008EF1B3 /* IPSCrashSummary+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSCrashSummary+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSCrashSummary+Obfuscating.m"; sourceTree = ""; }; F4DF81482893463C008EF1B3 /* IPSImage+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSImage+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSImage+Obfuscating.h"; sourceTree = ""; }; F4DF81492893463C008EF1B3 /* IPSThread+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSThread+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSThread+Obfuscating.m"; sourceTree = ""; }; F4DF814A2893463C008EF1B3 /* IPSThreadFrame+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSThreadFrame+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSThreadFrame+Obfuscating.m"; sourceTree = ""; }; F4DF814B2893463C008EF1B3 /* IPSRegisterState+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSRegisterState+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSRegisterState+Obfuscating.m"; sourceTree = ""; }; F4DF814C2893463C008EF1B3 /* IPSReport+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSReport+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSReport+Obfuscating.h"; sourceTree = ""; }; F4DF814D2893463C008EF1B3 /* IPSIncidentHeader+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSIncidentHeader+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncidentHeader+Obfuscating.h"; sourceTree = ""; }; F4DF814E2893463D008EF1B3 /* IPSCrashSummary+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSCrashSummary+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSCrashSummary+Obfuscating.h"; sourceTree = ""; }; F4DF814F2893463D008EF1B3 /* IPSImage+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSImage+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSImage+Obfuscating.m"; sourceTree = ""; }; F4DF81502893463D008EF1B3 /* IPSLegacyInfo+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSLegacyInfo+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSLegacyInfo+Obfuscating.m"; sourceTree = ""; }; F4DF81512893463D008EF1B3 /* IPSApplicationSpecificInformation+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSApplicationSpecificInformation+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSApplicationSpecificInformation+Obfuscating.h"; sourceTree = ""; }; F4DF81522893463D008EF1B3 /* IPSReport+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSReport+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSReport+Obfuscating.m"; sourceTree = ""; }; F4DF81532893463D008EF1B3 /* IPSIncidentExceptionInformation+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSIncidentExceptionInformation+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncidentExceptionInformation+Obfuscating.h"; sourceTree = ""; }; F4DF81542893463D008EF1B3 /* IPSThreadFrame+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSThreadFrame+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSThreadFrame+Obfuscating.h"; sourceTree = ""; }; F4DF81552893463D008EF1B3 /* IPSIncidentExceptionInformation+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSIncidentExceptionInformation+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncidentExceptionInformation+Obfuscating.m"; sourceTree = ""; }; F4DF81562893463D008EF1B3 /* IPSBundleInfo+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSBundleInfo+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSBundleInfo+Obfuscating.m"; sourceTree = ""; }; F4DF81572893463D008EF1B3 /* IPSIncident+Obfuscating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSIncident+Obfuscating.m"; path = "../submodules/ips2crash/Model + Obfuscating/IPSIncident+Obfuscating.m"; sourceTree = ""; }; F4DF81582893463D008EF1B3 /* IPSThread+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSThread+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSThread+Obfuscating.h"; sourceTree = ""; }; F4DF81592893463E008EF1B3 /* IPSRegisterState+Obfuscating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSRegisterState+Obfuscating.h"; path = "../submodules/ips2crash/Model + Obfuscating/IPSRegisterState+Obfuscating.h"; sourceTree = ""; }; F4E0BD23262078220048647C /* CUIAboutBoxWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIAboutBoxWindow.h; sourceTree = ""; }; F4E0BD24262078220048647C /* CUIAboutBoxWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIAboutBoxWindow.m; sourceTree = ""; }; F4E1C11124C22CF5000F5C0F /* CUILightTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUILightTableViewController.h; sourceTree = ""; }; F4E1C11224C22CF5000F5C0F /* CUILightTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUILightTableViewController.m; sourceTree = ""; }; F4E1C11324C22CF5000F5C0F /* CUILightTableViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUILightTableViewController.xib; sourceTree = ""; }; F4E1C11624C22F02000F5C0F /* CUICollectionViewVisibleThreadsLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICollectionViewVisibleThreadsLayout.h; sourceTree = ""; }; F4E1C11724C22F02000F5C0F /* CUICollectionViewVisibleThreadsLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICollectionViewVisibleThreadsLayout.m; sourceTree = ""; }; F4E1C11924C22F54000F5C0F /* CUICollectionViewVisibleThreadItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICollectionViewVisibleThreadItem.h; sourceTree = ""; }; F4E1C11A24C22F54000F5C0F /* CUICollectionViewVisibleThreadItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICollectionViewVisibleThreadItem.m; sourceTree = ""; }; F4E1C11B24C22F54000F5C0F /* CUICollectionViewVisibleThreadItem.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUICollectionViewVisibleThreadItem.xib; sourceTree = ""; }; F4E1C11E24C22FB5000F5C0F /* CUILightTableVisibleThreadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUILightTableVisibleThreadView.h; sourceTree = ""; }; F4E1C11F24C22FB5000F5C0F /* CUILightTableVisibleThreadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUILightTableVisibleThreadView.m; sourceTree = ""; }; F4E1C12124C22FEE000F5C0F /* CUILightTableVisibleInterGapView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUILightTableVisibleInterGapView.h; sourceTree = ""; }; F4E1C12224C22FEE000F5C0F /* CUILightTableVisibleInterGapView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUILightTableVisibleInterGapView.m; sourceTree = ""; }; F4E671902E2C3B1600E5A064 /* CUICodeSigningFlagsTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICodeSigningFlagsTableView.h; sourceTree = ""; }; F4E671912E2C3B1600E5A064 /* CUICodeSigningFlagsTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICodeSigningFlagsTableView.m; sourceTree = ""; }; F4E671942E2C405F00E5A064 /* CodeSigningFlags.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = CodeSigningFlags.plist; sourceTree = ""; }; F4E6ED9B2849695100766F9A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = Help/en.lproj/unknown_termination_reason.html; sourceTree = ""; }; F4E6ED9D2849696000766F9A /* es */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = es; path = Help/es.lproj/unknown_termination_reason.html; sourceTree = ""; }; F4E6ED9E2849696600766F9A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = Help/fr.lproj/unknown_termination_reason.html; sourceTree = ""; }; F4E6ED9F2849696C00766F9A /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = Help/ja.lproj/unknown_termination_reason.html; sourceTree = ""; }; F4E6EDA0284969DD00766F9A /* known_termination_reasons.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = known_termination_reasons.css; path = Help/known_termination_reasons.css; sourceTree = ""; }; F4E6EDA3284969E500766F9A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = Help/en.lproj/ENDPOINTSECURITY_2.html; sourceTree = ""; }; F4E6EDA528496E2A00766F9A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = Help/fr.lproj/ENDPOINTSECURITY_2.html; sourceTree = ""; }; F4E861B8255496310061E203 /* CUIRawCrashLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRawCrashLog.h; sourceTree = ""; }; F4E861B9255496310061E203 /* CUIRawCrashLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRawCrashLog.m; sourceTree = ""; }; F4E91ADB256A98050017C3EE /* CUIFontBoxView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIFontBoxView.h; sourceTree = ""; }; F4E91ADC256A98050017C3EE /* CUIFontBoxView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIFontBoxView.m; sourceTree = ""; }; F4EAFA2A24FA6CD100C0B729 /* CUICrashLogTextView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogTextView.h; sourceTree = ""; }; F4EAFA2B24FA6CD100C0B729 /* CUICrashLogTextView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogTextView.m; sourceTree = ""; }; F4EBADB224A8F04F00DF4271 /* CUICrashLog+UI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CUICrashLog+UI.h"; sourceTree = ""; }; F4EBADB324A8F04F00DF4271 /* CUICrashLog+UI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLog+UI.m"; sourceTree = ""; }; F4EBADB524A8F10000DF4271 /* CUICrashLogTableCellView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CUICrashLogTableCellView.h; sourceTree = ""; }; F4EBADB624A8F10000DF4271 /* CUICrashLogTableCellView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogTableCellView.m; sourceTree = ""; }; F4EBD24924E01556007F0252 /* CUITableCustomSelectionColorRowView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUITableCustomSelectionColorRowView.h; sourceTree = ""; }; F4EBD24A24E01556007F0252 /* CUITableCustomSelectionColorRowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUITableCustomSelectionColorRowView.m; sourceTree = ""; }; F4ED18A124EC77A300ED7EF2 /* NSArray+UniqueName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+UniqueName.m"; path = "Foundation + Extensions/NSArray+UniqueName.m"; sourceTree = ""; }; F4ED18A224EC77A300ED7EF2 /* NSArray+UniqueName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+UniqueName.h"; path = "Foundation + Extensions/NSArray+UniqueName.h"; sourceTree = ""; }; F4ED75882501A29700316E73 /* CUIStackFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIStackFrame.h; sourceTree = ""; }; F4ED75892501A29700316E73 /* CUIStackFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIStackFrame.m; sourceTree = ""; }; F4EFE75024BA48F500DB97AC /* CUIMainWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIMainWindow.h; sourceTree = ""; }; F4EFE75124BA48F500DB97AC /* CUIMainWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIMainWindow.m; sourceTree = ""; }; F4F2A9CE24BB7E3600F912D4 /* CUICrashLogsSourceSeparator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceSeparator.h; sourceTree = ""; }; F4F2A9CF24BB7E3600F912D4 /* CUICrashLogsSourceSeparator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceSeparator.m; sourceTree = ""; }; F4F2A9D124BB809200F912D4 /* CUICrashLogsSourceTableCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUICrashLogsSourceTableCellView.h; sourceTree = ""; }; F4F2A9D224BB809200F912D4 /* CUICrashLogsSourceTableCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUICrashLogsSourceTableCellView.m; sourceTree = ""; }; F4F5395624D21DB800D537BC /* CUIPreferencePaneGeneralViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPreferencePaneGeneralViewController.h; sourceTree = ""; }; F4F5395724D21DB800D537BC /* CUIPreferencePaneGeneralViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPreferencePaneGeneralViewController.m; sourceTree = ""; }; F4F5821A256FC7B90032FC53 /* DWRFSection_debug_str_offsets.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DWRFSection_debug_str_offsets.h; path = app_unexpectedly/DWARF/DWRFSection_debug_str_offsets.h; sourceTree = ""; }; F4F5821B256FC7B90032FC53 /* DWRFSection_debug_str_offsets.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DWRFSection_debug_str_offsets.m; path = app_unexpectedly/DWARF/DWRFSection_debug_str_offsets.m; sourceTree = ""; }; F4F892F82575A6DC00BE4CE0 /* CUIRegistersViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CUIRegistersViewController.xib; sourceTree = ""; }; F4F892FA2575A70800BE4CE0 /* CUIRegistersMainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIRegistersMainViewController.h; sourceTree = ""; }; F4F892FB2575A70800BE4CE0 /* CUIRegistersMainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIRegistersMainViewController.m; sourceTree = ""; }; F4F892FC2575A70800BE4CE0 /* CUIRegistersMainViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUIRegistersMainViewController.xib; sourceTree = ""; }; F4F8D26624F29624007661D6 /* CUIPresentationTextNavigationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIPresentationTextNavigationViewController.h; sourceTree = ""; }; F4F8D26724F29624007661D6 /* CUIPresentationTextNavigationViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIPresentationTextNavigationViewController.m; sourceTree = ""; }; F4F8D26824F29624007661D6 /* CUIPresentationTextNavigationViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CUIPresentationTextNavigationViewController.xib; sourceTree = ""; }; F4F9BAEF24EF060E00D08FBD /* CUIInspectorUserViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInspectorUserViewController.h; sourceTree = ""; }; F4F9BAF024EF060E00D08FBD /* CUIInspectorUserViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInspectorUserViewController.m; sourceTree = ""; }; F4F9BAF424EF06BC00D08FBD /* CUIInspectorGeneralViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIInspectorGeneralViewController.h; sourceTree = ""; }; F4F9BAF524EF06BC00D08FBD /* CUIInspectorGeneralViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIInspectorGeneralViewController.m; sourceTree = ""; }; F4F9D3332556C7DB00D28E6E /* CUILineJumperWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUILineJumperWindowController.h; sourceTree = ""; }; F4F9D3342556C7DB00D28E6E /* CUILineJumperWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUILineJumperWindowController.m; sourceTree = ""; }; F4FA4321273EF2F30068EDB8 /* NSString+CPU.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "NSString+CPU.h"; path = "Foundation + Extensions/NSString+CPU.h"; sourceTree = ""; }; F4FA4322273EF2F30068EDB8 /* NSString+CPU.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "NSString+CPU.m"; path = "Foundation + Extensions/NSString+CPU.m"; sourceTree = ""; }; F4FC3629278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/RemoteCheck.strings; sourceTree = ""; }; F4FC362A278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIAboutBoxWindowController.xib; sourceTree = ""; }; F4FC362B278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePaneGeneralViewController.xib; sourceTree = ""; }; F4FC362C278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePanePresentationTextViewController.xib; sourceTree = ""; }; F4FC362D278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePanePresentationOutlineViewController.xib; sourceTree = ""; }; F4FC362E278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePanePresentationViewController.xib; sourceTree = ""; }; F4FC362F278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePaneFontscolorsViewController.xib; sourceTree = ""; }; F4FC3630278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUISymbolsFilesLibraryViewController.xib; sourceTree = ""; }; F4FC3631278F914200669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePaneSymbolicationViewController.xib; sourceTree = ""; }; F4FC3632278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePaneCrashreporterViewController.xib; sourceTree = ""; }; F4FC3633278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencePaneAdvancedViewController.xib; sourceTree = ""; }; F4FC3634278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIPreferencesWindowController.xib; sourceTree = ""; }; F4FC3635278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUICrashLogsSourceSmartEditorWindowController.xib; sourceTree = ""; }; F4FC3636278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUICrashLogsSourcesViewController.xib; sourceTree = ""; }; F4FC3637278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUICrashLogsListViewController.xib; sourceTree = ""; }; F4FC3638278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIInspectorGeneralViewController.xib; sourceTree = ""; }; F4FC3639278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIInspectorUserViewController.xib; sourceTree = ""; }; F4FC363A278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIInspectorExecutableViewController.xib; sourceTree = ""; }; F4FC363B278F914300669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIInspectorProcessesViewController.xib; sourceTree = ""; }; F4FC363C278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/unknown_exception_type.html; sourceTree = ""; }; F4FC363D278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_BAD_ACCESS_SIGBUS.html; sourceTree = ""; }; F4FC363E278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_BAD_ACCESS_SIGSEGV.html; sourceTree = ""; }; F4FC363F278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_BAD_INSTRUCTION_SIGILL.html; sourceTree = ""; }; F4FC3640278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_BREAKPOINT_SIGTRAP.html; sourceTree = ""; }; F4FC3641278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_CRASH_SIGABRT.html; sourceTree = ""; }; F4FC3642278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_CRASH_SIGKILL.html; sourceTree = ""; }; F4FC3643278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_CRASH_SIGQUIT.html; sourceTree = ""; }; F4FC3644278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = ja.lproj/EXC_CRASH_SIGSEGV.html; sourceTree = ""; }; F4FC3645278F914400669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = ja; path = "ja.lproj/EXC_CRASH_Code Signature Invalid.html"; sourceTree = ""; }; F4FC3646278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIExportAccessoryViewController.xib; sourceTree = ""; }; F4FC3647278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUICrashLogPresentationTextViewController.xib; sourceTree = ""; }; F4FC3648278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUICrashLogPresentationOutlineViewController.xib; sourceTree = ""; }; F4FC3649278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUICollectionViewRegisterItem.xib; sourceTree = ""; }; F4FC364A278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIBinaryImagesViewController.xib; sourceTree = ""; }; F4FC364B278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/CUIMainWindowController.xib; sourceTree = ""; }; F4FC364C278F914500669B32 /* ja */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; F4FC364D278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Predicates.strings; sourceTree = ""; }; F4FC364E278F914500669B32 /* ja */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ja; path = ja.lproj/MainMenu.xib; sourceTree = ""; }; F4FC364F278F914500669B32 /* ja */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = ""; }; F4FC8EA527C1A6EE00291875 /* CUIReportThemedTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIReportThemedTransform.h; sourceTree = ""; }; F4FC8EA627C1A6EE00291875 /* CUIReportThemedTransform.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CUIReportThemedTransform.m; sourceTree = ""; }; F4FE2DE525613B5400C1774A /* CUIKeyViews.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CUIKeyViews.h; sourceTree = ""; }; F4FE2DE825615CA800C1774A /* CUICrashLogExceptionInformation+UI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CUICrashLogExceptionInformation+UI.h"; sourceTree = ""; }; F4FE2DE925615CA800C1774A /* CUICrashLogExceptionInformation+UI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CUICrashLogExceptionInformation+UI.m"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ F4CC56FC24A79EDA00150EC4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ D0BD22382F3FC6430052AD8E /* RSCore */ = { isa = PBXGroup; children = ( D0BD22392F3FC6810052AD8E /* NSMenuItem+RSCore.h */, D0BD223A2F3FC6810052AD8E /* NSMenuItem+RSCore.m */, ); name = RSCore; sourceTree = ""; }; F4040A7324F5B9B40072BF65 /* Views */ = { isa = PBXGroup; children = ( F497F0142576E1A100BD1970 /* CUIRoundedRectBezelView.h */, F497F0152576E1A100BD1970 /* CUIRoundedRectBezelView.m */, F420C9B7254F30A100D24249 /* CUIFileDeadDropView.h */, F420C9B8254F30A100D24249 /* CUIFileDeadDropView.m */, F4040A7424F5B9CE0072BF65 /* CUINavigationChevronView.h */, F4040A7524F5B9CE0072BF65 /* CUINavigationChevronView.m */, F4040A7724F5BC230072BF65 /* CUINavigationView.h */, F4040A7824F5BC230072BF65 /* CUINavigationView.m */, F420C9BF254F335000D24249 /* CUIdSYMDropView.h */, F420C9C0254F335000D24249 /* CUIdSYMDropView.m */, ); name = Views; sourceTree = ""; }; F405A96A255015B500AD2F24 /* Demangling */ = { isa = PBXGroup; children = ( F405A96B255015D800AD2F24 /* CUICXXDemangler.h */, F405A96C255015D800AD2F24 /* CUICXXDemangler.mm */, F472CC952550631A003F6338 /* CUISwiftDemangler.h */, F472CC962550631A003F6338 /* CUISwiftDemangler.m */, ); name = Demangling; sourceTree = ""; }; F40B0D7724D3557F00663282 /* Views */ = { isa = PBXGroup; children = ( F46BAF57250162C900991970 /* CUIPreferencesWindow.h */, F46BAF58250162C900991970 /* CUIPreferencesWindow.m */, F40B0D7A24D3558800663282 /* CUIPreferencesTabBox.h */, F40B0D7824D3558700663282 /* CUIPreferencesTabBox.m */, F40B0D7C24D3558800663282 /* CUIPreferencesTabButton.h */, F40B0D7B24D3558800663282 /* CUIPreferencesTabButton.m */, F40B0D7D24D3558800663282 /* CUIPreferencesTabHeaderView.h */, F40B0D7924D3558800663282 /* CUIPreferencesTabHeaderView.m */, F414068924D6014D0059FF21 /* CUIFontAndColorsFramedView.h */, F414068A24D6014D0059FF21 /* CUIFontAndColorsFramedView.m */, F4BC576F24DF426200063545 /* CUIAATextFieldCell.h */, F4BC577024DF426200063545 /* CUIAATextFieldCell.m */, F40ED76524E72A6E00557BB8 /* CUICategoriesClipView.h */, F40ED76624E72A6E00557BB8 /* CUICategoriesClipView.m */, F4EBD24924E01556007F0252 /* CUITableCustomSelectionColorRowView.h */, F4EBD24A24E01556007F0252 /* CUITableCustomSelectionColorRowView.m */, F4775477255B0054006BA662 /* CUIThemesTableView.h */, F4775478255B0054006BA662 /* CUIThemesTableView.m */, F4E91ADB256A98050017C3EE /* CUIFontBoxView.h */, F4E91ADC256A98050017C3EE /* CUIFontBoxView.m */, ); name = Views; sourceTree = ""; }; F40B0D8124D3568000663282 /* Foundation + Extensions */ = { isa = PBXGroup; children = ( F4ED18A224EC77A300ED7EF2 /* NSArray+UniqueName.h */, F4ED18A124EC77A300ED7EF2 /* NSArray+UniqueName.m */, F40B0D8C24D356A200663282 /* NSArray+WBExtensions.h */, F40B0D8924D356A200663282 /* NSArray+WBExtensions.m */, F40BEAFA24E9FEF8007A3F60 /* NSDictionary+WBExtensions.h */, F40BEAFB24E9FEF8007A3F60 /* NSDictionary+WBExtensions.m */, F40B0D9B24D370A200663282 /* NSDictionary+MutableDeepCopy.h */, F40B0D9C24D370A200663282 /* NSDictionary+MutableDeepCopy.m */, F40B0D8A24D356A200663282 /* NSIndexSet+Analysis.h */, F40B0D8B24D356A200663282 /* NSIndexSet+Analysis.m */, F45F2F592538EF3F0030A402 /* NSFileManager+ExtendedAttributes.h */, F45F2F5A2538EF3F0030A402 /* NSFileManager+ExtendedAttributes.m */, F464FA1325D2DA2A00E024A3 /* NSSet+WBExtensions.h */, F464FA1425D2DA2A00E024A3 /* NSSet+WBExtensions.m */, F4FA4321273EF2F30068EDB8 /* NSString+CPU.h */, F4FA4322273EF2F30068EDB8 /* NSString+CPU.m */, ); name = "Foundation + Extensions"; sourceTree = ""; }; F40B0D8224D3568A00663282 /* AppKit + Extensions */ = { isa = PBXGroup; children = ( F40B0D8324D3569800663282 /* NSColor+LabelColor.h */, F40B0D8424D3569800663282 /* NSColor+LabelColor.m */, F40B0D9624D3572E00663282 /* NSColor+String.h */, F40B0D9524D3572E00663282 /* NSColor+String.m */, F40B0D8624D3569800663282 /* NSResponder+Appearance.h */, F40B0D8524D3569800663282 /* NSResponder+Appearance.m */, F40B0D9324D3571B00663282 /* NSTableView+Selection.h */, F40B0D9224D3571A00663282 /* NSTableView+Selection.m */, F40B0D8F24D356F900663282 /* NSToolbar+Packages.h */, F40B0D9024D356F900663282 /* NSToolbar+Packages.m */, ); name = "AppKit + Extensions"; sourceTree = ""; }; F40B77DB24AF163F001A8131 /* Views */ = { isa = PBXGroup; children = ( F45442A724AF355700EE79E4 /* CUICaptionView.h */, F45442A824AF355700EE79E4 /* CUICaptionView.m */, F4F2A9D124BB809200F912D4 /* CUICrashLogsSourceTableCellView.h */, F4F2A9D224BB809200F912D4 /* CUICrashLogsSourceTableCellView.m */, ); name = Views; sourceTree = ""; }; F423818E267D3511003837AC /* RemoteVersionChecker */ = { isa = PBXGroup; children = ( F423818F267D3521003837AC /* WBRemoteVersionChecker.h */, F4238190267D3522003837AC /* WBRemoteVersionChecker.m */, F4D6C56A2680028200B78B3D /* Resources */, ); name = RemoteVersionChecker; sourceTree = ""; }; F423D8CA2673F5F200E2D31D /* Panels */ = { isa = PBXGroup; children = ( F419376D2672B2BE00B796EB /* CUICrashLogsOpenErrorPanel.h */, F419376E2672B2BE00B796EB /* CUICrashLogsOpenErrorPanel.m */, F4A9967B2675078A0001B40E /* CUICrashLogsOpenErrorWindowController.xib */, ); name = Panels; sourceTree = ""; }; F428C0402724591300FB8CAC /* ips model */ = { isa = PBXGroup; children = ( F428C0652724592C00FB8CAC /* IPSApplicationSpecificInformation.h */, F428C04B2724592A00FB8CAC /* IPSApplicationSpecificInformation.m */, F428C0672724592C00FB8CAC /* IPSBundleInfo.h */, F428C0532724592A00FB8CAC /* IPSBundleInfo.m */, F428C05C2724592B00FB8CAC /* IPSDateFormatter.h */, F428C04A2724592A00FB8CAC /* IPSDateFormatter.m */, F428C04F2724592A00FB8CAC /* IPSError.h */, F428C05B2724592B00FB8CAC /* IPSError.m */, F428C06F2724592D00FB8CAC /* IPSException.h */, F428C0542724592A00FB8CAC /* IPSException.m */, F4BD8C682DF4DDCA00BD61A8 /* IPSExceptionReason.h */, F4BD8C692DF4DDCA00BD61A8 /* IPSExceptionReason.m */, F428C0642724592C00FB8CAC /* IPSExternalModificationStatistics.h */, F428C0502724592A00FB8CAC /* IPSExternalModificationStatistics.m */, F428C05A2724592B00FB8CAC /* IPSExternalModificationSummary.h */, F428C04E2724592A00FB8CAC /* IPSExternalModificationSummary.m */, F428C0632724592B00FB8CAC /* IPSImage.h */, F428C0412724592900FB8CAC /* IPSImage.m */, F428C0482724592900FB8CAC /* IPSIncident.h */, F428C06A2724592C00FB8CAC /* IPSIncident.m */, F428C06B2724592C00FB8CAC /* IPSIncidentDiagnosticMessage.h */, F428C0442724592900FB8CAC /* IPSIncidentDiagnosticMessage.m */, F428C0582724592B00FB8CAC /* IPSIncidentExceptionInformation.h */, F428C0432724592900FB8CAC /* IPSIncidentExceptionInformation.m */, F428C06D2724592C00FB8CAC /* IPSIncidentHeader.h */, F428C0422724592900FB8CAC /* IPSIncidentHeader.m */, F428C0662724592C00FB8CAC /* IPSLegacyInfo.h */, F428C0682724592C00FB8CAC /* IPSLegacyInfo.m */, F428C0552724592A00FB8CAC /* IPSObjectProtocol.h */, F428C06E2724592D00FB8CAC /* IPSOperatingSystemVersion.h */, F428C05E2724592B00FB8CAC /* IPSOperatingSystemVersion.m */, F428C06C2724592C00FB8CAC /* IPSRegisterState.h */, F428C0492724592900FB8CAC /* IPSRegisterState.m */, F428C0512724592A00FB8CAC /* IPSReport.h */, F428C0452724592900FB8CAC /* IPSReport.m */, F428C0562724592A00FB8CAC /* IPSSummary.h */, F428C04C2724592A00FB8CAC /* IPSSummary.m */, F4440FDF282C4103003C810B /* IPSCrashSummary.h */, F4440FDD282C4103003C810B /* IPSCrashSummary.m */, F4440FDE282C4103003C810B /* IPSSummarySerialization.h */, F4440FDC282C4103003C810B /* IPSSummarySerialization.m */, F428C0522724592A00FB8CAC /* IPSTermination.h */, F428C04D2724592A00FB8CAC /* IPSTermination.m */, F428C0692724592C00FB8CAC /* IPSThread.h */, F428C0572724592A00FB8CAC /* IPSThread.m */, F428C05D2724592B00FB8CAC /* IPSThreadFrame.h */, F428C0592724592B00FB8CAC /* IPSThreadFrame.m */, F428C05F2724592B00FB8CAC /* IPSThreadInstructionState.h */, F428C0462724592900FB8CAC /* IPSThreadInstructionState.m */, F428C0602724592B00FB8CAC /* IPSThreadInstructionStream.h */, F428C0472724592900FB8CAC /* IPSThreadInstructionStream.m */, F428C0612724592B00FB8CAC /* IPSThreadState.h */, F428C0622724592B00FB8CAC /* IPSThreadState.m */, ); name = "ips model"; sourceTree = ""; }; F428C08727245BBF00FB8CAC /* ips model + Extensions */ = { isa = PBXGroup; children = ( F4DAF0B127C44AA700256EA4 /* IPSImage+Offset.h */, F4DAF0B227C44AA700256EA4 /* IPSImage+Offset.m */, F4D14D672745C0A9003698AD /* IPSImage+UserCode.h */, F4D14D662745C0A9003698AD /* IPSImage+UserCode.m */, F4CF6CF52DF6111B0078458E /* IPSIncident+ApplicationSpecificInformation.h */, F4CF6CF42DF6111B0078458E /* IPSIncident+ApplicationSpecificInformation.m */, F4D0EE94273DB8CC00CC9737 /* IPSThreadState+RegisterDisplayName.h */, F4D0EE93273DB8CC00CC9737 /* IPSThreadState+RegisterDisplayName.m */, ); name = "ips model + Extensions"; sourceTree = ""; }; F4341C68258EB8B8001A5605 /* CrashReporterPreferences */ = { isa = PBXGroup; children = ( F4341C69258EB8FE001A5605 /* CUICrashReporterDefaults.h */, F4341C6A258EB8FE001A5605 /* CUICrashReporterDefaults.m */, ); name = CrashReporterPreferences; sourceTree = ""; }; F43D8FF224A7FA97008147F9 /* UI */ = { isa = PBXGroup; children = ( F423D8CA2673F5F200E2D31D /* Panels */, F4040A7324F5B9B40072BF65 /* Views */, F46198E724CA390700FA9717 /* CUICrashLogBacktraces+Utilities.h */, F46198E824CA390700FA9717 /* CUICrashLogBacktraces+Utilities.m */, F416687124B0AF4D00C2AB89 /* CUICenteredLabelViewController.h */, F416687224B0AF4D00C2AB89 /* CUICenteredLabelViewController.m */, F4CE83DD2554B97300A8BD87 /* CUICenteredLabelViewController.xib */, F4B74C1624B233C900CD1E60 /* CUIRightViewController.h */, F4B74C1724B233C900CD1E60 /* CUIRightViewController.m */, F4B74C1824B233C900CD1E60 /* CUIRightViewController.xib */, F42B57E024ABEF6E00F77ED5 /* CUICallsSelection.h */, F42B57E124ABEF6E00F77ED5 /* CUICallsSelection.m */, F44356FD24A8A8B5001D3D35 /* CUIThreadNamedTableCellView.h */, F44356FE24A8A8B5001D3D35 /* CUIThreadNamedTableCellView.m */, F4F1C31624F950FC00D1A7A0 /* Exception Info Controller */, F416688024B0BBFC00C2AB89 /* CUICrashLogPresentationViewController.h */, F416688124B0BBFC00C2AB89 /* CUICrashLogPresentationViewController.m */, F4E1C10E24C22CA0000F5C0F /* Presentation Text */, F4E1C10F24C22CB1000F5C0F /* Presentation Outline */, F4545C38256C1ADB00F62A39 /* Registers Palette */, F48BAB3425D9D4140005F3E5 /* CUIThreadImageCell.h */, F48BAB3525D9D4140005F3E5 /* CUIThreadImageCell.m */, D0790DBB2E00BACF00CD6A72 /* CUIThreadImageView.h */, D0790DBC2E00BACF00CD6A72 /* CUIThreadImageView.m */, F48906AC25D2BA0C002D79A9 /* CUISelectedWhiteTextFieldCell.h */, F48906AD25D2BA0C002D79A9 /* CUISelectedWhiteTextFieldCell.m */, F442FCEA24AB855C00E87B69 /* CUIBinaryImagesViewController.h */, F442FCEB24AB855C00E87B69 /* CUIBinaryImagesViewController.m */, F45A2D6B25EC602B0007D50E /* CUIBinaryImagesViewController.xib */, F416687624B0BA5000C2AB89 /* CUICrashLogContentsViewController.h */, F416687724B0BA5000C2AB89 /* CUICrashLogContentsViewController.m */, F416687824B0BA5000C2AB89 /* CUICrashLogContentsViewController.xib */, F4F8D26624F29624007661D6 /* CUIPresentationTextNavigationViewController.h */, F4F8D26724F29624007661D6 /* CUIPresentationTextNavigationViewController.m */, F4F8D26824F29624007661D6 /* CUIPresentationTextNavigationViewController.xib */, F416686C24B0AEE800C2AB89 /* CUIContentsViewController.h */, F416686D24B0AEE800C2AB89 /* CUIContentsViewController.m */, F416686E24B0AEE800C2AB89 /* CUIContentsViewController.xib */, F416688324B0BF2000C2AB89 /* CUISidebarViewController.h */, F416688424B0BF2000C2AB89 /* CUISidebarViewController.m */, F416688524B0BF2000C2AB89 /* CUISidebarViewController.xib */, F464F20924ACF9CF007A3A96 /* CUICrashLogsMainViewController.h */, F464F20A24ACF9CF007A3A96 /* CUICrashLogsMainViewController.m */, F464F20B24ACF9CF007A3A96 /* CUICrashLogsMainViewController.xib */, F4EFE75024BA48F500DB97AC /* CUIMainWindow.h */, F4EFE75124BA48F500DB97AC /* CUIMainWindow.m */, F4FE2DE525613B5400C1774A /* CUIKeyViews.h */, F43D8FF424A7FAD2008147F9 /* CUIMainWindowController.h */, F43D8FF524A7FAD2008147F9 /* CUIMainWindowController.m */, F4055C8325EEE37400DC6CCA /* CUIMainWindowController.xib */, ); name = UI; sourceTree = ""; }; F43D8FF324A7FA9F008147F9 /* Model */ = { isa = PBXGroup; children = ( F405A96E25501A5F00AD2F24 /* CUIParsingErrors.h */, F405A96F25501A5F00AD2F24 /* CUIParsingErrors.m */, F4651F8424B297420090DF10 /* CUIOperatingSystemVersion.h */, F4651F8524B297420090DF10 /* CUIOperatingSystemVersion.m */, F4C269CE2503BE6500C8F3B3 /* CUISymbolicationData.h */, F4C269CF2503BE6500C8F3B3 /* CUISymbolicationData.m */, F49A6D7F25476F7B00466D15 /* CUISymbolicationDataFormatter.h */, F49A6D8025476F7B00466D15 /* CUISymbolicationDataFormatter.m */, F4871E0B25437A6A00580562 /* CUISymbolicationDataCache.h */, F4871E0C25437A6A00580562 /* CUISymbolicationDataCache.m */, F4C269CB2503BCC100C8F3B3 /* CUISymbolicationManager.h */, F4C269CC2503BCC100C8F3B3 /* CUISymbolicationManager.m */, F45B518A24AFA04000E97B87 /* CUICrashLogsSelection.h */, F45B518B24AFA04000E97B87 /* CUICrashLogsSelection.m */, F4559F3524AF232800B8EF41 /* CUICrashLogHeader.h */, F4559F3624AF232800B8EF41 /* CUICrashLogHeader.m */, F469AB2324B3DDEA0053C824 /* CUICrashLogExceptionInformation.h */, F469AB2424B3DDEA0053C824 /* CUICrashLogExceptionInformation.m */, F4FE2DE825615CA800C1774A /* CUICrashLogExceptionInformation+UI.h */, F4FE2DE925615CA800C1774A /* CUICrashLogExceptionInformation+UI.m */, F414D08C24BFB57700A7095C /* CUICrashLogDianosticMessages.h */, F414D08D24BFB57700A7095C /* CUICrashLogDianosticMessages.m */, F414D08F24BFBC3A00A7095C /* CUICrashLogBacktraces.h */, F414D09024BFBC3A00A7095C /* CUICrashLogBacktraces.m */, F414D09224BFBC4A00A7095C /* CUICrashLogThreadState.h */, F414D09324BFBC4A00A7095C /* CUICrashLogThreadState.m */, F4306D572577E168007E667F /* CUICrashLogThreadState+UI.h */, F4306D582577E168007E667F /* CUICrashLogThreadState+UI.m */, F414D09524BFBC6300A7095C /* CUICrashLogBinaryImages.h */, F414D09624BFBC6300A7095C /* CUICrashLogBinaryImages.m */, F464F20E24ACFBA1007A3A96 /* CUIRegister.h */, F464F20F24ACFBA1007A3A96 /* CUIRegister.m */, F4BBAC5B24AA7D37000511BE /* CUIBinaryImage.h */, F4BBAC5C24AA7D37000511BE /* CUIBinaryImage.m */, F4ED75882501A29700316E73 /* CUIStackFrame.h */, F4ED75892501A29700316E73 /* CUIStackFrame.m */, F4CC573124A7ABAF00150EC4 /* CUICallStackBacktrace.h */, F4CC573224A7ABAF00150EC4 /* CUICallStackBacktrace.m */, F49227C624A8D45000772411 /* CUIStackFrame+UI.h */, F49227C724A8D45000772411 /* CUIStackFrame+UI.m */, F4CC572E24A7A95A00150EC4 /* CUIThread.h */, F4CC572F24A7A95A00150EC4 /* CUIThread.m */, F4BD69FE25553E8F00F98F3E /* CUICrashLogSectionsDetector.h */, F4BD69FF25553E9000F98F3E /* CUICrashLogSectionsDetector.m */, F4E861B8255496310061E203 /* CUIRawCrashLog.h */, F4E861B9255496310061E203 /* CUIRawCrashLog.m */, F4A769682555D9DD00F9D9D3 /* CUIRawCrashLog+UI.h */, F4A769692555D9DD00F9D9D3 /* CUIRawCrashLog+UI.m */, F43362FC25FCEFBA006E7894 /* CUIRawCrashLog+Path.h */, F43362FD25FCEFBA006E7894 /* CUIRawCrashLog+Path.m */, F497303B25F7A121001D01FE /* CUICodeType.h */, F4CC572524A7A2B200150EC4 /* CUICrashLog.h */, F4CC572624A7A2B200150EC4 /* CUICrashLog.m */, F4EBADB224A8F04F00DF4271 /* CUICrashLog+UI.h */, F4EBADB324A8F04F00DF4271 /* CUICrashLog+UI.m */, F4CC572B24A7A5F000150EC4 /* CUICrashLog+Transform.h */, F4CC572C24A7A5F000150EC4 /* CUICrashLog+Transform.m */, F4CC572224A7A1D100150EC4 /* CUICrashLogsProvider.h */, F4CC572324A7A1D100150EC4 /* CUICrashLogsProvider.m */, F47F7666267355EA00A74905 /* CUICrashLogErrors.h */, F47F7667267355EA00A74905 /* CUICrashLogErrors.m */, F47F76632673548600A74905 /* CUICrashLogsOpenErrorRecord.h */, F47F76642673548600A74905 /* CUICrashLogsOpenErrorRecord.m */, F47F76602673542600A74905 /* CUICrashLogsOpenErrorRecord+UI.h */, F47F76612673542600A74905 /* CUICrashLogsOpenErrorRecord+UI.m */, F4386B0E2849541B00B83525 /* CUICrashLogExceptionInformation+QuickHelp.h */, F4386B0D2849541B00B83525 /* CUICrashLogExceptionInformation+QuickHelp.m */, ); name = Model; sourceTree = ""; }; F44A5F3824CCE28F006B59B8 /* Views */ = { isa = PBXGroup; children = ( F4E1C12124C22FEE000F5C0F /* CUILightTableVisibleInterGapView.h */, F4E1C12224C22FEE000F5C0F /* CUILightTableVisibleInterGapView.m */, F44A5F3C24CCE2D6006B59B8 /* CUILightTableThreadView.h */, F44A5F3D24CCE2D6006B59B8 /* CUILightTableThreadView.m */, F4E1C11E24C22FB5000F5C0F /* CUILightTableVisibleThreadView.h */, F4E1C11F24C22FB5000F5C0F /* CUILightTableVisibleThreadView.m */, F44A5F3924CCE2B6006B59B8 /* CUILightTableDockedThreadView.h */, F44A5F3A24CCE2B6006B59B8 /* CUILightTableDockedThreadView.m */, ); name = Views; sourceTree = ""; }; F44E7B7A255C831B00025C04 /* Noodle */ = { isa = PBXGroup; children = ( F44E7B7B255C83D500025C04 /* NoodleLineNumberMarker.h */, F44E7B7D255C83D500025C04 /* NoodleLineNumberMarker.m */, F44E7B7E255C83D500025C04 /* NoodleLineNumberView.h */, F44E7B7C255C83D500025C04 /* NoodleLineNumberView.m */, ); name = Noodle; sourceTree = ""; }; F4545C38256C1ADB00F62A39 /* Registers Palette */ = { isa = PBXGroup; children = ( F4D5C77D2571AF980029B051 /* Views */, F4627F0F25704557007E5CD0 /* CUICollectionViewRegisterItem.h */, F4627F1025704557007E5CD0 /* CUICollectionViewRegisterItem.m */, F46D77AD25ED9EAE00039663 /* CUICollectionViewRegisterItem.xib */, F4F892FF2575A77000BE4CE0 /* Controllers */, ); name = "Registers Palette"; sourceTree = ""; }; F45F84D4266ABB5800F354F3 /* Products */ = { isa = PBXGroup; children = ( F45F84D8266ABB5800F354F3 /* crashreport.qlgenerator */, ); name = Products; sourceTree = ""; }; F46198EA24CA41E900FA9717 /* Inspector */ = { isa = PBXGroup; children = ( F46198EB24CA457E00FA9717 /* Views */, F493DB1924F1C19F001AA8C0 /* Controllers */, F41ECA5024AB689B00CE56C7 /* CUIInspectorViewController.h */, F41ECA5124AB689B00CE56C7 /* CUIInspectorViewController.m */, F41ECA5224AB689B00CE56C7 /* CUIInspectorViewController.xib */, ); name = Inspector; sourceTree = ""; }; F46198EB24CA457E00FA9717 /* Views */ = { isa = PBXGroup; children = ( F4E671902E2C3B1600E5A064 /* CUICodeSigningFlagsTableView.h */, F4E671912E2C3B1600E5A064 /* CUICodeSigningFlagsTableView.m */, F46198EC24CA459700FA9717 /* CUIInspectorAlternateBackgroundView.h */, F46198ED24CA459700FA9717 /* CUIInspectorAlternateBackgroundView.m */, ); name = Views; sourceTree = ""; }; F480692924AF7D4E009665F2 /* Logs */ = { isa = PBXGroup; children = ( F4EAFA2924FA538F00C0B729 /* Views */, F480692A24AF7D5A009665F2 /* Controllers */, ); name = Logs; sourceTree = ""; }; F480692A24AF7D5A009665F2 /* Controllers */ = { isa = PBXGroup; children = ( F480692B24AF7D83009665F2 /* CUICrashLogsListViewController.h */, F480692C24AF7D83009665F2 /* CUICrashLogsListViewController.m */, F45A2D7325EC60D90007D50E /* CUICrashLogsListViewController.xib */, ); name = Controllers; sourceTree = ""; }; F4871DF125435AE500580562 /* DWARF */ = { isa = PBXGroup; children = ( F4871DFC25435AF300580562 /* DWRFEnums.h */, F4871DF625435AF300580562 /* LEB128.h */, F4871DFE25435AF400580562 /* LEB128.c */, F4871E0025435AF400580562 /* DWRFObject.h */, F4871E0125435AF400580562 /* DWRFObject.m */, F4871DF425435AF300580562 /* DWRFFileObject.h */, F4871DFB25435AF300580562 /* DWRFFileObject.m */, F4871DFF25435AF400580562 /* DWRFSection_debug_abbrev.h */, F4871DF925435AF300580562 /* DWRFSection_debug_abbrev.m */, F4871DFD25435AF300580562 /* DWRFSection_debug_aranges.h */, F4871E0225435AF400580562 /* DWRFSection_debug_aranges.m */, F4871DF825435AF300580562 /* DWRFSection_debug_info.h */, F4871DF225435AF300580562 /* DWRFSection_debug_info.m */, F4871DF525435AF300580562 /* DWRFSection_debug_line.h */, F4871DF725435AF300580562 /* DWRFSection_debug_line.m */, F4871DFA25435AF300580562 /* DWRFSection_debug_str.h */, F4871DF325435AF300580562 /* DWRFSection_debug_str.m */, F4F5821A256FC7B90032FC53 /* DWRFSection_debug_str_offsets.h */, F4F5821B256FC7B90032FC53 /* DWRFSection_debug_str_offsets.m */, F43AF0CF256FE2AE0066CA1B /* DWRFSection_debug_addr.h */, F43AF0D0256FE2AE0066CA1B /* DWRFSection_debug_addr.m */, ); name = DWARF; sourceTree = ""; }; F493DB1924F1C19F001AA8C0 /* Controllers */ = { isa = PBXGroup; children = ( F4B649D524EDD09A00008C47 /* CUIInspectorStackableViewController.h */, F4B649D624EDD09A00008C47 /* CUIInspectorStackableViewController.m */, F4F9BAF424EF06BC00D08FBD /* CUIInspectorGeneralViewController.h */, F4F9BAF524EF06BC00D08FBD /* CUIInspectorGeneralViewController.m */, F46D779D25ED8D1800039663 /* CUIInspectorGeneralViewController.xib */, F4F9BAEF24EF060E00D08FBD /* CUIInspectorUserViewController.h */, F4F9BAF024EF060E00D08FBD /* CUIInspectorUserViewController.m */, F46D77A125ED8D3600039663 /* CUIInspectorUserViewController.xib */, F4B649D024EDCD2300008C47 /* CUIInspectorExecutableViewController.h */, F4B649D124EDCD2300008C47 /* CUIInspectorExecutableViewController.m */, F46D77A525ED8D5700039663 /* CUIInspectorExecutableViewController.xib */, D06294352E1DD8150008895D /* CUICodeSigningInformationViewController.h */, D06294362E1DD8150008895D /* CUICodeSigningInformationViewController.m */, F4E671942E2C405F00E5A064 /* CodeSigningFlags.plist */, F45DED6B2E350F07008F4CE8 /* CUICodeSigningInformationViewController.xib */, F4B649D824EDD64900008C47 /* CUIInspectorProcessesViewController.h */, F4B649D924EDD64900008C47 /* CUIInspectorProcessesViewController.m */, F46D77A925ED8E3B00039663 /* CUIInspectorProcessesViewController.xib */, ); name = Controllers; sourceTree = ""; }; F49673F524D0CF3B00716289 /* Preferences */ = { isa = PBXGroup; children = ( F40B0D7724D3557F00663282 /* Views */, F496740024D0D04400716289 /* Controllers */, F49673FB24D0CF6400716289 /* CUIPreferencesWindowController.h */, F49673FC24D0CF6400716289 /* CUIPreferencesWindowController.m */, F40B124724E89BBE005E82DD /* CUIPreferencesWindowController+Convenience.h */, F40B124824E89BBE005E82DD /* CUIPreferencesWindowController+Convenience.m */, F45A2D5F25EC5CA00007D50E /* CUIPreferencesWindowController.xib */, ); name = Preferences; sourceTree = ""; }; F496740024D0D04400716289 /* Controllers */ = { isa = PBXGroup; children = ( F496740124D0D05800716289 /* CUIPreferencePaneViewController.h */, F496740224D0D05800716289 /* CUIPreferencePaneViewController.m */, F4F5395624D21DB800D537BC /* CUIPreferencePaneGeneralViewController.h */, F4F5395724D21DB800D537BC /* CUIPreferencePaneGeneralViewController.m */, F4A3A6E525ED81260018053E /* CUIPreferencePaneGeneralViewController.xib */, F43C828524D892620096F27B /* CUIPreferencePanePresentationTextViewController.h */, F43C828624D892620096F27B /* CUIPreferencePanePresentationTextViewController.m */, F495AEBE25F029C2000D92E1 /* CUIPreferencePanePresentationTextViewController.xib */, F4577BE72592848D009B2AD2 /* CUIPreferencePanePresentationOutlineViewController.h */, F4577BE82592848D009B2AD2 /* CUIPreferencePanePresentationOutlineViewController.m */, F495AEC225F02F74000D92E1 /* CUIPreferencePanePresentationOutlineViewController.xib */, F41D66AD25921F3400C0D491 /* CUIPreferencePanePresentationViewController.h */, F41D66AE25921F3400C0D491 /* CUIPreferencePanePresentationViewController.m */, F4301A6A25EF0DE000ACDA3F /* CUIPreferencePanePresentationViewController.xib */, F496740724D0D2A300716289 /* CUIPreferencePaneFontscolorsViewController.h */, F496740824D0D2A300716289 /* CUIPreferencePaneFontscolorsViewController.m */, F45A2D6325EC5D130007D50E /* CUIPreferencePaneFontscolorsViewController.xib */, F489441F2545836F00E3E360 /* CUISymbolsFilesLibraryViewController.h */, F48944202545836F00E3E360 /* CUISymbolsFilesLibraryViewController.m */, F4D7F15D25F04A620024E9A5 /* CUISymbolsFilesLibraryViewController.xib */, F4CD32B3257D17B3008C71AA /* CUIPreferencePaneSymbolicationViewController.h */, F4CD32B4257D17B3008C71AA /* CUIPreferencePaneSymbolicationViewController.m */, F4D7F16125F04A9D0024E9A5 /* CUIPreferencePaneSymbolicationViewController.xib */, F4B67835258F702E0047369E /* CUIPreferencePaneCrashreporterViewController.h */, F4B67836258F702E0047369E /* CUIPreferencePaneCrashreporterViewController.m */, F4A3A6E925ED817E0018053E /* CUIPreferencePaneCrashreporterViewController.xib */, F4238189267D1D4A003837AC /* CUIPreferencePaneAdvancedViewController.h */, F423818A267D1D4A003837AC /* CUIPreferencePaneAdvancedViewController.m */, F406B49B2687AB1400B90C7B /* CUIPreferencePaneAdvancedViewController.xib */, ); name = Controllers; sourceTree = ""; }; F497AD5224B8FE51008517B7 /* Panel */ = { isa = PBXGroup; children = ( F497AD5324B8FE88008517B7 /* CUICrashLogsSourceSmartEditorPanel.h */, F497AD5424B8FE88008517B7 /* CUICrashLogsSourceSmartEditorPanel.m */, F4A3A6E125ED7F450018053E /* CUICrashLogsSourceSmartEditorWindowController.xib */, ); name = Panel; sourceTree = ""; }; F4A0BEE0261BC38800BADEED /* clock */ = { isa = PBXGroup; children = ( F4B018362620FEC7009727F1 /* CUIApplicationIconView.h */, F4B018352620FEC7009727F1 /* CUIApplicationIconView.m */, F4A0BEEC261BC39700BADEED /* CUIWatchAxis.h */, F4A0BEE6261BC39600BADEED /* CUIWatchAxis.m */, F4A0BEEE261BC39700BADEED /* CUIWatchBridge.h */, F4A0BEED261BC39700BADEED /* CUIWatchBridge.m */, F4A0BEE9261BC39700BADEED /* CUIWatchDrawablePart.h */, F4A0BEE4261BC39600BADEED /* CUIWatchGear.h */, F4A0BEE2261BC39600BADEED /* CUIWatchGear.m */, F4A0BEF0261BC39700BADEED /* CUIWatchJewel.h */, F4A0BEE3261BC39600BADEED /* CUIWatchJewel.m */, F4A0BEE8261BC39600BADEED /* CUIWatchPart.h */, F4A0BEEB261BC39700BADEED /* CUIWatchPart.m */, F4A0BEE1261BC39600BADEED /* CUIWatchScrew.h */, F4A0BEEF261BC39700BADEED /* CUIWatchScrew.m */, F4B018342620FEBB009727F1 /* Resources */, ); name = clock; sourceTree = ""; }; F4A43E80257ECE81005D076C /* Resources */ = { isa = PBXGroup; children = ( F45854F925C76591007A3A79 /* Unexpectedly_Acknowledgements.pdf */, F45854F825C76590007A3A79 /* Unexpectedly_License.pdf */, F45A2D6725EC5F850007D50E /* CUIAboutBoxWindowController.xib */, ); name = Resources; sourceTree = ""; }; F4A43E81257ECE8A005D076C /* Views */ = { isa = PBXGroup; children = ( F4E0BD23262078220048647C /* CUIAboutBoxWindow.h */, F4E0BD24262078220048647C /* CUIAboutBoxWindow.m */, F476EEC025686EC000F40F87 /* CUIContentBox.h */, F476EEBF25686EC000F40F87 /* CUIContentBox.m */, F476EEBC25686DEF00F40F87 /* CUIAboutBoxFooterView.h */, F476EEBD25686DEF00F40F87 /* CUIAboutBoxFooterView.m */, ); name = Views; sourceTree = ""; }; F4AA22B32561A206001A1315 /* About Box */ = { isa = PBXGroup; children = ( F4A0BEE0261BC38800BADEED /* clock */, F4A43E81257ECE8A005D076C /* Views */, F4AA22B42561A233001A1315 /* CUIAboutBoxWindowController.h */, F4AA22B52561A233001A1315 /* CUIAboutBoxWindowController.m */, F4A43E80257ECE81005D076C /* Resources */, ); name = "About Box"; sourceTree = ""; }; F4B018342620FEBB009727F1 /* Resources */ = { isa = PBXGroup; children = ( F4A0BEE5261BC39600BADEED /* brushed-alum.png */, ); name = Resources; sourceTree = ""; }; F4B138542522945E00D9DE2F /* dSYM */ = { isa = PBXGroup; children = ( F4B138552522948700D9DE2F /* NSBundle+dSYM.h */, F4B138562522948700D9DE2F /* NSBundle+dSYM.m */, F4871DBE2543566E00580562 /* CUIdSYMBundle.h */, F4871DBF2543566E00580562 /* CUIdSYMBundle.m */, F4B52E1F2548B8B4007593FD /* CUIdSYMBundle+UI.h */, F4B52E202548B8B4007593FD /* CUIdSYMBundle+UI.m */, F4871E0E254384E100580562 /* CUIdSYMBundlesManager.h */, F4871E0F254384E100580562 /* CUIdSYMBundlesManager.m */, F420C9C2254F5F4C00D24249 /* CUIdSYMHunter.h */, F420C9C3254F5F4C00D24249 /* CUIdSYMHunter.m */, ); name = dSYM; sourceTree = ""; }; F4B9AD23253199EE0083FA6C /* Mach-o */ = { isa = PBXGroup; children = ( F4B9AD2A25319A400083FA6C /* MCHMemoryBufferWrapper.h */, F4B9AD2425319A400083FA6C /* MCHMemoryBufferWrapper.m */, F4B9AD2725319A400083FA6C /* MCHMachBinary.h */, F4B9AD3025319A410083FA6C /* MCHMachBinary.m */, F4B9AD2525319A400083FA6C /* MCHObjectFile.h */, F4B9AD2825319A400083FA6C /* MCHObjectFile.m */, F4B9AD2925319A400083FA6C /* MCHLoadCommand.h */, F4B9AD2D25319A410083FA6C /* MCHLoadCommand.m */, F4B9AD2F25319A410083FA6C /* MCHUUIDLoadCommand.h */, F4B9AD2B25319A400083FA6C /* MCHUUIDLoadCommand.m */, F4B9AD3A25319D7C0083FA6C /* MCHSegmentLoadCommand.h */, F4B9AD3925319D7B0083FA6C /* MCHSegmentLoadCommand.m */, F4B9AD3125319A410083FA6C /* MCHSection.h */, F4B9AD2E25319A410083FA6C /* MCHSection.m */, F4B9AD2C25319A410083FA6C /* MCHSegment.h */, F4B9AD2625319A400083FA6C /* MCHSegment.m */, ); name = "Mach-o"; sourceTree = ""; }; F4BC576E24DF423C00063545 /* Views */ = { isa = PBXGroup; children = ( F4EAFA2A24FA6CD100C0B729 /* CUICrashLogTextView.h */, F4EAFA2B24FA6CD100C0B729 /* CUICrashLogTextView.m */, F47AF8BE255DE61E0037E2D8 /* NSCrashLogTextScrollView.h */, F47AF8BF255DE61E0037E2D8 /* NSCrashLogTextScrollView.m */, F44E7B7A255C831B00025C04 /* Noodle */, ); name = Views; sourceTree = ""; }; F4CC56F624A79EDA00150EC4 = { isa = PBXGroup; children = ( F45F84D3266ABB5800F354F3 /* crashreport.xcodeproj */, F43BA4E425F2674100D8D68A /* SharedConfigurationSettings.xcconfig */, F43C828D24D8AD850096F27B /* CUIStackFrameComponents.h */, F428C0402724591300FB8CAC /* ips model */, F428C08727245BBF00FB8CAC /* ips model + Extensions */, F4DF813A2893460E008EF1B3 /* ips model + Obfuscating */, F4B9AD23253199EE0083FA6C /* Mach-o */, F405A96A255015B500AD2F24 /* Demangling */, F4871DF125435AE500580562 /* DWARF */, F40B0D8124D3568000663282 /* Foundation + Extensions */, F40B0D8224D3568A00663282 /* AppKit + Extensions */, D0BD22382F3FC6430052AD8E /* RSCore */, F4CC570124A79EDA00150EC4 /* app_unexpectedly */, F4CC570024A79EDA00150EC4 /* Products */, ); sourceTree = ""; }; F4CC570024A79EDA00150EC4 /* Products */ = { isa = PBXGroup; children = ( F4CC56FF24A79EDA00150EC4 /* Unexpectedly.app */, ); name = Products; sourceTree = ""; }; F4CC570124A79EDA00150EC4 /* app_unexpectedly */ = { isa = PBXGroup; children = ( F423818E267D3511003837AC /* RemoteVersionChecker */, F4341C68258EB8B8001A5605 /* CrashReporterPreferences */, F4CDFB50257EE1BC002A73D0 /* Views */, F4B138542522945E00D9DE2F /* dSYM */, F4CC570424A79EDA00150EC4 /* AppDelegate.h */, F4CC570524A79EDA00150EC4 /* AppDelegate.m */, F4AA22B32561A206001A1315 /* About Box */, F40ACE2B255697A3006855E5 /* CUICrashLogBrowsingState.h */, F40ACE2C255697A3006855E5 /* CUICrashLogBrowsingState.m */, F40ACE2E255697CE006855E5 /* CUICrashLogBrowsingStateRegistry.h */, F40ACE2F255697CE006855E5 /* CUICrashLogBrowsingStateRegistry.m */, F43C828A24D8A39B0096F27B /* CUITextModeDisplaySettings.h */, F43C828B24D8A39B0096F27B /* CUITextModeDisplaySettings.m */, F461CE8825F6DD75007CFDE7 /* CUIApplicationItemAttributes.h */, F461CE8925F6DD75007CFDE7 /* CUIApplicationItemAttributes.m */, F497303825F796E6001D01FE /* CUIHopperDisassemblerManager.h */, F497303925F796E6001D01FE /* CUIHopperDisassemblerManager.m */, F483844F24EB041B00FAEF5D /* CUIThemeItemsGroup.h */, F483845024EB041B00FAEF5D /* CUIThemeItemsGroup.m */, F483845724EB26DF00FAEF5D /* CUIThemeItemsGroup+UI.h */, F483845824EB26DF00FAEF5D /* CUIThemeItemsGroup+UI.m */, F40BEAEF24E9F754007A3F60 /* CUIThemeItemAttributes.h */, F40BEAF024E9F754007A3F60 /* CUIThemeItemAttributes.m */, F420F35024E95E5F006C82CD /* CUITheme.h */, F420F35124E95E5F006C82CD /* CUITheme.m */, F49C47C824E9B48B003FC65C /* CUIThemesManager.h */, F49C47C924E9B48B003FC65C /* CUIThemesManager.m */, F442FCEF24AB8A8B00E87B69 /* CUIBinaryImageUtility.h */, F442FCF024AB8A8B00E87B69 /* CUIBinaryImageUtility.m */, F496740C24D0D74A00716289 /* CUIApplicationPreferences.h */, F496740D24D0D74A00716289 /* CUIApplicationPreferences.m */, F483845424EB1BEB00FAEF5D /* CUIApplicationPreferences+Themes.h */, F483845524EB1BEB00FAEF5D /* CUIApplicationPreferences+Themes.m */, F49673F524D0CF3B00716289 /* Preferences */, F43D8FF324A7FA9F008147F9 /* Model */, F4CCCC6624AE83040031BC27 /* Sources */, F480692924AF7D4E009665F2 /* Logs */, F46198EA24CA41E900FA9717 /* Inspector */, F43D8FF224A7FA97008147F9 /* UI */, F4CC570924A79EDA00150EC4 /* Images.xcassets */, F4CC570724A79EDA00150EC4 /* main.m */, F497AD5B24B90481008517B7 /* app_unexpectedly_Prefix.pch */, F4CC570224A79EDA00150EC4 /* Supporting Files */, ); path = app_unexpectedly; sourceTree = ""; }; F4CC570224A79EDA00150EC4 /* Supporting Files */ = { isa = PBXGroup; children = ( F493DB1A24F1CF2F001AA8C0 /* Localizable.strings */, F46D2A2824C33FA200652D50 /* Predicates.strings */, F45DED6D2E3510D9008F4CE8 /* CodeSigning.strings */, F4CC570B24A79EDA00150EC4 /* MainMenu.xib */, F483845224EB11F700FAEF5D /* default_themes.plist */, F4CC570324A79EDA00150EC4 /* Info.plist */, F497303C25F7F74B001D01FE /* InfoPlist.strings */, F42D0BC225514B2E0021A551 /* template.source */, ); name = "Supporting Files"; sourceTree = ""; }; F4CCCC6624AE83040031BC27 /* Sources */ = { isa = PBXGroup; children = ( F497AD5224B8FE51008517B7 /* Panel */, F4CCCC6724AE83130031BC27 /* Model */, F4CCCC6F24AEA09B0031BC27 /* Model + UI */, F40B77DB24AF163F001A8131 /* Views */, F4CCCC6824AE831E0031BC27 /* Controllers */, ); name = Sources; sourceTree = ""; }; F4CCCC6724AE83130031BC27 /* Model */ = { isa = PBXGroup; children = ( F4132C8D24AA19F70086B99C /* CUICrashLogsSource.h */, F4132C8E24AA19F70086B99C /* CUICrashLogsSource.m */, F4F2A9CE24BB7E3600F912D4 /* CUICrashLogsSourceSeparator.h */, F4F2A9CF24BB7E3600F912D4 /* CUICrashLogsSourceSeparator.m */, F440A3EA24AA38E600C23DA1 /* CUICrashLogsSourceAll.h */, F440A3EB24AA38E600C23DA1 /* CUICrashLogsSourceAll.m */, F4CCCC6924AE95430031BC27 /* CUICrashLogsSourceFileSystemItem.h */, F4CCCC6A24AE95430031BC27 /* CUICrashLogsSourceFileSystemItem.m */, F440A3E124AA315800C23DA1 /* CUICrashLogsSourceStandardDirectory.h */, F440A3E224AA315800C23DA1 /* CUICrashLogsSourceStandardDirectory.m */, F440A3E424AA31B500C23DA1 /* CUICrashLogsSourceFile.h */, F440A3E524AA31B500C23DA1 /* CUICrashLogsSourceFile.m */, F440A3E724AA35AC00C23DA1 /* CUICrashLogsSourceDirectory.h */, F440A3E824AA35AC00C23DA1 /* CUICrashLogsSourceDirectory.m */, F462DD2F24ADC5F900044AB1 /* CUICrashLogsSourceSmart.h */, F462DD3024ADC5F900044AB1 /* CUICrashLogsSourceSmart.m */, F4B57C0A24AF5607000851FF /* CUICrashLogsSourceToday.h */, F4B57C0B24AF5607000851FF /* CUICrashLogsSourceToday.m */, F4214CB324B6534400852DDE /* CUICrashLogsSourcesManager.h */, F4214CB424B6534400852DDE /* CUICrashLogsSourcesManager.m */, F4CCCC6324AE810E0031BC27 /* CUICrashLogsSourcesSelection.h */, F4CCCC6424AE810E0031BC27 /* CUICrashLogsSourcesSelection.m */, ); name = Model; sourceTree = ""; }; F4CCCC6824AE831E0031BC27 /* Controllers */ = { isa = PBXGroup; children = ( F4CCCC5E24AE76780031BC27 /* CUICrashLogsSourcesViewController.h */, F4CCCC5F24AE76780031BC27 /* CUICrashLogsSourcesViewController.m */, F45A2D6F25EC60920007D50E /* CUICrashLogsSourcesViewController.xib */, ); name = Controllers; sourceTree = ""; }; F4CCCC6F24AEA09B0031BC27 /* Model + UI */ = { isa = PBXGroup; children = ( F40B77D824AF1426001A8131 /* CUICrashLogsSourceAll+UI.h */, F40B77D924AF1426001A8131 /* CUICrashLogsSourceAll+UI.m */, F4CCCC6C24AE9EDA0031BC27 /* CUICrashLogsSource+UI.h */, F4CCCC6D24AE9EDA0031BC27 /* CUICrashLogsSource+UI.m */, F4B57C0D24AF5655000851FF /* CUICrashLogsSourceToday+UI.h */, F4B57C0E24AF5655000851FF /* CUICrashLogsSourceToday+UI.m */, F40B77D524AF0F5C001A8131 /* CUICrashLogsSourceStandardDirectory+UI.h */, F40B77D624AF0F5C001A8131 /* CUICrashLogsSourceStandardDirectory+UI.m */, ); name = "Model + UI"; sourceTree = ""; }; F4CDFB50257EE1BC002A73D0 /* Views */ = { isa = PBXGroup; children = ( F49A6D7C25474F6E00466D15 /* CUIInactiveButton.h */, F49A6D7D25474F6E00466D15 /* CUIInactiveButton.m */, F475FB3E26DBAC8200A113D8 /* CUITableViewNoSpace.h */, F475FB3F26DBAC8200A113D8 /* CUITableViewNoSpace.m */, ); name = Views; sourceTree = ""; }; F4D5C77D2571AF980029B051 /* Views */ = { isa = PBXGroup; children = ( F4D5C77A2571AF900029B051 /* CUIRegisterLabel.h */, F4D5C77B2571AF900029B051 /* CUIRegisterLabel.m */, ); name = Views; sourceTree = ""; }; F4D6C56A2680028200B78B3D /* Resources */ = { isa = PBXGroup; children = ( F4D6C56B2680028A00B78B3D /* RemoteCheck.strings */, ); name = Resources; sourceTree = ""; }; F4DF813A2893460E008EF1B3 /* ips model + Obfuscating */ = { isa = PBXGroup; children = ( F4DF81412893463B008EF1B3 /* IPSObfuscator.h */, F4DF81462893463C008EF1B3 /* IPSObfuscator.m */, F4DF81512893463D008EF1B3 /* IPSApplicationSpecificInformation+Obfuscating.h */, F4DF81402893463B008EF1B3 /* IPSApplicationSpecificInformation+Obfuscating.m */, F4DF81422893463C008EF1B3 /* IPSBundleInfo+Obfuscating.h */, F4DF81562893463D008EF1B3 /* IPSBundleInfo+Obfuscating.m */, F4DF814E2893463D008EF1B3 /* IPSCrashSummary+Obfuscating.h */, F4DF81472893463C008EF1B3 /* IPSCrashSummary+Obfuscating.m */, F4DF81482893463C008EF1B3 /* IPSImage+Obfuscating.h */, F4DF814F2893463D008EF1B3 /* IPSImage+Obfuscating.m */, F4DF81452893463C008EF1B3 /* IPSIncident+Obfuscating.h */, F4DF81572893463D008EF1B3 /* IPSIncident+Obfuscating.m */, F4DF813B2893463B008EF1B3 /* IPSIncidentDiagnosticMessage+Obfuscating.h */, F4DF813D2893463B008EF1B3 /* IPSIncidentDiagnosticMessage+Obfuscating.m */, F4DF81532893463D008EF1B3 /* IPSIncidentExceptionInformation+Obfuscating.h */, F4DF81552893463D008EF1B3 /* IPSIncidentExceptionInformation+Obfuscating.m */, F4DF814D2893463C008EF1B3 /* IPSIncidentHeader+Obfuscating.h */, F4DF81432893463C008EF1B3 /* IPSIncidentHeader+Obfuscating.m */, F4DF81442893463C008EF1B3 /* IPSLegacyInfo+Obfuscating.h */, F4DF81502893463D008EF1B3 /* IPSLegacyInfo+Obfuscating.m */, F4DF813E2893463B008EF1B3 /* IPSObfuscator+Extended.h */, F4DF81592893463E008EF1B3 /* IPSRegisterState+Obfuscating.h */, F4DF814B2893463C008EF1B3 /* IPSRegisterState+Obfuscating.m */, F4DF814C2893463C008EF1B3 /* IPSReport+Obfuscating.h */, F4DF81522893463D008EF1B3 /* IPSReport+Obfuscating.m */, F4DF81582893463D008EF1B3 /* IPSThread+Obfuscating.h */, F4DF81492893463C008EF1B3 /* IPSThread+Obfuscating.m */, F4DF81542893463D008EF1B3 /* IPSThreadFrame+Obfuscating.h */, F4DF814A2893463C008EF1B3 /* IPSThreadFrame+Obfuscating.m */, F4DF813F2893463B008EF1B3 /* IPSThreadState+Obfuscating.h */, F4DF813C2893463B008EF1B3 /* IPSThreadState+Obfuscating.m */, ); name = "ips model + Obfuscating"; sourceTree = ""; }; F4E1C10E24C22CA0000F5C0F /* Presentation Text */ = { isa = PBXGroup; children = ( F4BC576E24DF423C00063545 /* Views */, F4DAFBEF2736B7D500FB50A6 /* CUIDataTransform.h */, F4DAFBF02736B7D500FB50A6 /* CUIDataTransform.m */, F4FC8EA527C1A6EE00291875 /* CUIReportThemedTransform.h */, F4FC8EA627C1A6EE00291875 /* CUIReportThemedTransform.m */, F42E4FFF2724B7550092181A /* CUICrashDataTransform.h */, F42E50002724B7550092181A /* CUICrashDataTransform.m */, F4DAFBEC2736B7B200FB50A6 /* CUIIPSTransform.h */, F4DAFBED2736B7B200FB50A6 /* CUIIPSTransform.m */, F4F9D3332556C7DB00D28E6E /* CUILineJumperWindowController.h */, F4F9D3342556C7DB00D28E6E /* CUILineJumperWindowController.m */, F4895F5927A72D1000D75369 /* CUILineJumperWindowController.xib */, F4AC86472558A03B004F2637 /* CUIExportAccessoryViewController.h */, F4AC86482558A03B004F2637 /* CUIExportAccessoryViewController.m */, F453AE4B25EE706F00B7BEF0 /* CUIExportAccessoryViewController.xib */, F416687B24B0BBA300C2AB89 /* CUICrashLogPresentationTextViewController.h */, F416687C24B0BBA300C2AB89 /* CUICrashLogPresentationTextViewController.m */, F453AE4F25EE70E800B7BEF0 /* CUICrashLogPresentationTextViewController.xib */, ); name = "Presentation Text"; sourceTree = ""; }; F4E1C10F24C22CB1000F5C0F /* Presentation Outline */ = { isa = PBXGroup; children = ( F49A55DC24C7A7F900D249DE /* CUICallTableCellView.h */, F49A55DD24C7A7F900D249DE /* CUICallTableCellView.m */, F40FC81425EAF7B000DB4B27 /* CUISourceFileTableCellView.h */, F40FC81525EAF7B000DB4B27 /* CUISourceFileTableCellView.m */, F43A9A812591260C005AB2AA /* CUIOutlineModeDisplaySettings.h */, F43A9A822591260C005AB2AA /* CUIOutlineModeDisplaySettings.m */, F44356F024A8A113001D3D35 /* CUICrashLogPresentationOutlineViewController.h */, F44356F124A8A113001D3D35 /* CUICrashLogPresentationOutlineViewController.m */, F4754D7325F5678700B0D48F /* CUICrashLogPresentationOutlineViewController.xib */, F432ACCA24A9502A000A3E7A /* CUIThreadsViewController.h */, F432ACCB24A9502A000A3E7A /* CUIThreadsViewController.m */, F4F5395324D2063100D537BC /* View Mode - List */, F4F5395424D2064600D537BC /* View Mode - Columns */, F4E1C11024C22CD0000F5C0F /* View Mode - Light Table - Not used */, ); name = "Presentation Outline"; sourceTree = ""; }; F4E1C11024C22CD0000F5C0F /* View Mode - Light Table - Not used */ = { isa = PBXGroup; children = ( F44A5F3824CCE28F006B59B8 /* Views */, F44A5F3224CCDD00006B59B8 /* CUICollectionViewThreadItem.h */, F44A5F3324CCDD00006B59B8 /* CUICollectionViewThreadItem.m */, F4E1C11924C22F54000F5C0F /* CUICollectionViewVisibleThreadItem.h */, F4E1C11A24C22F54000F5C0F /* CUICollectionViewVisibleThreadItem.m */, F4E1C11B24C22F54000F5C0F /* CUICollectionViewVisibleThreadItem.xib */, F4E1C11624C22F02000F5C0F /* CUICollectionViewVisibleThreadsLayout.h */, F4E1C11724C22F02000F5C0F /* CUICollectionViewVisibleThreadsLayout.m */, F44A5F2D24CCDCB1006B59B8 /* CUICollectionViewDockedThreadItem.h */, F44A5F2E24CCDCB1006B59B8 /* CUICollectionViewDockedThreadItem.m */, F44A5F2F24CCDCB1006B59B8 /* CUICollectionViewDockedThreadItem.xib */, F44A5F3524CCDFD9006B59B8 /* CUICollectionViewDockedThreadsLayout.h */, F44A5F3624CCDFD9006B59B8 /* CUICollectionViewDockedThreadsLayout.m */, F4E1C11124C22CF5000F5C0F /* CUILightTableViewController.h */, F4E1C11224C22CF5000F5C0F /* CUILightTableViewController.m */, F4E1C11324C22CF5000F5C0F /* CUILightTableViewController.xib */, ); name = "View Mode - Light Table - Not used"; sourceTree = ""; }; F4EAFA2924FA538F00C0B729 /* Views */ = { isa = PBXGroup; children = ( F4EBADB524A8F10000DF4271 /* CUICrashLogTableCellView.h */, F4EBADB624A8F10000DF4271 /* CUICrashLogTableCellView.m */, ); name = Views; sourceTree = ""; }; F4F1C31624F950FC00D1A7A0 /* Exception Info Controller */ = { isa = PBXGroup; children = ( F4C7498B24F84689004F38C0 /* CUIQuickHelpPopUpViewController.h */, F4C7498C24F84689004F38C0 /* CUIQuickHelpPopUpViewController.m */, F4C7498D24F84689004F38C0 /* CUIQuickHelpPopUpViewController.xib */, F4B5BE6C2848277400C33F6F /* CUIExceptionTypePopUpViewController.h */, F4B5BE6D2848277400C33F6F /* CUIExceptionTypePopUpViewController.m */, F4B5BE6F28482A4300C33F6F /* CUITerminationReasonPopUpViewController.h */, F4B5BE7028482A4300C33F6F /* CUITerminationReasonPopUpViewController.m */, F4F1C31724F9510E00D1A7A0 /* Resources */, ); name = "Exception Info Controller"; sourceTree = ""; }; F4F1C31724F9510E00D1A7A0 /* Resources */ = { isa = PBXGroup; children = ( F49282C225696BF900D255D8 /* known_exceptions.css */, F495AEC625F03141000D92E1 /* unknown_exception_type.html */, F4A3A6ED25ED82F10018053E /* EXC_BAD_ACCESS_SIGBUS.html */, F45015C825FABCAC000C4B8D /* EXC_BAD_ACCESS_SIGSEGV.html */, F45015CC25FABE00000C4B8D /* EXC_BAD_INSTRUCTION_SIGILL.html */, F495AED225F034C0000D92E1 /* EXC_BREAKPOINT_SIGTRAP.html */, F495AECA25F0320D000D92E1 /* EXC_CRASH_SIGABRT.html */, F495AECE25F033CC000D92E1 /* EXC_CRASH_SIGKILL.html */, F45015D025FAD279000C4B8D /* EXC_CRASH_SIGQUIT.html */, F40B832825FC0AEC0091D886 /* EXC_CRASH_SIGSEGV.html */, F495AED625F03820000D92E1 /* EXC_CRASH_Code Signature Invalid.html */, D0BA6A442E09FEB50010D630 /* EXC_GUARD.html */, F4E6EDA0284969DD00766F9A /* known_termination_reasons.css */, F4E6ED9A2849695100766F9A /* unknown_termination_reason.html */, F4E6EDA2284969E500766F9A /* ENDPOINTSECURITY_2.html */, ); name = Resources; sourceTree = ""; }; F4F5395324D2063100D537BC /* View Mode - List */ = { isa = PBXGroup; children = ( F4F5395524D2066300D537BC /* Views */, F432ACC524A95014000A3E7A /* CUIThreadsListViewController.h */, F432ACC624A95014000A3E7A /* CUIThreadsListViewController.m */, F47C381C2A422E880020D88F /* CUIThreadsListViewController.xib */, F47C381D2A422E880020D88F /* CUIThreadsListViewController_RTL.xib */, ); name = "View Mode - List"; sourceTree = ""; }; F4F5395424D2064600D537BC /* View Mode - Columns */ = { isa = PBXGroup; children = ( F432ACCD24A95042000A3E7A /* CUIThreadsColumnViewController.h */, F432ACCE24A95042000A3E7A /* CUIThreadsColumnViewController.m */, F47C38202A4230370020D88F /* CUIThreadsColumnViewController.xib */, F47C38212A4230370020D88F /* CUIThreadsColumnViewController_RTL.xib */, ); name = "View Mode - Columns"; sourceTree = ""; }; F4F5395524D2066300D537BC /* Views */ = { isa = PBXGroup; children = ( F414068624D5F1D20059FF21 /* CUIApplicationSpecificBacktraceRowView.h */, F414068724D5F1D20059FF21 /* CUIApplicationSpecificBacktraceRowView.m */, F4A58D1924CA4B1500D98FDB /* CUICrashedThreadRowView.h */, F4A58D1A24CA4B1500D98FDB /* CUICrashedThreadRowView.m */, F4A58D1C24CA4CDA00D98FDB /* CUICrashedThreadCallRowView.h */, F4A58D1D24CA4CDA00D98FDB /* CUICrashedThreadCallRowView.m */, ); name = Views; sourceTree = ""; }; F4F892FF2575A77000BE4CE0 /* Controllers */ = { isa = PBXGroup; children = ( F4545C3E256C1B2400F62A39 /* CUIRegistersViewController.h */, F4545C3F256C1B2400F62A39 /* CUIRegistersViewController.m */, F4F892F82575A6DC00BE4CE0 /* CUIRegistersViewController.xib */, F4F892FA2575A70800BE4CE0 /* CUIRegistersMainViewController.h */, F4F892FB2575A70800BE4CE0 /* CUIRegistersMainViewController.m */, F4F892FC2575A70800BE4CE0 /* CUIRegistersMainViewController.xib */, F4545C39256C1AF900F62A39 /* CUIRegistersWindowController.h */, F4545C3A256C1AF900F62A39 /* CUIRegistersWindowController.m */, F4545C3B256C1AF900F62A39 /* CUIRegistersWindowController.xib */, ); name = Controllers; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ F4CC56FE24A79EDA00150EC4 /* Unexpectedly */ = { isa = PBXNativeTarget; buildConfigurationList = F4CC571C24A79EDA00150EC4 /* Build configuration list for PBXNativeTarget "Unexpectedly" */; buildPhases = ( F4CC56FB24A79EDA00150EC4 /* Sources */, F4CC56FC24A79EDA00150EC4 /* Frameworks */, F4CC56FD24A79EDA00150EC4 /* Resources */, F42D0BC525514CCB0021A551 /* Rename template file */, F45F84DB266ABB7000F354F3 /* CopyFiles */, ); buildRules = ( ); dependencies = ( F45F84DA266ABB6300F354F3 /* PBXTargetDependency */, ); name = Unexpectedly; productName = Unexpectedly; productReference = F4CC56FF24A79EDA00150EC4 /* Unexpectedly.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ F4CC56F724A79EDA00150EC4 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Acme, Inc"; TargetAttributes = { F4CC56FE24A79EDA00150EC4 = { CreatedOnToolsVersion = 6.4; }; }; }; buildConfigurationList = F4CC56FA24A79EDA00150EC4 /* Build configuration list for PBXProject "app_unexpectedly" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, fr, es, ja, he, ); mainGroup = F4CC56F624A79EDA00150EC4; productRefGroup = F4CC570024A79EDA00150EC4 /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = F45F84D4266ABB5800F354F3 /* Products */; ProjectRef = F45F84D3266ABB5800F354F3 /* crashreport.xcodeproj */; }, ); projectRoot = ""; targets = ( F4CC56FE24A79EDA00150EC4 /* Unexpectedly */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ F45F84D8266ABB5800F354F3 /* crashreport.qlgenerator */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = crashreport.qlgenerator; remoteRef = F45F84D7266ABB5800F354F3 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ F4CC56FD24A79EDA00150EC4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( F42D0BC425514B670021A551 /* template.source in Resources */, F497303E25F7F74C001D01FE /* InfoPlist.strings in Resources */, F495AEBC25F029C2000D92E1 /* CUIPreferencePanePresentationTextViewController.xib in Resources */, F416687024B0AEE800C2AB89 /* CUIContentsViewController.xib in Resources */, F495AED025F034C0000D92E1 /* EXC_BREAKPOINT_SIGTRAP.html in Resources */, F45015CE25FAD279000C4B8D /* EXC_CRASH_SIGQUIT.html in Resources */, F45DED6F2E3510D9008F4CE8 /* CodeSigning.strings in Resources */, F45A2D6D25EC60920007D50E /* CUICrashLogsSourcesViewController.xib in Resources */, F47C38232A4230370020D88F /* CUIThreadsColumnViewController_RTL.xib in Resources */, F48CF5FF24A96992002AD214 /* MainMenu.xib in Resources */, F483845324EB11F700FAEF5D /* default_themes.plist in Resources */, F4CE83DE2554B97400A8BD87 /* CUICenteredLabelViewController.xib in Resources */, F4E6ED9C2849695200766F9A /* unknown_termination_reason.html in Resources */, F4C7498F24F84689004F38C0 /* CUIQuickHelpPopUpViewController.xib in Resources */, F4F8D26A24F29624007661D6 /* CUIPresentationTextNavigationViewController.xib in Resources */, F45854FB25C76591007A3A79 /* Unexpectedly_Acknowledgements.pdf in Resources */, F495AED425F03820000D92E1 /* EXC_CRASH_Code Signature Invalid.html in Resources */, F45A2D6125EC5D130007D50E /* CUIPreferencePaneFontscolorsViewController.xib in Resources */, F495AEC425F03141000D92E1 /* unknown_exception_type.html in Resources */, F4A3A6DF25ED7F450018053E /* CUICrashLogsSourceSmartEditorWindowController.xib in Resources */, F453AE4925EE706F00B7BEF0 /* CUIExportAccessoryViewController.xib in Resources */, F41ECA5424AB689B00CE56C7 /* CUIInspectorViewController.xib in Resources */, F4A3A6EB25ED82F10018053E /* EXC_BAD_ACCESS_SIGBUS.html in Resources */, F4A9967C2675078B0001B40E /* CUICrashLogsOpenErrorWindowController.xib in Resources */, F4895F5727A72D1000D75369 /* CUILineJumperWindowController.xib in Resources */, F416688724B0BF2000C2AB89 /* CUISidebarViewController.xib in Resources */, F453AE4D25EE70E800B7BEF0 /* CUICrashLogPresentationTextViewController.xib in Resources */, F4545C3D256C1AF900F62A39 /* CUIRegistersWindowController.xib in Resources */, F4055C8125EEE37400DC6CCA /* CUIMainWindowController.xib in Resources */, F4B74C1A24B233C900CD1E60 /* CUIRightViewController.xib in Resources */, F47C38222A4230370020D88F /* CUIThreadsColumnViewController.xib in Resources */, F45A2D7125EC60D90007D50E /* CUICrashLogsListViewController.xib in Resources */, F495AEC025F02F74000D92E1 /* CUIPreferencePanePresentationOutlineViewController.xib in Resources */, F45854FA25C76591007A3A79 /* Unexpectedly_License.pdf in Resources */, F4301A6825EF0DE000ACDA3F /* CUIPreferencePanePresentationViewController.xib in Resources */, F4CC570A24A79EDA00150EC4 /* Images.xcassets in Resources */, F47C381E2A422E880020D88F /* CUIThreadsListViewController.xib in Resources */, F40B832625FC0AEC0091D886 /* EXC_CRASH_SIGSEGV.html in Resources */, F4E6EDA1284969DD00766F9A /* known_termination_reasons.css in Resources */, F493DB1C24F1CF30001AA8C0 /* Localizable.strings in Resources */, F45015C625FABCAC000C4B8D /* EXC_BAD_ACCESS_SIGSEGV.html in Resources */, F45015CA25FABE00000C4B8D /* EXC_BAD_INSTRUCTION_SIGILL.html in Resources */, F46D77A725ED8E3B00039663 /* CUIInspectorProcessesViewController.xib in Resources */, F495AECC25F033CC000D92E1 /* EXC_CRASH_SIGKILL.html in Resources */, F4A0BEF3261BC39700BADEED /* brushed-alum.png in Resources */, F46D2A2624C33FA200652D50 /* Predicates.strings in Resources */, F4E671952E2C405F00E5A064 /* CodeSigningFlags.plist in Resources */, F4E6EDA4284969E500766F9A /* ENDPOINTSECURITY_2.html in Resources */, F45A2D6525EC5F850007D50E /* CUIAboutBoxWindowController.xib in Resources */, D0BA6A462E09FEB50010D630 /* EXC_GUARD.html in Resources */, F45DED692E350F07008F4CE8 /* CUICodeSigningInformationViewController.xib in Resources */, F49282C325696BF900D255D8 /* known_exceptions.css in Resources */, F4D7F15F25F04A9D0024E9A5 /* CUIPreferencePaneSymbolicationViewController.xib in Resources */, F4754D7125F5678700B0D48F /* CUICrashLogPresentationOutlineViewController.xib in Resources */, F4F892F92575A6DC00BE4CE0 /* CUIRegistersViewController.xib in Resources */, F4D6C56D2680028A00B78B3D /* RemoteCheck.strings in Resources */, F46D779F25ED8D3600039663 /* CUIInspectorUserViewController.xib in Resources */, F464F20D24ACF9CF007A3A96 /* CUICrashLogsMainViewController.xib in Resources */, F46D77AB25ED9EAE00039663 /* CUICollectionViewRegisterItem.xib in Resources */, F45A2D5D25EC5CA00007D50E /* CUIPreferencesWindowController.xib in Resources */, F46D77A325ED8D5700039663 /* CUIInspectorExecutableViewController.xib in Resources */, F4A3A6E325ED81260018053E /* CUIPreferencePaneGeneralViewController.xib in Resources */, F4D7F15B25F04A620024E9A5 /* CUISymbolsFilesLibraryViewController.xib in Resources */, F4F892FE2575A70800BE4CE0 /* CUIRegistersMainViewController.xib in Resources */, F406B4992687AB1400B90C7B /* CUIPreferencePaneAdvancedViewController.xib in Resources */, F45A2D6925EC602B0007D50E /* CUIBinaryImagesViewController.xib in Resources */, F47C381F2A422E880020D88F /* CUIThreadsListViewController_RTL.xib in Resources */, F4A3A6E725ED817E0018053E /* CUIPreferencePaneCrashreporterViewController.xib in Resources */, F416687A24B0BA5000C2AB89 /* CUICrashLogContentsViewController.xib in Resources */, F495AEC825F0320D000D92E1 /* EXC_CRASH_SIGABRT.html in Resources */, F46D779B25ED8D1800039663 /* CUIInspectorGeneralViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ F42D0BC525514CCB0021A551 /* Rename template file */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "Rename template file"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "# Rename template.source to template.c\n\necho \"$TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/template.source\"\necho \"$TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/template.c\"\n\n/bin/mv \"$TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/template.source\" \"$TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/template.c\"\n\nexit 0\n"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ F4CC56FB24A79EDA00150EC4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( F428C07F2724592D00FB8CAC /* IPSException.m in Sources */, F483845924EB26DF00FAEF5D /* CUIThemeItemsGroup+UI.m in Sources */, F4DF81622893463E008EF1B3 /* IPSRegisterState+Obfuscating.m in Sources */, F4D14D682745C0A9003698AD /* IPSImage+UserCode.m in Sources */, F4871E0625435AF400580562 /* DWRFSection_debug_abbrev.m in Sources */, F43C828824D892620096F27B /* CUIPreferencePanePresentationTextViewController.m in Sources */, F40B0D9724D3572E00663282 /* NSColor+String.m in Sources */, F44E7B80255C83D500025C04 /* NoodleLineNumberMarker.m in Sources */, F4DF815E2893463E008EF1B3 /* IPSObfuscator.m in Sources */, F442FCF124AB8A8B00E87B69 /* CUIBinaryImageUtility.m in Sources */, F4651F8624B297420090DF10 /* CUIOperatingSystemVersion.m in Sources */, F48944222545836F00E3E360 /* CUISymbolsFilesLibraryViewController.m in Sources */, F4B9AD3325319A410083FA6C /* MCHSegment.m in Sources */, F4DF81642893463E008EF1B3 /* IPSLegacyInfo+Obfuscating.m in Sources */, F43362FE25FCEFBA006E7894 /* CUIRawCrashLog+Path.m in Sources */, F4FE2DEA25615CA800C1774A /* CUICrashLogExceptionInformation+UI.m in Sources */, F405A96D255015D800AD2F24 /* CUICXXDemangler.mm in Sources */, F497AD5524B8FE88008517B7 /* CUICrashLogsSourceSmartEditorPanel.m in Sources */, F4A0BEF8261BC39700BADEED /* CUIWatchScrew.m in Sources */, F416686F24B0AEE800C2AB89 /* CUIContentsViewController.m in Sources */, F40ED76724E72A6E00557BB8 /* CUICategoriesClipView.m in Sources */, F4B9AD3825319A410083FA6C /* MCHMachBinary.m in Sources */, F4AA22B72561A233001A1315 /* CUIAboutBoxWindowController.m in Sources */, F40ACE30255697CE006855E5 /* CUICrashLogBrowsingStateRegistry.m in Sources */, F428C0792724592D00FB8CAC /* IPSApplicationSpecificInformation.m in Sources */, F4D0EE95273DB8CD00CC9737 /* IPSThreadState+RegisterDisplayName.m in Sources */, F49C47CA24E9B48B003FC65C /* CUIThemesManager.m in Sources */, D0BD223B2F3FC6810052AD8E /* NSMenuItem+RSCore.m in Sources */, F416688224B0BBFC00C2AB89 /* CUICrashLogPresentationViewController.m in Sources */, F428C0802724592D00FB8CAC /* IPSThread.m in Sources */, F4A0BEF4261BC39700BADEED /* CUIWatchAxis.m in Sources */, F4EFE75224BA48F500DB97AC /* CUIMainWindow.m in Sources */, F43C828C24D8A39B0096F27B /* CUITextModeDisplaySettings.m in Sources */, F414D08E24BFB57700A7095C /* CUICrashLogDianosticMessages.m in Sources */, F4871E0325435AF400580562 /* DWRFSection_debug_info.m in Sources */, F4CC573024A7A95A00150EC4 /* CUIThread.m in Sources */, F428C0732724592D00FB8CAC /* IPSIncidentDiagnosticMessage.m in Sources */, F4BD6A0025553E9000F98F3E /* CUICrashLogSectionsDetector.m in Sources */, F4F8D26924F29624007661D6 /* CUIPresentationTextNavigationViewController.m in Sources */, F469AB2524B3DDEA0053C824 /* CUICrashLogExceptionInformation.m in Sources */, F419376F2672B2BE00B796EB /* CUICrashLogsOpenErrorPanel.m in Sources */, D06294382E1DD8150008895D /* CUICodeSigningInformationViewController.m in Sources */, F4F5395924D21DB800D537BC /* CUIPreferencePaneGeneralViewController.m in Sources */, F4B9AD3425319A410083FA6C /* MCHObjectFile.m in Sources */, F4B649D324EDCD2300008C47 /* CUIInspectorExecutableViewController.m in Sources */, F428C0812724592D00FB8CAC /* IPSThreadFrame.m in Sources */, F476EEC125686EC000F40F87 /* CUIContentBox.m in Sources */, F4CC572724A7A2B200150EC4 /* CUICrashLog.m in Sources */, F4DF815D2893463E008EF1B3 /* IPSIncidentHeader+Obfuscating.m in Sources */, F4FA4323273EF2F30068EDB8 /* NSString+CPU.m in Sources */, F476EEBE25686DEF00F40F87 /* CUIAboutBoxFooterView.m in Sources */, F420C9C4254F5F4C00D24249 /* CUIdSYMHunter.m in Sources */, F4A0BEF1261BC39700BADEED /* CUIWatchGear.m in Sources */, F4E91ADD256A98050017C3EE /* CUIFontBoxView.m in Sources */, F4B9AD3B25319D7C0083FA6C /* MCHSegmentLoadCommand.m in Sources */, F4F5821C256FC7B90032FC53 /* DWRFSection_debug_str_offsets.m in Sources */, F4559F3724AF232800B8EF41 /* CUICrashLogHeader.m in Sources */, F428C0762724592D00FB8CAC /* IPSThreadInstructionStream.m in Sources */, F4545C3C256C1AF900F62A39 /* CUIRegistersWindowController.m in Sources */, F4A0BEF6261BC39700BADEED /* CUIWatchPart.m in Sources */, F428C07C2724592D00FB8CAC /* IPSExternalModificationSummary.m in Sources */, F4B649D724EDD09A00008C47 /* CUIInspectorStackableViewController.m in Sources */, F4CC572D24A7A5F000150EC4 /* CUICrashLog+Transform.m in Sources */, F4627F1225704557007E5CD0 /* CUICollectionViewRegisterItem.m in Sources */, F464FA1525D2DA2A00E024A3 /* NSSet+WBExtensions.m in Sources */, F4CCCC6124AE76780031BC27 /* CUICrashLogsSourcesViewController.m in Sources */, F4F9D3362556C7DB00D28E6E /* CUILineJumperWindowController.m in Sources */, F464F20C24ACF9CF007A3A96 /* CUICrashLogsMainViewController.m in Sources */, F4C269D02503BE6500C8F3B3 /* CUISymbolicationData.m in Sources */, F41ECA5324AB689B00CE56C7 /* CUIInspectorViewController.m in Sources */, F440A3E624AA31B500C23DA1 /* CUICrashLogsSourceFile.m in Sources */, F472CC972550631A003F6338 /* CUISwiftDemangler.m in Sources */, F428C07A2724592D00FB8CAC /* IPSSummary.m in Sources */, F428C0782724592D00FB8CAC /* IPSDateFormatter.m in Sources */, F4CF6CF62DF6111B0078458E /* IPSIncident+ApplicationSpecificInformation.m in Sources */, F4040A7924F5BC230072BF65 /* CUINavigationView.m in Sources */, F4B018372620FEC7009727F1 /* CUIApplicationIconView.m in Sources */, F4BC577124DF426200063545 /* CUIAATextFieldCell.m in Sources */, F47F76652673548600A74905 /* CUICrashLogsOpenErrorRecord.m in Sources */, F428C07E2724592D00FB8CAC /* IPSBundleInfo.m in Sources */, F428C07D2724592D00FB8CAC /* IPSExternalModificationStatistics.m in Sources */, F428C0752724592D00FB8CAC /* IPSThreadInstructionState.m in Sources */, F40B0D8824D3569800663282 /* NSResponder+Appearance.m in Sources */, F43A9A832591260C005AB2AA /* CUIOutlineModeDisplaySettings.m in Sources */, F4AC864A2558A03B004F2637 /* CUIExportAccessoryViewController.m in Sources */, F414068824D5F1D20059FF21 /* CUIApplicationSpecificBacktraceRowView.m in Sources */, F49A6D7E25474F6E00466D15 /* CUIInactiveButton.m in Sources */, F4E861BA255496310061E203 /* CUIRawCrashLog.m in Sources */, F4775479255B0054006BA662 /* CUIThemesTableView.m in Sources */, F4F892FD2575A70800BE4CE0 /* CUIRegistersMainViewController.m in Sources */, F461CE8A25F6DD75007CFDE7 /* CUIApplicationItemAttributes.m in Sources */, F40ACE2D255697A3006855E5 /* CUICrashLogBrowsingState.m in Sources */, F4871E0925435AF400580562 /* DWRFObject.m in Sources */, F4214CB524B6534400852DDE /* CUICrashLogsSourcesManager.m in Sources */, F4871E0D25437A6A00580562 /* CUISymbolicationDataCache.m in Sources */, F4440FE0282C4104003C810B /* IPSSummarySerialization.m in Sources */, F428C07B2724592D00FB8CAC /* IPSTermination.m in Sources */, F440A3E924AA35AC00C23DA1 /* CUICrashLogsSourceDirectory.m in Sources */, F414D09124BFBC3A00A7095C /* CUICrashLogBacktraces.m in Sources */, F4A0BEF7261BC39700BADEED /* CUIWatchBridge.m in Sources */, F4DF81682893463E008EF1B3 /* IPSIncident+Obfuscating.m in Sources */, F440A3E324AA315800C23DA1 /* CUICrashLogsSourceStandardDirectory.m in Sources */, F43AF0D1256FE2AE0066CA1B /* DWRFSection_debug_addr.m in Sources */, F4871E0525435AF400580562 /* DWRFSection_debug_line.m in Sources */, F4DF81672893463E008EF1B3 /* IPSBundleInfo+Obfuscating.m in Sources */, F40BEAF124E9F754007A3F60 /* CUIThemeItemAttributes.m in Sources */, F4B138572522948700D9DE2F /* NSBundle+dSYM.m in Sources */, F428C0742724592D00FB8CAC /* IPSReport.m in Sources */, F49A6D8125476F7B00466D15 /* CUISymbolicationDataFormatter.m in Sources */, F4DF81612893463E008EF1B3 /* IPSThreadFrame+Obfuscating.m in Sources */, F4DF815C2893463E008EF1B3 /* IPSApplicationSpecificInformation+Obfuscating.m in Sources */, F416687E24B0BBA300C2AB89 /* CUICrashLogPresentationTextViewController.m in Sources */, F4EBADB724A8F10000DF4271 /* CUICrashLogTableCellView.m in Sources */, F45B518C24AFA04000E97B87 /* CUICrashLogsSelection.m in Sources */, F4BBAC5D24AA7D37000511BE /* CUIBinaryImage.m in Sources */, F40B0D7F24D3558800663282 /* CUIPreferencesTabHeaderView.m in Sources */, F4CCCC6B24AE95430031BC27 /* CUICrashLogsSourceFileSystemItem.m in Sources */, F420F35224E95E5F006C82CD /* CUITheme.m in Sources */, F497F0162576E1A100BD1970 /* CUIRoundedRectBezelView.m in Sources */, F44356FF24A8A8B5001D3D35 /* CUIThreadNamedTableCellView.m in Sources */, F4B9AD3625319A410083FA6C /* MCHLoadCommand.m in Sources */, F480692E24AF7D83009665F2 /* CUICrashLogsListViewController.m in Sources */, F4ED18A324EC77A300ED7EF2 /* NSArray+UniqueName.m in Sources */, F42E50012724B7550092181A /* CUICrashDataTransform.m in Sources */, F428C0822724592D00FB8CAC /* IPSError.m in Sources */, F4E0BD25262078220048647C /* CUIAboutBoxWindow.m in Sources */, F4DF81662893463E008EF1B3 /* IPSIncidentExceptionInformation+Obfuscating.m in Sources */, F4C269CD2503BCC100C8F3B3 /* CUISymbolicationManager.m in Sources */, F4DF815F2893463E008EF1B3 /* IPSCrashSummary+Obfuscating.m in Sources */, F4E671922E2C3B1600E5A064 /* CUICodeSigningFlagsTableView.m in Sources */, F4DAFBEE2736B7B200FB50A6 /* CUIIPSTransform.m in Sources */, F47F76622673542600A74905 /* CUICrashLogsOpenErrorRecord+UI.m in Sources */, F462DD3124ADC5F900044AB1 /* CUICrashLogsSourceSmart.m in Sources */, F483845624EB1BEB00FAEF5D /* CUIApplicationPreferences+Themes.m in Sources */, F4306D592577E168007E667F /* CUICrashLogThreadState+UI.m in Sources */, F4B9AD3725319A410083FA6C /* MCHSection.m in Sources */, F414D09724BFBC6300A7095C /* CUICrashLogBinaryImages.m in Sources */, F47AF8C0255DE61E0037E2D8 /* NSCrashLogTextScrollView.m in Sources */, F40B0D8724D3569800663282 /* NSColor+LabelColor.m in Sources */, F4238191267D3522003837AC /* WBRemoteVersionChecker.m in Sources */, F48BAB3625D9D4140005F3E5 /* CUIThreadImageCell.m in Sources */, F416687924B0BA5000C2AB89 /* CUICrashLogContentsViewController.m in Sources */, F428C0842724592D00FB8CAC /* IPSThreadState.m in Sources */, F49673FE24D0CF6400716289 /* CUIPreferencesWindowController.m in Sources */, F4040A7624F5B9CE0072BF65 /* CUINavigationChevronView.m in Sources */, F4EAFA2C24FA6CD100C0B729 /* CUICrashLogTextView.m in Sources */, F4341C6B258EB8FE001A5605 /* CUICrashReporterDefaults.m in Sources */, F428C0722724592D00FB8CAC /* IPSIncidentExceptionInformation.m in Sources */, F496740E24D0D74A00716289 /* CUIApplicationPreferences.m in Sources */, F40B0D9D24D370A200663282 /* NSDictionary+MutableDeepCopy.m in Sources */, F40B0D9424D3571B00663282 /* NSTableView+Selection.m in Sources */, F40B0D7E24D3558800663282 /* CUIPreferencesTabBox.m in Sources */, F4CCCC6E24AE9EDA0031BC27 /* CUICrashLogsSource+UI.m in Sources */, F4C7498E24F84689004F38C0 /* CUIQuickHelpPopUpViewController.m in Sources */, F4A58D1E24CA4CDA00D98FDB /* CUICrashedThreadCallRowView.m in Sources */, F4545C41256C1B2400F62A39 /* CUIRegistersViewController.m in Sources */, F4386B0F2849541C00B83525 /* CUICrashLogExceptionInformation+QuickHelp.m in Sources */, F440A3EC24AA38E600C23DA1 /* CUICrashLogsSourceAll.m in Sources */, F4871E0725435AF400580562 /* DWRFFileObject.m in Sources */, F4871E10254384E100580562 /* CUIdSYMBundlesManager.m in Sources */, F4B74C1924B233C900CD1E60 /* CUIRightViewController.m in Sources */, F428C0712724592D00FB8CAC /* IPSIncidentHeader.m in Sources */, F428C0772724592D00FB8CAC /* IPSRegisterState.m in Sources */, F4CD32B6257D17B3008C71AA /* CUIPreferencePaneSymbolicationViewController.m in Sources */, F41D66B025921F3400C0D491 /* CUIPreferencePanePresentationViewController.m in Sources */, F49A55DE24C7A7F900D249DE /* CUICallTableCellView.m in Sources */, F4B649DB24EDD64900008C47 /* CUIInspectorProcessesViewController.m in Sources */, F40B0D9124D356F900663282 /* NSToolbar+Packages.m in Sources */, F46198E924CA390700FA9717 /* CUICrashLogBacktraces+Utilities.m in Sources */, F49227C824A8D45000772411 /* CUIStackFrame+UI.m in Sources */, F428C0832724592D00FB8CAC /* IPSOperatingSystemVersion.m in Sources */, F432ACD024A95042000A3E7A /* CUIThreadsColumnViewController.m in Sources */, F416688624B0BF2000C2AB89 /* CUISidebarViewController.m in Sources */, F4B57C0C24AF5607000851FF /* CUICrashLogsSourceToday.m in Sources */, F420C9C1254F335000D24249 /* CUIdSYMDropView.m in Sources */, F44356F324A8A113001D3D35 /* CUICrashLogPresentationOutlineViewController.m in Sources */, F40B0D8D24D356A200663282 /* NSArray+WBExtensions.m in Sources */, D0790DBD2E00BACF00CD6A72 /* CUIThreadImageView.m in Sources */, F4A58D1B24CA4B1500D98FDB /* CUICrashedThreadRowView.m in Sources */, F4871E0825435AF400580562 /* LEB128.c in Sources */, F4EBD24B24E01556007F0252 /* CUITableCustomSelectionColorRowView.m in Sources */, F4BD8C6A2DF4DDCB00BD61A8 /* IPSExceptionReason.m in Sources */, F442FCED24AB855C00E87B69 /* CUIBinaryImagesViewController.m in Sources */, F496740A24D0D2A300716289 /* CUIPreferencePaneFontscolorsViewController.m in Sources */, F4DF815A2893463E008EF1B3 /* IPSThreadState+Obfuscating.m in Sources */, F416687424B0AF4D00C2AB89 /* CUICenteredLabelViewController.m in Sources */, F4DF81632893463E008EF1B3 /* IPSImage+Obfuscating.m in Sources */, F40B77D724AF0F5C001A8131 /* CUICrashLogsSourceStandardDirectory+UI.m in Sources */, F4B5BE7128482A4300C33F6F /* CUITerminationReasonPopUpViewController.m in Sources */, F45442A924AF355700EE79E4 /* CUICaptionView.m in Sources */, F4DF81602893463E008EF1B3 /* IPSThread+Obfuscating.m in Sources */, F40FC81625EAF7B000DB4B27 /* CUISourceFileTableCellView.m in Sources */, F414D09424BFBC4A00A7095C /* CUICrashLogThreadState.m in Sources */, F4B57C0F24AF5655000851FF /* CUICrashLogsSourceToday+UI.m in Sources */, F4F9BAF724EF06BC00D08FBD /* CUIInspectorGeneralViewController.m in Sources */, F4440FE1282C4104003C810B /* IPSCrashSummary.m in Sources */, F414068B24D6014D0059FF21 /* CUIFontAndColorsFramedView.m in Sources */, F40B124924E89BBE005E82DD /* CUIPreferencesWindowController+Convenience.m in Sources */, F4132C8F24AA19F70086B99C /* CUICrashLogsSource.m in Sources */, F4DAF0B327C44AA800256EA4 /* IPSImage+Offset.m in Sources */, F4CCCC6524AE810E0031BC27 /* CUICrashLogsSourcesSelection.m in Sources */, F432ACCC24A9502A000A3E7A /* CUIThreadsViewController.m in Sources */, F40B0D8E24D356A200663282 /* NSIndexSet+Analysis.m in Sources */, F4FC8EA727C1A6EE00291875 /* CUIReportThemedTransform.m in Sources */, F4DAFBF12736B7D500FB50A6 /* CUIDataTransform.m in Sources */, F4B9AD3225319A410083FA6C /* MCHMemoryBufferWrapper.m in Sources */, F40B0D8024D3558800663282 /* CUIPreferencesTabButton.m in Sources */, F464F21024ACFBA1007A3A96 /* CUIRegister.m in Sources */, F4EBADB424A8F04F00DF4271 /* CUICrashLog+UI.m in Sources */, F46198EE24CA459700FA9717 /* CUIInspectorAlternateBackgroundView.m in Sources */, F475FB4026DBAC8200A113D8 /* CUITableViewNoSpace.m in Sources */, F47F7668267355EA00A74905 /* CUICrashLogErrors.m in Sources */, F4F9BAF224EF060E00D08FBD /* CUIInspectorUserViewController.m in Sources */, F4CC570824A79EDA00150EC4 /* main.m in Sources */, F420C9B9254F30A100D24249 /* CUIFileDeadDropView.m in Sources */, F42B57E224ABEF6E00F77ED5 /* CUICallsSelection.m in Sources */, F44E7B7F255C83D500025C04 /* NoodleLineNumberView.m in Sources */, F4DF81652893463E008EF1B3 /* IPSReport+Obfuscating.m in Sources */, F483845124EB041B00FAEF5D /* CUIThemeItemsGroup.m in Sources */, F4F2A9D024BB7E3600F912D4 /* CUICrashLogsSourceSeparator.m in Sources */, F4DF815B2893463E008EF1B3 /* IPSIncidentDiagnosticMessage+Obfuscating.m in Sources */, F4D5C77C2571AF900029B051 /* CUIRegisterLabel.m in Sources */, F45F2F5B2538EF3F0030A402 /* NSFileManager+ExtendedAttributes.m in Sources */, F4B67838258F702E0047369E /* CUIPreferencePaneCrashreporterViewController.m in Sources */, F4F2A9D324BB809200F912D4 /* CUICrashLogsSourceTableCellView.m in Sources */, F4577BEA2592848D009B2AD2 /* CUIPreferencePanePresentationOutlineViewController.m in Sources */, F4B9AD3525319A410083FA6C /* MCHUUIDLoadCommand.m in Sources */, F432ACC824A95014000A3E7A /* CUIThreadsListViewController.m in Sources */, F405A97025501A5F00AD2F24 /* CUIParsingErrors.m in Sources */, F4CC573324A7ABAF00150EC4 /* CUICallStackBacktrace.m in Sources */, F4B52E212548B8B4007593FD /* CUIdSYMBundle+UI.m in Sources */, F496740324D0D05800716289 /* CUIPreferencePaneViewController.m in Sources */, F4ED758A2501A29700316E73 /* CUIStackFrame.m in Sources */, F428C0702724592D00FB8CAC /* IPSImage.m in Sources */, F4871DC02543566E00580562 /* CUIdSYMBundle.m in Sources */, F4A7696A2555D9DE00F9D9D3 /* CUIRawCrashLog+UI.m in Sources */, F4871E0425435AF400580562 /* DWRFSection_debug_str.m in Sources */, F4B5BE6E2848277400C33F6F /* CUIExceptionTypePopUpViewController.m in Sources */, F48906AE25D2BA0C002D79A9 /* CUISelectedWhiteTextFieldCell.m in Sources */, F43D8FF724A7FAD2008147F9 /* CUIMainWindowController.m in Sources */, F40B77DA24AF1426001A8131 /* CUICrashLogsSourceAll+UI.m in Sources */, F4A0BEF2261BC39700BADEED /* CUIWatchJewel.m in Sources */, F46BAF59250162C900991970 /* CUIPreferencesWindow.m in Sources */, F428C0862724592D00FB8CAC /* IPSIncident.m in Sources */, F4871E0A25435AF400580562 /* DWRFSection_debug_aranges.m in Sources */, F40BEAFC24E9FEF8007A3F60 /* NSDictionary+WBExtensions.m in Sources */, F423818C267D1D4A003837AC /* CUIPreferencePaneAdvancedViewController.m in Sources */, F497303A25F796E6001D01FE /* CUIHopperDisassemblerManager.m in Sources */, F4CC570624A79EDA00150EC4 /* AppDelegate.m in Sources */, F4CC572424A7A1D100150EC4 /* CUICrashLogsProvider.m in Sources */, F428C0852724592D00FB8CAC /* IPSLegacyInfo.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ F45F84DA266ABB6300F354F3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = crashreport; targetProxy = F45F84D9266ABB6300F354F3 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ D0BA6A442E09FEB50010D630 /* EXC_GUARD.html */ = { isa = PBXVariantGroup; children = ( D0BA6A452E09FEB50010D630 /* en */, D00B152C2E0B52740098456B /* fr */, D0AECAE42E0F34830028246E /* he */, D000743B2E11F30900CC5121 /* ja */, D000743C2E11F30B00CC5121 /* es */, ); name = EXC_GUARD.html; sourceTree = ""; }; F4055C8325EEE37400DC6CCA /* CUIMainWindowController.xib */ = { isa = PBXVariantGroup; children = ( F4055C8225EEE37400DC6CCA /* en */, F4055C8425EEE37600DC6CCA /* fr */, F4111AE4265EE92600FD8950 /* es */, F4FC364B278F914500669B32 /* ja */, F43066EA2A12EDE8002AB430 /* he */, ); name = CUIMainWindowController.xib; sourceTree = ""; }; F406B49B2687AB1400B90C7B /* CUIPreferencePaneAdvancedViewController.xib */ = { isa = PBXVariantGroup; children = ( F406B49A2687AB1400B90C7B /* en */, F406B49C2687AB1800B90C7B /* fr */, F406B49D2687AC1900B90C7B /* es */, F4FC3633278F914300669B32 /* ja */, F43066CF2A12EDE6002AB430 /* he */, ); name = CUIPreferencePaneAdvancedViewController.xib; sourceTree = ""; }; F40B832825FC0AEC0091D886 /* EXC_CRASH_SIGSEGV.html */ = { isa = PBXVariantGroup; children = ( F40B832725FC0AEC0091D886 /* en */, F40B832925FC0AEE0091D886 /* fr */, F4111ADD265EE92500FD8950 /* es */, F4FC3644278F914400669B32 /* ja */, F43066E02A12EDE7002AB430 /* he */, ); name = EXC_CRASH_SIGSEGV.html; path = Help; sourceTree = ""; }; F4301A6A25EF0DE000ACDA3F /* CUIPreferencePanePresentationViewController.xib */ = { isa = PBXVariantGroup; children = ( F4301A6925EF0DE000ACDA3F /* en */, F4301A6B25EF0DE200ACDA3F /* fr */, F4111AC8265EE92200FD8950 /* es */, F4FC362E278F914200669B32 /* ja */, F43066CA2A12EDE5002AB430 /* he */, ); name = CUIPreferencePanePresentationViewController.xib; sourceTree = ""; }; F45015C825FABCAC000C4B8D /* EXC_BAD_ACCESS_SIGSEGV.html */ = { isa = PBXVariantGroup; children = ( F45015C725FABCAC000C4B8D /* en */, F45015C925FABCAF000C4B8D /* fr */, F4111AD7265EE92400FD8950 /* es */, F4FC363E278F914400669B32 /* ja */, F43066DA2A12EDE7002AB430 /* he */, ); name = EXC_BAD_ACCESS_SIGSEGV.html; path = Help; sourceTree = ""; }; F45015CC25FABE00000C4B8D /* EXC_BAD_INSTRUCTION_SIGILL.html */ = { isa = PBXVariantGroup; children = ( F45015CB25FABE00000C4B8D /* en */, F45015CD25FABE02000C4B8D /* fr */, F4111AD8265EE92400FD8950 /* es */, F4FC363F278F914400669B32 /* ja */, F43066DB2A12EDE7002AB430 /* he */, ); name = EXC_BAD_INSTRUCTION_SIGILL.html; path = Help; sourceTree = ""; }; F45015D025FAD279000C4B8D /* EXC_CRASH_SIGQUIT.html */ = { isa = PBXVariantGroup; children = ( F45015CF25FAD279000C4B8D /* en */, F45015D125FAD27B000C4B8D /* fr */, F4111ADC265EE92500FD8950 /* es */, F4FC3643278F914400669B32 /* ja */, F43066DF2A12EDE7002AB430 /* he */, ); name = EXC_CRASH_SIGQUIT.html; path = Help; sourceTree = ""; }; F453AE4B25EE706F00B7BEF0 /* CUIExportAccessoryViewController.xib */ = { isa = PBXVariantGroup; children = ( F453AE4A25EE706F00B7BEF0 /* en */, F453AE4C25EE707000B7BEF0 /* fr */, F4111ADF265EE92500FD8950 /* es */, F4FC3646278F914500669B32 /* ja */, F43066E52A12EDE8002AB430 /* he */, ); name = CUIExportAccessoryViewController.xib; sourceTree = ""; }; F453AE4F25EE70E800B7BEF0 /* CUICrashLogPresentationTextViewController.xib */ = { isa = PBXVariantGroup; children = ( F453AE4E25EE70E800B7BEF0 /* en */, F453AE5025EE70E900B7BEF0 /* fr */, F4111AE0265EE92500FD8950 /* es */, F4FC3647278F914500669B32 /* ja */, F43066E62A12EDE8002AB430 /* he */, ); name = CUICrashLogPresentationTextViewController.xib; sourceTree = ""; }; F45A2D5F25EC5CA00007D50E /* CUIPreferencesWindowController.xib */ = { isa = PBXVariantGroup; children = ( F45A2D5E25EC5CA00007D50E /* en */, F45A2D6025EC5CA30007D50E /* fr */, F4111ACD265EE92300FD8950 /* es */, F4FC3634278F914300669B32 /* ja */, F43066D02A12EDE6002AB430 /* he */, ); name = CUIPreferencesWindowController.xib; sourceTree = ""; }; F45A2D6325EC5D130007D50E /* CUIPreferencePaneFontscolorsViewController.xib */ = { isa = PBXVariantGroup; children = ( F45A2D6225EC5D130007D50E /* en */, F45A2D6425EC5D140007D50E /* fr */, F4111AC9265EE92200FD8950 /* es */, F4FC362F278F914200669B32 /* ja */, F43066CB2A12EDE5002AB430 /* he */, ); name = CUIPreferencePaneFontscolorsViewController.xib; sourceTree = ""; }; F45A2D6725EC5F850007D50E /* CUIAboutBoxWindowController.xib */ = { isa = PBXVariantGroup; children = ( F45A2D6625EC5F850007D50E /* en */, F45A2D6825EC5F870007D50E /* fr */, F4111AC4265EE92200FD8950 /* es */, F4FC362A278F914200669B32 /* ja */, F43066C62A12EDE4002AB430 /* he */, ); name = CUIAboutBoxWindowController.xib; sourceTree = ""; }; F45A2D6B25EC602B0007D50E /* CUIBinaryImagesViewController.xib */ = { isa = PBXVariantGroup; children = ( F45A2D6A25EC602B0007D50E /* en */, F45A2D6C25EC60310007D50E /* fr */, F4111AE3265EE92600FD8950 /* es */, F4FC364A278F914500669B32 /* ja */, F43066E92A12EDE8002AB430 /* he */, ); name = CUIBinaryImagesViewController.xib; sourceTree = ""; }; F45A2D6F25EC60920007D50E /* CUICrashLogsSourcesViewController.xib */ = { isa = PBXVariantGroup; children = ( F45A2D6E25EC60920007D50E /* en */, F45A2D7025EC60930007D50E /* fr */, F4111ACF265EE92300FD8950 /* es */, F4FC3636278F914300669B32 /* ja */, F43066D22A12EDE6002AB430 /* he */, ); name = CUICrashLogsSourcesViewController.xib; sourceTree = ""; }; F45A2D7325EC60D90007D50E /* CUICrashLogsListViewController.xib */ = { isa = PBXVariantGroup; children = ( F45A2D7225EC60D90007D50E /* en */, F45A2D7425EC60DB0007D50E /* fr */, F4111AD0265EE92300FD8950 /* es */, F4FC3637278F914300669B32 /* ja */, F43066D32A12EDE6002AB430 /* he */, ); name = CUICrashLogsListViewController.xib; sourceTree = ""; }; F45DED6B2E350F07008F4CE8 /* CUICodeSigningInformationViewController.xib */ = { isa = PBXVariantGroup; children = ( F45DED6A2E350F07008F4CE8 /* en */, F45DED6C2E350F0D008F4CE8 /* fr */, F45DED742E351277008F4CE8 /* es */, F45DED752E351279008F4CE8 /* ja */, F45DED762E35127A008F4CE8 /* he */, ); name = CUICodeSigningInformationViewController.xib; sourceTree = ""; }; F45DED6D2E3510D9008F4CE8 /* CodeSigning.strings */ = { isa = PBXVariantGroup; children = ( F45DED6E2E3510D9008F4CE8 /* en */, F45DED702E351134008F4CE8 /* fr */, F45DED712E3511B8008F4CE8 /* es */, F45DED722E3511BB008F4CE8 /* ja */, F45DED732E3511BC008F4CE8 /* he */, ); name = CodeSigning.strings; sourceTree = ""; }; F46D2A2824C33FA200652D50 /* Predicates.strings */ = { isa = PBXVariantGroup; children = ( F46D2A2724C33FA200652D50 /* en */, F45A2D5625EC50960007D50E /* fr */, F4111AE6265EE92600FD8950 /* es */, F4FC364D278F914500669B32 /* ja */, F43066EC2A12EDE9002AB430 /* he */, ); name = Predicates.strings; sourceTree = ""; }; F46D779D25ED8D1800039663 /* CUIInspectorGeneralViewController.xib */ = { isa = PBXVariantGroup; children = ( F46D779C25ED8D1800039663 /* en */, F46D779E25ED8D1900039663 /* fr */, F4111AD1265EE92300FD8950 /* es */, F4FC3638278F914300669B32 /* ja */, F43066D42A12EDE6002AB430 /* he */, ); name = CUIInspectorGeneralViewController.xib; sourceTree = ""; }; F46D77A125ED8D3600039663 /* CUIInspectorUserViewController.xib */ = { isa = PBXVariantGroup; children = ( F46D77A025ED8D3600039663 /* en */, F46D77A225ED8D3900039663 /* fr */, F4111AD2265EE92300FD8950 /* es */, F4FC3639278F914300669B32 /* ja */, F43066D52A12EDE6002AB430 /* he */, ); name = CUIInspectorUserViewController.xib; sourceTree = ""; }; F46D77A525ED8D5700039663 /* CUIInspectorExecutableViewController.xib */ = { isa = PBXVariantGroup; children = ( F46D77A425ED8D5700039663 /* en */, F46D77A625ED8D5900039663 /* fr */, F4111AD3265EE92400FD8950 /* es */, F4FC363A278F914300669B32 /* ja */, F43066D62A12EDE6002AB430 /* he */, ); name = CUIInspectorExecutableViewController.xib; sourceTree = ""; }; F46D77A925ED8E3B00039663 /* CUIInspectorProcessesViewController.xib */ = { isa = PBXVariantGroup; children = ( F46D77A825ED8E3B00039663 /* en */, F46D77AA25ED8E3E00039663 /* fr */, F4111AD4265EE92400FD8950 /* es */, F4FC363B278F914300669B32 /* ja */, F43066D72A12EDE6002AB430 /* he */, ); name = CUIInspectorProcessesViewController.xib; sourceTree = ""; }; F46D77AD25ED9EAE00039663 /* CUICollectionViewRegisterItem.xib */ = { isa = PBXVariantGroup; children = ( F46D77AC25ED9EAE00039663 /* en */, F46D77AE25ED9EAF00039663 /* fr */, F4111AE2265EE92500FD8950 /* es */, F4FC3649278F914500669B32 /* ja */, F43066E82A12EDE8002AB430 /* he */, ); name = CUICollectionViewRegisterItem.xib; sourceTree = ""; }; F4754D7325F5678700B0D48F /* CUICrashLogPresentationOutlineViewController.xib */ = { isa = PBXVariantGroup; children = ( F4754D7225F5678700B0D48F /* en */, F4754D7425F5678A00B0D48F /* fr */, F4111AE1265EE92500FD8950 /* es */, F4FC3648278F914500669B32 /* ja */, F43066E72A12EDE8002AB430 /* he */, ); name = CUICrashLogPresentationOutlineViewController.xib; sourceTree = ""; }; F4895F5927A72D1000D75369 /* CUILineJumperWindowController.xib */ = { isa = PBXVariantGroup; children = ( F4895F5827A72D1000D75369 /* en */, F4895F5A27A72D1300D75369 /* fr */, F4895F5B27A72D3300D75369 /* es */, F4895F5C27A72D6300D75369 /* ja */, F43066E42A12EDE8002AB430 /* he */, ); name = CUILineJumperWindowController.xib; sourceTree = ""; }; F493DB1A24F1CF2F001AA8C0 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( F493DB1B24F1CF2F001AA8C0 /* en */, F45A2D5525EC50960007D50E /* fr */, F4111AE5265EE92600FD8950 /* es */, F4FC364C278F914500669B32 /* ja */, F43066EB2A12EDE8002AB430 /* he */, ); name = Localizable.strings; sourceTree = ""; }; F495AEBE25F029C2000D92E1 /* CUIPreferencePanePresentationTextViewController.xib */ = { isa = PBXVariantGroup; children = ( F495AEBD25F029C2000D92E1 /* en */, F495AEBF25F029CD000D92E1 /* fr */, F4111AC6265EE92200FD8950 /* es */, F4FC362C278F914200669B32 /* ja */, F43066C82A12EDE5002AB430 /* he */, ); name = CUIPreferencePanePresentationTextViewController.xib; sourceTree = ""; }; F495AEC225F02F74000D92E1 /* CUIPreferencePanePresentationOutlineViewController.xib */ = { isa = PBXVariantGroup; children = ( F495AEC125F02F74000D92E1 /* en */, F495AEC325F02F76000D92E1 /* fr */, F4111AC7265EE92200FD8950 /* es */, F4FC362D278F914200669B32 /* ja */, F43066C92A12EDE5002AB430 /* he */, ); name = CUIPreferencePanePresentationOutlineViewController.xib; sourceTree = ""; }; F495AEC625F03141000D92E1 /* unknown_exception_type.html */ = { isa = PBXVariantGroup; children = ( F495AEC525F03141000D92E1 /* en */, F495AEC725F0314A000D92E1 /* fr */, F4111AD5265EE92400FD8950 /* es */, F4FC363C278F914400669B32 /* ja */, F43066D82A12EDE7002AB430 /* he */, ); name = unknown_exception_type.html; path = Help; sourceTree = ""; }; F495AECA25F0320D000D92E1 /* EXC_CRASH_SIGABRT.html */ = { isa = PBXVariantGroup; children = ( F495AEC925F0320D000D92E1 /* en */, F495AECB25F03213000D92E1 /* fr */, F4111ADA265EE92500FD8950 /* es */, F4FC3641278F914400669B32 /* ja */, F43066DD2A12EDE7002AB430 /* he */, ); name = EXC_CRASH_SIGABRT.html; path = Help; sourceTree = ""; }; F495AECE25F033CC000D92E1 /* EXC_CRASH_SIGKILL.html */ = { isa = PBXVariantGroup; children = ( F495AECD25F033CC000D92E1 /* en */, F495AECF25F033D0000D92E1 /* fr */, F4111ADB265EE92500FD8950 /* es */, F4FC3642278F914400669B32 /* ja */, F43066DE2A12EDE7002AB430 /* he */, ); name = EXC_CRASH_SIGKILL.html; path = Help; sourceTree = ""; }; F495AED225F034C0000D92E1 /* EXC_BREAKPOINT_SIGTRAP.html */ = { isa = PBXVariantGroup; children = ( F495AED125F034C0000D92E1 /* en */, F495AED325F034C4000D92E1 /* fr */, F4111AD9265EE92400FD8950 /* es */, F4FC3640278F914400669B32 /* ja */, F43066DC2A12EDE7002AB430 /* he */, ); name = EXC_BREAKPOINT_SIGTRAP.html; path = Help; sourceTree = ""; }; F495AED625F03820000D92E1 /* EXC_CRASH_Code Signature Invalid.html */ = { isa = PBXVariantGroup; children = ( F495AED525F03820000D92E1 /* en */, F495AED725F03825000D92E1 /* fr */, F4111ADE265EE92500FD8950 /* es */, F4FC3645278F914400669B32 /* ja */, F43066E12A12EDE7002AB430 /* he */, ); name = "EXC_CRASH_Code Signature Invalid.html"; path = Help; sourceTree = ""; }; F497303C25F7F74B001D01FE /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( F497303D25F7F74B001D01FE /* en */, F497303F25F7F7A6001D01FE /* fr */, F4111AE8265EE92600FD8950 /* es */, F4FC364F278F914500669B32 /* ja */, F43066EE2A12EDE9002AB430 /* he */, ); name = InfoPlist.strings; sourceTree = ""; }; F4A3A6E125ED7F450018053E /* CUICrashLogsSourceSmartEditorWindowController.xib */ = { isa = PBXVariantGroup; children = ( F4A3A6E025ED7F450018053E /* en */, F4A3A6E225ED7F460018053E /* fr */, F4111ACE265EE92300FD8950 /* es */, F4FC3635278F914300669B32 /* ja */, F43066D12A12EDE6002AB430 /* he */, ); name = CUICrashLogsSourceSmartEditorWindowController.xib; sourceTree = ""; }; F4A3A6E525ED81260018053E /* CUIPreferencePaneGeneralViewController.xib */ = { isa = PBXVariantGroup; children = ( F4A3A6E425ED81260018053E /* en */, F4A3A6E625ED81290018053E /* fr */, F4111AC5265EE92200FD8950 /* es */, F4FC362B278F914200669B32 /* ja */, F43066C72A12EDE5002AB430 /* he */, ); name = CUIPreferencePaneGeneralViewController.xib; sourceTree = ""; }; F4A3A6E925ED817E0018053E /* CUIPreferencePaneCrashreporterViewController.xib */ = { isa = PBXVariantGroup; children = ( F4A3A6E825ED817E0018053E /* en */, F4A3A6EA25ED81800018053E /* fr */, F4111ACC265EE92300FD8950 /* es */, F4FC3632278F914300669B32 /* ja */, F43066CE2A12EDE6002AB430 /* he */, ); name = CUIPreferencePaneCrashreporterViewController.xib; sourceTree = ""; }; F4A3A6ED25ED82F10018053E /* EXC_BAD_ACCESS_SIGBUS.html */ = { isa = PBXVariantGroup; children = ( F4A3A6EC25ED82F10018053E /* en */, F4A3A6EE25ED82F20018053E /* fr */, F4111AD6265EE92400FD8950 /* es */, F4FC363D278F914400669B32 /* ja */, F43066D92A12EDE7002AB430 /* he */, ); name = EXC_BAD_ACCESS_SIGBUS.html; path = Help; sourceTree = ""; }; F4CC570B24A79EDA00150EC4 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( F48CF60024A969B5002AD214 /* en */, F45A2D5725EC50960007D50E /* fr */, F4111AE7265EE92600FD8950 /* es */, F4FC364E278F914500669B32 /* ja */, F43066ED2A12EDE9002AB430 /* he */, ); name = MainMenu.xib; sourceTree = ""; }; F4D6C56B2680028A00B78B3D /* RemoteCheck.strings */ = { isa = PBXVariantGroup; children = ( F4D6C56C2680028A00B78B3D /* en */, F4D6C56E268002DE00B78B3D /* fr */, F4D6C56F2680031E00B78B3D /* es */, F4FC3629278F914200669B32 /* ja */, F43066C52A12EDE4002AB430 /* he */, ); name = RemoteCheck.strings; sourceTree = ""; }; F4D7F15D25F04A620024E9A5 /* CUISymbolsFilesLibraryViewController.xib */ = { isa = PBXVariantGroup; children = ( F4D7F15C25F04A620024E9A5 /* en */, F4D7F15E25F04A630024E9A5 /* fr */, F4111ACA265EE92200FD8950 /* es */, F4FC3630278F914200669B32 /* ja */, F43066CC2A12EDE5002AB430 /* he */, ); name = CUISymbolsFilesLibraryViewController.xib; sourceTree = ""; }; F4D7F16125F04A9D0024E9A5 /* CUIPreferencePaneSymbolicationViewController.xib */ = { isa = PBXVariantGroup; children = ( F4D7F16025F04A9D0024E9A5 /* en */, F4D7F16225F04A9E0024E9A5 /* fr */, F4111ACB265EE92300FD8950 /* es */, F4FC3631278F914200669B32 /* ja */, F43066CD2A12EDE6002AB430 /* he */, ); name = CUIPreferencePaneSymbolicationViewController.xib; sourceTree = ""; }; F4E6ED9A2849695100766F9A /* unknown_termination_reason.html */ = { isa = PBXVariantGroup; children = ( F4E6ED9B2849695100766F9A /* en */, F4E6ED9D2849696000766F9A /* es */, F4E6ED9E2849696600766F9A /* fr */, F4E6ED9F2849696C00766F9A /* ja */, F43066E22A12EDE7002AB430 /* he */, ); name = unknown_termination_reason.html; sourceTree = ""; }; F4E6EDA2284969E500766F9A /* ENDPOINTSECURITY_2.html */ = { isa = PBXVariantGroup; children = ( F4E6EDA3284969E500766F9A /* en */, F4E6EDA528496E2A00766F9A /* fr */, F43066E32A12EDE8002AB430 /* he */, F4CE09A42A76E43300BACB71 /* es */, F4CE09A52A76E44D00BACB71 /* ja */, ); name = ENDPOINTSECURITY_2.html; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ F4CC571A24A79EDA00150EC4 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F43BA4E425F2674100D8D68A /* SharedConfigurationSettings.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_HARDENED_RUNTIME = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; SDKROOT = macosx; }; name = Debug; }; F4CC571B24A79EDA00150EC4 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = F43BA4E425F2674100D8D68A /* SharedConfigurationSettings.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_HARDENED_RUNTIME = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; SDKROOT = macosx; }; name = Release; }; F4CC571D24A79EDA00150EC4 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_WARN_BOOL_CONVERSION = YES_ERROR; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 78; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = app_unexpectedly/app_unexpectedly_Prefix.pch; INFOPLIST_FILE = app_unexpectedly/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = fr.whitebox.unexpectedly; PRODUCT_NAME = Unexpectedly; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; F4CC571E24A79EDA00150EC4 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_WARN_BOOL_CONVERSION = YES_ERROR; CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 78; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = app_unexpectedly/app_unexpectedly_Prefix.pch; INFOPLIST_FILE = app_unexpectedly/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = fr.whitebox.unexpectedly; PRODUCT_NAME = Unexpectedly; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ F4CC56FA24A79EDA00150EC4 /* Build configuration list for PBXProject "app_unexpectedly" */ = { isa = XCConfigurationList; buildConfigurations = ( F4CC571A24A79EDA00150EC4 /* Debug */, F4CC571B24A79EDA00150EC4 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; F4CC571C24A79EDA00150EC4 /* Build configuration list for PBXNativeTarget "Unexpectedly" */ = { isa = XCConfigurationList; buildConfigurations = ( F4CC571D24A79EDA00150EC4 /* Debug */, F4CC571E24A79EDA00150EC4 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = F4CC56F724A79EDA00150EC4 /* Project object */; } ================================================ FILE: app_unexpectedly/app_unexpectedly.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: app_unexpectedly/app_unexpectedly.xcodeproj/xcshareddata/xcschemes/app_unexpectedly.xcscheme ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly.xcodeproj/xcuserdata/stephane.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist ================================================ ================================================ FILE: app_unexpectedly/app_unexpectedly.xcodeproj/xcuserdata/stephane.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState app_unexpectedly.xcscheme_^#shared#^_ orderHint 0 ================================================ FILE: build.sh ================================================ #!/bin/sh BASEDIR="$( dirname "$0" )" cd "$BASEDIR" ABSOLUTE_FOLDER_PATH=`pwd` ABSOLUTE_BUILD_PATH="$ABSOLUTE_FOLDER_PATH"/distribution/build echo "$ABSOLUTE_FOLDER_PATH" ## Clean and create the build folder /bin/rm -rf distribution/build /bin/mkdir -p distribution/build ## Create the artifacts folder if needed /bin/mkdir -p distribution/artifacts # Retrieve the version VERSION="1.0" if [ -f distribution/Version ]; then VERSION=`cat distribution/Version` fi ## Build the application pushd app_unexpectedly /usr/bin/xcrun agvtool next-version -all /usr/bin/xcrun agvtool new-marketing-version $VERSION /usr/bin/xcodebuild -project "app_unexpectedly.xcodeproj" clean build -configuration Release -scheme "app_unexpectedly" -derivedDataPath "$ABSOLUTE_BUILD_PATH" CONFIGURATION_BUILD_DIR="$ABSOLUTE_BUILD_PATH" popd ## Notarize if supported if [ -f request_notarization-notarytool.sh ]; then /bin/sh request_notarization-notarytool.sh fi ## Create the disk image pushd distribution DISKIMAGE_NAME="Unexpectedly" ## Convert disk image template to read-write disk image if [ -f build/"$DISKIMAGE_NAME"_rw.dmg ] then /bin/rm build/"$DISKIMAGE_NAME"_rw.dmg fi /usr/bin/hdiutil convert Template/Template_ro.dmg -format UDRW -o build/"$DISKIMAGE_NAME"_rw.dmg > /dev/null ## Mount the disk image /usr/bin/hdiutil attach build/"$DISKIMAGE_NAME"_rw.dmg -mountpoint build/diskimage_rw > /dev/null ## Rename the disk image if [ -f Version ]; then /usr/sbin/diskutil rename "$DISKIMAGE_NAME" "$DISKIMAGE_NAME $VERSION" fi ## Copy the ReadMe to the disk image and prevent edition if [ -f "Documents/ReadMe.rtf" ] then /usr/bin/sed '2 s/^/\\readonlydoc1/' <"Documents/ReadMe.rtf" > "build/diskimage_rw/ReadMe.rtf" else echo "Missing ReadMe.rtf" fi ## Copy the application to the disk image if [ -d build/Unexpectedly.app ] then /bin/cp -R build/Unexpectedly.app build/diskimage_rw/ else echo "Missing application" fi ## Remove useless files for a disk image /bin/rm "build/diskimage_rw/Desktop DB" /bin/rm "build/diskimage_rw/Desktop DF" /bin/rm -r build/diskimage_rw/.fseventsd ## Unmount the disk image /usr/bin/hdiutil detach build/diskimage_rw > /dev/null ## Convert disk image to read-only if [ -f artifacts/"$DISKIMAGE_NAME".dmg ] then /bin/rm artifacts/"$DISKIMAGE_NAME".dmg fi /usr/bin/hdiutil convert build/"$DISKIMAGE_NAME"_rw.dmg -format UDZO -o artifacts/"$DISKIMAGE_NAME".dmg > /dev/null ## Remove the temporary disk image if [ -f build/"$DISKIMAGE_NAME"_rw.dmg ] then /bin/rm build/"$DISKIMAGE_NAME"_rw.dmg fi popd exit 0 ================================================ FILE: distribution/Documents/ReadMe.rtf ================================================ {\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 LucidaGrande;\f2\fswiss\fcharset0 Helvetica-Bold; } {\colortbl;\red255\green255\blue255;\red46\green111\blue253;\red0\green0\blue0;\red255\green255\blue255; \red100\green100\blue100;\red59\green24\blue255;} {\*\expandedcolortbl;;\cssrgb\c22750\c53231\c99501;\cssrgb\c0\c0\c0;\cssrgb\c100000\c100000\c100000; \cssrgb\c46667\c46667\c46667;\csgenericrgb\c23137\c9412\c100000;} \margl1440\margr1440\vieww16440\viewh23220\viewkind0 \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \f0\fs24 \cf0 \ \fs72 Unexpectedly 1.0 ( \fs54 beta 4 \fs72 ) \fs24 \ \ \ \f1 Unexpectedly is a macOS utility to browse crash reports. \f0 \ \ \f2\b\fs28 \ System Requirements \ \f0\b0\fs24 \ \f1 \'95 Intel or Apple Silicon based Mac\ \'95 macOS 10.13 or later \f0 \ \ \ \f2\b\fs28 Installing Unexpectedly \f0\b0\fs24 \ \ \f1 To manually install Unexpectedly on a Mac, follow these instructions: \ \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\sl312\slmult1\partightenfactor0 \cf0 \cf2 1.\cf0 Double-click the Unexpectedly.dmg disk image file to mount it on the desktop.\ \cf2 2.\cf0 Double-click the Unexpectedly volume.\ \cf2 3.\cf0 Drag and drop the Unexpectedly.app application to the Applications folder of your Mac.\ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \f0 \cf0 \ \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\sl312\slmult1\partightenfactor0 \f2\b\fs28 \cf0 First launch of Unexpectedly \f0\b0\fs24 \ \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\sl312\slmult1\partightenfactor0 \f1 \cf0 Just double-click the icon of the Unexpectedly application in the Finder as usual. \f0 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \cf0 \ \ \f2\b\fs28 Legal Stuff \f0\b0\fs24 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \cf0 \ \f1 Copyright \'a9 2021-2026, St\'e9phane Sudre. All rights reserved.\ \ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\ \ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\ \ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\ \ Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\ \ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\ \ License for the third party code Included in this software: \ \ \pard\tx593\pardeftab720\li232\fi14\partightenfactor0 \cf0 NoodleLineNumberView & NoodleLineNumberMarker \f2\b\fs22 \cf3 \cb4 \expnd0\expndtw0\kerning0 \ \f0\b0 \ \f1\fs24 \cf0 \cb1 \kerning1\expnd0\expndtw0 Created by Paul Kim on 9/28/08.\ Copyright (c) 2008 Noodlesoft, LLC. All rights reserved.\ \ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\ \ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\ \ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\ \f0 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \f1 \cf0 License for the brushed-alum.png file: \f2\b\fs26 \cf5 \expnd0\expndtw0\kerning0 \ \pard\pardeftab720\partightenfactor0 \cf5 \ \pard\tx593\pardeftab720\li232\fi14\partightenfactor0 \f1\b0\fs24 \cf0 \kerning1\expnd0\expndtw0 CC BY-SA 3.0 - Subtle Patterns \'a9 {\field{\*\fldinst{HYPERLINK "https://www.toptal.com/designers"}}{\fldrslt Toptal Designers}}\ \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \cf0 License for the NSMenuItem+RSCore.h/.m files:\ \ \pard\tx593\pardeftab720\li232\fi14\partightenfactor0 \f0 \cf0 Copyright (c) 2002-2025 Brent Simmons\ \ Permission is hereby granted, free of charge, to any person obtaining a copy\ of this software and associated documentation files (the "Software"), to deal\ in the Software without restriction, including without limitation the rights\ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ copies of the Software, and to permit persons to whom the Software is\ furnished to do so, subject to the following conditions:\ \ The above copyright notice and this permission notice shall be included in all\ copies or substantial portions of the Software.\ \ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\ SOFTWARE.\ \ \pard\pardeftab720\partightenfactor0 \cf0 \ \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \f2\b\fs28 \cf0 Bug Reports, Suggestions \f0\b0\fs24 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \cf0 \ \f1 For bug reports, suggestions and localizations , please send an e-mail to \f0 \cf6 \ul \ulc6 dev.unexpectedly@gmail.com \f1 \cf0 \ulnone . \f0 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \cf0 \ \ \f2\b\fs28 Price \f0\b0\fs24 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \cf0 \ \f1 Unexpectedly is offered free of charge. \f0 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \cf0 \ \ \f2\b\fs28 Source Code \f0\b0\fs24 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \cf0 \ \f1 The source code for Unexpectedly is available at \f0 \cf6 \ul https://github.com/packagesdev/unexpectedly\cf0 \ulnone \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \cf0 \ \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \f1\fs20 \cf0 Apple, Mac, Mac OS and macOS are trademarks of Apple, Inc. \fs24 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\pardirnatural\partightenfactor0 \f0 \cf0 \ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\li139\fi-4\partightenfactor0 \fs18 \cf0 Disclaimer: It is not possible to guarantee that the crash reports of an application will not look better than the application itself.} ================================================ FILE: distribution/Unexpectedly.pkgproj ================================================ PROJECT PACKAGE_FILES DEFAULT_INSTALL_LOCATION / HIERARCHY CHILDREN CHILDREN BUNDLE_CAN_DOWNGRADE BUNDLE_POSTINSTALL_PATH PATH_TYPE 0 BUNDLE_PREINSTALL_PATH PATH_TYPE 0 CHILDREN GID 0 PATH build/Unexpectedly.app PATH_TYPE 1 PERMISSIONS 493 TYPE 3 UID 0 GID 80 PATH Applications PATH_TYPE 0 PERMISSIONS 509 TYPE 1 UID 0 CHILDREN CHILDREN GID 80 PATH Application Support PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Automator PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Documentation PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Extensions PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Filesystems PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Frameworks PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Input Methods PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Internet Plug-Ins PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH LaunchAgents PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH LaunchDaemons PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH PreferencePanes PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Preferences PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 80 PATH Printers PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH PrivilegedHelperTools PATH_TYPE 0 PERMISSIONS 1005 TYPE 1 UID 0 CHILDREN GID 0 PATH QuickLook PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH QuickTime PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Screen Savers PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Scripts PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Services PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN GID 0 PATH Widgets PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 GID 0 PATH Library PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 CHILDREN CHILDREN GID 0 PATH Shared PATH_TYPE 0 PERMISSIONS 1023 TYPE 1 UID 0 GID 80 PATH Users PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 GID 0 PATH / PATH_TYPE 0 PERMISSIONS 493 TYPE 1 UID 0 PAYLOAD_TYPE 0 PRESERVE_EXTENDED_ATTRIBUTES SHOW_INVISIBLE SPLIT_FORKS TREAT_MISSING_FILES_AS_WARNING VERSION 5 PACKAGE_SCRIPTS POSTINSTALL_PATH PATH_TYPE 0 PREINSTALL_PATH PATH_TYPE 0 RESOURCES PACKAGE_SETTINGS AUTHENTICATION 1 CONCLUSION_ACTION 0 FOLLOW_SYMBOLIC_LINKS IDENTIFIER fr.whitebox.pkg.unexpectedly-app LOCATION 0 NAME OVERWRITE_PERMISSIONS PAYLOAD_SIZE -1 REFERENCE_PATH RELOCATABLE USE_HFS+_COMPRESSION VERSION 1.0 PROJECT_COMMENTS NOTES PROJECT_SETTINGS BUILD_PATH PATH build PATH_TYPE 1 EXCLUDED_FILES PATTERNS_ARRAY REGULAR_EXPRESSION STRING .DS_Store TYPE 0 PROTECTED PROXY_NAME Remove .DS_Store files PROXY_TOOLTIP Remove ".DS_Store" files created by the Finder. STATE PATTERNS_ARRAY REGULAR_EXPRESSION STRING .pbdevelopment TYPE 0 PROTECTED PROXY_NAME Remove .pbdevelopment files PROXY_TOOLTIP Remove ".pbdevelopment" files created by ProjectBuilder or Xcode. STATE PATTERNS_ARRAY REGULAR_EXPRESSION STRING CVS TYPE 1 REGULAR_EXPRESSION STRING .cvsignore TYPE 0 REGULAR_EXPRESSION STRING .cvspass TYPE 0 REGULAR_EXPRESSION STRING .svn TYPE 1 REGULAR_EXPRESSION STRING .git TYPE 1 REGULAR_EXPRESSION STRING .gitignore TYPE 0 PROTECTED PROXY_NAME Remove SCM metadata PROXY_TOOLTIP Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems. STATE PATTERNS_ARRAY REGULAR_EXPRESSION STRING classes.nib TYPE 0 REGULAR_EXPRESSION STRING designable.db TYPE 0 REGULAR_EXPRESSION STRING info.nib TYPE 0 PROTECTED PROXY_NAME Optimize nib files PROXY_TOOLTIP Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles. STATE PATTERNS_ARRAY REGULAR_EXPRESSION STRING Resources Disabled TYPE 1 PROTECTED PROXY_NAME Remove Resources Disabled folders PROXY_TOOLTIP Remove "Resources Disabled" folders. STATE SEPARATOR NAME Unexpectedly PAYLOAD_ONLY TYPE 1 VERSION 2 ================================================ FILE: distribution/Version ================================================ 1.0 ================================================ FILE: plugin_quicklook/crashreport/GeneratePreviewForURL.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #include #include #import "CUICrashLogsProvider.h" #import "CUIIPSTransform.h" #import "CUICrashDataTransform.h" #import "CUIThemesManager.h" #import "CUIApplicationPreferences+Themes.h" #import "CUIThemeItemsGroup+UI.h" #import "QLCUIThemesProvider.h" extern NSString * const CUITextModeDisplaySettingsVisibleSectionKey; extern NSString * const CUITextModeDisplaySettingsVisibleStackFrameComponentsKey; OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); /* ----------------------------------------------------------------------------- Generate a preview for file This function's job is to create preview for designated file ----------------------------------------------------------------------------- */ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) { @autoreleasepool { CUIRawCrashLog * tCrashLog=[[CUICrashLogsProvider defaultProvider] crashLogWithContentsOfFile:((__bridge NSURL *)url).path error:NULL]; if (tCrashLog==nil) return noErr; [tCrashLog finalizeParsing]; CUITextModeDisplaySettings * tDisplaySettings=[CUITextModeDisplaySettings new]; tDisplaySettings.visibleSections=CUIDocumentAllSections; tDisplaySettings.visibleStackFrameComponents=CUIStackFrameAllComponents; QLCUIThemesProvider * tThemesProvider = [QLCUIThemesProvider new]; CUIReportThemedTransform * tReportThemedTransform=nil; if (tCrashLog.ipsReport!=nil) { tReportThemedTransform=[[CUIIPSTransform alloc] initWithThemesProvider:tThemesProvider]; tReportThemedTransform.input=tCrashLog.ipsReport; } else { tReportThemedTransform=[[CUICrashDataTransform alloc] initWithThemesProvider:tThemesProvider]; tReportThemedTransform.input=tCrashLog; } tReportThemedTransform.displaySettings=tDisplaySettings; tReportThemedTransform.fontSizeDelta=0; tReportThemedTransform.hyperlinksStyle=CUIHyperlinksNone; if ([tReportThemedTransform transform]==NO) { // A COMPLETER } NSAttributedString * tAttributedString=tReportThemedTransform.output; CUIThemeItemsGroup * tGroup=[tThemesProvider.currentTheme itemsGroupWithIdentifier:[CUIApplicationPreferences groupIdentifierForPresentationMode:CUIPresentationModeText]]; NSColor * tBackgroundColor=[tGroup attributesForItem:CUIThemeItemBackground].color; NSData *tRTFData = [tAttributedString dataFromRange:NSMakeRange(0, tAttributedString.length) documentAttributes:@{ NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType, NSBackgroundColorDocumentAttribute:tBackgroundColor } error:NULL]; if (tRTFData==nil) return noErr; QLPreviewRequestSetDataRepresentation(preview, (__bridge CFDataRef)tRTFData, kUTTypeRTF, NULL); } return noErr; } void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview) { // Implement only if supported } ================================================ FILE: plugin_quicklook/crashreport/GenerateThumbnailForURL.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #include #include #include #import "CUICrashLogsProvider.h" #import "CUIThemesManager.h" #import "CUIApplicationPreferences+Themes.h" #import "CUIThemeItemsGroup+UI.h" #import "CUIIPSTransform.h" #import "CUICrashDataTransform.h" #import "QLCUIThemesProvider.h" extern const CFStringRef kQLThumbnailPropertyIconFlavorKey; OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail); /* ----------------------------------------------------------------------------- Generate a thumbnail for file This function's job is to create thumbnail for designated file as fast as possible ----------------------------------------------------------------------------- */ OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) { CUIRawCrashLog * tCrashLog=[[CUICrashLogsProvider defaultProvider] crashLogWithContentsOfFile:((__bridge NSURL *)url).path error:NULL]; if (tCrashLog==nil) return noErr; [tCrashLog finalizeParsing]; CUITextModeDisplaySettings * tDisplaySettings=[CUITextModeDisplaySettings new]; tDisplaySettings.visibleSections=CUIDocumentAllSections; tDisplaySettings.visibleStackFrameComponents=CUIStackFrameAllComponents; QLCUIThemesProvider * tThemesProvider = [QLCUIThemesProvider new]; CUIReportThemedTransform * tReportThemedTransform=nil; if (tCrashLog.ipsReport!=nil) { tReportThemedTransform=[[CUIIPSTransform alloc] initWithThemesProvider:tThemesProvider]; tReportThemedTransform.input=tCrashLog.ipsReport; } else { tReportThemedTransform=[[CUICrashDataTransform alloc] initWithThemesProvider:tThemesProvider]; tReportThemedTransform.input=tCrashLog; } tReportThemedTransform.displaySettings=tDisplaySettings; tReportThemedTransform.fontSizeDelta=0; tReportThemedTransform.hyperlinksStyle=CUIHyperlinksNone; if ([tReportThemedTransform transform]==NO) { // A COMPLETER } NSAttributedString * tAttributedString=tReportThemedTransform.output; CUIThemeItemsGroup * tGroup=[tThemesProvider.currentTheme itemsGroupWithIdentifier:[CUIApplicationPreferences groupIdentifierForPresentationMode:CUIPresentationModeText]]; NSColor * tBackgroundColor=[tGroup attributesForItem:CUIThemeItemBackground].color; NSData *tRTFData = [tAttributedString dataFromRange:NSMakeRange(0, tAttributedString.length) documentAttributes:@{ NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType, NSBackgroundColorDocumentAttribute:tBackgroundColor } error:NULL]; if (tRTFData==nil) return noErr; NSDictionary * tProperties=@{ (__bridge NSString *)kQLThumbnailPropertyExtensionKey:@"", (__bridge NSString *)kQLThumbnailPropertyIconFlavorKey:@(9), }; QLThumbnailRequestSetThumbnailWithDataRepresentation(thumbnail, (__bridge CFDataRef)tRTFData, kUTTypeRTF, NULL,(__bridge CFDictionaryRef)tProperties); return noErr; } void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail) { // Implement only if supported } ================================================ FILE: plugin_quicklook/crashreport/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDocumentTypes CFBundleTypeRole QLGenerator LSItemContentTypes com.apple.crashreport CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundleShortVersionString 1.0 CFBundleVersion 1 CFPlugInDynamicRegisterFunction CFPlugInDynamicRegistration NO CFPlugInFactories 411DC9EF-E613-47F4-8F9E-641ACBEC733E QuickLookGeneratorPluginFactory CFPlugInTypes 5E2D9680-5022-40FA-B806-43349622E5B9 411DC9EF-E613-47F4-8F9E-641ACBEC733E CFPlugInUnloadFunction NSHumanReadableCopyright Copyright © 2021-2022 Stéphane Sudre. All rights reserved. QLNeedsToBeRunInMainThread QLPreviewHeight 800 QLPreviewWidth 800 QLSupportsConcurrentRequests QLThumbnailMinimumSize 129 ================================================ FILE: plugin_quicklook/crashreport/NSUserDefaults+UNXQuickLookGenerator.h ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import @interface NSUserDefaults (UNXQuickLookGenerator) @end ================================================ FILE: plugin_quicklook/crashreport/NSUserDefaults+UNXQuickLookGenerator.m ================================================ /* Copyright (c) 2021, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Category so that the QuickLookGenerator can access the main application preferences as if it was its own. #import "NSUserDefaults+UNXQuickLookGenerator.h" @implementation NSUserDefaults (UNXQuickLookGenerator) + (NSUserDefaults *)standardUserDefaults { return [[NSUserDefaults alloc] initWithSuiteName:@"fr.whitebox.unexpectedly"]; } @end ================================================ FILE: plugin_quicklook/crashreport/QLCUIThemesProvider.h ================================================ /* Copyright (c) 2021-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "CUITheme.h" @interface QLCUIThemesProvider : NSObject @end ================================================ FILE: plugin_quicklook/crashreport/QLCUIThemesProvider.m ================================================ /* Copyright (c) 2021-2025, Stephane Sudre All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the WhiteBox nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // Category to replace the init and currentTheme methods as defined in the main application. // For the preview and thumbnail, use the default theme UUID. #import "QLCUIThemesProvider.h" static NSMutableDictionary * sQLThemeRegistry=nil; NSString * const QLCUIThemesQuickLookGeneratorThemeUUIDKey=@"themes.quicklook-generator.UUID"; @implementation QLCUIThemesProvider - (instancetype)init { self=[super init]; if (self!=nil) { [[NSUserDefaults standardUserDefaults] registerDefaults:@{ QLCUIThemesQuickLookGeneratorThemeUUIDKey:@"UUID2" }]; sQLThemeRegistry=[NSMutableDictionary dictionary]; NSArray * tThemesArray=[NSArray arrayWithContentsOfURL:[[NSBundle bundleForClass:QLCUIThemesProvider.class] URLForResource:@"default_themes" withExtension:@"plist"]]; for (NSDictionary * tThemeRepresentation in tThemesArray) { CUITheme * tTheme=[[CUITheme alloc] initWithRepresentation:tThemeRepresentation]; if (tTheme==nil) { NSLog(@"Archive representation of theme could not be loaded"); return nil; } sQLThemeRegistry[tTheme.UUID]=tTheme; } } return self; } #pragma mark - - (NSArray *)allThemes { return sQLThemeRegistry.allValues; } - (CUITheme *)currentTheme { return sQLThemeRegistry[[[NSUserDefaults standardUserDefaults] objectForKey:QLCUIThemesQuickLookGeneratorThemeUUIDKey]]; } @end ================================================ FILE: plugin_quicklook/crashreport/main.c ================================================ //============================================================================== // // DO NO MODIFY THE CONTENT OF THIS FILE // // This file contains the generic CFPlug-in code necessary for your generator // To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c // //============================================================================== #include #include #include #include // ----------------------------------------------------------------------------- // constants // ----------------------------------------------------------------------------- // Don't modify this line #define PLUGIN_ID "921B146B-60AC-4F91-8AFB-EB28AA72E8DC" // // Below is the generic glue code for all plug-ins. // // You should not have to modify this code aside from changing // names if you decide to change the names defined in the Info.plist // // ----------------------------------------------------------------------------- // typedefs // ----------------------------------------------------------------------------- // The thumbnail generation function to be implemented in GenerateThumbnailForURL.c OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail); // The preview generation function to be implemented in GeneratePreviewForURL.c OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); // The layout for an instance of QuickLookGeneratorPlugIn typedef struct __QuickLookGeneratorPluginType { void *conduitInterface; CFUUIDRef factoryID; UInt32 refCount; } QuickLookGeneratorPluginType; // ----------------------------------------------------------------------------- // prototypes // ----------------------------------------------------------------------------- // Forward declaration for the IUnknown implementation. // QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID); void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance); HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv); void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID); ULONG QuickLookGeneratorPluginAddRef(void *thisInstance); ULONG QuickLookGeneratorPluginRelease(void *thisInstance); // ----------------------------------------------------------------------------- // myInterfaceFtbl definition // ----------------------------------------------------------------------------- // The QLGeneratorInterfaceStruct function table. // static QLGeneratorInterfaceStruct myInterfaceFtbl = { NULL, QuickLookGeneratorQueryInterface, QuickLookGeneratorPluginAddRef, QuickLookGeneratorPluginRelease, NULL, NULL, NULL, NULL }; // ----------------------------------------------------------------------------- // AllocQuickLookGeneratorPluginType // ----------------------------------------------------------------------------- // Utility function that allocates a new instance. // You can do some initial setup for the generator here if you wish // like allocating globals etc... // QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID) { QuickLookGeneratorPluginType *theNewInstance; theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType)); memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType)); /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */ theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct)); memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct)); /* Retain and keep an open instance refcount for each factory. */ theNewInstance->factoryID = CFRetain(inFactoryID); CFPlugInAddInstanceForFactory(inFactoryID); /* This function returns the IUnknown interface so set the refCount to one. */ theNewInstance->refCount = 1; return theNewInstance; } // ----------------------------------------------------------------------------- // DeallocQuickLookGeneratorPluginType // ----------------------------------------------------------------------------- // Utility function that deallocates the instance when // the refCount goes to zero. // In the current implementation generator interfaces are never deallocated // but implement this as this might change in the future // void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance) { CFUUIDRef theFactoryID; theFactoryID = thisInstance->factoryID; /* Free the conduitInterface table up */ free(thisInstance->conduitInterface); /* Free the instance structure */ free(thisInstance); if (theFactoryID){ CFPlugInRemoveInstanceForFactory(theFactoryID); CFRelease(theFactoryID); } } // ----------------------------------------------------------------------------- // QuickLookGeneratorQueryInterface // ----------------------------------------------------------------------------- // Implementation of the IUnknown QueryInterface function. // HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv) { CFUUIDRef interfaceID; interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid); if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){ /* If the Right interface was requested, bump the ref count, * set the ppv parameter equal to the instance, and * return good status. */ ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration; ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance); *ppv = thisInstance; CFRelease(interfaceID); return S_OK; }else{ /* Requested interface unknown, bail with error. */ *ppv = NULL; CFRelease(interfaceID); return E_NOINTERFACE; } } // ----------------------------------------------------------------------------- // QuickLookGeneratorPluginAddRef // ----------------------------------------------------------------------------- // Implementation of reference counting for this type. Whenever an interface // is requested, bump the refCount for the instance. NOTE: returning the // refcount is a convention but is not required so don't rely on it. // ULONG QuickLookGeneratorPluginAddRef(void *thisInstance) { ((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1; return ((QuickLookGeneratorPluginType*) thisInstance)->refCount; } // ----------------------------------------------------------------------------- // QuickLookGeneratorPluginRelease // ----------------------------------------------------------------------------- // When an interface is released, decrement the refCount. // If the refCount goes to zero, deallocate the instance. // ULONG QuickLookGeneratorPluginRelease(void *thisInstance) { ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1; if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){ DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance ); return 0; }else{ return ((QuickLookGeneratorPluginType*) thisInstance )->refCount; } } // ----------------------------------------------------------------------------- // QuickLookGeneratorPluginFactory // ----------------------------------------------------------------------------- void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID) { QuickLookGeneratorPluginType *result; CFUUIDRef uuid; /* If correct type is being requested, allocate an * instance of kQLGeneratorTypeID and return the IUnknown interface. */ if (CFEqual(typeID,kQLGeneratorTypeID)){ uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID)); result = AllocQuickLookGeneratorPluginType(uuid); CFRelease(uuid); return result; } /* If the requested type is incorrect, return NULL. */ return NULL; } ================================================ FILE: plugin_quicklook/crashreport.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 50; objects = { /* Begin PBXBuildFile section */ F40681CE2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = F40681CC2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.h */; }; F40681CF2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = F40681CD2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.m */; }; F4069C5726683CC7002B32F5 /* CUICrashLog.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C5226683CC6002B32F5 /* CUICrashLog.m */; }; F4069C5826683CC7002B32F5 /* CUICodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C5326683CC6002B32F5 /* CUICodeType.h */; }; F4069C5926683CC7002B32F5 /* CUIRawCrashLog.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C5426683CC6002B32F5 /* CUIRawCrashLog.m */; }; F4069C5A26683CC7002B32F5 /* CUICrashLog.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C5526683CC7002B32F5 /* CUICrashLog.h */; }; F4069C5B26683CC7002B32F5 /* CUIRawCrashLog.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C5626683CC7002B32F5 /* CUIRawCrashLog.h */; }; F4069C7026683CF9002B32F5 /* CUICrashLogBacktraces.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C5C26683CF7002B32F5 /* CUICrashLogBacktraces.m */; }; F4069C7126683CF9002B32F5 /* CUIRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C5D26683CF8002B32F5 /* CUIRegister.h */; }; F4069C7226683CF9002B32F5 /* CUICrashLogExceptionInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C5E26683CF8002B32F5 /* CUICrashLogExceptionInformation.h */; }; F4069C7326683CF9002B32F5 /* CUIBinaryImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C5F26683CF8002B32F5 /* CUIBinaryImage.m */; }; F4069C7426683CF9002B32F5 /* CUICrashLogExceptionInformation+UI.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6026683CF8002B32F5 /* CUICrashLogExceptionInformation+UI.h */; }; F4069C7526683CF9002B32F5 /* CUICrashLogExceptionInformation+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6126683CF8002B32F5 /* CUICrashLogExceptionInformation+UI.m */; }; F4069C7626683CF9002B32F5 /* CUICrashLogHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6226683CF8002B32F5 /* CUICrashLogHeader.m */; }; F4069C7726683CF9002B32F5 /* CUICrashLogThreadState.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6326683CF8002B32F5 /* CUICrashLogThreadState.h */; }; F4069C7826683CF9002B32F5 /* CUICrashLogThreadState+UI.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6426683CF8002B32F5 /* CUICrashLogThreadState+UI.h */; }; F4069C7926683CF9002B32F5 /* CUICrashLogThreadState+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6526683CF8002B32F5 /* CUICrashLogThreadState+UI.m */; }; F4069C7A26683CF9002B32F5 /* CUICrashLogBinaryImages.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6626683CF8002B32F5 /* CUICrashLogBinaryImages.h */; }; F4069C7B26683CF9002B32F5 /* CUICrashLogHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6726683CF8002B32F5 /* CUICrashLogHeader.h */; }; F4069C7C26683CF9002B32F5 /* CUICrashLogExceptionInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6826683CF8002B32F5 /* CUICrashLogExceptionInformation.m */; }; F4069C7D26683CF9002B32F5 /* CUIRegister.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6926683CF8002B32F5 /* CUIRegister.m */; }; F4069C7E26683CF9002B32F5 /* CUICrashLogDianosticMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6A26683CF9002B32F5 /* CUICrashLogDianosticMessages.h */; }; F4069C7F26683CF9002B32F5 /* CUICrashLogBinaryImages.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6B26683CF9002B32F5 /* CUICrashLogBinaryImages.m */; }; F4069C8026683CF9002B32F5 /* CUICrashLogDianosticMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6C26683CF9002B32F5 /* CUICrashLogDianosticMessages.m */; }; F4069C8126683CF9002B32F5 /* CUICrashLogBacktraces.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6D26683CF9002B32F5 /* CUICrashLogBacktraces.h */; }; F4069C8226683CF9002B32F5 /* CUICrashLogThreadState.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C6E26683CF9002B32F5 /* CUICrashLogThreadState.m */; }; F4069C8326683CF9002B32F5 /* CUIBinaryImage.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C6F26683CF9002B32F5 /* CUIBinaryImage.h */; }; F4069C8A26683D10002B32F5 /* CUICallStackBacktrace.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C8426683D10002B32F5 /* CUICallStackBacktrace.m */; }; F4069C8B26683D10002B32F5 /* CUIStackFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C8526683D10002B32F5 /* CUIStackFrame.m */; }; F4069C8C26683D10002B32F5 /* CUIThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C8626683D10002B32F5 /* CUIThread.m */; }; F4069C8D26683D10002B32F5 /* CUICallStackBacktrace.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C8726683D10002B32F5 /* CUICallStackBacktrace.h */; }; F4069C8E26683D10002B32F5 /* CUIStackFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C8826683D10002B32F5 /* CUIStackFrame.h */; }; F4069C8F26683D10002B32F5 /* CUIThread.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C8926683D10002B32F5 /* CUIThread.h */; }; F4069C9326683D2E002B32F5 /* NSArray+WBExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C9126683D2D002B32F5 /* NSArray+WBExtensions.m */; }; F4069C9426683D2E002B32F5 /* NSArray+WBExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C9226683D2D002B32F5 /* NSArray+WBExtensions.h */; }; F4069C9726683D88002B32F5 /* CUIParsingErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C9526683D88002B32F5 /* CUIParsingErrors.m */; }; F4069C9A26683DA0002B32F5 /* CUICrashLogSectionsDetector.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C9826683DA0002B32F5 /* CUICrashLogSectionsDetector.h */; }; F4069C9B26683DA0002B32F5 /* CUICrashLogSectionsDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C9926683DA0002B32F5 /* CUICrashLogSectionsDetector.m */; }; F4069C9E26683DFF002B32F5 /* CUIOperatingSystemVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069C9C26683DFE002B32F5 /* CUIOperatingSystemVersion.h */; }; F4069C9F26683DFF002B32F5 /* CUIOperatingSystemVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069C9D26683DFF002B32F5 /* CUIOperatingSystemVersion.m */; }; F4069CA226683E33002B32F5 /* CUICrashLogsProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CA026683E33002B32F5 /* CUICrashLogsProvider.m */; }; F4069CA326683E33002B32F5 /* CUICrashLogsProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CA126683E33002B32F5 /* CUICrashLogsProvider.h */; }; F4069CAB26683F49002B32F5 /* CUITextModeDisplaySettings.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CA926683F49002B32F5 /* CUITextModeDisplaySettings.h */; }; F4069CAC26683F49002B32F5 /* CUITextModeDisplaySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CAA26683F49002B32F5 /* CUITextModeDisplaySettings.m */; }; F4069CB12668409E002B32F5 /* CUIThemeItemsGroup+UI.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CAF2668409D002B32F5 /* CUIThemeItemsGroup+UI.m */; }; F4069CB22668409E002B32F5 /* CUIThemeItemsGroup+UI.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CB02668409D002B32F5 /* CUIThemeItemsGroup+UI.h */; }; F4069CB5266840D1002B32F5 /* CUIThemeItemsGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CB3266840D1002B32F5 /* CUIThemeItemsGroup.h */; }; F4069CB6266840D1002B32F5 /* CUIThemeItemsGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CB4266840D1002B32F5 /* CUIThemeItemsGroup.m */; }; F4069CB9266840E2002B32F5 /* NSDictionary+WBExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CB7266840E2002B32F5 /* NSDictionary+WBExtensions.m */; }; F4069CBE266840FB002B32F5 /* CUITheme.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CBA266840FA002B32F5 /* CUITheme.h */; }; F4069CBF266840FB002B32F5 /* CUIThemeItemAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CBB266840FB002B32F5 /* CUIThemeItemAttributes.h */; }; F4069CC0266840FB002B32F5 /* CUITheme.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CBC266840FB002B32F5 /* CUITheme.m */; }; F4069CC1266840FB002B32F5 /* CUIThemeItemAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CBD266840FB002B32F5 /* CUIThemeItemAttributes.m */; }; F4069CC52668411A002B32F5 /* NSColor+String.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CC32668411A002B32F5 /* NSColor+String.h */; }; F4069CC62668411A002B32F5 /* NSColor+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CC42668411A002B32F5 /* NSColor+String.m */; }; F4069CC926684136002B32F5 /* CUIThemesManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CC726684135002B32F5 /* CUIThemesManager.h */; }; F4069CCA26684136002B32F5 /* CUIThemesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CC826684135002B32F5 /* CUIThemesManager.m */; }; F4069CCD26684143002B32F5 /* NSArray+UniqueName.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CCB26684143002B32F5 /* NSArray+UniqueName.h */; }; F4069CCE26684143002B32F5 /* NSArray+UniqueName.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CCC26684143002B32F5 /* NSArray+UniqueName.m */; }; F4069CD32668415A002B32F5 /* CUIApplicationPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CCF2668415A002B32F5 /* CUIApplicationPreferences.h */; }; F4069CD42668415A002B32F5 /* CUIApplicationPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CD02668415A002B32F5 /* CUIApplicationPreferences.m */; }; F4069CD52668415A002B32F5 /* CUIApplicationPreferences+Themes.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CD12668415A002B32F5 /* CUIApplicationPreferences+Themes.m */; }; F4069CD62668415A002B32F5 /* CUIApplicationPreferences+Themes.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CD22668415A002B32F5 /* CUIApplicationPreferences+Themes.h */; }; F4069CD92668416B002B32F5 /* NSDictionary+MutableDeepCopy.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CD72668416B002B32F5 /* NSDictionary+MutableDeepCopy.h */; }; F4069CDA2668416B002B32F5 /* NSDictionary+MutableDeepCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CD82668416B002B32F5 /* NSDictionary+MutableDeepCopy.m */; }; F4069CDD26684199002B32F5 /* CUIOutlineModeDisplaySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CDB26684199002B32F5 /* CUIOutlineModeDisplaySettings.m */; }; F4069CDE26684199002B32F5 /* CUIOutlineModeDisplaySettings.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CDC26684199002B32F5 /* CUIOutlineModeDisplaySettings.h */; }; F4069CE1266842E5002B32F5 /* NSFileManager+ExtendedAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = F4069CDF266842E5002B32F5 /* NSFileManager+ExtendedAttributes.h */; }; F4069CE2266842E5002B32F5 /* NSFileManager+ExtendedAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = F4069CE0266842E5002B32F5 /* NSFileManager+ExtendedAttributes.m */; }; F4069CE42668430B002B32F5 /* default_themes.plist in Resources */ = {isa = PBXBuildFile; fileRef = F4069CE32668430B002B32F5 /* default_themes.plist */; }; F41C5D64266988AB00DE5D3A /* CUIStackFrameComponents.h in Headers */ = {isa = PBXBuildFile; fileRef = F41C5D63266988AB00DE5D3A /* CUIStackFrameComponents.h */; }; F428C08F27245CF400FB8CAC /* IPSReport+CrashRepresentation.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C08D27245CF400FB8CAC /* IPSReport+CrashRepresentation.h */; }; F428C09027245CF400FB8CAC /* IPSReport+CrashRepresentation.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C08E27245CF400FB8CAC /* IPSReport+CrashRepresentation.m */; }; F428C0C027245D0800FB8CAC /* IPSImage.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09127245D0500FB8CAC /* IPSImage.m */; }; F428C0C127245D0800FB8CAC /* IPSIncidentHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09227245D0500FB8CAC /* IPSIncidentHeader.m */; }; F428C0C227245D0800FB8CAC /* IPSIncidentExceptionInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09327245D0500FB8CAC /* IPSIncidentExceptionInformation.m */; }; F428C0C327245D0800FB8CAC /* IPSIncidentDiagnosticMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09427245D0500FB8CAC /* IPSIncidentDiagnosticMessage.m */; }; F428C0C427245D0800FB8CAC /* IPSReport.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09527245D0500FB8CAC /* IPSReport.m */; }; F428C0C527245D0800FB8CAC /* IPSThreadInstructionState.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09627245D0500FB8CAC /* IPSThreadInstructionState.m */; }; F428C0C627245D0800FB8CAC /* IPSThreadInstructionStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09727245D0500FB8CAC /* IPSThreadInstructionStream.m */; }; F428C0C727245D0800FB8CAC /* IPSIncident.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C09827245D0500FB8CAC /* IPSIncident.h */; }; F428C0C827245D0800FB8CAC /* IPSRegisterState.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09927245D0500FB8CAC /* IPSRegisterState.m */; }; F428C0C927245D0800FB8CAC /* IPSDateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09A27245D0500FB8CAC /* IPSDateFormatter.m */; }; F428C0CA27245D0800FB8CAC /* IPSApplicationSpecificInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09B27245D0600FB8CAC /* IPSApplicationSpecificInformation.m */; }; F428C0CB27245D0800FB8CAC /* IPSSummary.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09C27245D0600FB8CAC /* IPSSummary.m */; }; F428C0CC27245D0800FB8CAC /* IPSTermination.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09D27245D0600FB8CAC /* IPSTermination.m */; }; F428C0CD27245D0800FB8CAC /* IPSExternalModificationSummary.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C09E27245D0600FB8CAC /* IPSExternalModificationSummary.m */; }; F428C0CE27245D0800FB8CAC /* IPSError.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C09F27245D0600FB8CAC /* IPSError.h */; }; F428C0CF27245D0800FB8CAC /* IPSExternalModificationStatistics.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0A027245D0600FB8CAC /* IPSExternalModificationStatistics.m */; }; F428C0D027245D0800FB8CAC /* IPSReport.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0A127245D0600FB8CAC /* IPSReport.h */; }; F428C0D127245D0800FB8CAC /* IPSTermination.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0A227245D0600FB8CAC /* IPSTermination.h */; }; F428C0D227245D0800FB8CAC /* IPSBundleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0A327245D0600FB8CAC /* IPSBundleInfo.m */; }; F428C0D327245D0800FB8CAC /* IPSException.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0A427245D0600FB8CAC /* IPSException.m */; }; F428C0D427245D0800FB8CAC /* IPSObjectProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0A527245D0600FB8CAC /* IPSObjectProtocol.h */; }; F428C0D527245D0800FB8CAC /* IPSSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0A627245D0600FB8CAC /* IPSSummary.h */; }; F428C0D627245D0800FB8CAC /* IPSThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0A727245D0600FB8CAC /* IPSThread.m */; }; F428C0D727245D0800FB8CAC /* IPSIncidentExceptionInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0A827245D0600FB8CAC /* IPSIncidentExceptionInformation.h */; }; F428C0D827245D0800FB8CAC /* IPSThreadFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0A927245D0600FB8CAC /* IPSThreadFrame.m */; }; F428C0D927245D0800FB8CAC /* IPSExternalModificationSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0AA27245D0600FB8CAC /* IPSExternalModificationSummary.h */; }; F428C0DA27245D0800FB8CAC /* IPSError.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0AB27245D0600FB8CAC /* IPSError.m */; }; F428C0DB27245D0800FB8CAC /* IPSDateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0AC27245D0600FB8CAC /* IPSDateFormatter.h */; }; F428C0DC27245D0800FB8CAC /* IPSThreadFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0AD27245D0600FB8CAC /* IPSThreadFrame.h */; }; F428C0DD27245D0800FB8CAC /* IPSOperatingSystemVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0AE27245D0700FB8CAC /* IPSOperatingSystemVersion.m */; }; F428C0DE27245D0800FB8CAC /* IPSThreadInstructionState.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0AF27245D0700FB8CAC /* IPSThreadInstructionState.h */; }; F428C0DF27245D0800FB8CAC /* IPSThreadInstructionStream.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B027245D0700FB8CAC /* IPSThreadInstructionStream.h */; }; F428C0E027245D0800FB8CAC /* IPSThreadState.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B127245D0700FB8CAC /* IPSThreadState.h */; }; F428C0E127245D0800FB8CAC /* IPSThreadState.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0B227245D0700FB8CAC /* IPSThreadState.m */; }; F428C0E227245D0800FB8CAC /* IPSImage.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B327245D0700FB8CAC /* IPSImage.h */; }; F428C0E327245D0800FB8CAC /* IPSExternalModificationStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B427245D0700FB8CAC /* IPSExternalModificationStatistics.h */; }; F428C0E427245D0800FB8CAC /* IPSApplicationSpecificInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B527245D0700FB8CAC /* IPSApplicationSpecificInformation.h */; }; F428C0E527245D0800FB8CAC /* IPSLegacyInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B627245D0700FB8CAC /* IPSLegacyInfo.h */; }; F428C0E627245D0800FB8CAC /* IPSBundleInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B727245D0700FB8CAC /* IPSBundleInfo.h */; }; F428C0E727245D0800FB8CAC /* IPSLegacyInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0B827245D0700FB8CAC /* IPSLegacyInfo.m */; }; F428C0E827245D0800FB8CAC /* IPSThread.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0B927245D0700FB8CAC /* IPSThread.h */; }; F428C0E927245D0800FB8CAC /* IPSIncident.m in Sources */ = {isa = PBXBuildFile; fileRef = F428C0BA27245D0700FB8CAC /* IPSIncident.m */; }; F428C0EA27245D0800FB8CAC /* IPSIncidentDiagnosticMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0BB27245D0800FB8CAC /* IPSIncidentDiagnosticMessage.h */; }; F428C0EB27245D0800FB8CAC /* IPSRegisterState.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0BC27245D0800FB8CAC /* IPSRegisterState.h */; }; F428C0EC27245D0800FB8CAC /* IPSIncidentHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0BD27245D0800FB8CAC /* IPSIncidentHeader.h */; }; F428C0ED27245D0800FB8CAC /* IPSOperatingSystemVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0BE27245D0800FB8CAC /* IPSOperatingSystemVersion.h */; }; F428C0EE27245D0800FB8CAC /* IPSException.h in Headers */ = {isa = PBXBuildFile; fileRef = F428C0BF27245D0800FB8CAC /* IPSException.h */; }; F4386B0B284953F600B83525 /* CUICrashLogExceptionInformation+QuickHelp.m in Sources */ = {isa = PBXBuildFile; fileRef = F4386B09284953F500B83525 /* CUICrashLogExceptionInformation+QuickHelp.m */; }; F4386B0C284953F600B83525 /* CUICrashLogExceptionInformation+QuickHelp.h in Headers */ = {isa = PBXBuildFile; fileRef = F4386B0A284953F600B83525 /* CUICrashLogExceptionInformation+QuickHelp.h */; }; F4440FD8282C40F9003C810B /* IPSSummarySerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4440FD4282C40F9003C810B /* IPSSummarySerialization.m */; }; F4440FD9282C40F9003C810B /* IPSCrashSummary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4440FD5282C40F9003C810B /* IPSCrashSummary.m */; }; F4440FDA282C40F9003C810B /* IPSSummarySerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = F4440FD6282C40F9003C810B /* IPSSummarySerialization.h */; }; F4440FDB282C40F9003C810B /* IPSCrashSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = F4440FD7282C40F9003C810B /* IPSCrashSummary.h */; }; F47D66AA2DF6310300E078F8 /* IPSExceptionReason.m in Sources */ = {isa = PBXBuildFile; fileRef = F47D66A82DF6310200E078F8 /* IPSExceptionReason.m */; }; F47D66AB2DF6310300E078F8 /* IPSExceptionReason.h in Headers */ = {isa = PBXBuildFile; fileRef = F47D66A92DF6310200E078F8 /* IPSExceptionReason.h */; }; F47F766D2673577C00A74905 /* CUICrashLogErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = F47F76692673577C00A74905 /* CUICrashLogErrors.h */; }; F47F766E2673577C00A74905 /* CUICrashLogErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = F47F766A2673577C00A74905 /* CUICrashLogErrors.m */; }; F47F766F2673577C00A74905 /* CUICrashLogsOpenErrorRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = F47F766B2673577C00A74905 /* CUICrashLogsOpenErrorRecord.m */; }; F47F76702673577C00A74905 /* CUICrashLogsOpenErrorRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = F47F766C2673577C00A74905 /* CUICrashLogsOpenErrorRecord.h */; }; F480FF76273B01B600905974 /* CUIBinaryImageUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F480FF74273B01B500905974 /* CUIBinaryImageUtility.m */; }; F480FF77273B01B600905974 /* CUIBinaryImageUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = F480FF75273B01B600905974 /* CUIBinaryImageUtility.h */; }; F48DAE292661207800C93D40 /* GenerateThumbnailForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = F48DAE282661207800C93D40 /* GenerateThumbnailForURL.m */; }; F48DAE2B2661207800C93D40 /* GeneratePreviewForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = F48DAE2A2661207800C93D40 /* GeneratePreviewForURL.m */; }; F48DAE2D2661207800C93D40 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = F48DAE2C2661207800C93D40 /* main.c */; }; F4ACF4BD266EC92000272A25 /* QLCUIThemesProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = F4ACF4BB266EC92000272A25 /* QLCUIThemesProvider.h */; }; F4ACF4BE266EC92000272A25 /* QLCUIThemesProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = F4ACF4BC266EC92000272A25 /* QLCUIThemesProvider.m */; }; F4BD8C6D2DF4DDE900BD61A8 /* IPSExceptionReason.h in Headers */ = {isa = PBXBuildFile; fileRef = F4BD8C6B2DF4DDE900BD61A8 /* IPSExceptionReason.h */; }; F4BD8C6E2DF4DDE900BD61A8 /* IPSExceptionReason.m in Sources */ = {isa = PBXBuildFile; fileRef = F4BD8C6C2DF4DDE900BD61A8 /* IPSExceptionReason.m */; }; F4CF6CF22DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.m in Sources */ = {isa = PBXBuildFile; fileRef = F4CF6CF02DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.m */; }; F4CF6CF32DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = F4CF6CF12DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.h */; }; F4D0EE98273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D0EE96273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.m */; }; F4D0EE99273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.h in Headers */ = {isa = PBXBuildFile; fileRef = F4D0EE97273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.h */; }; F4D14D642745BFBC003698AD /* IPSImage+UserCode.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D14D622745BFBB003698AD /* IPSImage+UserCode.m */; }; F4D14D652745BFBC003698AD /* IPSImage+UserCode.h in Headers */ = {isa = PBXBuildFile; fileRef = F4D14D632745BFBC003698AD /* IPSImage+UserCode.h */; }; F4DAF0AF27C448E600256EA4 /* IPSImage+Offset.h in Headers */ = {isa = PBXBuildFile; fileRef = F4DAF0AD27C448E600256EA4 /* IPSImage+Offset.h */; }; F4DAF0B027C448E600256EA4 /* IPSImage+Offset.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DAF0AE27C448E600256EA4 /* IPSImage+Offset.m */; }; F4DAFBF42736BA2100FB50A6 /* CUIDataTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = F4DAFBF22736BA2000FB50A6 /* CUIDataTransform.h */; }; F4DAFBF52736BA2100FB50A6 /* CUIDataTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DAFBF32736BA2100FB50A6 /* CUIDataTransform.m */; }; F4DAFBF82736BA3100FB50A6 /* CUIIPSTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DAFBF62736BA3100FB50A6 /* CUIIPSTransform.m */; }; F4DAFBF92736BA3100FB50A6 /* CUIIPSTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = F4DAFBF72736BA3100FB50A6 /* CUIIPSTransform.h */; }; F4E112B02735E6170072D40B /* CUICrashDataTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = F4E112AE2735E6160072D40B /* CUICrashDataTransform.h */; }; F4E112B12735E6170072D40B /* CUICrashDataTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E112AF2735E6170072D40B /* CUICrashDataTransform.m */; }; F4FA4326273EF3FE0068EDB8 /* NSString+CPU.m in Sources */ = {isa = PBXBuildFile; fileRef = F4FA4324273EF3FD0068EDB8 /* NSString+CPU.m */; }; F4FA4327273EF3FE0068EDB8 /* NSString+CPU.h in Headers */ = {isa = PBXBuildFile; fileRef = F4FA4325273EF3FE0068EDB8 /* NSString+CPU.h */; }; F4FC8EAB27C1AA6700291875 /* CUIReportThemedTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = F4FC8EA927C1AA6700291875 /* CUIReportThemedTransform.m */; }; F4FC8EAD27C1AA7C00291875 /* CUIReportThemedTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = F4FC8EAC27C1AA7C00291875 /* CUIReportThemedTransform.h */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ F40681CC2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSUserDefaults+UNXQuickLookGenerator.h"; sourceTree = ""; }; F40681CD2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSUserDefaults+UNXQuickLookGenerator.m"; sourceTree = ""; }; F4069C5226683CC6002B32F5 /* CUICrashLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLog.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLog.m; sourceTree = ""; }; F4069C5326683CC6002B32F5 /* CUICodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICodeType.h; path = ../../app_unexpectedly/app_unexpectedly/CUICodeType.h; sourceTree = ""; }; F4069C5426683CC6002B32F5 /* CUIRawCrashLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIRawCrashLog.m; path = ../../app_unexpectedly/app_unexpectedly/CUIRawCrashLog.m; sourceTree = ""; }; F4069C5526683CC7002B32F5 /* CUICrashLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLog.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLog.h; sourceTree = ""; }; F4069C5626683CC7002B32F5 /* CUIRawCrashLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIRawCrashLog.h; path = ../../app_unexpectedly/app_unexpectedly/CUIRawCrashLog.h; sourceTree = ""; }; F4069C5C26683CF7002B32F5 /* CUICrashLogBacktraces.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogBacktraces.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogBacktraces.m; sourceTree = ""; }; F4069C5D26683CF8002B32F5 /* CUIRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIRegister.h; path = ../../app_unexpectedly/app_unexpectedly/CUIRegister.h; sourceTree = ""; }; F4069C5E26683CF8002B32F5 /* CUICrashLogExceptionInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogExceptionInformation.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation.h; sourceTree = ""; }; F4069C5F26683CF8002B32F5 /* CUIBinaryImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIBinaryImage.m; path = ../../app_unexpectedly/app_unexpectedly/CUIBinaryImage.m; sourceTree = ""; }; F4069C6026683CF8002B32F5 /* CUICrashLogExceptionInformation+UI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CUICrashLogExceptionInformation+UI.h"; path = "../../app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+UI.h"; sourceTree = ""; }; F4069C6126683CF8002B32F5 /* CUICrashLogExceptionInformation+UI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CUICrashLogExceptionInformation+UI.m"; path = "../../app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+UI.m"; sourceTree = ""; }; F4069C6226683CF8002B32F5 /* CUICrashLogHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogHeader.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogHeader.m; sourceTree = ""; }; F4069C6326683CF8002B32F5 /* CUICrashLogThreadState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogThreadState.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogThreadState.h; sourceTree = ""; }; F4069C6426683CF8002B32F5 /* CUICrashLogThreadState+UI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CUICrashLogThreadState+UI.h"; path = "../../app_unexpectedly/app_unexpectedly/CUICrashLogThreadState+UI.h"; sourceTree = ""; }; F4069C6526683CF8002B32F5 /* CUICrashLogThreadState+UI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CUICrashLogThreadState+UI.m"; path = "../../app_unexpectedly/app_unexpectedly/CUICrashLogThreadState+UI.m"; sourceTree = ""; }; F4069C6626683CF8002B32F5 /* CUICrashLogBinaryImages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogBinaryImages.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogBinaryImages.h; sourceTree = ""; }; F4069C6726683CF8002B32F5 /* CUICrashLogHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogHeader.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogHeader.h; sourceTree = ""; }; F4069C6826683CF8002B32F5 /* CUICrashLogExceptionInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogExceptionInformation.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation.m; sourceTree = ""; }; F4069C6926683CF8002B32F5 /* CUIRegister.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIRegister.m; path = ../../app_unexpectedly/app_unexpectedly/CUIRegister.m; sourceTree = ""; }; F4069C6A26683CF9002B32F5 /* CUICrashLogDianosticMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogDianosticMessages.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogDianosticMessages.h; sourceTree = ""; }; F4069C6B26683CF9002B32F5 /* CUICrashLogBinaryImages.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogBinaryImages.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogBinaryImages.m; sourceTree = ""; }; F4069C6C26683CF9002B32F5 /* CUICrashLogDianosticMessages.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogDianosticMessages.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogDianosticMessages.m; sourceTree = ""; }; F4069C6D26683CF9002B32F5 /* CUICrashLogBacktraces.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogBacktraces.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogBacktraces.h; sourceTree = ""; }; F4069C6E26683CF9002B32F5 /* CUICrashLogThreadState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogThreadState.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogThreadState.m; sourceTree = ""; }; F4069C6F26683CF9002B32F5 /* CUIBinaryImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIBinaryImage.h; path = ../../app_unexpectedly/app_unexpectedly/CUIBinaryImage.h; sourceTree = ""; }; F4069C8426683D10002B32F5 /* CUICallStackBacktrace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICallStackBacktrace.m; path = ../../app_unexpectedly/app_unexpectedly/CUICallStackBacktrace.m; sourceTree = ""; }; F4069C8526683D10002B32F5 /* CUIStackFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIStackFrame.m; path = ../../app_unexpectedly/app_unexpectedly/CUIStackFrame.m; sourceTree = ""; }; F4069C8626683D10002B32F5 /* CUIThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIThread.m; path = ../../app_unexpectedly/app_unexpectedly/CUIThread.m; sourceTree = ""; }; F4069C8726683D10002B32F5 /* CUICallStackBacktrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICallStackBacktrace.h; path = ../../app_unexpectedly/app_unexpectedly/CUICallStackBacktrace.h; sourceTree = ""; }; F4069C8826683D10002B32F5 /* CUIStackFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIStackFrame.h; path = ../../app_unexpectedly/app_unexpectedly/CUIStackFrame.h; sourceTree = ""; }; F4069C8926683D10002B32F5 /* CUIThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIThread.h; path = ../../app_unexpectedly/app_unexpectedly/CUIThread.h; sourceTree = ""; }; F4069C9126683D2D002B32F5 /* NSArray+WBExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+WBExtensions.m"; path = "../../app_unexpectedly/Foundation + Extensions/NSArray+WBExtensions.m"; sourceTree = ""; }; F4069C9226683D2D002B32F5 /* NSArray+WBExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+WBExtensions.h"; path = "../../app_unexpectedly/Foundation + Extensions/NSArray+WBExtensions.h"; sourceTree = ""; }; F4069C9526683D88002B32F5 /* CUIParsingErrors.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CUIParsingErrors.m; path = ../../app_unexpectedly/app_unexpectedly/CUIParsingErrors.m; sourceTree = ""; }; F4069C9626683D88002B32F5 /* CUIParsingErrors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CUIParsingErrors.h; path = ../../app_unexpectedly/app_unexpectedly/CUIParsingErrors.h; sourceTree = ""; }; F4069C9826683DA0002B32F5 /* CUICrashLogSectionsDetector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogSectionsDetector.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogSectionsDetector.h; sourceTree = ""; }; F4069C9926683DA0002B32F5 /* CUICrashLogSectionsDetector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogSectionsDetector.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogSectionsDetector.m; sourceTree = ""; }; F4069C9C26683DFE002B32F5 /* CUIOperatingSystemVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIOperatingSystemVersion.h; path = ../../app_unexpectedly/app_unexpectedly/CUIOperatingSystemVersion.h; sourceTree = ""; }; F4069C9D26683DFF002B32F5 /* CUIOperatingSystemVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIOperatingSystemVersion.m; path = ../../app_unexpectedly/app_unexpectedly/CUIOperatingSystemVersion.m; sourceTree = ""; }; F4069CA026683E33002B32F5 /* CUICrashLogsProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogsProvider.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogsProvider.m; sourceTree = ""; }; F4069CA126683E33002B32F5 /* CUICrashLogsProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogsProvider.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogsProvider.h; sourceTree = ""; }; F4069CA926683F49002B32F5 /* CUITextModeDisplaySettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUITextModeDisplaySettings.h; path = ../../app_unexpectedly/app_unexpectedly/CUITextModeDisplaySettings.h; sourceTree = ""; }; F4069CAA26683F49002B32F5 /* CUITextModeDisplaySettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUITextModeDisplaySettings.m; path = ../../app_unexpectedly/app_unexpectedly/CUITextModeDisplaySettings.m; sourceTree = ""; }; F4069CAF2668409D002B32F5 /* CUIThemeItemsGroup+UI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CUIThemeItemsGroup+UI.m"; path = "../../app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup+UI.m"; sourceTree = ""; }; F4069CB02668409D002B32F5 /* CUIThemeItemsGroup+UI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CUIThemeItemsGroup+UI.h"; path = "../../app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup+UI.h"; sourceTree = ""; }; F4069CB3266840D1002B32F5 /* CUIThemeItemsGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIThemeItemsGroup.h; path = ../../app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup.h; sourceTree = ""; }; F4069CB4266840D1002B32F5 /* CUIThemeItemsGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIThemeItemsGroup.m; path = ../../app_unexpectedly/app_unexpectedly/CUIThemeItemsGroup.m; sourceTree = ""; }; F4069CB7266840E2002B32F5 /* NSDictionary+WBExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+WBExtensions.m"; path = "../../app_unexpectedly/Foundation + Extensions/NSDictionary+WBExtensions.m"; sourceTree = ""; }; F4069CB8266840E2002B32F5 /* NSDictionary+WBExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+WBExtensions.h"; path = "../../app_unexpectedly/Foundation + Extensions/NSDictionary+WBExtensions.h"; sourceTree = ""; }; F4069CBA266840FA002B32F5 /* CUITheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUITheme.h; path = ../../app_unexpectedly/app_unexpectedly/CUITheme.h; sourceTree = ""; }; F4069CBB266840FB002B32F5 /* CUIThemeItemAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIThemeItemAttributes.h; path = ../../app_unexpectedly/app_unexpectedly/CUIThemeItemAttributes.h; sourceTree = ""; }; F4069CBC266840FB002B32F5 /* CUITheme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUITheme.m; path = ../../app_unexpectedly/app_unexpectedly/CUITheme.m; sourceTree = ""; }; F4069CBD266840FB002B32F5 /* CUIThemeItemAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIThemeItemAttributes.m; path = ../../app_unexpectedly/app_unexpectedly/CUIThemeItemAttributes.m; sourceTree = ""; }; F4069CC32668411A002B32F5 /* NSColor+String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSColor+String.h"; path = "../../app_unexpectedly/AppKit + Extensions/NSColor+String.h"; sourceTree = ""; }; F4069CC42668411A002B32F5 /* NSColor+String.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSColor+String.m"; path = "../../app_unexpectedly/AppKit + Extensions/NSColor+String.m"; sourceTree = ""; }; F4069CC726684135002B32F5 /* CUIThemesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIThemesManager.h; path = ../../app_unexpectedly/app_unexpectedly/CUIThemesManager.h; sourceTree = ""; }; F4069CC826684135002B32F5 /* CUIThemesManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIThemesManager.m; path = ../../app_unexpectedly/app_unexpectedly/CUIThemesManager.m; sourceTree = ""; }; F4069CCB26684143002B32F5 /* NSArray+UniqueName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+UniqueName.h"; path = "../../app_unexpectedly/Foundation + Extensions/NSArray+UniqueName.h"; sourceTree = ""; }; F4069CCC26684143002B32F5 /* NSArray+UniqueName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+UniqueName.m"; path = "../../app_unexpectedly/Foundation + Extensions/NSArray+UniqueName.m"; sourceTree = ""; }; F4069CCF2668415A002B32F5 /* CUIApplicationPreferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIApplicationPreferences.h; path = ../../app_unexpectedly/app_unexpectedly/CUIApplicationPreferences.h; sourceTree = ""; }; F4069CD02668415A002B32F5 /* CUIApplicationPreferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIApplicationPreferences.m; path = ../../app_unexpectedly/app_unexpectedly/CUIApplicationPreferences.m; sourceTree = ""; }; F4069CD12668415A002B32F5 /* CUIApplicationPreferences+Themes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CUIApplicationPreferences+Themes.m"; path = "../../app_unexpectedly/app_unexpectedly/CUIApplicationPreferences+Themes.m"; sourceTree = ""; }; F4069CD22668415A002B32F5 /* CUIApplicationPreferences+Themes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CUIApplicationPreferences+Themes.h"; path = "../../app_unexpectedly/app_unexpectedly/CUIApplicationPreferences+Themes.h"; sourceTree = ""; }; F4069CD72668416B002B32F5 /* NSDictionary+MutableDeepCopy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+MutableDeepCopy.h"; path = "../../app_unexpectedly/Foundation + Extensions/NSDictionary+MutableDeepCopy.h"; sourceTree = ""; }; F4069CD82668416B002B32F5 /* NSDictionary+MutableDeepCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+MutableDeepCopy.m"; path = "../../app_unexpectedly/Foundation + Extensions/NSDictionary+MutableDeepCopy.m"; sourceTree = ""; }; F4069CDB26684199002B32F5 /* CUIOutlineModeDisplaySettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIOutlineModeDisplaySettings.m; path = ../../app_unexpectedly/app_unexpectedly/CUIOutlineModeDisplaySettings.m; sourceTree = ""; }; F4069CDC26684199002B32F5 /* CUIOutlineModeDisplaySettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIOutlineModeDisplaySettings.h; path = ../../app_unexpectedly/app_unexpectedly/CUIOutlineModeDisplaySettings.h; sourceTree = ""; }; F4069CDF266842E5002B32F5 /* NSFileManager+ExtendedAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSFileManager+ExtendedAttributes.h"; path = "../../app_unexpectedly/app_unexpectedly/NSFileManager+ExtendedAttributes.h"; sourceTree = ""; }; F4069CE0266842E5002B32F5 /* NSFileManager+ExtendedAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSFileManager+ExtendedAttributes.m"; path = "../../app_unexpectedly/app_unexpectedly/NSFileManager+ExtendedAttributes.m"; sourceTree = ""; }; F4069CE32668430B002B32F5 /* default_themes.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = default_themes.plist; path = ../../app_unexpectedly/app_unexpectedly/default_themes.plist; sourceTree = ""; }; F41C5D63266988AB00DE5D3A /* CUIStackFrameComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIStackFrameComponents.h; path = ../../app_unexpectedly/app_unexpectedly/CUIStackFrameComponents.h; sourceTree = ""; }; F428C08D27245CF400FB8CAC /* IPSReport+CrashRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSReport+CrashRepresentation.h"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSReport+CrashRepresentation.h"; sourceTree = ""; }; F428C08E27245CF400FB8CAC /* IPSReport+CrashRepresentation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSReport+CrashRepresentation.m"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSReport+CrashRepresentation.m"; sourceTree = ""; }; F428C09127245D0500FB8CAC /* IPSImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSImage.m; path = ../../submodules/ips2crash/Model/IPSImage.m; sourceTree = ""; }; F428C09227245D0500FB8CAC /* IPSIncidentHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncidentHeader.m; path = ../../submodules/ips2crash/Model/IPSIncidentHeader.m; sourceTree = ""; }; F428C09327245D0500FB8CAC /* IPSIncidentExceptionInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncidentExceptionInformation.m; path = ../../submodules/ips2crash/Model/IPSIncidentExceptionInformation.m; sourceTree = ""; }; F428C09427245D0500FB8CAC /* IPSIncidentDiagnosticMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncidentDiagnosticMessage.m; path = ../../submodules/ips2crash/Model/IPSIncidentDiagnosticMessage.m; sourceTree = ""; }; F428C09527245D0500FB8CAC /* IPSReport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSReport.m; path = ../../submodules/ips2crash/Model/IPSReport.m; sourceTree = ""; }; F428C09627245D0500FB8CAC /* IPSThreadInstructionState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadInstructionState.m; path = ../../submodules/ips2crash/Model/IPSThreadInstructionState.m; sourceTree = ""; }; F428C09727245D0500FB8CAC /* IPSThreadInstructionStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadInstructionStream.m; path = ../../submodules/ips2crash/Model/IPSThreadInstructionStream.m; sourceTree = ""; }; F428C09827245D0500FB8CAC /* IPSIncident.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncident.h; path = ../../submodules/ips2crash/Model/IPSIncident.h; sourceTree = ""; }; F428C09927245D0500FB8CAC /* IPSRegisterState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSRegisterState.m; path = ../../submodules/ips2crash/Model/IPSRegisterState.m; sourceTree = ""; }; F428C09A27245D0500FB8CAC /* IPSDateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSDateFormatter.m; path = ../../submodules/ips2crash/Model/IPSDateFormatter.m; sourceTree = ""; }; F428C09B27245D0600FB8CAC /* IPSApplicationSpecificInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSApplicationSpecificInformation.m; path = ../../submodules/ips2crash/Model/IPSApplicationSpecificInformation.m; sourceTree = ""; }; F428C09C27245D0600FB8CAC /* IPSSummary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSSummary.m; path = ../../submodules/ips2crash/Model/IPSSummary.m; sourceTree = ""; }; F428C09D27245D0600FB8CAC /* IPSTermination.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSTermination.m; path = ../../submodules/ips2crash/Model/IPSTermination.m; sourceTree = ""; }; F428C09E27245D0600FB8CAC /* IPSExternalModificationSummary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSExternalModificationSummary.m; path = ../../submodules/ips2crash/Model/IPSExternalModificationSummary.m; sourceTree = ""; }; F428C09F27245D0600FB8CAC /* IPSError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSError.h; path = ../../submodules/ips2crash/Model/IPSError.h; sourceTree = ""; }; F428C0A027245D0600FB8CAC /* IPSExternalModificationStatistics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSExternalModificationStatistics.m; path = ../../submodules/ips2crash/Model/IPSExternalModificationStatistics.m; sourceTree = ""; }; F428C0A127245D0600FB8CAC /* IPSReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSReport.h; path = ../../submodules/ips2crash/Model/IPSReport.h; sourceTree = ""; }; F428C0A227245D0600FB8CAC /* IPSTermination.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSTermination.h; path = ../../submodules/ips2crash/Model/IPSTermination.h; sourceTree = ""; }; F428C0A327245D0600FB8CAC /* IPSBundleInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSBundleInfo.m; path = ../../submodules/ips2crash/Model/IPSBundleInfo.m; sourceTree = ""; }; F428C0A427245D0600FB8CAC /* IPSException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSException.m; path = ../../submodules/ips2crash/Model/IPSException.m; sourceTree = ""; }; F428C0A527245D0600FB8CAC /* IPSObjectProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSObjectProtocol.h; path = ../../submodules/ips2crash/Model/IPSObjectProtocol.h; sourceTree = ""; }; F428C0A627245D0600FB8CAC /* IPSSummary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSSummary.h; path = ../../submodules/ips2crash/Model/IPSSummary.h; sourceTree = ""; }; F428C0A727245D0600FB8CAC /* IPSThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThread.m; path = ../../submodules/ips2crash/Model/IPSThread.m; sourceTree = ""; }; F428C0A827245D0600FB8CAC /* IPSIncidentExceptionInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncidentExceptionInformation.h; path = ../../submodules/ips2crash/Model/IPSIncidentExceptionInformation.h; sourceTree = ""; }; F428C0A927245D0600FB8CAC /* IPSThreadFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadFrame.m; path = ../../submodules/ips2crash/Model/IPSThreadFrame.m; sourceTree = ""; }; F428C0AA27245D0600FB8CAC /* IPSExternalModificationSummary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSExternalModificationSummary.h; path = ../../submodules/ips2crash/Model/IPSExternalModificationSummary.h; sourceTree = ""; }; F428C0AB27245D0600FB8CAC /* IPSError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSError.m; path = ../../submodules/ips2crash/Model/IPSError.m; sourceTree = ""; }; F428C0AC27245D0600FB8CAC /* IPSDateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSDateFormatter.h; path = ../../submodules/ips2crash/Model/IPSDateFormatter.h; sourceTree = ""; }; F428C0AD27245D0600FB8CAC /* IPSThreadFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadFrame.h; path = ../../submodules/ips2crash/Model/IPSThreadFrame.h; sourceTree = ""; }; F428C0AE27245D0700FB8CAC /* IPSOperatingSystemVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSOperatingSystemVersion.m; path = ../../submodules/ips2crash/Model/IPSOperatingSystemVersion.m; sourceTree = ""; }; F428C0AF27245D0700FB8CAC /* IPSThreadInstructionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadInstructionState.h; path = ../../submodules/ips2crash/Model/IPSThreadInstructionState.h; sourceTree = ""; }; F428C0B027245D0700FB8CAC /* IPSThreadInstructionStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadInstructionStream.h; path = ../../submodules/ips2crash/Model/IPSThreadInstructionStream.h; sourceTree = ""; }; F428C0B127245D0700FB8CAC /* IPSThreadState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThreadState.h; path = ../../submodules/ips2crash/Model/IPSThreadState.h; sourceTree = ""; }; F428C0B227245D0700FB8CAC /* IPSThreadState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSThreadState.m; path = ../../submodules/ips2crash/Model/IPSThreadState.m; sourceTree = ""; }; F428C0B327245D0700FB8CAC /* IPSImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSImage.h; path = ../../submodules/ips2crash/Model/IPSImage.h; sourceTree = ""; }; F428C0B427245D0700FB8CAC /* IPSExternalModificationStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSExternalModificationStatistics.h; path = ../../submodules/ips2crash/Model/IPSExternalModificationStatistics.h; sourceTree = ""; }; F428C0B527245D0700FB8CAC /* IPSApplicationSpecificInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSApplicationSpecificInformation.h; path = ../../submodules/ips2crash/Model/IPSApplicationSpecificInformation.h; sourceTree = ""; }; F428C0B627245D0700FB8CAC /* IPSLegacyInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSLegacyInfo.h; path = ../../submodules/ips2crash/Model/IPSLegacyInfo.h; sourceTree = ""; }; F428C0B727245D0700FB8CAC /* IPSBundleInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSBundleInfo.h; path = ../../submodules/ips2crash/Model/IPSBundleInfo.h; sourceTree = ""; }; F428C0B827245D0700FB8CAC /* IPSLegacyInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSLegacyInfo.m; path = ../../submodules/ips2crash/Model/IPSLegacyInfo.m; sourceTree = ""; }; F428C0B927245D0700FB8CAC /* IPSThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSThread.h; path = ../../submodules/ips2crash/Model/IPSThread.h; sourceTree = ""; }; F428C0BA27245D0700FB8CAC /* IPSIncident.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSIncident.m; path = ../../submodules/ips2crash/Model/IPSIncident.m; sourceTree = ""; }; F428C0BB27245D0800FB8CAC /* IPSIncidentDiagnosticMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncidentDiagnosticMessage.h; path = ../../submodules/ips2crash/Model/IPSIncidentDiagnosticMessage.h; sourceTree = ""; }; F428C0BC27245D0800FB8CAC /* IPSRegisterState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSRegisterState.h; path = ../../submodules/ips2crash/Model/IPSRegisterState.h; sourceTree = ""; }; F428C0BD27245D0800FB8CAC /* IPSIncidentHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSIncidentHeader.h; path = ../../submodules/ips2crash/Model/IPSIncidentHeader.h; sourceTree = ""; }; F428C0BE27245D0800FB8CAC /* IPSOperatingSystemVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSOperatingSystemVersion.h; path = ../../submodules/ips2crash/Model/IPSOperatingSystemVersion.h; sourceTree = ""; }; F428C0BF27245D0800FB8CAC /* IPSException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSException.h; path = ../../submodules/ips2crash/Model/IPSException.h; sourceTree = ""; }; F4386B09284953F500B83525 /* CUICrashLogExceptionInformation+QuickHelp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CUICrashLogExceptionInformation+QuickHelp.m"; path = "../../app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+QuickHelp.m"; sourceTree = ""; }; F4386B0A284953F600B83525 /* CUICrashLogExceptionInformation+QuickHelp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CUICrashLogExceptionInformation+QuickHelp.h"; path = "../../app_unexpectedly/app_unexpectedly/CUICrashLogExceptionInformation+QuickHelp.h"; sourceTree = ""; }; F4440FD4282C40F9003C810B /* IPSSummarySerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSSummarySerialization.m; path = ../../submodules/ips2crash/Model/IPSSummarySerialization.m; sourceTree = ""; }; F4440FD5282C40F9003C810B /* IPSCrashSummary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSCrashSummary.m; path = ../../submodules/ips2crash/Model/IPSCrashSummary.m; sourceTree = ""; }; F4440FD6282C40F9003C810B /* IPSSummarySerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSSummarySerialization.h; path = ../../submodules/ips2crash/Model/IPSSummarySerialization.h; sourceTree = ""; }; F4440FD7282C40F9003C810B /* IPSCrashSummary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSCrashSummary.h; path = ../../submodules/ips2crash/Model/IPSCrashSummary.h; sourceTree = ""; }; F47D66A82DF6310200E078F8 /* IPSExceptionReason.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSExceptionReason.m; path = ../../submodules/ips2crash/Model/IPSExceptionReason.m; sourceTree = ""; }; F47D66A92DF6310200E078F8 /* IPSExceptionReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSExceptionReason.h; path = ../../submodules/ips2crash/Model/IPSExceptionReason.h; sourceTree = ""; }; F47F76692673577C00A74905 /* CUICrashLogErrors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogErrors.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogErrors.h; sourceTree = ""; }; F47F766A2673577C00A74905 /* CUICrashLogErrors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogErrors.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogErrors.m; sourceTree = ""; }; F47F766B2673577C00A74905 /* CUICrashLogsOpenErrorRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashLogsOpenErrorRecord.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorRecord.m; sourceTree = ""; }; F47F766C2673577C00A74905 /* CUICrashLogsOpenErrorRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashLogsOpenErrorRecord.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashLogsOpenErrorRecord.h; sourceTree = ""; }; F480FF74273B01B500905974 /* CUIBinaryImageUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIBinaryImageUtility.m; path = ../../app_unexpectedly/app_unexpectedly/CUIBinaryImageUtility.m; sourceTree = ""; }; F480FF75273B01B600905974 /* CUIBinaryImageUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIBinaryImageUtility.h; path = ../../app_unexpectedly/app_unexpectedly/CUIBinaryImageUtility.h; sourceTree = ""; }; F48DAE252661207800C93D40 /* crashreport.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = crashreport.qlgenerator; sourceTree = BUILT_PRODUCTS_DIR; }; F48DAE282661207800C93D40 /* GenerateThumbnailForURL.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GenerateThumbnailForURL.m; sourceTree = ""; }; F48DAE2A2661207800C93D40 /* GeneratePreviewForURL.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GeneratePreviewForURL.m; sourceTree = ""; }; F48DAE2C2661207800C93D40 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; F48DAE2E2661207800C93D40 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F48DAE3B266123C300C93D40 /* SharedConfigurationSettings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = SharedConfigurationSettings.xcconfig; path = ../Configs/SharedConfigurationSettings.xcconfig; sourceTree = ""; }; F4ACF4BB266EC92000272A25 /* QLCUIThemesProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QLCUIThemesProvider.h; sourceTree = ""; }; F4ACF4BC266EC92000272A25 /* QLCUIThemesProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QLCUIThemesProvider.m; sourceTree = ""; }; F4BD8C6B2DF4DDE900BD61A8 /* IPSExceptionReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IPSExceptionReason.h; path = ../../submodules/ips2crash/Model/IPSExceptionReason.h; sourceTree = ""; }; F4BD8C6C2DF4DDE900BD61A8 /* IPSExceptionReason.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IPSExceptionReason.m; path = ../../submodules/ips2crash/Model/IPSExceptionReason.m; sourceTree = ""; }; F4CF6CF02DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSIncident+ApplicationSpecificInformation.m"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSIncident+ApplicationSpecificInformation.m"; sourceTree = ""; }; F4CF6CF12DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSIncident+ApplicationSpecificInformation.h"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSIncident+ApplicationSpecificInformation.h"; sourceTree = ""; }; F4D0EE96273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSThreadState+RegisterDisplayName.m"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSThreadState+RegisterDisplayName.m"; sourceTree = ""; }; F4D0EE97273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSThreadState+RegisterDisplayName.h"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSThreadState+RegisterDisplayName.h"; sourceTree = ""; }; F4D14D622745BFBB003698AD /* IPSImage+UserCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "IPSImage+UserCode.m"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSImage+UserCode.m"; sourceTree = ""; }; F4D14D632745BFBC003698AD /* IPSImage+UserCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "IPSImage+UserCode.h"; path = "../../submodules/ips2crash/tool_ips2crash/ips2crash/IPSImage+UserCode.h"; sourceTree = ""; }; F4DAF0AD27C448E600256EA4 /* IPSImage+Offset.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "IPSImage+Offset.h"; path = "../../app_unexpectedly/app_unexpectedly/ips + Extensions/IPSImage+Offset.h"; sourceTree = ""; }; F4DAF0AE27C448E600256EA4 /* IPSImage+Offset.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "IPSImage+Offset.m"; path = "../../app_unexpectedly/app_unexpectedly/ips + Extensions/IPSImage+Offset.m"; sourceTree = ""; }; F4DAFBF22736BA2000FB50A6 /* CUIDataTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIDataTransform.h; path = ../../app_unexpectedly/app_unexpectedly/CUIDataTransform.h; sourceTree = ""; }; F4DAFBF32736BA2100FB50A6 /* CUIDataTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIDataTransform.m; path = ../../app_unexpectedly/app_unexpectedly/CUIDataTransform.m; sourceTree = ""; }; F4DAFBF62736BA3100FB50A6 /* CUIIPSTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIIPSTransform.m; path = ../../app_unexpectedly/app_unexpectedly/CUIIPSTransform.m; sourceTree = ""; }; F4DAFBF72736BA3100FB50A6 /* CUIIPSTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIIPSTransform.h; path = ../../app_unexpectedly/app_unexpectedly/CUIIPSTransform.h; sourceTree = ""; }; F4E112AE2735E6160072D40B /* CUICrashDataTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUICrashDataTransform.h; path = ../../app_unexpectedly/app_unexpectedly/CUICrashDataTransform.h; sourceTree = ""; }; F4E112AF2735E6170072D40B /* CUICrashDataTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUICrashDataTransform.m; path = ../../app_unexpectedly/app_unexpectedly/CUICrashDataTransform.m; sourceTree = ""; }; F4FA4324273EF3FD0068EDB8 /* NSString+CPU.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+CPU.m"; path = "../../app_unexpectedly/Foundation + Extensions/NSString+CPU.m"; sourceTree = ""; }; F4FA4325273EF3FE0068EDB8 /* NSString+CPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+CPU.h"; path = "../../app_unexpectedly/Foundation + Extensions/NSString+CPU.h"; sourceTree = ""; }; F4FC8EA927C1AA6700291875 /* CUIReportThemedTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CUIReportThemedTransform.m; path = ../../app_unexpectedly/app_unexpectedly/CUIReportThemedTransform.m; sourceTree = ""; }; F4FC8EAC27C1AA7C00291875 /* CUIReportThemedTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CUIReportThemedTransform.h; path = ../../app_unexpectedly/app_unexpectedly/CUIReportThemedTransform.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ F48DAE222661207700C93D40 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ F40681D0266982B200BE6BEE /* Preferences */ = { isa = PBXGroup; children = ( F4069CCF2668415A002B32F5 /* CUIApplicationPreferences.h */, F4069CD02668415A002B32F5 /* CUIApplicationPreferences.m */, F4069CD22668415A002B32F5 /* CUIApplicationPreferences+Themes.h */, F4069CD12668415A002B32F5 /* CUIApplicationPreferences+Themes.m */, F4069CA926683F49002B32F5 /* CUITextModeDisplaySettings.h */, F4069CAA26683F49002B32F5 /* CUITextModeDisplaySettings.m */, F4069CDC26684199002B32F5 /* CUIOutlineModeDisplaySettings.h */, F4069CDB26684199002B32F5 /* CUIOutlineModeDisplaySettings.m */, ); name = Preferences; sourceTree = ""; }; F40681D1266982F600BE6BEE /* Themes */ = { isa = PBXGroup; children = ( F4069CBA266840FA002B32F5 /* CUITheme.h */, F4069CBC266840FB002B32F5 /* CUITheme.m */, F4069CBB266840FB002B32F5 /* CUIThemeItemAttributes.h */, F4069CBD266840FB002B32F5 /* CUIThemeItemAttributes.m */, F4069CB3266840D1002B32F5 /* CUIThemeItemsGroup.h */, F4069CB4266840D1002B32F5 /* CUIThemeItemsGroup.m */, F4069CB02668409D002B32F5 /* CUIThemeItemsGroup+UI.h */, F4069CAF2668409D002B32F5 /* CUIThemeItemsGroup+UI.m */, F4069CC726684135002B32F5 /* CUIThemesManager.h */, F4069CC826684135002B32F5 /* CUIThemesManager.m */, ); name = Themes; sourceTree = ""; }; F4069C9026683D1F002B32F5 /* Foundation + Extensions */ = { isa = PBXGroup; children = ( F4069CCB26684143002B32F5 /* NSArray+UniqueName.h */, F4069CCC26684143002B32F5 /* NSArray+UniqueName.m */, F4069C9226683D2D002B32F5 /* NSArray+WBExtensions.h */, F4069C9126683D2D002B32F5 /* NSArray+WBExtensions.m */, F4069CD72668416B002B32F5 /* NSDictionary+MutableDeepCopy.h */, F4069CD82668416B002B32F5 /* NSDictionary+MutableDeepCopy.m */, F4069CB8266840E2002B32F5 /* NSDictionary+WBExtensions.h */, F4069CB7266840E2002B32F5 /* NSDictionary+WBExtensions.m */, F4069CDF266842E5002B32F5 /* NSFileManager+ExtendedAttributes.h */, F4069CE0266842E5002B32F5 /* NSFileManager+ExtendedAttributes.m */, F4FA4325273EF3FE0068EDB8 /* NSString+CPU.h */, F4FA4324273EF3FD0068EDB8 /* NSString+CPU.m */, ); name = "Foundation + Extensions"; sourceTree = ""; }; F4069CA426683F04002B32F5 /* Transform */ = { isa = PBXGroup; children = ( F4DAFBF22736BA2000FB50A6 /* CUIDataTransform.h */, F4DAFBF32736BA2100FB50A6 /* CUIDataTransform.m */, F4FC8EAC27C1AA7C00291875 /* CUIReportThemedTransform.h */, F4FC8EA927C1AA6700291875 /* CUIReportThemedTransform.m */, F4DAFBF72736BA3100FB50A6 /* CUIIPSTransform.h */, F4DAFBF62736BA3100FB50A6 /* CUIIPSTransform.m */, F4E112AE2735E6160072D40B /* CUICrashDataTransform.h */, F4E112AF2735E6170072D40B /* CUICrashDataTransform.m */, ); name = Transform; sourceTree = ""; }; F4069CC22668410A002B32F5 /* AppKit + Extensions */ = { isa = PBXGroup; children = ( F4069CC32668411A002B32F5 /* NSColor+String.h */, F4069CC42668411A002B32F5 /* NSColor+String.m */, ); name = "AppKit + Extensions"; sourceTree = ""; }; F428C08B27245CCD00FB8CAC /* ips model */ = { isa = PBXGroup; children = ( F428C0B527245D0700FB8CAC /* IPSApplicationSpecificInformation.h */, F428C09B27245D0600FB8CAC /* IPSApplicationSpecificInformation.m */, F428C0B727245D0700FB8CAC /* IPSBundleInfo.h */, F428C0A327245D0600FB8CAC /* IPSBundleInfo.m */, F428C0AC27245D0600FB8CAC /* IPSDateFormatter.h */, F428C09A27245D0500FB8CAC /* IPSDateFormatter.m */, F428C09F27245D0600FB8CAC /* IPSError.h */, F428C0AB27245D0600FB8CAC /* IPSError.m */, F428C0BF27245D0800FB8CAC /* IPSException.h */, F428C0A427245D0600FB8CAC /* IPSException.m */, F4BD8C6B2DF4DDE900BD61A8 /* IPSExceptionReason.h */, F4BD8C6C2DF4DDE900BD61A8 /* IPSExceptionReason.m */, F428C0B427245D0700FB8CAC /* IPSExternalModificationStatistics.h */, F428C0A027245D0600FB8CAC /* IPSExternalModificationStatistics.m */, F428C0AA27245D0600FB8CAC /* IPSExternalModificationSummary.h */, F428C09E27245D0600FB8CAC /* IPSExternalModificationSummary.m */, F428C0B327245D0700FB8CAC /* IPSImage.h */, F428C09127245D0500FB8CAC /* IPSImage.m */, F428C09827245D0500FB8CAC /* IPSIncident.h */, F428C0BA27245D0700FB8CAC /* IPSIncident.m */, F428C0BB27245D0800FB8CAC /* IPSIncidentDiagnosticMessage.h */, F428C09427245D0500FB8CAC /* IPSIncidentDiagnosticMessage.m */, F428C0A827245D0600FB8CAC /* IPSIncidentExceptionInformation.h */, F428C09327245D0500FB8CAC /* IPSIncidentExceptionInformation.m */, F428C0BD27245D0800FB8CAC /* IPSIncidentHeader.h */, F428C09227245D0500FB8CAC /* IPSIncidentHeader.m */, F428C0B627245D0700FB8CAC /* IPSLegacyInfo.h */, F428C0B827245D0700FB8CAC /* IPSLegacyInfo.m */, F428C0A527245D0600FB8CAC /* IPSObjectProtocol.h */, F428C0BE27245D0800FB8CAC /* IPSOperatingSystemVersion.h */, F428C0AE27245D0700FB8CAC /* IPSOperatingSystemVersion.m */, F428C0BC27245D0800FB8CAC /* IPSRegisterState.h */, F428C09927245D0500FB8CAC /* IPSRegisterState.m */, F428C0A127245D0600FB8CAC /* IPSReport.h */, F428C09527245D0500FB8CAC /* IPSReport.m */, F428C0A627245D0600FB8CAC /* IPSSummary.h */, F428C09C27245D0600FB8CAC /* IPSSummary.m */, F4440FD7282C40F9003C810B /* IPSCrashSummary.h */, F4440FD5282C40F9003C810B /* IPSCrashSummary.m */, F4440FD6282C40F9003C810B /* IPSSummarySerialization.h */, F4440FD4282C40F9003C810B /* IPSSummarySerialization.m */, F428C0A227245D0600FB8CAC /* IPSTermination.h */, F428C09D27245D0600FB8CAC /* IPSTermination.m */, F428C0B927245D0700FB8CAC /* IPSThread.h */, F428C0A727245D0600FB8CAC /* IPSThread.m */, F428C0AD27245D0600FB8CAC /* IPSThreadFrame.h */, F428C0A927245D0600FB8CAC /* IPSThreadFrame.m */, F428C0AF27245D0700FB8CAC /* IPSThreadInstructionState.h */, F428C09627245D0500FB8CAC /* IPSThreadInstructionState.m */, F428C0B027245D0700FB8CAC /* IPSThreadInstructionStream.h */, F428C09727245D0500FB8CAC /* IPSThreadInstructionStream.m */, F428C0B127245D0700FB8CAC /* IPSThreadState.h */, F428C0B227245D0700FB8CAC /* IPSThreadState.m */, ); name = "ips model"; sourceTree = ""; }; F428C08C27245CD500FB8CAC /* ips model + Extensions */ = { isa = PBXGroup; children = ( F4DAF0AD27C448E600256EA4 /* IPSImage+Offset.h */, F4DAF0AE27C448E600256EA4 /* IPSImage+Offset.m */, F4D14D632745BFBC003698AD /* IPSImage+UserCode.h */, F4D14D622745BFBB003698AD /* IPSImage+UserCode.m */, F428C08D27245CF400FB8CAC /* IPSReport+CrashRepresentation.h */, F428C08E27245CF400FB8CAC /* IPSReport+CrashRepresentation.m */, F4CF6CF12DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.h */, F4CF6CF02DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.m */, F4D0EE97273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.h */, F4D0EE96273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.m */, ); name = "ips model + Extensions"; sourceTree = ""; }; F48DAE1B2661207700C93D40 = { isa = PBXGroup; children = ( F48DAE3B266123C300C93D40 /* SharedConfigurationSettings.xcconfig */, F48DAE272661207800C93D40 /* crashreport */, F48DAE262661207800C93D40 /* Products */, ); sourceTree = ""; }; F48DAE262661207800C93D40 /* Products */ = { isa = PBXGroup; children = ( F48DAE252661207800C93D40 /* crashreport.qlgenerator */, ); name = Products; sourceTree = ""; }; F48DAE272661207800C93D40 /* crashreport */ = { isa = PBXGroup; children = ( F41C5D63266988AB00DE5D3A /* CUIStackFrameComponents.h */, F480FF75273B01B600905974 /* CUIBinaryImageUtility.h */, F480FF74273B01B500905974 /* CUIBinaryImageUtility.m */, F428C08B27245CCD00FB8CAC /* ips model */, F428C08C27245CD500FB8CAC /* ips model + Extensions */, F4069CC22668410A002B32F5 /* AppKit + Extensions */, F4069C9026683D1F002B32F5 /* Foundation + Extensions */, F48DAE342661223300C93D40 /* Model */, F40681D0266982B200BE6BEE /* Preferences */, F40681D1266982F600BE6BEE /* Themes */, F4069CA426683F04002B32F5 /* Transform */, F40681CC2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.h */, F40681CD2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.m */, F4ACF4BB266EC92000272A25 /* QLCUIThemesProvider.h */, F4ACF4BC266EC92000272A25 /* QLCUIThemesProvider.m */, F48DAE282661207800C93D40 /* GenerateThumbnailForURL.m */, F48DAE2A2661207800C93D40 /* GeneratePreviewForURL.m */, F48DAE2C2661207800C93D40 /* main.c */, F48DAE2E2661207800C93D40 /* Info.plist */, F4069CE32668430B002B32F5 /* default_themes.plist */, ); path = crashreport; sourceTree = ""; }; F48DAE342661223300C93D40 /* Model */ = { isa = PBXGroup; children = ( F4069C9626683D88002B32F5 /* CUIParsingErrors.h */, F4069C9526683D88002B32F5 /* CUIParsingErrors.m */, F4069C9C26683DFE002B32F5 /* CUIOperatingSystemVersion.h */, F4069C9D26683DFF002B32F5 /* CUIOperatingSystemVersion.m */, F4069C8726683D10002B32F5 /* CUICallStackBacktrace.h */, F4069C8426683D10002B32F5 /* CUICallStackBacktrace.m */, F4069C8826683D10002B32F5 /* CUIStackFrame.h */, F4069C8526683D10002B32F5 /* CUIStackFrame.m */, F4069C8926683D10002B32F5 /* CUIThread.h */, F4069C8626683D10002B32F5 /* CUIThread.m */, F4069C6F26683CF9002B32F5 /* CUIBinaryImage.h */, F4069C5F26683CF8002B32F5 /* CUIBinaryImage.m */, F4069C6D26683CF9002B32F5 /* CUICrashLogBacktraces.h */, F4069C5C26683CF7002B32F5 /* CUICrashLogBacktraces.m */, F4069C6626683CF8002B32F5 /* CUICrashLogBinaryImages.h */, F4069C6B26683CF9002B32F5 /* CUICrashLogBinaryImages.m */, F4069C6A26683CF9002B32F5 /* CUICrashLogDianosticMessages.h */, F4069C6C26683CF9002B32F5 /* CUICrashLogDianosticMessages.m */, F4069C5E26683CF8002B32F5 /* CUICrashLogExceptionInformation.h */, F4069C6826683CF8002B32F5 /* CUICrashLogExceptionInformation.m */, F4069C6026683CF8002B32F5 /* CUICrashLogExceptionInformation+UI.h */, F4069C6126683CF8002B32F5 /* CUICrashLogExceptionInformation+UI.m */, F4069C6726683CF8002B32F5 /* CUICrashLogHeader.h */, F4069C6226683CF8002B32F5 /* CUICrashLogHeader.m */, F4069C6326683CF8002B32F5 /* CUICrashLogThreadState.h */, F4069C6E26683CF9002B32F5 /* CUICrashLogThreadState.m */, F4069C6426683CF8002B32F5 /* CUICrashLogThreadState+UI.h */, F4069C6526683CF8002B32F5 /* CUICrashLogThreadState+UI.m */, F4069C5D26683CF8002B32F5 /* CUIRegister.h */, F4069C6926683CF8002B32F5 /* CUIRegister.m */, F4069C9826683DA0002B32F5 /* CUICrashLogSectionsDetector.h */, F4069C9926683DA0002B32F5 /* CUICrashLogSectionsDetector.m */, F4069C5626683CC7002B32F5 /* CUIRawCrashLog.h */, F4069C5426683CC6002B32F5 /* CUIRawCrashLog.m */, F4069C5326683CC6002B32F5 /* CUICodeType.h */, F4069C5526683CC7002B32F5 /* CUICrashLog.h */, F4069C5226683CC6002B32F5 /* CUICrashLog.m */, F4069CA126683E33002B32F5 /* CUICrashLogsProvider.h */, F4069CA026683E33002B32F5 /* CUICrashLogsProvider.m */, F47F76692673577C00A74905 /* CUICrashLogErrors.h */, F47F766A2673577C00A74905 /* CUICrashLogErrors.m */, F47F766C2673577C00A74905 /* CUICrashLogsOpenErrorRecord.h */, F47F766B2673577C00A74905 /* CUICrashLogsOpenErrorRecord.m */, F4386B0A284953F600B83525 /* CUICrashLogExceptionInformation+QuickHelp.h */, F4386B09284953F500B83525 /* CUICrashLogExceptionInformation+QuickHelp.m */, ); name = Model; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ F48DAE202661207700C93D40 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( F428C0DB27245D0800FB8CAC /* IPSDateFormatter.h in Headers */, F428C08F27245CF400FB8CAC /* IPSReport+CrashRepresentation.h in Headers */, F428C0EC27245D0800FB8CAC /* IPSIncidentHeader.h in Headers */, F4069C8126683CF9002B32F5 /* CUICrashLogBacktraces.h in Headers */, F4069CB22668409E002B32F5 /* CUIThemeItemsGroup+UI.h in Headers */, F428C0DE27245D0800FB8CAC /* IPSThreadInstructionState.h in Headers */, F428C0E227245D0800FB8CAC /* IPSImage.h in Headers */, F428C0E027245D0800FB8CAC /* IPSThreadState.h in Headers */, F4069C9A26683DA0002B32F5 /* CUICrashLogSectionsDetector.h in Headers */, F428C0D427245D0800FB8CAC /* IPSObjectProtocol.h in Headers */, F428C0E327245D0800FB8CAC /* IPSExternalModificationStatistics.h in Headers */, F47F766D2673577C00A74905 /* CUICrashLogErrors.h in Headers */, F4069C9E26683DFF002B32F5 /* CUIOperatingSystemVersion.h in Headers */, F428C0EB27245D0800FB8CAC /* IPSRegisterState.h in Headers */, F428C0E527245D0800FB8CAC /* IPSLegacyInfo.h in Headers */, F4069C7726683CF9002B32F5 /* CUICrashLogThreadState.h in Headers */, F4ACF4BD266EC92000272A25 /* QLCUIThemesProvider.h in Headers */, F428C0EA27245D0800FB8CAC /* IPSIncidentDiagnosticMessage.h in Headers */, F428C0EE27245D0800FB8CAC /* IPSException.h in Headers */, F428C0DC27245D0800FB8CAC /* IPSThreadFrame.h in Headers */, F41C5D64266988AB00DE5D3A /* CUIStackFrameComponents.h in Headers */, F4069C7A26683CF9002B32F5 /* CUICrashLogBinaryImages.h in Headers */, F4069C7E26683CF9002B32F5 /* CUICrashLogDianosticMessages.h in Headers */, F4DAFBF42736BA2100FB50A6 /* CUIDataTransform.h in Headers */, F428C0E627245D0800FB8CAC /* IPSBundleInfo.h in Headers */, F428C0D927245D0800FB8CAC /* IPSExternalModificationSummary.h in Headers */, F4069C9426683D2E002B32F5 /* NSArray+WBExtensions.h in Headers */, F4069C8326683CF9002B32F5 /* CUIBinaryImage.h in Headers */, F4440FDB282C40F9003C810B /* IPSCrashSummary.h in Headers */, F428C0D027245D0800FB8CAC /* IPSReport.h in Headers */, F428C0C727245D0800FB8CAC /* IPSIncident.h in Headers */, F4069C5826683CC7002B32F5 /* CUICodeType.h in Headers */, F4069C7126683CF9002B32F5 /* CUIRegister.h in Headers */, F428C0CE27245D0800FB8CAC /* IPSError.h in Headers */, F480FF77273B01B600905974 /* CUIBinaryImageUtility.h in Headers */, F4D0EE99273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.h in Headers */, F4069CBF266840FB002B32F5 /* CUIThemeItemAttributes.h in Headers */, F4069CA326683E33002B32F5 /* CUICrashLogsProvider.h in Headers */, F4069CDE26684199002B32F5 /* CUIOutlineModeDisplaySettings.h in Headers */, F4069C7426683CF9002B32F5 /* CUICrashLogExceptionInformation+UI.h in Headers */, F4069CD92668416B002B32F5 /* NSDictionary+MutableDeepCopy.h in Headers */, F40681CE2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.h in Headers */, F4069CD32668415A002B32F5 /* CUIApplicationPreferences.h in Headers */, F4069CD62668415A002B32F5 /* CUIApplicationPreferences+Themes.h in Headers */, F4D14D652745BFBC003698AD /* IPSImage+UserCode.h in Headers */, F4069CC926684136002B32F5 /* CUIThemesManager.h in Headers */, F4440FDA282C40F9003C810B /* IPSSummarySerialization.h in Headers */, F4069C8D26683D10002B32F5 /* CUICallStackBacktrace.h in Headers */, F4CF6CF32DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.h in Headers */, F4069C7226683CF9002B32F5 /* CUICrashLogExceptionInformation.h in Headers */, F4069C8F26683D10002B32F5 /* CUIThread.h in Headers */, F4069C8E26683D10002B32F5 /* CUIStackFrame.h in Headers */, F428C0D727245D0800FB8CAC /* IPSIncidentExceptionInformation.h in Headers */, F4FA4327273EF3FE0068EDB8 /* NSString+CPU.h in Headers */, F4BD8C6D2DF4DDE900BD61A8 /* IPSExceptionReason.h in Headers */, F47F76702673577C00A74905 /* CUICrashLogsOpenErrorRecord.h in Headers */, F428C0D127245D0800FB8CAC /* IPSTermination.h in Headers */, F428C0ED27245D0800FB8CAC /* IPSOperatingSystemVersion.h in Headers */, F4069C7B26683CF9002B32F5 /* CUICrashLogHeader.h in Headers */, F4069CB5266840D1002B32F5 /* CUIThemeItemsGroup.h in Headers */, F4DAF0AF27C448E600256EA4 /* IPSImage+Offset.h in Headers */, F4069CCD26684143002B32F5 /* NSArray+UniqueName.h in Headers */, F4FC8EAD27C1AA7C00291875 /* CUIReportThemedTransform.h in Headers */, F4069C5B26683CC7002B32F5 /* CUIRawCrashLog.h in Headers */, F4DAFBF92736BA3100FB50A6 /* CUIIPSTransform.h in Headers */, F4069CBE266840FB002B32F5 /* CUITheme.h in Headers */, F428C0E427245D0800FB8CAC /* IPSApplicationSpecificInformation.h in Headers */, F4069CC52668411A002B32F5 /* NSColor+String.h in Headers */, F428C0D527245D0800FB8CAC /* IPSSummary.h in Headers */, F4386B0C284953F600B83525 /* CUICrashLogExceptionInformation+QuickHelp.h in Headers */, F4069C5A26683CC7002B32F5 /* CUICrashLog.h in Headers */, F428C0DF27245D0800FB8CAC /* IPSThreadInstructionStream.h in Headers */, F4069CAB26683F49002B32F5 /* CUITextModeDisplaySettings.h in Headers */, F428C0E827245D0800FB8CAC /* IPSThread.h in Headers */, F4069CE1266842E5002B32F5 /* NSFileManager+ExtendedAttributes.h in Headers */, F4069C7826683CF9002B32F5 /* CUICrashLogThreadState+UI.h in Headers */, F4E112B02735E6170072D40B /* CUICrashDataTransform.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ F48DAE242661207700C93D40 /* crashreport */ = { isa = PBXNativeTarget; buildConfigurationList = F48DAE312661207800C93D40 /* Build configuration list for PBXNativeTarget "crashreport" */; buildPhases = ( F48DAE202661207700C93D40 /* Headers */, F48DAE212661207700C93D40 /* Sources */, F48DAE222661207700C93D40 /* Frameworks */, F48DAE232661207700C93D40 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = crashreport; productName = crashreport; productReference = F48DAE252661207800C93D40 /* crashreport.qlgenerator */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ F48DAE1C2661207700C93D40 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1010; ORGANIZATIONNAME = Whitebox; TargetAttributes = { F48DAE242661207700C93D40 = { CreatedOnToolsVersion = 10.1; }; }; }; buildConfigurationList = F48DAE1F2661207700C93D40 /* Build configuration list for PBXProject "crashreport" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = F48DAE1B2661207700C93D40; productRefGroup = F48DAE262661207800C93D40 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( F48DAE242661207700C93D40 /* crashreport */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ F48DAE232661207700C93D40 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( F4069CE42668430B002B32F5 /* default_themes.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ F48DAE212661207700C93D40 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( F428C0D627245D0800FB8CAC /* IPSThread.m in Sources */, F4069CC0266840FB002B32F5 /* CUITheme.m in Sources */, F4069CC1266840FB002B32F5 /* CUIThemeItemAttributes.m in Sources */, F4440FD9282C40F9003C810B /* IPSCrashSummary.m in Sources */, F4069C7926683CF9002B32F5 /* CUICrashLogThreadState+UI.m in Sources */, F480FF76273B01B600905974 /* CUIBinaryImageUtility.m in Sources */, F40681CF2669820700BE6BEE /* NSUserDefaults+UNXQuickLookGenerator.m in Sources */, F4069CD52668415A002B32F5 /* CUIApplicationPreferences+Themes.m in Sources */, F4E112B12735E6170072D40B /* CUICrashDataTransform.m in Sources */, F4069C8226683CF9002B32F5 /* CUICrashLogThreadState.m in Sources */, F4069C5926683CC7002B32F5 /* CUIRawCrashLog.m in Sources */, F4D14D642745BFBC003698AD /* IPSImage+UserCode.m in Sources */, F4069CD42668415A002B32F5 /* CUIApplicationPreferences.m in Sources */, F4ACF4BE266EC92000272A25 /* QLCUIThemesProvider.m in Sources */, F4BD8C6E2DF4DDE900BD61A8 /* IPSExceptionReason.m in Sources */, F428C0CC27245D0800FB8CAC /* IPSTermination.m in Sources */, F4069CC62668411A002B32F5 /* NSColor+String.m in Sources */, F4069CDD26684199002B32F5 /* CUIOutlineModeDisplaySettings.m in Sources */, F428C0E727245D0800FB8CAC /* IPSLegacyInfo.m in Sources */, F428C0CD27245D0800FB8CAC /* IPSExternalModificationSummary.m in Sources */, F428C0C827245D0800FB8CAC /* IPSRegisterState.m in Sources */, F4FA4326273EF3FE0068EDB8 /* NSString+CPU.m in Sources */, F4069C9726683D88002B32F5 /* CUIParsingErrors.m in Sources */, F4DAF0B027C448E600256EA4 /* IPSImage+Offset.m in Sources */, F4069CDA2668416B002B32F5 /* NSDictionary+MutableDeepCopy.m in Sources */, F4069C9B26683DA0002B32F5 /* CUICrashLogSectionsDetector.m in Sources */, F4386B0B284953F600B83525 /* CUICrashLogExceptionInformation+QuickHelp.m in Sources */, F4069C8B26683D10002B32F5 /* CUIStackFrame.m in Sources */, F4CF6CF22DF6110C0078458E /* IPSIncident+ApplicationSpecificInformation.m in Sources */, F4069CE2266842E5002B32F5 /* NSFileManager+ExtendedAttributes.m in Sources */, F428C0E127245D0800FB8CAC /* IPSThreadState.m in Sources */, F428C0DA27245D0800FB8CAC /* IPSError.m in Sources */, F4DAFBF52736BA2100FB50A6 /* CUIDataTransform.m in Sources */, F428C0CF27245D0800FB8CAC /* IPSExternalModificationStatistics.m in Sources */, F428C0D227245D0800FB8CAC /* IPSBundleInfo.m in Sources */, F428C0C627245D0800FB8CAC /* IPSThreadInstructionStream.m in Sources */, F4069C7526683CF9002B32F5 /* CUICrashLogExceptionInformation+UI.m in Sources */, F4069C5726683CC7002B32F5 /* CUICrashLog.m in Sources */, F428C0D827245D0800FB8CAC /* IPSThreadFrame.m in Sources */, F428C0C127245D0800FB8CAC /* IPSIncidentHeader.m in Sources */, F4069CAC26683F49002B32F5 /* CUITextModeDisplaySettings.m in Sources */, F428C0C027245D0800FB8CAC /* IPSImage.m in Sources */, F428C0D327245D0800FB8CAC /* IPSException.m in Sources */, F4069C8A26683D10002B32F5 /* CUICallStackBacktrace.m in Sources */, F4069CA226683E33002B32F5 /* CUICrashLogsProvider.m in Sources */, F4069CCA26684136002B32F5 /* CUIThemesManager.m in Sources */, F4FC8EAB27C1AA6700291875 /* CUIReportThemedTransform.m in Sources */, F428C0CA27245D0800FB8CAC /* IPSApplicationSpecificInformation.m in Sources */, F4069C8C26683D10002B32F5 /* CUIThread.m in Sources */, F428C0CB27245D0800FB8CAC /* IPSSummary.m in Sources */, F428C09027245CF400FB8CAC /* IPSReport+CrashRepresentation.m in Sources */, F428C0C927245D0800FB8CAC /* IPSDateFormatter.m in Sources */, F4069C7326683CF9002B32F5 /* CUIBinaryImage.m in Sources */, F4069CB12668409E002B32F5 /* CUIThemeItemsGroup+UI.m in Sources */, F47F766E2673577C00A74905 /* CUICrashLogErrors.m in Sources */, F4069C8026683CF9002B32F5 /* CUICrashLogDianosticMessages.m in Sources */, F428C0C227245D0800FB8CAC /* IPSIncidentExceptionInformation.m in Sources */, F4069C9326683D2E002B32F5 /* NSArray+WBExtensions.m in Sources */, F4DAFBF82736BA3100FB50A6 /* CUIIPSTransform.m in Sources */, F4069CB9266840E2002B32F5 /* NSDictionary+WBExtensions.m in Sources */, F47F766F2673577C00A74905 /* CUICrashLogsOpenErrorRecord.m in Sources */, F48DAE292661207800C93D40 /* GenerateThumbnailForURL.m in Sources */, F428C0E927245D0800FB8CAC /* IPSIncident.m in Sources */, F4069CB6266840D1002B32F5 /* CUIThemeItemsGroup.m in Sources */, F4069C7D26683CF9002B32F5 /* CUIRegister.m in Sources */, F4069C7026683CF9002B32F5 /* CUICrashLogBacktraces.m in Sources */, F4069C7626683CF9002B32F5 /* CUICrashLogHeader.m in Sources */, F428C0DD27245D0800FB8CAC /* IPSOperatingSystemVersion.m in Sources */, F4069CCE26684143002B32F5 /* NSArray+UniqueName.m in Sources */, F4069C7C26683CF9002B32F5 /* CUICrashLogExceptionInformation.m in Sources */, F48DAE2B2661207800C93D40 /* GeneratePreviewForURL.m in Sources */, F4069C9F26683DFF002B32F5 /* CUIOperatingSystemVersion.m in Sources */, F428C0C327245D0800FB8CAC /* IPSIncidentDiagnosticMessage.m in Sources */, F48DAE2D2661207800C93D40 /* main.c in Sources */, F4069C7F26683CF9002B32F5 /* CUICrashLogBinaryImages.m in Sources */, F4D0EE98273DB91600CC9737 /* IPSThreadState+RegisterDisplayName.m in Sources */, F428C0C427245D0800FB8CAC /* IPSReport.m in Sources */, F4440FD8282C40F9003C810B /* IPSSummarySerialization.m in Sources */, F428C0C527245D0800FB8CAC /* IPSThreadInstructionState.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ F48DAE2F2661207800C93D40 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; }; name = Debug; }; F48DAE302661207800C93D40 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; }; name = Release; }; F48DAE322661207800C93D40 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F48DAE3B266123C300C93D40 /* SharedConfigurationSettings.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; INFOPLIST_FILE = crashreport/Info.plist; INSTALL_PATH = /Library/QuickLook; OTHER_CFLAGS = "-D__DISABLE_SYMBOLICATION_=1"; PRODUCT_BUNDLE_IDENTIFIER = fr.whitebox.unexpectedly.qlgenerator.crashreport; PRODUCT_MODULE_NAME = crashreport; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; WRAPPER_EXTENSION = qlgenerator; }; name = Debug; }; F48DAE332661207800C93D40 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = F48DAE3B266123C300C93D40 /* SharedConfigurationSettings.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = crashreport/Info.plist; INSTALL_PATH = /Library/QuickLook; OTHER_CFLAGS = "-D__DISABLE_SYMBOLICATION_=1"; PRODUCT_BUNDLE_IDENTIFIER = fr.whitebox.unexpectedly.qlgenerator.crashreport; PRODUCT_MODULE_NAME = crashreport; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; WRAPPER_EXTENSION = qlgenerator; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ F48DAE1F2661207700C93D40 /* Build configuration list for PBXProject "crashreport" */ = { isa = XCConfigurationList; buildConfigurations = ( F48DAE2F2661207800C93D40 /* Debug */, F48DAE302661207800C93D40 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; F48DAE312661207800C93D40 /* Build configuration list for PBXNativeTarget "crashreport" */ = { isa = XCConfigurationList; buildConfigurations = ( F48DAE322661207800C93D40 /* Debug */, F48DAE332661207800C93D40 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = F48DAE1C2661207700C93D40 /* Project object */; } ================================================ FILE: plugin_quicklook/crashreport.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: plugin_quicklook/crashreport.xcodeproj/xcuserdata/stephane.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState crashreport.xcscheme_^#shared#^_ orderHint 1