- An Equate is a string substitution for scalar (a numeric value) in any code unit (instruction
- operand or data). For example, consider the instruction below:
+
An Equate is a string substitution for scalar (a numeric value) in any code unit
+ (instruction operand or data). For example, consider the instruction below:
-
- MOV R2, $0xb
-
+
MOV R2, $0xb
-
The scalar $0xb can be replaced with the string BATTERY_FLAG_CRITICAL.
- This will yield the following:
+
The scalar $0xb can be replaced with the string BATTERY_FLAG_CRITICAL. This
+ will yield the following:
-
- MOV R2, BATTERY_FLAG_CRITICAL
-
+
MOV R2, BATTERY_FLAG_CRITICAL
The substitution of "BATTERY_FLAG_CRITICAL" for $0xb is called an equate. That is,
- $0xb is equated to "BATTERY_FLAG_CRITICAL". Note that the default choice for the new
- equate application is your current location. "BATTERY_FLAG_CRITICAL" will
- replace the scalar value $0xb only at the current cursor location unless you choose a
- different option. However, when replacing another scalar of the same value,
- a list of previously declared Equates for that
- scalar value is presented.
+ $0xb is equated to "BATTERY_FLAG_CRITICAL". Note that the default choice for the new
+ equate application is your current location. "BATTERY_FLAG_CRITICAL" will replace the scalar
+ value $0xb only at the current cursor location unless you choose a different option.
+ However, when replacing another scalar of the same value, a list of previously declared Equates
+ for that scalar value is presented.
+
+
Scalars can only be equated to strings. The string can be of any length and may contain
+ spaces and special characters. Duplicate equate names are not allowed.
-
Scalars can only be equated to strings. The string can be of any length and may
- contain spaces and special characters. Duplicate equate names are not allowed.
-
-
It should be noted that for the purposes of this document, "scalars" refers to scalar values
- contained in code units. A code unit is an instruction operand or other data element.
+
It should be noted that for the purposes of
+ this document, "scalars" refers to scalar values contained in code units. A code unit
+ is an instruction operand or other data element.
There are several operations that are associated with Equates. They are:
The Set Equate action will create one or more Equates in the Listing.
To set an Equate:
-
-
-
+
- Right-mouse-click on the target scalar value, and select Set Equate or press
- <E>.
-
-
-
-
-
-
+ Right-mouse-click on the target scalar value, and select Set Equate or
+ press <E>.
+
+
+
+
When the dialog appears, either type in an equate string or choose one from the list of
- strings that are known to be associated with the given value. As you type in the
- "Equate String" field, the list will be narrowed down to show only the strings that contain
- the text that has been typed.
+ strings that are known to be associated with the given value. As you type in the "Equate
+ String" fi1eld, the list will be narrowed down to show only the strings that contain the
+ text that has been typed.
-
- Select one of the choices from the "Apply To" list. Current Location is
- the default choice unless a selection is made, in which case the Current Selection option
- will be set. The other option is Entire Program.
-
-
-
- Current Location: When selected the equate will be applied to the scalar
- value at the current location of your cursor only.
-
-
- Current Selection: When selected the equate will be applied to all of
- the scalar values in your current selection that match the value
- of the scalar that you originally clicked. When you make a
- selection in your program this button will become enabled. If you do not make a
- selection then it will not be enabled and the option will be grayed out. Note that
- scalars in your selection that already have an equate set will not be affected
- by this unless you also select the overwrite option.
-
-
- Entire Program: When selected the equate will be applied to all of the
- scalar values in the entire program that also match the value of the scalar that
- you originally right-mouse-clicked on.
-
-
- Overwrite existing equates: This option is only enabled when setting equates in a selection or the whole program. If this
- option is selected, all scalars and all named equates in the selection or entire program, depending on which option is selected, will be
- set with the user-given equate name. If the overwrite option is not selected, only scalars not already with equates set will be assigned the user-given equate name.
-
-
-
+
+ Select one of the choices from the "Apply To" list. Current Location is the
+ default choice unless a selection is made, in which case the Current Selection
+ option will be set. The other option is Entire Program.
-
Double-click on an entry in the list, or select an entry in the list and press OK, or type in the string and press OK. If any item
- in the list is selected it will be used, otherwise the text in the "Equate String" field
- will be used.
-
-
-
-
-
-
+
+
Current Location: When selected the equate will be applied to the scalar
+ value at the current location of your cursor only.
-
-
The list of strings shown in the Set
- Equate dialog are generated from two sources. The first source is all the currently
- assigned equates to the given value. The other source is all the Enum datatypes that
- exist in all the open datatype archives. If an
- Enum datatype exists that has a member value equal to the given equate value, then that string
- will be included.
-
-
-
The open data type archives
- contain valid enums and "fake" enums. The fake enums are created from #define values
- (parsed from .h files), specifically so that they will be available in the Set Equate dialog.
+
Current Selection: When selected the equate will be applied to all of the
+ scalar values in your current selection that match the value of the scalar that you
+ originally clicked. When you make a selection in your program this button will become
+ enabled. If you do not make a selection then it will not be enabled and the option will
+ be grayed out. Note that scalars in your selection that already have an equate set will
+ not be affected by this unless you also select the overwrite option.
-
Each entry in the dialog is color-coded based upon how it is being used
- as an equate.
-
-
-
- Blue: Blue entries are existing user-defined string equates that are being used
- for that scalar.
-
-
-
- Black: Black entries are existing enum field equates being used for that scalar.
-
-
-
- Gray: Gray entries are suggested enum fields that have the same value as the
- scalar. These entries are only suggestions, and have not yet been made equates.
-
-
-
-
+
Entire Program: When selected the equate will be applied to all of the
+ scalar values in the entire program that also match the value of the scalar that you
+ originally right-mouse-clicked on.
+
+
Overwrite existing equates: This option is only enabled when setting equates
+ in a selection or the whole program. If this option is selected, all scalars and all
+ named equates in the selection or entire program, depending on which option is
+ selected, will be set with the user-given equate name. If the overwrite option is not
+ selected, only scalars not already with equates set will be assigned the user-given
+ equate name.
+
+
+
+
Double-click on an entry in the list, or select an entry in the list and press
+ OK, or type in the string and press OK. If any item in the list is selected it will
+ be used, otherwise the text in the "Equate String" field will be used.
+
-
Rename Equate
-
-
-
The Rename Equate action will rename one or more instances of a named Equate in the Listing.
+
+
The list of strings shown in the Set
+ Equate dialog are generated from two sources. The first source is all the currently
+ assigned equates to the given value. The other source is all the Enum datatypes that exist in
+ all the open datatype archives. If an Enum datatype exists that has a member value
+ equal to the given equate value, then that string will be included.
+
+
The open data type archives contain
+ valid enums and "fake" enums. The fake enums are created from #define values (parsed from .h
+ files), specifically so that they will be available in the Set Equate
+ dialog./P>
+
+
Each entry in the dialog is color-coded based
+ upon how it is being used as an equate.
+
+
+
Blue: Blue entries are existing user-defined string equates that are being used
+ for that scalar.
+
+
Black: Black entries are existing enum field equates being used for that
+ scalar.
+
+
Gray: Gray entries are suggested enum fields that have the same value as the
+ scalar. These entries are only suggestions, and have not yet been made equates.
+
+
+
+
Rename Equate
+
+
+
The Rename Equate action will rename one or more instances of a named Equate in the
+ Listing.
To rename an Equate:
-
-
Right-mouse-click on the current Equate, and select Rename Equate or press
<E>.
-
-
-
-
-
+
+
+
-
- Select one of the choices from the "Apply To" list. Current Location is
- the default choice unless a selection is made, in which case the Current Selection option
- will be set. The other option is Entire Program.
-
-
-
- Current Location: When selected the equate will be applied to the scalar
- value at the current location of your cursor only.
-
-
- Current Selection: When selected the equate will be applied to all of
- the scalar values in your current selection that match the value
- of the scalar that you originally clicked. When you make a
- selection in your program this button will become enabled. If you do not make a
- selection then it will not be enabled and the option will be grayed out.
-
-
- Entire Program: When selected the equate will be applied to all of the
- scalar values in the entire program that match the value of the scalar that you
- originally clicked. Scalars that already have an equate set that
- is different from the one you selected will not be affected.
-
-
-
+
+ Select one of the choices from the "Apply To" list. Current Location is the
+ default choice unless a selection is made, in which case the Current Selection
+ option will be set. The other option is Entire Program.
+
+
+
Current Location: When selected the equate will be applied to the scalar
+ value at the current location of your cursor only.
+
+
Current Selection: When selected the equate will be applied to all of the
+ scalar values in your current selection that match the value of the scalar that you
+ originally clicked. When you make a selection in your program this button will become
+ enabled. If you do not make a selection then it will not be enabled and the option will
+ be grayed out.
+
+
Entire Program: When selected the equate will be applied to all of the
+ scalar values in the entire program that match the value of the scalar that you
+ originally clicked. Scalars that already have an equate set that is different from the
+ one you selected will not be affected.
+
+
+
+
Double-click an entry in the list, select an entry in the list and press OK, or
+ type in the string and press OK. If any item in the list is selected it will be
+ used, otherwise the text in the "Equate String" field will be used.
+
+
+
+
Remove Equate
-
Double-click an entry in the list, select an entry in the list and press OK, or type in the string and press OK. If any item
- in the list is selected it will be used, otherwise the text in the "Equate String" field
- will be used.
-
-
Remove Equate
-
-
The Remove Equate action will remove an Equate(s) from a listing; effectively returning the operand to its original scalar value.
+
The Remove Equate action will remove an Equate(s) from a listing; effectively
+ returning the operand to its original scalar value.
To remove references to an Equate via the context popup menu:
-
-
-
Right-mouse-click on an existing Equate, or select a group of equates and right-click on an equate within that selection, then choose Remove Equate or press
+
Right-mouse-click on an existing Equate, or select a group of equates and right-click
+ on an equate within that selection, then choose Remove Equate or press
<Delete>.
-
-
If you made a group selection, a confirmation dialog will appear to ensure you want to remove all equates in the selection; equates within the selection
- matching the one you clicked will be removed.
-
-
-
-
+
+ If you made a group selection, a confirmation dialog will appear to ensure you want to
+ remove all equates in the selection; equates within the selection matching the one you
+ clicked will be removed.
+
+
+
+
-
-
To remove all references of an Equate via the Equates Table window:
-
-
-
Select the Code Browser menu option WindowEquates Table to bring up the Equates Table window.
+
Select the Code Browser menu option WindowEquates Table to bring up the Equates Table window.
Right-mouse-click on the Equate to be deleted and select Delete.
A confirmation dialog will appear.
-
-
-
-
+
+
+
Select Delete to remove all references to the equate and the Equate's definition
itself.
-
-
-
Apply Enum
-
-
-
The Apply Enum action (only available when there is a selection), will apply
- enum member names to scalars in the current selection if any of the enum values match
- those scalars.
-
-
To apply an enum to the selection:
-
+
+
+
Edit Enum
+
+
+
The Edit Enum action is available from the Equates Table window.
+ Right-mouse-click on an existing Equate in the table. If that equate is part of an enum,
+ then this action will show the enum in an editor window.
+
+
+
+
+
Show Enum
+
+
+
The Show Enum action is available from the Equates Table window.
+ Right-mouse-click on an existing Equate in the table. If that equate is part of an enum,
+ then this action will show that enum in the Data Type Manager window.
+
+
+
+
+
+
Apply Enum
+
+
+
The Apply Enum action (only available when there is a selection), will apply enum
+ member names to scalars in the current selection if any of the enum values match those
+ scalars.
+
+
To apply an enum to the selection:
+
-
Make a selection and then Right-mouse-click, then choose Apply Enum.
-
-
-
+
+ Make a selection and then Right-mouse-click, then choose Apply Enum.
-
+
+
+
-
-
A dialog similar to the one below should appear. Select the enum that
- you want to be applied to the selection. The data type must be an enum for the action
- to work.
-
-
-
-
-
-
-
-
Apply to sub-operands - Applies the enum to scalars within operands.
-
-
-
Once the data type is selected, the scalars in the selection will have equates
- applied to them as shown below.
-
-
-
+
+ A dialog similar to the one below should appear. Select the enum that you want to be
+ applied to the selection. The data type must be an enum for the action to work.
-
-
+
+
+
+
+
+
Apply to sub-operands - Applies the enum to scalars within operands.
+
+
+
Once the data type is selected, the scalars in the selection will have equates applied
+ to them as shown below.
+
+
+
+
-
+
View Equates
The Display Equates Table action displays a window which lists all of the Equates
and their references in a tabular format.
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
The left panel, Equates, lists name, value, and number of references for all
- Equates. The right panel, References, lists the address and operand index of
- each location that references the Equate selected in the left panel. Selecting an
- address on the References panel will cause the Code Browser to go to that address in
- the listing. The Equates panel and the References panel can each be
- sorted by any column. The ascending and descending indicator displays the sort order of
- the information.
+ Equates. The right panel, References, lists the address and operand index of each
+ location that references the Equate selected in the left panel. Selecting an address on the
+ References panel will cause the Code Browser to go to that address in the listing. The
+ Equates panel and the References panel can each be sorted by any column. The
+ ascending and descending indicator displays the sort order of the information.
-
To view the Equates Table select the Code Browser menu option WindowEquates Table to bring up the Equates Table
+
To view the Equates Table select the Code Browser menu option WindowEquates Table to bring up the Equates Table
window.
You can re-order the columns in the Equates table by dragging the header to another
@@ -363,118 +326,114 @@
Op Index. By default, the references are sorted by reference address in ascending order.
-
You can also rename the equate by double clicking in the name field and entering a
- new name. If the equate is based off of an enum, then an enum editor dialog will appear.
- Changing the matching field name will also change the equate name.
+
You can rename an equate by double-clicking the name field and entering a new
+ name. If the equate is based off of an enum, then double-clicking will not trigger an edit.
+ Instead, you can right-click and edit the containing enum. In the enum editor, changing
+ the matching field name will also change the equate name.
-
-
Each equate is color-coded based upon how it is being used.
-
-
-
- Blue: Blue equates are existing user-defined string equates that are being used
- for that scalar.
-
-
-
- Black: Black equates are existing enum field equates being used for that scalar.
-
-
-
- Red: Red entries are bad equates. A bad equate could either mean that the enum
- that this equate is based off of was deleted, the field inside the enum was deleted, or
- the field's value was changed.
-
-
-
-
+
+
Each equate is color-coded based upon how it
+ is being used.
+
+
+
+
Blue: Blue equates are existing user-defined string equates that are being
+ used for that scalar.
+
+
Black: Black equates are existing enum field equates being used for that
+ scalar.
+
+
Red: Red entries are bad equates. A bad equate could either mean that the enum
+ that this equate is based off of was deleted, the field inside the enum was deleted, or
+ the field's value was changed.
+
+
-
Convert
+
Convert
-
-
The various convert actions are used to change the number format display of scalars
- displayed in the code browser. These actions are available whenever the cursor is on a number
- in the operand field, or the value field of a data item (byte, word, dword, qword). Note that
- these actions and equates are not currently supported for composite and array data.
- For instruction operands, the scalar number is converted visually by replacing the number with an
- appropriately named equate. Such a conversion can be cleared by removing the equate
- from the operand. For data value fields, a combination of data format settings and signed/unsigned
- data type alteration is used to reflect a conversion. The available formats are as follows.
-
-
+
The various convert actions are used to change the number format display of scalars
+ displayed in the code browser. These actions are available whenever the cursor is on a number
+ in the operand field, or the value field of a data item (byte, word, dword, qword). Note that
+ these actions and equates are not currently supported for composite and array data. For
+ instruction operands, the scalar number is converted visually by replacing the number with an
+ appropriately named equate. Such a conversion can be cleared by removing the equate from the
+ operand. For data value fields, a combination of data format settings and signed/unsigned data
+ type alteration is used to reflect a conversion. The available formats are as follows.
Signed Decimal
-
The existing scalar value will be displayed as a signed decimal number. This action
- is only available if the value can be interpreted as a negative value.
+
The existing scalar value will be displayed as a signed decimal number. This action is
+ only available if the value can be interpreted as a negative value.
Unsigned Decimal
-
The existing scalar value will be displayed as an unsigned decimal number. If the
- value would be positive even if the signed decimal format was selected, the action will
- simply be name Decimal instead of Unsigned Decimal.
+
The existing scalar value will be displayed as an unsigned decimal number. If the value
+ would be positive even if the signed decimal format was selected, the action will simply be
+ name Decimal instead of Unsigned Decimal.
Unsigned Octal
The existing scalar value will be displayed as an unsigned octal number.
-
Signed Hex
+
Signed Hex
+
+
The existing scalar value will be displayed as a signed hexadecimal number. This action is
+ only available if the value can be interpreted as a negative value, and is only supported on
+ instruction operands since the data hex format currently supports unsigned rendering
+ only.
-
The existing scalar value will be displayed as a signed hexadecimal number. This action
- is only available if the value can be interpreted as a negative value, and
- is only supported on instruction operands since the data hex format
- currently supports unsigned rendering only.
-
Unsigned Hex
The existing scalar value will be displayed as an unsigned hexadecimal number.
-
+
Char / Char Sequence
The existing scalar value will be displayed as either a single ASCII character or a
- sequence of ASCII characters, whichever is more appropriate. Invalid and non-printable
- ASCII characters will be rendered in hex (e.g., \x20).
-
+ sequence of ASCII characters, whichever is more appropriate. Invalid and non-printable ASCII
+ characters will be rendered in hex (e.g., \x20).
Unsigned Binary
-
The existing scalar value will be displayed as an unsigned binary number.
-
-
-
Float
-
The existing scalar value will be displayed as a IEEE 754 single
- precision floating point number. The floating point size is processor specific
- and will match the size of the Float data type. This action is only supported on instruction
- operands.
-
-
-
Double
-
The existing scalar value will be displayed as a IEEE 754 double
- precision floating point number. The floating point size is processor specific
- and will match the size of the Double data type. This action is only supported on instruction
- operands.
-
+
The existing scalar value will be displayed as an unsigned binary number.
-
The convert actions also work on an
- instruction selection. Just make a selection then choose an operand scalar value to convert.
- All matching instruction scalar values in the selection will be converted.
-
-
Based upon how an instruction
- is implemented by its' associated language module, a hexadecimal operand which appears
- to be negative may in fact be a positive scalar with negative sign '-' character prepended.
- In such cases, the convert action may not produce the expected result.
-
-
The presence of a primary reference
- on an operand may prevent rendering of the converted scalar value since reference
- markup takes precedence over equates and data formatting.
-
+
Float
+
+
The existing scalar value will be displayed as a IEEE 754 single precision floating point
+ number. The floating point size is processor specific and will match the size of the Float
+ data type. This action is only supported on instruction operands.
+
+
Double
+
+
The existing scalar value will be displayed as a IEEE 754 double precision floating point
+ number. The floating point size is processor specific and will match the size of the Double
+ data type. This action is only supported on instruction operands.
+
+
The convert actions also work on an
+ instruction selection. Just make a selection then choose an operand scalar value to convert.
+ All matching instruction scalar values in the selection will be converted.
+
+
Based upon how an instruction is
+ implemented by its' associated language module, a hexadecimal operand which appears to be
+ negative may in fact be a positive scalar with negative sign '-' character prepended. In such
+ cases, the convert action may not produce the expected result.
+
+
The presence of a primary reference on
+ an operand may prevent rendering of the converted scalar value since reference markup takes
+ precedence over equates and data formatting.
+
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateReferenceTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateReferenceTableModel.java
index 4d705c4fef..ea93373fa2 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateReferenceTableModel.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateReferenceTableModel.java
@@ -32,7 +32,6 @@ class EquateReferenceTableModel extends GDynamicColumnTableModel referenceList = new ArrayList<>();
- private Equate currentEquate = null;
EquateReferenceTableModel(EquateTablePlugin plugin) {
super(plugin.getTool());
@@ -70,18 +69,11 @@ class EquateReferenceTableModel extends GDynamicColumnTableModel referenceList.add(r));
- // @formatter:on
+ referenceList.addAll(Arrays.asList(equate.getReferences()));
fireTableDataChanged();
}
@@ -131,7 +120,7 @@ class EquateReferenceTableModel extends GDynamicColumnTableModel {
}
@Override
- public String getValue(Equate rowObject, Settings settings, Object data,
- ServiceProvider sp) throws IllegalArgumentException {
+ public String getValue(Equate rowObject, Settings settings, Object data, ServiceProvider sp)
+ throws IllegalArgumentException {
return rowObject.getDisplayName();
}
@@ -251,8 +251,8 @@ class EquateTableModel extends GDynamicColumnTableModel {
}
@Override
- public Long getValue(Equate rowObject, Settings settings, Object data,
- ServiceProvider sp) throws IllegalArgumentException {
+ public Long getValue(Equate rowObject, Settings settings, Object data, ServiceProvider sp)
+ throws IllegalArgumentException {
FormatSettingsDefinition formatDef = FormatSettingsDefinition.DEF;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java
index 56f30a71fe..2d51af030d 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTableProvider.java
@@ -26,7 +26,7 @@ import javax.swing.table.TableCellEditor;
import docking.ActionContext;
import docking.action.*;
-import docking.widgets.OptionDialog;
+import docking.action.builder.ActionBuilder;
import docking.widgets.label.GLabel;
import ghidra.app.context.ProgramActionContext;
import ghidra.app.services.DataTypeManagerService;
@@ -61,7 +61,7 @@ public class EquateTableProvider extends ComponentProviderAdapter {
this.plugin = plugin;
mainPanel = createWorkPanel();
addToTool();
- createAction();
+ createActions();
}
@Override
@@ -107,18 +107,12 @@ public class EquateTableProvider extends ComponentProviderAdapter {
void updateEquates() {
// restore selection after update
- int row = equatesTable.getSelectedRow();
+ List selectedItems = equatesFilterPanel.getSelectedItems();
equatesModel.update();
- int rows = equatesTable.getRowCount();
- if (row < 0 || row >= rows) {
- row = 0;
- }
+ equatesFilterPanel.setSelectedItems(selectedItems);
- if (rows > 0) {
- equatesTable.setRowSelectionInterval(row, row);
- }
handleEquateTableSelection();
}
@@ -165,43 +159,6 @@ public class EquateTableProvider extends ComponentProviderAdapter {
}
});
- // Allows for the user to double click on an equate to rename it from a data type editor
- // dialog if the equate is based off of an enum data type.
- equatesTable.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseClicked(MouseEvent evt) {
- if (evt.getClickCount() == 2) {
- DataTypeManager dtm = plugin.getProgram().getDataTypeManager();
- Object obj = evt.getSource();
- if (obj instanceof GhidraTable) {
- GhidraTable table = (GhidraTable) obj;
- int row = table.rowAtPoint(evt.getPoint());
- int column = table.columnAtPoint(evt.getPoint());
-
- if (!table.isCellEditable(row, column)) {
- return;
- }
-
- DataTypeManagerService dtms = tool.getService(DataTypeManagerService.class);
- if (dtms == null) {
- return;
- }
- Equate equate = (Equate) table.getValueAt(row, column);
-
- UniversalID id =
- new UniversalID(Long.parseLong(equate.getName().split(":")[1]));
- Enum enoom = (Enum) dtm.findDataTypeForID(id);
- if (enoom != null) {
- dtms.edit(enoom);
- }
- else {
- showDeleteEquateOptionDialog();
- }
- }
- }
- }
- });
-
equatesTable.getSelectionModel().addListSelectionListener(e -> {
if (e.getValueIsAdjusting()) {
return;
@@ -212,7 +169,7 @@ public class EquateTableProvider extends ComponentProviderAdapter {
equatesTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
equatesTable.setPreferredScrollableViewportSize(new Dimension(350, 150));
equatesTable.setRowSelectionAllowed(true);
- equatesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ equatesTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
equatesFilterPanel = new GhidraTableFilterPanel<>(equatesTable, equatesModel);
@@ -223,8 +180,6 @@ public class EquateTableProvider extends ComponentProviderAdapter {
equatesPanel.add(equatesTablePane, BorderLayout.CENTER);
equatesPanel.add(equatesFilterPanel, BorderLayout.SOUTH);
- //////////////////////////////////////////////////////////////
-
referencesModel = new EquateReferenceTableModel(plugin);
referencesTable = new GhidraTable(referencesModel);
@@ -248,8 +203,6 @@ public class EquateTableProvider extends ComponentProviderAdapter {
referencesPanel.add(new GLabel("References", SwingConstants.CENTER), "North");
referencesPanel.add(referencesTablePane, "Center");
- //////////////////////////////////////////////////////////////
-
JPanel workPanel = new JPanel(new BorderLayout());
JSplitPane splitPane =
new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, equatesPanel, referencesPanel);
@@ -260,12 +213,47 @@ public class EquateTableProvider extends ComponentProviderAdapter {
}
private void handleEquateTableSelection() {
+
+ int[] rows = equatesTable.getSelectedRows();
+ if (rows.length > 1) {
+ referencesTable.clearSelection();
+ referencesModel.setEquate(null);
+ return;
+ }
+
Equate equate = equatesFilterPanel.getSelectedItem();
referencesTable.clearSelection();
referencesModel.setEquate(equate);
}
- private void createAction() {
+ private void createActions() {
+
+ //@formatter:off
+ String group = "Popup Group";
+ new ActionBuilder("Show Enum", plugin.getName())
+ .popupMenuGroup(group)
+ .popupMenuPath("Show Enum")
+ .popupWhen(c -> true)
+ .enabledWhen(c -> getEnum(getSelectedEquate()) != null)
+ .onAction(c -> {
+ DataTypeManagerService dtms = tool.getService(DataTypeManagerService.class);
+ if (dtms != null) {
+ dtms.setDataTypeSelected(getEnum(getSelectedEquate()));
+ }
+ })
+ .helpLocation(new HelpLocation("EquatePlugin", "Show_Enum"))
+ .buildAndInstallLocal(this);
+
+ new ActionBuilder("Edit Enum", plugin.getName())
+ .popupMenuGroup(group)
+ .popupMenuPath("Edit Enum")
+ .popupWhen(c -> true)
+ .enabledWhen(c -> getEnum(getSelectedEquate()) != null)
+ .onAction(c -> edit(getEnum(getSelectedEquate())))
+ .helpLocation(new HelpLocation("EquatePlugin", "Edit_Enum"))
+ .buildAndInstallLocal(this);
+
+ //@formatter:on
Icon deleteImage = Icons.DELETE_ICON;
deleteAction = new DockingAction("Delete Equate", plugin.getName()) {
@@ -290,22 +278,56 @@ public class EquateTableProvider extends ComponentProviderAdapter {
SelectionNavigationAction selectionNavigationAction =
new SelectionNavigationAction(plugin, referencesTable);
- selectionNavigationAction.setHelpLocation(
- new HelpLocation(HelpTopics.SEARCH, "Selection_Navigation"));
+ selectionNavigationAction
+ .setHelpLocation(new HelpLocation(HelpTopics.SEARCH, "Selection_Navigation"));
tool.addLocalAction(this, deleteAction);
tool.addLocalAction(this, selectionNavigationAction);
}
- private void delete() {
+ private Equate getSelectedEquate() {
+ if (equatesTable.getSelectedRowCount() != 1) {
+ return null;
+ }
- List equates = equatesFilterPanel.getSelectedItems();
+ return equatesFilterPanel.getSelectedItem();
+ }
+
+ private Enum getEnum(Equate equate) {
+ if (equate == null) {
+ return null;
+ }
+
+ if (!equate.isEnumBased()) {
+ return null;
+ }
+
+ DataTypeManagerService dtms = tool.getService(DataTypeManagerService.class);
+ if (dtms == null) {
+ return null;
+ }
+
+ DataTypeManager dtm = plugin.getProgram().getDataTypeManager();
+ UniversalID id = equate.getEnumUUID();
+ Enum enoom = (Enum) dtm.findDataTypeForID(id);
+ return enoom;
+ }
+
+ private void edit(Enum enoom) {
+ DataTypeManagerService dtms = tool.getService(DataTypeManagerService.class);
+ if (dtms != null) {
+ dtms.edit(enoom);
+ }
+ }
+
+ private void delete() {
TableCellEditor cellEditor = equatesTable.getCellEditor();
if (cellEditor != null) {
cellEditor.stopCellEditing();
}
+ List equates = equatesFilterPanel.getSelectedItems();
plugin.deleteEquates(equates);
}
@@ -318,15 +340,6 @@ public class EquateTableProvider extends ComponentProviderAdapter {
}
}
- private void showDeleteEquateOptionDialog() {
- String message = "Data type not found. Would you like to delete this equate?";
- int choice = OptionDialog.showOptionDialogWithCancelAsDefaultButton(equatesFilterPanel,
- "Delete Equate", message, "Delete Equate", OptionDialog.ERROR_MESSAGE);
- if (choice == OptionDialog.OPTION_ONE) {
- delete();
- }
- }
-
EquateTableModel getEquatesModel() {
return equatesModel;
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java
index aab736caa9..537921988e 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java
@@ -646,7 +646,7 @@ public class EquatePlugin1Test extends AbstractGhidraHeadedIntegrationTest {
/*
* Tests that the user is prompted before attempting to remove an equate within
* a selection.
- *
+ *
* @throws Exception
*/
@Test
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquateTablePluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquateTablePluginTest.java
index 5cc1426c7f..b627b3cf15 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquateTablePluginTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquateTablePluginTest.java
@@ -17,9 +17,6 @@ package ghidra.app.plugin.core.equate;
import static org.junit.Assert.*;
-import java.awt.Rectangle;
-import java.util.*;
-
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
@@ -40,7 +37,6 @@ import ghidra.program.util.OperandFieldLocation;
import ghidra.program.util.ProgramLocation;
import ghidra.test.*;
import ghidra.util.table.GhidraTable;
-import util.CollectionUtils;
/**
* Tests for the equate table plugin.
@@ -114,16 +110,6 @@ public class EquateTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
env.dispose();
}
- @Test
- public void testEquateTableView() throws Exception {
- // verify that the equate table shows the equates and the references
- assertNotNull(refsTable);
- assertNotNull(refsModel);
- assertEquals(1, refsModel.getRowCount());
-
- checkTableValues();
- }
-
@Test
public void testShowReferences() {
setRowSelection(equatesTable, 1, 1);// this triggers the refs table to update
@@ -370,37 +356,6 @@ public class EquateTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
waitForProgram(program);
}
- private void checkTableValues() throws Exception {
- Iterator iter = et.getEquates();
- List list = CollectionUtils.asList(iter);
-
- Collections.sort(list, (e1, e2) -> e1.getName().compareTo(e2.getName()));
- assertEquals(list.size(), equatesModel.getRowCount());
-
- TableCellRenderer nameRenderer = getRenderer(EquateTableModel.NAME_COL);
- TableCellRenderer valueRenderer = getRenderer(EquateTableModel.VALUE_COL);
- TableCellRenderer refCountRenderer = getRenderer(EquateTableModel.REFS_COL);
-
- for (int i = 0; i < list.size(); i++) {
-
- Equate eq = list.get(i);
- Rectangle rect = equatesTable.getCellRect(i, EquateTableModel.NAME_COL, true);
- runSwing(() -> equatesTable.scrollRectToVisible(rect));
-
- String value = getRenderedValue(nameRenderer, i, EquateTableModel.NAME_COL);
- assertEquals("Name not equal at index: " + i, eq.getName(), value);
-
- // The value column is default-rendered as hex
- value = getRenderedValue(valueRenderer, i, EquateTableModel.VALUE_COL);
- assertEquals("Value not equal at index: " + i, Long.toHexString(eq.getValue()) + "h",
- value);
-
- value = getRenderedValue(refCountRenderer, i, EquateTableModel.REFS_COL);
- assertEquals("Reference count not equal at index: " + i,
- Integer.toString(eq.getReferenceCount()), value);
- }
- }
-
private String getRenderedValue(TableCellRenderer renderer, int row, int column) {
return runSwing(() -> {
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableFilterPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableFilterPanel.java
index a230b8f752..fdc644ee66 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableFilterPanel.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableFilterPanel.java
@@ -26,6 +26,7 @@ import javax.swing.event.*;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
+import org.apache.commons.collections4.CollectionUtils;
import org.jdom.Element;
import docking.DockingWindowManager;
@@ -67,7 +68,7 @@ import utility.function.Callback;
*
*
* Filtering
- * The filtering behavior is controlled by the filter button displayed to the right of this
+ * The filtering behavior is controlled by the filter button displayed to the right of this
* panel's text field.
*
*
@@ -104,7 +105,7 @@ import utility.function.Callback;
* To get a row count that is always all of the model's data, call
* {@link #getUnfilteredRowCount()}.
*
- *
+ *
* @param the row object type for this given table and model
*/
public class GTableFilterPanel extends JPanel {
@@ -690,11 +691,16 @@ public class GTableFilterPanel extends JPanel {
/**
* Select the given row object. No selection will be made if the object is filtered out of
- * view.
+ * view. Passing {@code null} will clear the selection.
*
* @param t the row object to select
*/
public void setSelectedItem(ROW_OBJECT t) {
+ if (t == null) {
+ table.clearSelection();
+ return;
+ }
+
int viewRow = textFilterModel.getViewIndex(t);
if (viewRow >= 0) {
table.setRowSelectionInterval(viewRow, viewRow);
@@ -702,6 +708,52 @@ public class GTableFilterPanel extends JPanel {
}
}
+ /**
+ * Select the given row objects. No selection will be made if the objects are filtered out of
+ * view. Passing a {@code null} list or an empty list will clear the selection.
+ *
+ * @param items the row objects to select
+ */
+ public void setSelectedItems(List items) {
+
+ if (CollectionUtils.isEmpty(items)) {
+ table.clearSelection();
+ return;
+ }
+
+ ListSelectionModel selectionModel = table.getSelectionModel();
+ int mode = selectionModel.getSelectionMode();
+ if (mode == ListSelectionModel.SINGLE_SELECTION) {
+ // take the last item to mimic what the selection model does internally
+ ROW_OBJECT item = items.get(items.size() - 1);
+ int viewRow = textFilterModel.getViewIndex(item);
+ table.setRowSelectionInterval(viewRow, viewRow);
+ return;
+ }
+
+ //
+ // For ListSelectionModel SINGLE_INTERVAL_SELECTION and MULTIPLE_INTERVAL_SELECTION, the
+ // model will update any selection given to it to match the current mode.
+ //
+ List rows = new ArrayList<>();
+ for (ROW_OBJECT item : items) {
+ int viewRow = textFilterModel.getViewIndex(item);
+ if (viewRow >= 0) {
+ rows.add(viewRow);
+ }
+ }
+ if (rows.isEmpty()) {
+ return; // items may be filtered out of view
+ }
+
+ selectionModel.setValueIsAdjusting(true);
+ selectionModel.clearSelection();
+ for (int row : rows) {
+ selectionModel.addSelectionInterval(row, row);
+ }
+ selectionModel.setValueIsAdjusting(false);
+ }
+
/**
* Scrolls the view to the currently selected item.
*/
@@ -915,7 +967,7 @@ public class GTableFilterPanel extends JPanel {
* a filter panel, then each provider will share the same filter settings when that provider
* is created. If this is not what you want, then you need to override this method to
* generate a unique key for each provider.
- *
+ *
* @param jTable the table
* @return a key used to store user filter configuration state.
*/
@@ -992,7 +1044,7 @@ public class GTableFilterPanel extends JPanel {
//==================================================================================================
// Inner Classes
-//==================================================================================================
+//==================================================================================================
private abstract class ColumnFilterActionState
extends ActionState> {
diff --git a/Ghidra/Framework/Help/src/main/resources/help/shared/DefaultStyle.css b/Ghidra/Framework/Help/src/main/resources/help/shared/DefaultStyle.css
index 557c37ca39..b45630ae27 100644
--- a/Ghidra/Framework/Help/src/main/resources/help/shared/DefaultStyle.css
+++ b/Ghidra/Framework/Help/src/main/resources/help/shared/DefaultStyle.css
@@ -15,22 +15,49 @@
*/
/*
WARNING!
- This file is copied to all help directories. If you change this file, you must copy it
- to each src/main/help/help/shared directory.
-
-
Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but
px (pixel) or with no type marking.
+ The blockquote tag is used heavily to control indentation throughout the help docs. Place the
+ blockquote tag around other elements to create a standard indentation. The default values of
+ blockquote are:
+
+ blockquote {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 40px;
+ margin-right: 40px;
+ }
+
*/
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
-li { font-family:times new roman; font-size:14pt; }
+
+/*
+ Add some indentation for lists to show their relation to the preceding text. The value is
+ chosen based on the left margin of the body and the blockquote.
+*/
+ul { margin-left: 50px; }
+ol { margin-left: 50px; }
+li { font-family:times new roman; font-size:14pt; margin-left: 5px; }
+
+
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
+
+/*
+ A class to be used for showing screenshot style images. These images will have padding above
+ and below the image and will be centered. To apply this to a file path, use this syntax:
+
+*/
+div.image { margin-top: 20px; margin-bottom: 40px; text-align: center; }
+
+
+
/*
P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
way it had been done in the beginning). The net effect is that the text is indented. In
@@ -40,11 +67,10 @@ h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size
*/
p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
blockquote p { margin-left: 10px; }
-
p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
-p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.relatedtopic { color:#800080; margin-left: 10px; font-size:14pt; }
-p.RelatedTopic { color:#800080; margin-left: 10px; font-size:14pt; }
+p.image { margin-top: 100; margin-bottom: 100; }
+
/*
We wish for a tables to have space between it and the preceding element, so that text
@@ -55,6 +81,8 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
+
+
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax: