diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Navigation/Navigation.htm b/Ghidra/Features/Base/src/main/help/help/topics/Navigation/Navigation.htm index 970a0c89bc..77f0acc93f 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/Navigation/Navigation.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/Navigation/Navigation.htm @@ -16,6 +16,7 @@

Often, users need to navigate to specific locations in a program.  Ghidra provides several different ways to do this: 

+
+

Go To Address, Label, or Expression

-

To perform a Go To: 

+

To Perform a Go To: 

  1. In the menu-bar of a tool, select Navigation Go To Expression
    -
    -

    Enter an arithmetic expression that can include addresses, symbols, or can be relative - to the current location. All numbers are assumed to be hexadecimal. Supported operator are - "+ - * / << >>".  Also, parentheses are supported to control order of - expresion evaluation.
    - For example:
    -

    -
    +
    +

    Enter an arithmetic expression that can include addresses, symbols, or can be relative + to the current location. All numbers are assumed to be hexadecimal. Supported operator are + "+ - * / << >>".  Also, parentheses are supported to control order of + expresion evaluation.
    + For example:
    +

    + + + + + + + + + + + + + + + + + + + + +
    + ENTRY+10 + Positions + the cursor at the address 0x10 addresses past the symbol ENTRY +
    0x100000+30 + Positions the cursor at address 0x100030 +
    0x100000+(2*10) + Posiitons the cursor at address 0x100020 +
    +20 + Positions the cursor at an address that is 0x20 past the current location +
    +
-
- -

Executing a Query

@@ -613,7 +630,7 @@

Provided by: ProviderNavigation plugin

- + +
+
+
+
+
+

Related Topics:

diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Selection/Selecting.htm b/Ghidra/Features/Base/src/main/help/help/topics/Selection/Selecting.htm index 353a3c849e..9224625e17 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/Selection/Selecting.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/Selection/Selecting.htm @@ -24,12 +24,10 @@ types of selections that are available from the tool Select menu. Each predefined type of selection exposes different characteristics of the program.

-

To create a selection using one of the predefined methods:

- - +

To create a selection using one of the predefined methods via the menu item + SelectSelectionType. +

The SelectionTypes and their descriptions are as follows:

diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java index e1fc295ff3..c63788c2a7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java @@ -135,7 +135,7 @@ public class CodeBrowserPlugin extends Plugin GhidraOptions.CATEGORY_BROWSER_POPUPS); ToolOptions displayOptions = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_DISPLAY); ToolOptions fieldOptions = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS); - displayOptions.registerOptionsEditor(new ListingDisplayOptionsEditor(this, displayOptions)); + displayOptions.registerOptionsEditor(new ListingDisplayOptionsEditor(displayOptions)); displayOptions.setOptionsHelpLocation( new HelpLocation(getName(), GhidraOptions.CATEGORY_BROWSER_DISPLAY)); fieldOptions.setOptionsHelpLocation( diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java index d16151325a..4f07f386fe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/flowarrow/FlowArrowPlugin.java @@ -267,12 +267,12 @@ public class FlowArrowPlugin extends Plugin implements MarginProvider, OptionsCh return address.compareTo(screenBottom) > 0; } - /** The y value of the start of the layout at the given address. */ + /* The y value of the start of the layout at the given address. */ Integer getStartPos(Address addr) { return startAddressToPixel.get(addr); } - /** The y value of the end of the layout at the given address. */ + /* The y value of the end of the layout at the given address. */ Integer getEndPos(Address addr) { return endAddressToPixel.get(addr); } @@ -294,7 +294,7 @@ public class FlowArrowPlugin extends Plugin implements MarginProvider, OptionsCh return flowArrows.iterator(); } - /** Those arrows starting at the current address */ + /* Those arrows starting at the current address */ Iterator getActiveArrows() { return activeArrows.iterator(); } @@ -584,8 +584,8 @@ public class FlowArrowPlugin extends Plugin implements MarginProvider, OptionsCh for (int layout = 0; layout < n; layout++) { Address addr = layoutToPixel.getLayoutAddress(layout); if (addr != null) { - startAddressToPixel.put(addr, new Integer(layoutToPixel.getBeginPosition(layout))); - endAddressToPixel.put(addr, new Integer(layoutToPixel.getEndPosition(layout))); + startAddressToPixel.put(addr, layoutToPixel.getBeginPosition(layout)); + endAddressToPixel.put(addr, layoutToPixel.getEndPosition(layout)); } } @@ -640,11 +640,14 @@ public class FlowArrowPlugin extends Plugin implements MarginProvider, OptionsCh ToolOptions opt = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_DISPLAY); opt.registerOption(OptionsGui.FLOW_ARROW_NON_ACTIVE.getColorOptionName(), - OptionsGui.FLOW_ARROW_NON_ACTIVE.getDefaultColor(), null, null); + OptionsGui.FLOW_ARROW_NON_ACTIVE.getDefaultColor(), null, + "The color for an arrow with no endpoint at the current address"); opt.registerOption(OptionsGui.FLOW_ARROW_ACTIVE.getColorOptionName(), - OptionsGui.FLOW_ARROW_ACTIVE.getDefaultColor(), null, null); + OptionsGui.FLOW_ARROW_ACTIVE.getDefaultColor(), null, + "The color for an arrow with an endpoint at the current address"); opt.registerOption(OptionsGui.FLOW_ARROW_SELECTED.getColorOptionName(), - OptionsGui.FLOW_ARROW_SELECTED.getDefaultColor(), null, null); + OptionsGui.FLOW_ARROW_SELECTED.getDefaultColor(), null, + "The color for an arrow that has been selected by the user"); Color c = opt.getColor(OptionsGui.BACKGROUND.getColorOptionName(), OptionsGui.BACKGROUND.getDefaultColor()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NavigationOptions.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NavigationOptions.java index 2fc32d5a0d..7bd3e0c7d6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NavigationOptions.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NavigationOptions.java @@ -20,9 +20,12 @@ import ghidra.framework.options.OptionsChangeListener; import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.util.OptionsService; +import ghidra.util.HelpLocation; public class NavigationOptions implements OptionsChangeListener { + static final String NAVIGATION_TOPIC = "Navigation"; + static final String NAVIGATION_OPTIONS = GhidraOptions.NAVIGATION_OPTIONS; static final String NAVIGATION_RANGE_OPTION = GhidraOptions.NAVIGATION_RANGE_OPTION; @@ -51,7 +54,7 @@ public class NavigationOptions implements OptionsChangeListener { static final String EXTERNAL_NAVIGATION_OPTION = GhidraOptions.EXTERNAL_NAVIGATION_OPTION; static final String EXTERNAL_NAVIGATION_DESCRIPTION = - "Determines the bahavior for navigation to external symbols and references. " + + "Determines the behavior for navigation to external symbols and references. " + "By default, navigating to an external will attempt to navigate within the " + "current program to the first linkage reference (pointer or thunk). " + "Alternatively, if an external program has been associated with an " + @@ -78,12 +81,12 @@ public class NavigationOptions implements OptionsChangeListener { GhidraOptions.FOLLOW_INDIRECTION_NAVIGATION_OPTION; static final String FOLLOW_INDIRECTION_NAVIGATION_DESCRIPTION = - "Determines the bahavior for navigation on indirect flow references. " + + "Determines the behavior for navigation on indirect flow references. " + "By default, this option is disabled providing navigation to the " + "referenced pointer data. If enabled, the pointer will be followed " + "to its referenced destination if contained within the program's memory."; - static final String ASSUME_CURRENT_ADDRESS_SPACE = "Prefer current Address Space"; + static final String ASSUME_CURRENT_ADDRESS_SPACE = "Prefer Current Address Space"; private static final String ASSUME_CURRENT_ADDRESS_SPACE_DESCRIPTION = "Determines if the 'Go To' action prefers the current address space when entering address offsets. " + "For example, if your program has multiple address spaces such as 'RAM' or 'DATA' and you " + @@ -92,7 +95,7 @@ public class NavigationOptions implements OptionsChangeListener { "cursor location. Otherwise, it will show a list of possible addresses for the given offset. " + "The default is on for this option."; - private final String RESTRICT_GOTO_CURRENT_TAB = "'Go To' in current program only"; + private final String RESTRICT_GOTO_CURRENT_TAB = "'Go To' in Current Program Only"; private static final String RESTRICT_GOTO_CURRENT_TAB_DESCRIPTION = "Determines if the " + "'Go To' service will only search for and navigate to labels in the current program. " + "If this option is off and the search label is not found in the current program, the " + @@ -120,32 +123,33 @@ public class NavigationOptions implements OptionsChangeListener { this.options = options; + HelpLocation help = new HelpLocation(NAVIGATION_TOPIC, "Navigation_Options"); options.registerOption(NavigationOptions.NAVIGATION_RANGE_OPTION, - RangeNavigationEnum.TopOfRangeOnly, null, + RangeNavigationEnum.TopOfRangeOnly, help, NavigationOptions.NAVIGATION_RANGE_DESCRIPTION); RangeNavigationEnum rangeNavigationOption = options.getEnum( NavigationOptions.NAVIGATION_RANGE_OPTION, RangeNavigationEnum.TopOfRangeOnly); gotoTopAndBottom = (rangeNavigationOption == RangeNavigationEnum.TopAndBottomOfRange); options.registerOption(NavigationOptions.EXTERNAL_NAVIGATION_OPTION, - ExternalNavigationEnum.NavigateToLinkage, null, + ExternalNavigationEnum.NavigateToLinkage, help, NavigationOptions.EXTERNAL_NAVIGATION_DESCRIPTION); ExternalNavigationEnum externalNavigationOption = options.getEnum( NavigationOptions.EXTERNAL_NAVIGATION_OPTION, ExternalNavigationEnum.NavigateToLinkage); gotoExternalProgram = (externalNavigationOption == ExternalNavigationEnum.NavigateToExternalProgram); - options.registerOption(NavigationOptions.FOLLOW_INDIRECTION_NAVIGATION_OPTION, false, null, + options.registerOption(NavigationOptions.FOLLOW_INDIRECTION_NAVIGATION_OPTION, false, help, NavigationOptions.FOLLOW_INDIRECTION_NAVIGATION_DESCRIPTION); followIndirectReferences = options.getBoolean(NavigationOptions.FOLLOW_INDIRECTION_NAVIGATION_OPTION, false); - options.registerOption(ASSUME_CURRENT_ADDRESS_SPACE, true, null, + options.registerOption(ASSUME_CURRENT_ADDRESS_SPACE, true, help, ASSUME_CURRENT_ADDRESS_SPACE_DESCRIPTION); preferCurrentAddressSpace = options.getBoolean(ASSUME_CURRENT_ADDRESS_SPACE, true); - options.registerOption(RESTRICT_GOTO_CURRENT_TAB, true, null, + options.registerOption(RESTRICT_GOTO_CURRENT_TAB, true, help, RESTRICT_GOTO_CURRENT_TAB_DESCRIPTION); restrictGotoToCurrentProgram = options.getBoolean(RESTRICT_GOTO_CURRENT_TAB, true); @@ -158,7 +162,7 @@ public class NavigationOptions implements OptionsChangeListener { } @Override - public void optionsChanged(ToolOptions options, String optionName, Object oldValue, + public void optionsChanged(ToolOptions toolOptions, String optionName, Object oldValue, Object newValue) { if (NavigationOptions.NAVIGATION_RANGE_OPTION.equals(optionName)) { RangeNavigationEnum rangeNavigationOption = (RangeNavigationEnum) newValue; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java index f94bf55c43..9af5bdc03a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java @@ -401,9 +401,10 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, "Toggles highlight search results"); opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_COLOR, null, null); + PluginConstants.SEARCH_HIGHLIGHT_COLOR, null, "The search result highlight color"); opt.registerOption(PluginConstants.SEARCH_HIGHLIGHT_CURRENT_COLOR_NAME, - PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR, null, null); + PluginConstants.SEARCH_HIGHLIGHT_CURRENT_ADDR_COLOR, null, + "The search result highlight color for the currently selected match"); opt.addOptionsChangeListener(this); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java index 59e8b1bdeb..e6d2a4defb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/AddressFieldFactory.java @@ -61,7 +61,7 @@ public class AddressFieldFactory extends FieldFactory { /** * Constructor * @param model the model that the field belongs to. - * @param hsProvider the HightLightStringProvider. + * @param hlProvider the HightLightStringProvider. * @param displayOptions the Options for display properties. * @param fieldOptions the Options for field specific properties. */ @@ -75,7 +75,8 @@ public class AddressFieldFactory extends FieldFactory { HelpLocation helpLoc = new HelpLocation("CodeBrowserPlugin", "Address_Field"); fieldOptions.registerOption(ADDRESS_DISPLAY_OPTIONS_NAME, OptionType.CUSTOM_TYPE, - new AddressFieldOptionsWrappedOption(), helpLoc, null, addressFieldOptionsEditor); + new AddressFieldOptionsWrappedOption(), helpLoc, "Adjusts the Address Field display", + addressFieldOptionsEditor); CustomOption customOption = fieldOptions.getCustomOption(ADDRESS_DISPLAY_OPTIONS_NAME, null); @@ -204,9 +205,9 @@ public class AddressFieldFactory extends FieldFactory { @Override public FieldFactory newInstance(FieldFormatModel newModel, - HighlightProvider highlightStringProvider, ToolOptions displayOptions, + HighlightProvider highlightStringProvider, ToolOptions toolOptions, ToolOptions fieldOptions) { - return new AddressFieldFactory(newModel, highlightStringProvider, displayOptions, + return new AddressFieldFactory(newModel, highlightStringProvider, toolOptions, fieldOptions); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java index af62be4332..b37a6752b9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/ArrayValuesFieldFactory.java @@ -43,16 +43,16 @@ public class ArrayValuesFieldFactory extends FieldFactory { @Override public FieldFactory newInstance(FieldFormatModel formatModel, - HighlightProvider highlightProvider, ToolOptions displayOptions, + HighlightProvider highlightProvider, ToolOptions toolOptions, ToolOptions fieldOptions) { - return new ArrayValuesFieldFactory(formatModel, highlightProvider, displayOptions, + return new ArrayValuesFieldFactory(formatModel, highlightProvider, toolOptions, fieldOptions); } /** * Constructor * @param model the model that the field belongs to. - * @param hsProvider the HightLightStringProvider. + * @param hlProvider the HightLightStringProvider. * @param displayOptions the Options for display properties. * @param fieldOptions the Options for field specific properties. */ @@ -65,7 +65,8 @@ public class ArrayValuesFieldFactory extends FieldFactory { private void setupOptions(Options fieldOptions) { // we need to install a custom editor that allows us to edit a group of related options fieldOptions.registerOption(FormatManager.ARRAY_DISPLAY_OPTIONS, OptionType.CUSTOM_TYPE, - new ArrayElementWrappedOption(), null, null, arrayOptionsEditor); + new ArrayElementWrappedOption(), null, FormatManager.ARRAY_DISPLAY_DESCRIPTION, + arrayOptionsEditor); CustomOption wrappedOption = fieldOptions.getCustomOption( FormatManager.ARRAY_DISPLAY_OPTIONS, new ArrayElementWrappedOption()); @@ -162,9 +163,6 @@ public class ArrayValuesFieldFactory extends FieldFactory { return (category == FieldFormatModel.ARRAY); } - /** - * @see ghidra.app.util.viewer.field.FieldFactory#fieldOptionsChanged(ghidra.framework.options.ToolOptions, java.lang.String, java.lang.Object, java.lang.Object) - */ @Override public void fieldOptionsChanged(Options options, String optionName, Object oldValue, Object newValue) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java index 8f8bc83681..c2c52f4c31 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/BrowserCodeUnitFormatOptions.java @@ -76,6 +76,8 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions */ private final static String NAMESPACE_OPTIONS = GhidraOptions.OPERAND_GROUP_TITLE + Options.DELIMITER + "Display Namespace"; + private static final String NAMESPACE_OPTIONS_DESCRIPTIONS = + "Adjusts the Operands Field namespace display"; /** * Option which controls the display of data mutability in the mnemonic representation @@ -106,7 +108,8 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions if (!exists) { fieldOptions.registerOption(NAMESPACE_OPTIONS, OptionType.CUSTOM_TYPE, - new NamespaceWrappedOption(), null, null, new NamespacePropertyEditor()); + new NamespaceWrappedOption(), null, NAMESPACE_OPTIONS_DESCRIPTIONS, + new NamespacePropertyEditor()); HelpLocation hl = new HelpLocation("CodeBrowserPlugin", "Operands_Field"); fieldOptions.getOptions(GhidraOptions.OPERAND_GROUP_TITLE).setOptionsHelpLocation(hl); @@ -157,7 +160,8 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions private void updateFormat() { fieldOptions.registerOption(NAMESPACE_OPTIONS, OptionType.CUSTOM_TYPE, - new NamespaceWrappedOption(), null, null, new NamespacePropertyEditor()); + new NamespaceWrappedOption(), null, NAMESPACE_OPTIONS_DESCRIPTIONS, + new NamespacePropertyEditor()); CustomOption customOption = fieldOptions.getCustomOption(NAMESPACE_OPTIONS, new NamespaceWrappedOption()); if (!(customOption instanceof NamespaceWrappedOption)) { @@ -208,7 +212,7 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions /** * Add format change listener. * Listeners will only be notified if autoUpdate was true when instantiated. - * @param listener + * @param listener the listener */ public void addChangeListener(ChangeListener listener) { listeners.add(listener); @@ -216,7 +220,7 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions /** * Remove format change listener - * @param listener + * @param listener the listener */ public void removeChangeListener(ChangeListener listener) { listeners.remove(listener); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java index 7adb849196..c8aa5a0be4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/FieldFactory.java @@ -87,10 +87,11 @@ public abstract class FieldFactory implements ExtensionPoint { baseFont = SystemUtilities.adjustForFontSizeOverride( displayOptions.getFont(FONT_OPTION_NAME, DEFAULT_FIELD_FONT)); // For most fields (defined in optionsGui) these will be set. But "ad hoc" fields won't, - //so register something. A second registration won't change the original + // so register something. A second registration won't change the original - displayOptions.registerOption(colorOptionName, Color.BLACK, null, null); - displayOptions.registerOption(styleOptionName, -1, null, null); + displayOptions.registerOption(colorOptionName, Color.BLACK, null, + "Sets the " + colorOptionName); + displayOptions.registerOption(styleOptionName, -1, null, "Sets the " + style); color = displayOptions.getColor(colorOptionName, getDefaultColor()); style = displayOptions.getInt(styleOptionName, -1); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java index 6110cc4fe9..548a05ad9b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/LabelFieldFactory.java @@ -81,7 +81,7 @@ public class LabelFieldFactory extends FieldFactory { /** * Constructor * @param model the model that the field belongs to. - * @param hsProvider the HightLightStringProvider. + * @param hlProvider the HightLightStringProvider. * @param displayOptions the Options for display properties. * @param fieldOptions the Options for field specific properties. */ @@ -116,7 +116,8 @@ public class LabelFieldFactory extends FieldFactory { private void setupNamespaceOptions(Options fieldOptions) { // we need to install a custom editor that allows us to edit a group of related options fieldOptions.registerOption(NAMESPACE_OPTIONS, OptionType.CUSTOM_TYPE, - new NamespaceWrappedOption(), null, null, namespaceOptionsEditor); + new NamespaceWrappedOption(), null, "Adjusts the Label Field namespace display", + namespaceOptionsEditor); CustomOption wrappedOption = fieldOptions.getCustomOption(NAMESPACE_OPTIONS, new NamespaceWrappedOption()); if (!(wrappedOption instanceof NamespaceWrappedOption)) { @@ -406,8 +407,7 @@ public class LabelFieldFactory extends FieldFactory { text = SymbolUtilities.getDynamicOffcutName(addr); } // since these labels are fictitious, they don't have a namespace. - return new LabelFieldLocation(cu.getProgram(), addr, cpath, text, null, row, - col); + return new LabelFieldLocation(cu.getProgram(), addr, cpath, text, null, row, col); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java index e66b21ffaf..47efa36cce 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PlateFieldFactory.java @@ -654,11 +654,11 @@ public class PlateFieldFactory extends FieldFactory { "Number of lines to displayed before a plate comment." + " This setting has precedence over Lines Before Labels."); + help = new HelpLocation(HelpTopics.CODE_BROWSER, "Function_Pointers"); options.registerOption(ListingModel.DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true, - help, null); + help, "Shows/hides function header format for pointers to external functions"); options.registerOption(ListingModel.DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false, - help, null); - + help, "Shows/hides function header format for pointers to non-external functions"); } //================================================================================================== diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PostCommentFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PostCommentFieldFactory.java index fa032fd3f5..bf6ee2468f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PostCommentFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PostCommentFieldFactory.java @@ -85,7 +85,7 @@ public class PostCommentFieldFactory extends FieldFactory { /** * Constructor * @param model the model that the field belongs to. - * @param hsProvider the HightLightStringProvider. + * @param hlProvider the HightLightStringProvider. * @param displayOptions the Options for display properties. * @param fieldOptions the Options for field specific properties. */ @@ -93,9 +93,12 @@ public class PostCommentFieldFactory extends FieldFactory { Options displayOptions, Options fieldOptions) { super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions); - fieldOptions.registerOption(FLAG_FUNCTION_EXIT_OPTION, false, null, null); - fieldOptions.registerOption(FLAG_TERMINATOR_OPTION, false, null, null); - fieldOptions.registerOption(LINES_AFTER_BLOCKS_OPTION, 0, null, null); + fieldOptions.registerOption(FLAG_FUNCTION_EXIT_OPTION, false, null, + "Toggles the display of a post-comment for a function exit"); + fieldOptions.registerOption(FLAG_TERMINATOR_OPTION, false, null, + "Toggles the display of a jump/return post-comments"); + fieldOptions.registerOption(LINES_AFTER_BLOCKS_OPTION, 0, null, + "The number of lines to display after basic blocks"); flagFunctionExits = fieldOptions.getBoolean(FLAG_FUNCTION_EXIT_OPTION, false); flagJMPsRETs = fieldOptions.getBoolean(FLAG_TERMINATOR_OPTION, false); @@ -226,9 +229,8 @@ public class PostCommentFieldFactory extends FieldFactory { comments.addFirst(callOtherCallOverrideComment); } else { - overrideData = - getOverrideCommentData(instr, RefType.CALLOTHER_OVERRIDE_JUMP, pcodeOps, - pCodeOverride); + overrideData = getOverrideCommentData(instr, RefType.CALLOTHER_OVERRIDE_JUMP, + pcodeOps, pCodeOverride); if (overrideData != null) { String callOtherJumpOverrideComment = "-- CALLOTHER(" + overrideData.getOverriddenCallOther() + @@ -313,8 +315,8 @@ public class PostCommentFieldFactory extends FieldFactory { @Override public FieldFactory newInstance(FieldFormatModel formatModel, HighlightProvider provider, - ToolOptions displayOptions, ToolOptions fieldOptions) { - return new PostCommentFieldFactory(formatModel, provider, displayOptions, fieldOptions); + ToolOptions toolOptions, ToolOptions fieldOptions) { + return new PostCommentFieldFactory(formatModel, provider, toolOptions, fieldOptions); } @Override @@ -525,7 +527,8 @@ public class PostCommentFieldFactory extends FieldFactory { "at a jump or a return instruction."); options.registerOption(LINES_AFTER_BLOCKS_OPTION, 0, null, "Number of lines to display in the post comment after a code block."); - options.registerOption(ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG, true, null, null); + options.registerOption(ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG, true, null, + "Toggles the display of the automatic post-comment"); isWordWrap = options.getBoolean(ENABLE_WORD_WRAP_MSG, false); alwaysShowAutomatic = options.getBoolean(ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG, true); @@ -557,6 +560,7 @@ public class PostCommentFieldFactory extends FieldFactory { return next; } catch (AddressOverflowException e) { + // don't care } return null; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java index 57d6e829e9..8cf9bed251 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/PreCommentFieldFactory.java @@ -77,17 +77,18 @@ public class PreCommentFieldFactory extends FieldFactory { /** * Constructor * @param model the model that the field belongs to. - * @param hsProvider the HightLightStringProvider. + * @param hlProvider the HightLightStringProvider. * @param displayOptions the Options for display properties. * @param fieldOptions the Options for field specific properties. - * @param serviceProvider the provider for services. */ private PreCommentFieldFactory(FieldFormatModel model, HighlightProvider hlProvider, Options displayOptions, Options fieldOptions) { super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions); - fieldOptions.registerOption(FLAG_FUNCTION_ENTRY_OPTION, false, null, null); - fieldOptions.registerOption(FLAG_SUBROUTINE_ENTRY_OPTION, false, null, null); + fieldOptions.registerOption(FLAG_FUNCTION_ENTRY_OPTION, false, null, + "Toggles the display of a pre-comment for a function entry"); + fieldOptions.registerOption(FLAG_SUBROUTINE_ENTRY_OPTION, false, null, + "Toggles the display of a pre-comment for a sub-routine entry"); flagFunctionEntry = fieldOptions.getBoolean(FLAG_FUNCTION_ENTRY_OPTION, false); flagSubroutineEntry = fieldOptions.getBoolean(FLAG_SUBROUTINE_ENTRY_OPTION, false); @@ -183,8 +184,8 @@ public class PreCommentFieldFactory extends FieldFactory { @Override public FieldFactory newInstance(FieldFormatModel formatModel, HighlightProvider provider, - ToolOptions displayOptions, ToolOptions fieldOptions) { - return new PreCommentFieldFactory(formatModel, provider, displayOptions, fieldOptions); + ToolOptions toolOptions, ToolOptions fieldOptions) { + return new PreCommentFieldFactory(formatModel, provider, toolOptions, fieldOptions); } @Override @@ -379,7 +380,8 @@ public class PreCommentFieldFactory extends FieldFactory { "wrapping is off, comments are displayed in line format " + "however the user entered them. Lines that are too long " + "for the field, are truncated."); - options.registerOption(ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG, true, null, null); + options.registerOption(ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG, true, null, + "Toggles the display of the automatic pre-comment"); isWordWrap = options.getBoolean(ENABLE_WORD_WRAP_MSG, false); alwaysShowAutomatic = options.getBoolean(ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG, true); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/RegisterFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/RegisterFieldFactory.java index 2f63adf94d..6ebffd1377 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/RegisterFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/RegisterFieldFactory.java @@ -63,7 +63,8 @@ public class RegisterFieldFactory extends FieldFactory { fieldOptions.registerOption(DISPLAY_HIDDEN_REGISTERS_OPTION_NAME, false, null, "Shows/hides context registers"); - fieldOptions.registerOption(DISPLAY_DEFAULT_REGISTER_VALUES_OPTION_NAME, false, null, null); + fieldOptions.registerOption(DISPLAY_DEFAULT_REGISTER_VALUES_OPTION_NAME, false, null, + "Shows/hides default register values"); regColor = displayOptions.getColor(OptionsGui.REGISTERS.getColorOptionName(), getDefaultColor()); @@ -74,10 +75,9 @@ public class RegisterFieldFactory extends FieldFactory { @Override public FieldFactory newInstance(FieldFormatModel formatModel, - HighlightProvider highlightProvider, ToolOptions displayOptions, + HighlightProvider highlightProvider, ToolOptions toolOptions, ToolOptions fieldOptions) { - return new RegisterFieldFactory(formatModel, highlightProvider, displayOptions, - fieldOptions); + return new RegisterFieldFactory(formatModel, highlightProvider, toolOptions, fieldOptions); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java index b3f385c04b..a2fbdee7be 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java @@ -173,7 +173,8 @@ public class XRefFieldFactory extends FieldFactory { private void setupNamespaceOptions(Options fieldOptions) { // we need to install a custom editor that allows us to edit a group of related options fieldOptions.registerOption(NAMESPACE_OPTIONS, OptionType.CUSTOM_TYPE, - new NamespaceWrappedOption(), null, null, namespaceOptionsEditor); + new NamespaceWrappedOption(), null, "Adjusts the XREFs Field namespace display", + namespaceOptionsEditor); CustomOption customOption = fieldOptions.getCustomOption(NAMESPACE_OPTIONS, null); fieldOptions.getOptions(NAMESPACE_OPTIONS).setOptionsHelpLocation( new HelpLocation("CodeBrowserPlugin", "XREFs_Field")); @@ -529,6 +530,7 @@ public class XRefFieldFactory extends FieldFactory { * Get an address location for this object. * * @param obj object to get location from + * @return the address */ protected Address getXRefLocation(Object obj) { if (obj == null || !(obj instanceof CodeUnit)) { @@ -556,7 +558,7 @@ public class XRefFieldFactory extends FieldFactory { @Override public FieldFactory newInstance(FieldFormatModel formatModel, HighlightProvider provider, - ToolOptions displayOptions, ToolOptions fieldOptions) { - return new XRefFieldFactory(formatModel, provider, displayOptions, fieldOptions); + ToolOptions toolOptions, ToolOptions fieldOptions) { + return new XRefFieldFactory(formatModel, provider, toolOptions, fieldOptions); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java index 27da2682f4..d018aeb404 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java @@ -45,6 +45,7 @@ public class FormatManager implements OptionsChangeListener { HIGHLIGHT_GROUP + Options.DELIMITER + "Alternate Highlight Color"; public final static String ARRAY_DISPLAY_OPTIONS = OPTIONS_GROUP + Options.DELIMITER + "Array Display Options"; + public final static String ARRAY_DISPLAY_DESCRIPTION = "Adjusts the Array Field display"; private static final int NUM_MODELS = 7; @@ -94,7 +95,8 @@ public class FormatManager implements OptionsChangeListener { private void getArrayDisplayOptions(Options options) { options.registerOption(ARRAY_DISPLAY_OPTIONS, OptionType.CUSTOM_TYPE, - new ArrayElementWrappedOption(), null, null, new ArrayElementPropertyEditor()); + new ArrayElementWrappedOption(), null, ARRAY_DISPLAY_DESCRIPTION, + new ArrayElementPropertyEditor()); CustomOption option = options.getCustomOption(ARRAY_DISPLAY_OPTIONS, null); if (option instanceof ArrayElementWrappedOption) { ArrayElementWrappedOption arrayOption = (ArrayElementWrappedOption) option; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModel.java index cbb9d310fc..ddc9b14649 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModel.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +15,13 @@ */ package ghidra.app.util.viewer.listingpanel; +import docking.widgets.fieldpanel.Layout; import ghidra.app.util.viewer.format.FormatManager; import ghidra.framework.options.Options; import ghidra.program.model.address.*; import ghidra.program.model.listing.Data; import ghidra.program.model.listing.Program; import ghidra.util.task.TaskMonitor; -import docking.widgets.fieldpanel.Layout; public interface ListingModel { @@ -30,10 +29,10 @@ public interface ListingModel { public static final String DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME = FUNCTION_POINTER_OPTION_GROUP_NAME + Options.DELIMITER + - "Display Function Header for External Function Pointers"; + "Display External Function Pointer Header"; public static final String DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME = FUNCTION_POINTER_OPTION_GROUP_NAME + Options.DELIMITER + - "Display Function Header for Non-External Function Pointers"; + "Display Non-External Function Pointer Header"; public AddressSetView getAddressSet(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java index c354ea264d..c5dc262db5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java @@ -69,11 +69,6 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener } private void initOptions() { - fieldOptions.registerOption(DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true, null, - "Shows/hides function header format for pointers to external functions"); - fieldOptions.registerOption(DISPLAY_NONEXTERNAL_FUNCTION_POINTER_OPTION_NAME, false, null, - "Shows/hides function header format for pointers to non-external functions"); - showExternalFunctionPointerFormat = fieldOptions.getBoolean(DISPLAY_EXTERNAL_FUNCTION_POINTER_OPTION_NAME, true); showNonExternalFunctionPointerFormat = diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/ListingDisplayOptionsEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/ListingDisplayOptionsEditor.java index 5ea7b5c0bf..920fa05650 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/ListingDisplayOptionsEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/options/ListingDisplayOptionsEditor.java @@ -23,7 +23,6 @@ import javax.swing.JComponent; import ghidra.GhidraOptions; import ghidra.framework.options.*; -import ghidra.framework.plugintool.Plugin; /** * Class for editing Listing display properties. @@ -35,14 +34,11 @@ public class ListingDisplayOptionsEditor implements OptionsEditor { private Options options; private PropertyChangeListener propertyChangeListener; - private final Plugin ownerPlugin; - /** * Constructs a new ListingDisplayOptionsEditor. * @param options the options object to edit */ - public ListingDisplayOptionsEditor(Plugin ownerPlugin, Options options) { - this.ownerPlugin = ownerPlugin; + public ListingDisplayOptionsEditor(Options options) { this.options = options; registerOptions(); } @@ -56,17 +52,18 @@ public class ListingDisplayOptionsEditor implements OptionsEditor { } private void registerOptions() { - options.registerOption(GhidraOptions.OPTION_BASE_FONT, DEFAULT_FONT, null, null); + String prefix = "Sets the "; + options.registerOption(GhidraOptions.OPTION_BASE_FONT, DEFAULT_FONT, null, + prefix + GhidraOptions.OPTION_BASE_FONT); for (ScreenElement element : OptionsGui.elements) { - options.registerOption(element.getColorOptionName(), element.getDefaultColor(), null, - null); - options.registerOption(element.getStyleOptionName(), -1, null, null); + String colorOptionName = element.getColorOptionName(); + options.registerOption(colorOptionName, element.getDefaultColor(), null, + prefix + colorOptionName); + String styleOptionName = element.getStyleOptionName(); + options.registerOption(styleOptionName, -1, null, prefix + styleOptionName); } } - /** - * Apply the changes. - */ @Override public void apply() { if (optionsGui != null) { @@ -105,9 +102,6 @@ public class ListingDisplayOptionsEditor implements OptionsEditor { // nothing to do, as this component is reloaded when options are changed } - /** - * @see ghidra.framework.options.OptionsEditor#setOptionsPropertyChangeListener(java.beans.PropertyChangeListener) - */ @Override public void setOptionsPropertyChangeListener(PropertyChangeListener listener) { this.propertyChangeListener = listener; @@ -120,14 +114,12 @@ public class ListingDisplayOptionsEditor implements OptionsEditor { /** * Returns true if this component has "good" resizing behavior. Components * that do not have this property will be placed in a scrolled pane. + * @return true if resizable */ public boolean isResizable() { return true; } - /** - * Get the editor component. - */ @Override public JComponent getEditorComponent(Options editableOptions, EditorStateFactory editorStateFactory) { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java index b0f74fed16..b6515adb21 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/codebrowser/CodeBrowserOptionsTest.java @@ -15,11 +15,11 @@ */ package ghidra.app.plugin.core.codebrowser; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.stream.Collectors; import org.junit.*; @@ -45,6 +45,8 @@ import ghidra.program.model.symbol.SourceType; import ghidra.program.util.BytesFieldLocation; import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.TestEnv; +import ghidra.util.HelpLocation; +import util.CollectionUtils; public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest { private TestEnv env; @@ -969,6 +971,38 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest assertTrue(btf.getText().endsWith("[more]")); } + @Test + public void testEveryOptionHasHelp() throws Exception { + showTool(tool); + + List missing = new ArrayList<>(); + ToolOptions[] toolOptions = tool.getOptions(); + for (ToolOptions options : toolOptions) { + + HelpLocation helpLocation = options.getOptionsHelpLocation(); + if (helpLocation != null) { + continue; // this is a top-level help location for all sub-options + } + + if (CollectionUtils.isOneOf(options.getName(), "Key Bindings", "Listing Display")) { + continue; + } + + List optionNames = options.getOptionNames(); + for (String name : optionNames) { + HelpLocation hl = options.getHelpLocation(name); + if (hl == null) { + missing.add(options.getName() + "." + name); + } + } + } + + if (!missing.isEmpty()) { + fail(missing.size() + " Tool Options is missing help\n" + + missing.stream().collect(Collectors.joining("\n"))); + } + } + enum DUMMY { // nothing; just a dummy } diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java index f43fb9d38e..8ea353eafc 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java @@ -149,7 +149,7 @@ public class VTPlugin extends Plugin { private void initializeOptions() { Options options = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_DISPLAY); - options.registerOptionsEditor(new ListingDisplayOptionsEditor(this, options)); + options.registerOptionsEditor(new ListingDisplayOptionsEditor(options)); options.setOptionsHelpLocation(new HelpLocation(CodeBrowserPlugin.class.getSimpleName(), GhidraOptions.CATEGORY_BROWSER_DISPLAY)); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index b00f0a98f0..0872e9ac69 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -1780,12 +1780,14 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder 2) A component provider's code 3) A dialog provider's code 4) A background thread + 5) The help window It seems like the parent should be the active window for 1-2. Case 3 should probably use the window of the dialog provider. Case 4 should probably use the main tool frame, since the user may be moving between windows while the thread is working. So, rather than using the active window, we can default to the tool's frame. + Case 5 should use the help window. We have not yet solidified how we should parent. This documentation is meant to move us towards clarity as we find Use Cases that don't make sense. (Once we @@ -1828,7 +1830,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder Component c = parent; while (c != null) { - if (c instanceof Frame) { + if (c instanceof Window) { return (Window) c; } c = c.getParent(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java index 66b1fbc3f9..203930a0e3 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java @@ -175,7 +175,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction { for (ActionData actionData : actions) { if (actionData.isMyProvider(localContext)) { hasLocalActionsForKeyBinding = true; - if (actionData.action.isEnabledForContext(localContext)) { + if (isValidAndEnabled(actionData, localContext)) { list.add(new ExecutableKeyActionAdapter(actionData.action, localContext)); } } @@ -199,7 +199,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction { (ComponentBasedDockingAction) actionData.action; if (componentAction.isValidComponentContext(localContext)) { hasLocalActionsForKeyBinding = true; - if (actionData.action.isEnabledForContext(localContext)) { + if (isValidAndEnabled(actionData, localContext)) { list.add(new ExecutableKeyActionAdapter(actionData.action, localContext)); } } @@ -219,21 +219,22 @@ public class MultipleKeyAction extends DockingKeyBindingAction { // When looking for context matches, we prefer local context, even though this // is a 'global' action. This allows more specific context to be used when // available - if (actionData.action.isValidContext(localContext)) { - if (actionData.action.isEnabledForContext(localContext)) { - list.add(new ExecutableKeyActionAdapter(actionData.action, localContext)); - } + if (isValidAndEnabled(actionData, localContext)) { + list.add(new ExecutableKeyActionAdapter(actionData.action, localContext)); } - else if (actionData.action.isValidGlobalContext(globalContext)) { - if (actionData.action.isEnabledForContext(globalContext)) { - list.add(new ExecutableKeyActionAdapter(actionData.action, globalContext)); - } + else if (isValidAndEnabled(actionData, globalContext)) { + list.add(new ExecutableKeyActionAdapter(actionData.action, globalContext)); } } } return list; } + private boolean isValidAndEnabled(ActionData actionData, ActionContext localContext) { + DockingActionIf a = actionData.action; + return a.isValidContext(localContext) && a.isEnabledForContext(localContext); + } + @Override public boolean isReservedKeybindingPrecedence() { return false; // MultipleKeyActions can never be reserved diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java index 704209c564..7db8dabd49 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/ToolActions.java @@ -142,8 +142,9 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener { } KeyStroke ks = action.getKeyBinding(); + String description = "Keybinding for " + action.getFullName(); keyBindingOptions.registerOption(action.getFullName(), OptionType.KEYSTROKE_TYPE, ks, null, - null); + description); KeyStroke newKs = keyBindingOptions.getKeyStroke(action.getFullName(), ks); if (!Objects.equals(ks, newKs)) { action.setUnvalidatedKeyBindingData(new KeyBindingData(newKs)); @@ -175,8 +176,9 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener { private void registerStub(SharedStubKeyBindingAction stub, KeyStroke defaultKeyStroke) { stub.addPropertyChangeListener(this); + String description = "Keybinding for Stub action: " + stub.getFullName(); keyBindingOptions.registerOption(stub.getFullName(), OptionType.KEYSTROKE_TYPE, - defaultKeyStroke, null, null); + defaultKeyStroke, null, description); keyBindingsManager.addAction(null, stub); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java index 0feb84ebb6..88b3dddda9 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/OptionsPanel.java @@ -319,14 +319,15 @@ public class OptionsPanel extends JPanel { return; // not sure this can happen } + HelpService help = Help.getHelpService(); HelpLocation location = options.getOptionsHelpLocation(); if (location == null) { // The tree node may or may not have help. The leaf options should all have help. - return; + help.clearHelp(this); + } + else { + help.registerHelp(this, location); } - - HelpService help = Help.getHelpService(); - help.registerHelp(this, location); } private OptionsEditor getOptionsEditor(OptionsTreeNode node) { diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java index 52a93f5165..cb18b19276 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java @@ -26,8 +26,10 @@ import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import ghidra.util.HelpLocation; +import ghidra.util.Msg; import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; +import utilities.util.reflection.ReflectionUtilities; public abstract class AbstractOptions implements Options { public static final Set> SUPPORTED_CLASSES = buildSupportedClassSet(); @@ -136,6 +138,10 @@ public abstract class AbstractOptions implements Options { throw new IllegalStateException( "Can't register a custom option without a property editor"); } + if (description == null) { + Msg.error(this, "Registered an option without a description: " + optionName, + ReflectionUtilities.createJavaFilteredThrowable()); + } Option currentOption = valueMap.get(optionName); if (currentOption == null) { diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java index 67c84c68c7..6d53fa321d 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java @@ -116,6 +116,9 @@ public class ToolOptions extends AbstractOptions { * Return an XML element for the option names and values. * Note: only those options which have been explicitly set * will be included. + * + * @param includeDefaultBindings true to include default key binding values in the xml + * @return the xml root element */ public Element getXmlRoot(boolean includeDefaultBindings) { SaveState saveState = new SaveState(XML_ELEMENT_NAME); @@ -268,7 +271,7 @@ public class ToolOptions extends AbstractOptions { /** * Adds all the options name/value pairs to this Options. - * @param newOptions + * @param newOptions the new options into which the current options values will be placed */ public void copyOptions(Options newOptions) { List optionNames = newOptions.getOptionNames();