diff --git a/Ghidra/Features/Base/data/base.theme.properties b/Ghidra/Features/Base/data/base.theme.properties index 4e2fcbd03f..74c9b0b196 100644 --- a/Ghidra/Features/Base/data/base.theme.properties +++ b/Ghidra/Features/Base/data/base.theme.properties @@ -81,7 +81,7 @@ color.bg.plugin.editors.compositeeditor.bit.active = green color.bg.plugin.editors.compositeeditor.bit.conflict = yellow color.bg.plugin.editors.compositeeditor.non.bit = #A0A0FF -color.fg.plugin.equate.enum = lightskyblue +color.fg.plugin.equate.enum = royalblue color.fg.plugin.function.editor.dialog.textfield.default = color.fg color.fg.plugin.function.editor.dialog.textfield.error = color.fg.error @@ -204,4 +204,6 @@ color.bg.plugin.datamgr.edge.default = deepskyblue color.bg.plugin.datamgr.edge.composite = plum color.bg.plugin.datamgr.edge.reference = deepskyblue +color.fg.plugin.equate.enum = deepskyblue + color.bg.plugin.programdiff.highlight = darkRed diff --git a/Ghidra/Features/Base/src/main/help/help/topics/EquatePlugin/Equates.htm b/Ghidra/Features/Base/src/main/help/help/topics/EquatePlugin/Equates.htm index 06663f5430..336a2674f3 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/EquatePlugin/Equates.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/EquatePlugin/Equates.htm @@ -2,67 +2,58 @@ - - Equates - - +

Equates

-

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

-
-

NoteIt 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.

+

NoteIt 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:

-
-
+

Set Equate

@@ -70,291 +61,263 @@

The Set Equate action will create one or more Equates in the Listing.

To set an Equate:

- -
-
    +
    1. - Right-mouse-click on the target scalar value, and select Set Equate or press - <E>.
      - - -

      -

      Set Equate Dialog
      -

      -

      + Right-mouse-click on the target scalar value, and select Set Equate or + press <E>. + + +
      Set Equate Dialog
      +
    2. 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.
    3. -
    4. - 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. - -
        -
      1. - Current Location: When selected the equate will be applied to the scalar - value at the current location of your cursor only. -
      2. -
      3. - 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. -
      4. -
      5. - 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. -
      6. -
      7. - 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. -
      8. -
      -
    5. +
    6. + 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. -
    7. 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.
    8. - - - -

    -
    -
+
    +
  1. Current Location: When selected the equate will be applied to the scalar + value at the current location of your cursor only.
  2. -
    -

    Note 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.
    -

    - -

    NoteThe 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.

    +
  3. 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.
  4. -

    Note Each entry in the dialog is color-coded based upon how it is being used - as an equate.
    - -

      -
    1. - Blue: Blue entries are existing user-defined string equates that are being used - for that scalar. -
    2. - -
    3. - Black: Black entries are existing enum field equates being used for that scalar. -
    4. - -
    5. - 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. -
    6. -
    - -

    +
  5. 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.
  6. + +
  7. 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.
  8. +
+ + +
  • 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.

    +
    +

    Note 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.

    + +

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

    + +

    Note Each entry in the dialog is color-coded based + upon how it is being used as an equate.

    + +
      +
    1. Blue: Blue entries are existing user-defined string equates that are being used + for that scalar.
    2. + +
    3. Black: Black entries are existing enum field equates being used for that + scalar.
    4. + +
    5. 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.
    6. +
    +
    + +

    Rename Equate

    + +
    +

    The Rename Equate action will rename one or more instances of a named Equate in the + Listing.

    To rename an Equate:

    -
    -
    1. Right-mouse-click on the current Equate, and select Rename Equate or press <E>.
      - -

      -

      Rename Equate Dialog
      -

      -

      +
      + Rename Equate Dialog +
    2. -
    3. - 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. - -
        -
      1. - Current Location: When selected the equate will be applied to the scalar - value at the current location of your cursor only. -
      2. -
      3. - 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. -
      4. -
      5. - 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. -
      6. -
      -
    4. +
    5. + 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. + +
        +
      1. Current Location: When selected the equate will be applied to the scalar + value at the current location of your cursor only.
      2. + +
      3. 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.
      4. + +
      5. 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.
      6. +
      +
    6. + +
    7. 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.
    8. +
    +
    + +

    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:

    -
    -
      -
    1. 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 +
    2. 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>.
    3. - -
    4. 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. - -


      - Confirm Equate Remove Dialog

      -

      +
    5. + 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. + +
      + Confirm Equate Remove Dialog +
    -
    -

    To remove all references of an Equate via the Equates Table window:

    -
    -
      -
    1. Select the Code Browser menu option WindowEquates Table to bring up the Equates Table window.
    2. +
    3. Select the Code Browser menu option WindowEquates Table to bring up the Equates Table window.
    4. Right-mouse-click on the Equate to be deleted and select Delete.
    5. A confirmation dialog will appear. -


      - Confirm Equate Delete Dialog

      - -

      +
      + Confirm Equate Delete Dialog +
    6. 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:

    +
      -
    1. Make a selection and then Right-mouse-click, then choose Apply Enum. - -


      - Apply Enum Popup

      +
    2. + Make a selection and then Right-mouse-click, then choose Apply Enum. -

      +
      + Apply Enum Popup +
    3. - -
    4. 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 Enum Popup

      -

      - -
        - -
      • 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.

      - -


      - Apply Enum Popup

      +
    5. + 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 Enum Popup +
      + +
        +
      • 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.

      + +
      + Apply Enum Popup +
    -
    +

    View Equates

    The Display Equates Table action displays a window which lists all of the Equates and their references in a tabular format.

    -
    -
    -
    - - - - - - -
    -
    -
    -
    +
    + Equates Table +
    +

    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.

    - -

    Note Each equate is color-coded based upon how it is being used.
    - -

      -
    1. - Blue: Blue equates are existing user-defined string equates that are being used - for that scalar. -
    2. - -
    3. - Black: Black equates are existing enum field equates being used for that scalar. -
    4. - -
    5. - 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. -
    6. -
    - -

    + +

    Note Each equate is color-coded based upon how it + is being used.

    + +
    +
      +
    1. Blue: Blue equates are existing user-defined string equates that are being + used for that scalar.
    2. + +
    3. Black: Black equates are existing enum field equates being used for that + scalar.
    4. + +
    5. 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.
    6. +
    +
    -

    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.

    +

    Provided By: EquatePlugin and EquateTablePlugin

    -
    + +

    Related Topics:

    + +
    +
    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: