Merge remote-tracking branch 'origin/GT-3179-dragonmacher-fixed-missing-help' into Ghidra_9.1

This commit is contained in:
Ryan Kurtz 2019-10-15 11:40:26 -04:00
commit 28a09b6468
32 changed files with 378 additions and 212 deletions

View file

@ -16,6 +16,7 @@
<P>Often, users need to navigate to specific locations in a program.&nbsp; Ghidra provides
several different ways to do this:&nbsp;</P>
<BLOCKQUOTE>
<UL>
<LI>&nbsp;&nbsp;&nbsp;Enter a particular address or label (<A href="#Go_To_Address_Label">Go
To</A>)</LI>
@ -29,11 +30,12 @@
<LI>&nbsp;&nbsp; Use the <A href="#Navigation_History">Navigation History</A> to return to a
previously visited location</LI>
</UL>
</BLOCKQUOTE>
<H2><A name="Go_To_Address_Label"></A>Go To Address, Label, or Expression</H2>
<BLOCKQUOTE>
<H3>To perform a Go To:&nbsp;</H3>
<H3>To Perform a Go To:&nbsp;</H3>
<OL>
<LI>In the menu-bar of a tool, select <B>Navigation <IMG src="../../shared/arrow.gif"
@ -221,32 +223,47 @@
<H3><A name="gotoexpression"></A>Go To Expression<BR>
</H3>
<BLOCKQUOTE>
<P>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
"+ - * / &lt;&lt; &gt;&gt;".&nbsp; Also, parentheses are supported to control order of
expresion evaluation.<BR>
For example:<BR>
</P>
</BLOCKQUOTE>
<BLOCKQUOTE>
<P>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
"+ - * / &lt;&lt; &gt;&gt;".&nbsp; Also, parentheses are supported to control order of
expresion evaluation.<BR>
For example:<BR>
</P>
<TABLE BORDER="1">
<TR>
<TD WIDTH="35%">
<B>ENTRY+10</B>
</TD>
<TD>Positions
the cursor at the address 0x10 addresses past the symbol ENTRY
</TD>
</TR>
<TR>
<TD><B>0x100000+30</B>
</TD>
<TD>Positions the cursor at address 0x100030
</TD>
</TR>
<TR>
<TD><B>0x100000+(2*10)</B>
</TD>
<TD>Posiitons the cursor at address 0x100020
</TD>
</TR>
<TR>
<TD><B>+20</B>
</TD>
<TD>Positions the cursor at an address that is 0x20 past the current location
</TD>
</TR>
</TABLE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<DIV style="margin-left: 4em">
<UL>
<LI>ENTRY+10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Positions
the cursor at the address 0x10 addresses past the symbol ENTRY.</LI>
<LI>0x100000+30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Positions the cursor
at address 0x100030.</LI>
<LI>0x100000+(2*10)&nbsp;&nbsp;&nbsp; Posiitons the cursor at address 0x100020.</LI>
<LI>
+20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Positions the cursor at an address that is 0x20 past the current location.<BR>
</LI>
</UL>
</DIV>
<BLOCKQUOTE>
<H3>Executing a Query</H3>
@ -613,7 +630,7 @@
<P class="providedbyplugin">Provided by: <I>ProviderNavigation</I> plugin</P>
</BLOCKQUOTE>
<!--
This file is different than most, since it has multiple plugins contributing to the
content. Add some space at the bottom of the file to separate this contribution.
@ -625,6 +642,79 @@
<BR>
<BR>
<HR WIDTH="80%">
<H2><A NAME="Navigation_Options"></A>Navigation Options</H2>
<BLOCKQUOTE>
<P>
<B>'Go To' in Current Program Only</B> -
'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
'Go To' action will search other open programs,
possibly resulting in the listing view switching to a different open program tab.
By default, this option is on, thereby guaranteeing that the listing view will not
change to a different program when performing a <A HREF="#Go_To_Address_Label">
'Go To' action</A>.
</P>
<P>
<B>External Navigation</B> -
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
import Library, then that program will be opened and positioned to the selected
external location if found.
</P>
<P>
<B>Follow Indirection</B> -
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.
</P>
<P>
<B>Prefer Current Address Space</B> -
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
enter 1000 into the 'Go To' field, you could mean RAM:1000 or DATA:1000. If this option
is on, then it will go to the address with the address space that matches the current
cursor location. Otherwise, it will show a list of possible addresses for the given offset.
The default is on for this option.
</P>
<P>
<B>Range Navigation</B> -
Determines how <A HREF="help/topics/Selection/Selecting.htm#NavigateOverSelection">
navigation of ranges</A>
(i.e., selection ranges and highlight ranges) takes place. By default, navigating
to ranges will place the cursor at the top of the
next range. You may use this option to navigate to both the top and the bottom of each
range being navigated.
</P>
</BLOCKQUOTE>
<!--
This file is different than most, since it has multiple plugins contributing to the
content. Add some space at the bottom of the file to separate this contribution.
-->
<BR>
<BR>
<BR>
<BR>
<BR>
<BR>
<P class="relatedtopic">Related Topics:</P>

View file

@ -24,12 +24,10 @@
types of selections that are available from the tool <B>Select</B> menu. Each predefined type
of selection exposes different characteristics of the program.</P>
<P>To create a selection using one of the predefined methods:</P>
<UL type="disc">
<LI>From the Code Browser, select the menu option <B>Select</B><I><B><IMG src=
"../../shared/arrow.gif">SelectionType</B>.</I></LI>
</UL>
<P>To create a selection using one of the predefined methods via the menu item
<B>Select</B><I><B><IMG src=
"../../shared/arrow.gif">SelectionType</B>.</I>
</P>
<P>The <I><B>SelectionTypes</B></I> and their descriptions are as follows:</P>

View file

@ -84,12 +84,11 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
// get the option so that an owner is associated with it, otherwise
// it will not show up in the Options dialog for the tool.
Options options = tool.getOptions(GhidraOptions.CATEGORY_AUTO_ANALYSIS);
String description =
"This option forces the analysis options"
+ " dialog to appear whenever auto-analysis action is invoked.";
String description = "This option forces the analysis options" +
" dialog to appear whenever auto-analysis action is invoked.";
helpLocation = new HelpLocation("AutoAnalysisPlugin", "AnalysisOptions");
options.setOptionsHelpLocation(helpLocation);
options.registerOption(SHOW_ANALYSIS_OPTIONS, true, helpLocation, description);
}
@ -266,8 +265,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);
options.registerOptionsEditor(new AnalysisOptionsEditor(program));
options.setOptionsHelpLocation(new HelpLocation("AutoAnalysisPlugin",
"Auto_Analysis_Option"));
options.setOptionsHelpLocation(
new HelpLocation("AutoAnalysisPlugin", "Auto_Analysis_Option"));
}
private void programActivated(final Program program) {
@ -316,9 +315,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
public void analysisEnded(AutoAnalysisManager manager) {
MessageLog log = manager.getMessageLog();
if (log.getMsgCount() > 0) {
MultiLineMessageDialog dialog =
new MultiLineMessageDialog("Auto Analysis Summary",
"There were warnings/errors issued during analysis.", log.toString(),
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Auto Analysis Summary",
"There were warnings/errors issued during analysis.", log.toString(),
MultiLineMessageDialog.WARNING_MESSAGE, false);//modal?
DockingWindowManager.showDialog(null, dialog);
}
@ -332,9 +330,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
public OneShotAnalyzerAction(Analyzer analyzer) {
super(analyzer.getName(), AutoAnalysisPlugin.this.getName());
this.analyzer = analyzer;
setMenuBarData(new MenuData(
new String[] { "Analysis", "One Shot", analyzer.getName() }, null,
ANALYZE_GROUP_NAME));
setMenuBarData(new MenuData(new String[] { "Analysis", "One Shot", analyzer.getName() },
null, ANALYZE_GROUP_NAME));
setHelpLocation(new HelpLocation("AutoAnalysisPlugin", "Auto_Analyzers"));
setEnabled(false);

View file

@ -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(

View file

@ -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<FlowArrow> 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());

View file

@ -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;

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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,12 +65,13 @@ 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());
HelpLocation hl = new HelpLocation("CodeBrowserPlugin", "Array_Options");
fieldOptions.getOptions(FormatManager.OPTIONS_GROUP).setOptionsHelpLocation(hl);
fieldOptions.getOptions(FormatManager.ARRAY_OPTIONS_GROUP).setOptionsHelpLocation(hl);
fieldOptions.getOptions(FormatManager.ARRAY_DISPLAY_OPTIONS).setOptionsHelpLocation(hl);
if (!(wrappedOption instanceof 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) {

View file

@ -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);

View file

@ -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);

View file

@ -23,6 +23,7 @@ import docking.widgets.fieldpanel.support.FieldLocation;
import ghidra.GhidraOptions;
import ghidra.app.util.HighlightProvider;
import ghidra.app.util.viewer.format.FieldFormatModel;
import ghidra.app.util.viewer.format.FormatManager;
import ghidra.app.util.viewer.options.OptionsGui;
import ghidra.app.util.viewer.proxy.ProxyObj;
import ghidra.framework.options.Options;
@ -34,16 +35,14 @@ import ghidra.program.util.FieldNameFieldLocation;
import ghidra.program.util.ProgramLocation;
/**
* Generates Data Field name Fields.
* Generates Data Field (structure field names and array indexes) name Fields.
*/
public class FieldNameFieldFactory extends FieldFactory {
public static final String FIELD_NAME = "Field Name";
private final static String GROUP_TITLE = FIELD_NAME;
public final static String ARRAY_INDEX_FORMAT_MSG =
GROUP_TITLE + Options.DELIMITER + "Array Index Format";
public final static String ARRAY_INDEX_FORMAT_NAME =
FormatManager.ARRAY_OPTIONS_GROUP + Options.DELIMITER + "Array Index Format";
public static enum IndexFormat {
@ -62,9 +61,6 @@ public class FieldNameFieldFactory extends FieldFactory {
private IndexFormat format;
/**
* Default constructor
*/
public FieldNameFieldFactory() {
super(FIELD_NAME);
}
@ -72,16 +68,16 @@ public class FieldNameFieldFactory 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.
*/
private FieldNameFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
Options displayOptions, ToolOptions fieldOptions) {
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
fieldOptions.registerOption(ARRAY_INDEX_FORMAT_MSG, IndexFormat.decimal, null,
"Hex or Decimal field offsets");
format = fieldOptions.getEnum(ARRAY_INDEX_FORMAT_MSG, IndexFormat.decimal);
fieldOptions.registerOption(ARRAY_INDEX_FORMAT_NAME, IndexFormat.decimal, null,
"Hex or Decimal field offsets for arrays");
format = fieldOptions.getEnum(ARRAY_INDEX_FORMAT_NAME, IndexFormat.decimal);
}
private String getFieldName(Data data) {
@ -94,25 +90,19 @@ public class FieldNameFieldFactory extends FieldFactory {
return data.getFieldName();
}
/**
* @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) {
super.fieldOptionsChanged(options, optionName, oldValue, newValue);
if (options.getName().equals(GhidraOptions.CATEGORY_BROWSER_FIELDS)) {
if (optionName.equals(ARRAY_INDEX_FORMAT_MSG)) {
if (optionName.equals(ARRAY_INDEX_FORMAT_NAME)) {
format = (IndexFormat) newValue;
model.update();
}
}
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#getField(ProxyObj, int)
*/
@Override
public ListingField getField(ProxyObj<?> proxy, int varWidth) {
Object obj = proxy.getObject();
@ -132,9 +122,6 @@ public class FieldNameFieldFactory extends FieldFactory {
width, hlProvider);
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#getProgramLocation(int, int, ghidra.app.util.viewer.field.ListingField)
*/
@Override
public ProgramLocation getProgramLocation(int row, int col, ListingField bf) {
Object obj = bf.getProxy().getObject();
@ -146,9 +133,6 @@ public class FieldNameFieldFactory extends FieldFactory {
data.getComponentPath(), getFieldName(data), col);
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#getFieldLocation(ghidra.app.util.viewer.field.ListingField, BigInteger, int, ghidra.program.util.ProgramLocation)
*/
@Override
public FieldLocation getFieldLocation(ListingField bf, BigInteger index, int fieldNum,
ProgramLocation programLoc) {
@ -163,9 +147,6 @@ public class FieldNameFieldFactory extends FieldFactory {
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#acceptsType(int, java.lang.Class)
*/
@Override
public boolean acceptsType(int category, Class<?> proxyObjectClass) {
if (!CodeUnit.class.isAssignableFrom(proxyObjectClass)) {
@ -176,13 +157,10 @@ public class FieldNameFieldFactory extends FieldFactory {
@Override
public FieldFactory newInstance(FieldFormatModel formatModel, HighlightProvider provider,
ToolOptions displayOptions, ToolOptions fieldOptions) {
return new FieldNameFieldFactory(formatModel, provider, displayOptions, fieldOptions);
ToolOptions toolOptions, ToolOptions fieldOptions) {
return new FieldNameFieldFactory(formatModel, provider, toolOptions, fieldOptions);
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#getDefaultColor()
*/
@Override
public Color getDefaultColor() {
return OptionsGui.FIELD_NAME.getDefaultColor();

View file

@ -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

View file

@ -44,7 +44,7 @@ public class PlateFieldFactory extends FieldFactory {
private static final String EMPTY_STRING = "";
public static final String FIELD_NAME = "Plate Comment";
public static final Color DEFAULT_COLOR = Color.BLUE;
private final static String FIELD_GROUP_TITLE = "Plate Comment";
private final static String FIELD_GROUP_TITLE = "Plate Comments Field";
public final static String ENABLE_WORD_WRAP_MSG =
FIELD_GROUP_TITLE + Options.DELIMITER + "Enable Word Wrapping";
@ -107,7 +107,7 @@ public class PlateFieldFactory 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.
*/
@ -249,7 +249,7 @@ public class PlateFieldFactory extends FieldFactory {
* Generate a text line for the plate text.
* Text will be left justified between two '*' and padded based upon the
* available field width.
* @param text plate text string
* @param elements the field elements that may get updated
* @return formatted plate text line
*/
private boolean addSideBorders(List<FieldElement> elements) {
@ -504,8 +504,8 @@ public class PlateFieldFactory extends FieldFactory {
@Override
public FieldFactory newInstance(FieldFormatModel formatModel, HighlightProvider hsProvider,
ToolOptions displayOptions, ToolOptions fieldOptions) {
return new PlateFieldFactory(formatModel, hsProvider, displayOptions, fieldOptions);
ToolOptions toolOptions, ToolOptions fieldOptions) {
return new PlateFieldFactory(formatModel, hsProvider, toolOptions, fieldOptions);
}
@Override
@ -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");
}
//==================================================================================================

View file

@ -49,7 +49,7 @@ public class PostCommentFieldFactory extends FieldFactory {
public static final String FIELD_NAME = "Post-Comment";
private final static String GROUP_TITLE = "Format Code";
private final static String FIELD_GROUP_TITLE = "Post Comment";
private final static String FIELD_GROUP_TITLE = "Post-comments Field";
public final static String ENABLE_WORD_WRAP_MSG =
FIELD_GROUP_TITLE + Options.DELIMITER + "Enable Word Wrapping";
public final static String ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG =
@ -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);
@ -232,9 +235,8 @@ public class PostCommentFieldFactory extends FieldFactory {
}
}
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() +
@ -325,8 +327,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
@ -537,7 +539,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);
@ -569,6 +572,7 @@ public class PostCommentFieldFactory extends FieldFactory {
return next;
}
catch (AddressOverflowException e) {
// don't care
}
return null;
}

View file

@ -46,7 +46,7 @@ public class PreCommentFieldFactory extends FieldFactory {
public static final String FIELD_NAME = "Pre-Comment";
private final static String GROUP_TITLE = "Format Code";
private final static String FIELD_GROUP_TITLE = "Pre-Comment";
private final static String FIELD_GROUP_TITLE = "Pre-comments Field";
public final static String ENABLE_WORD_WRAP_MSG =
FIELD_GROUP_TITLE + Options.DELIMITER + "Enable Word Wrapping";
public final static String ENABLE_ALWAYS_SHOW_AUTOMATIC_MSG =
@ -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);

View file

@ -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

View file

@ -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);
}
}

View file

@ -37,14 +37,15 @@ import ghidra.util.exception.AssertException;
* Class to manage the set of format models.
*/
public class FormatManager implements OptionsChangeListener {
public static final String OPTIONS_GROUP = "Array Options";
public static final String ARRAY_OPTIONS_GROUP = "Array Options";
private static final String HIGHLIGHT_GROUP = "Cursor Text Highlight";
public static final String HIGHLIGHT_COLOR_NAME =
HIGHLIGHT_GROUP + Options.DELIMITER + "Highlight Color";
public static final String HIGHLIGHT_ALT_COLOR_NAME =
HIGHLIGHT_GROUP + Options.DELIMITER + "Alternate Highlight Color";
public final static String ARRAY_DISPLAY_OPTIONS =
OPTIONS_GROUP + Options.DELIMITER + "Array Display Options";
ARRAY_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;

View file

@ -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();

View file

@ -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 =

View file

@ -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) {

View file

@ -15,15 +15,18 @@
*/
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.*;
import docking.help.Help;
import docking.help.HelpService;
import docking.widgets.fieldpanel.field.*;
import generic.test.TestUtils;
import ghidra.GhidraOptions;
import ghidra.app.cmd.comments.SetCommentCmd;
import ghidra.app.cmd.data.CreateDataCmd;
@ -32,6 +35,7 @@ import ghidra.app.cmd.refs.AddMemRefCmd;
import ghidra.app.cmd.refs.AddRegisterRefCmd;
import ghidra.app.services.ProgramManager;
import ghidra.app.util.viewer.field.*;
import ghidra.base.help.GhidraHelpService;
import ghidra.framework.cmd.Command;
import ghidra.framework.options.Options;
import ghidra.framework.options.ToolOptions;
@ -45,6 +49,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 +975,72 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest
assertTrue(btf.getText().endsWith("[more]"));
}
@Test
public void testEveryOptionHasHelp() throws Exception {
showTool(tool);
loadProgram();
List<String> missing = new ArrayList<>();
ToolOptions[] toolOptions = tool.getOptions();
GhidraHelpService.install();
for (ToolOptions options : toolOptions) {
HelpLocation optionsHelp = options.getOptionsHelpLocation();
boolean hasParentHelp = optionsHelp != null;
if (CollectionUtils.isOneOf(options.getName(), "Key Bindings", "Listing Display")) {
continue; // these custom widgets are known to have help
}
List<String> optionNames = options.getOptionNames();
for (String name : optionNames) {
HelpLocation hl = options.getHelpLocation(name);
if (hl == null) {
if (!hasParentHelp) {
missing.add("Option missing help: " + options.getName() + "." + name);
}
}
List<HelpLocation> nestedHelp = getParentHelpLocations(options, name);
for (HelpLocation help : nestedHelp) {
if (help != null && !isValidHelpLocation(help)) {
missing.add("Bad help location: " + help.toString());
}
}
// it has a help location; is it valid?
if (hl != null && !isValidHelpLocation(hl)) {
missing.add(name + "." + name);
}
}
}
if (!missing.isEmpty()) {
fail(missing.size() + " Tool Options is missing/invalid help\n" +
missing.stream().collect(Collectors.joining("\n")));
}
}
private List<HelpLocation> getParentHelpLocations(ToolOptions options, String name) {
List<HelpLocation> list = new LinkedList<>();
List<String> parts = CollectionUtils.asList(name.split("\\."));
Collections.reverse(parts); // put lowest-level first
for (String optionName : parts) {
Options parentOption = options.getOptions(optionName);
HelpLocation help = parentOption.getOptionsHelpLocation();
list.add(help);
}
return list;
}
private boolean isValidHelpLocation(HelpLocation helpLocation) {
HelpService help = Help.getHelpService();
boolean isValid =
(boolean) TestUtils.invokeInstanceMethod("isValidHelpLocation", help, helpLocation);
return isValid;
}
enum DUMMY {
// nothing; just a dummy
}

View file

@ -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));

View file

@ -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,6 +1830,10 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
Component c = parent;
while (c != null) {
// Note: using a Frame here means that we will not find and use a dialog that is a
// parent of 'c' if it itself is parented to a Frame. The issue is that
// Use Case 'C' above may not work correctly. If we find that to be the case,
// then we can try changing 'Frame' to 'Window' here.
if (c instanceof Frame) {
return (Window) c;
}

View file

@ -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,27 @@ 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 (isValidAndEnabledGlobally(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);
}
private boolean isValidAndEnabledGlobally(ActionData actionData, ActionContext globalContext) {
DockingActionIf a = actionData.action;
return a.isValidGlobalContext(globalContext) && a.isEnabledForContext(globalContext);
}
@Override
public boolean isReservedKeybindingPrecedence() {
return false; // MultipleKeyActions can never be reserved

View file

@ -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);
}

View file

@ -24,7 +24,6 @@ import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import javax.help.*;
import javax.help.Map.ID;
@ -497,9 +496,7 @@ public class HelpManager implements HelpService {
private Map<Object, HelpLocation> copyHelpLocations() {
// we must copy the help locations, since we are in a background thread and the
// locations map is frequently updated by the Swing thread
AtomicReference<Map<Object, HelpLocation>> ref = new AtomicReference<>();
SystemUtilities.runSwingNow(() -> ref.set(new HashMap<>(helpLocations)));
return ref.get();
return Swing.runNow(() -> new HashMap<>(helpLocations));
}
//

View file

@ -15,12 +15,12 @@
*/
package docking.help;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.regex.*;
import javax.help.*;
@ -34,6 +34,7 @@ import docking.DockingUtils;
import docking.DockingWindowManager;
import docking.actions.KeyBindingUtils;
import docking.widgets.*;
import generic.util.WindowUtilities;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
import ghidra.util.task.*;
@ -232,7 +233,8 @@ class HelpViewSearcher {
@Override
public void actionPerformed(ActionEvent e) {
DockingWindowManager.showDialog(htmlEditorPane, findDialog);
Window helpWindow = WindowUtilities.windowForComponent(htmlEditorPane);
DockingWindowManager.showDialog(helpWindow, findDialog);
}
}

View file

@ -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) {

View file

@ -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<Class<?>> 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) {

View file

@ -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<String> optionNames = newOptions.getOptionNames();