mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch
'origin/GP-4728-dragonmacher-edit-structure-field--SQUASHED' (Closes #5717)
This commit is contained in:
commit
c95c7581d7
8 changed files with 152 additions and 34 deletions
|
@ -54,6 +54,11 @@ public class DefaultDataTypeManagerService extends DefaultDataTypeArchiveService
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void edit(Structure structure, String fieldName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType(String filterText) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -20,8 +20,7 @@ import java.awt.datatransfer.DataFlavor;
|
|||
import java.awt.dnd.*;
|
||||
import java.awt.event.*;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.EventObject;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -218,6 +217,47 @@ public abstract class CompositeEditorPanel extends JPanel
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the field by the given name in this panel's table.
|
||||
*
|
||||
* @param fieldName the field name
|
||||
*/
|
||||
public void selectField(String fieldName) {
|
||||
|
||||
if (!model.isLoaded()) {
|
||||
return; // disposed; not sure if this can happen
|
||||
}
|
||||
|
||||
// Find the given field by name in the current editor, which, if edited, may not match the
|
||||
// original data type. If the user has renamed the field, but not saved the editor, then
|
||||
// we may not find the field.
|
||||
int row = findRowForFieldName(fieldName);
|
||||
if (row == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
table.getSelectionModel().setSelectionInterval(row, row);
|
||||
}
|
||||
|
||||
private int findRowForFieldName(String fieldName) {
|
||||
int n = model.getRowCount();
|
||||
for (int row = 0; row < n; row++) {
|
||||
|
||||
DataTypeComponent dtc = model.getComponent(row);
|
||||
if (dtc != null) {
|
||||
String dtcFieldName = dtc.getFieldName();
|
||||
if (Objects.equals(fieldName, dtcFieldName)) {
|
||||
return row;
|
||||
}
|
||||
String defaultName = dtc.getDefaultFieldName();
|
||||
if (Objects.equals(fieldName, defaultName)) {
|
||||
return row;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected void cancelCellEditing() {
|
||||
TableCellEditor cellEditor = table.getCellEditor();
|
||||
if (cellEditor != null) {
|
||||
|
@ -1416,5 +1456,4 @@ public abstract class CompositeEditorPanel extends JPanel
|
|||
KeyBindingUtils.clearKeyBinding(this, keyStroke);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -89,4 +89,10 @@ public class StructureEditorProvider extends CompositeEditorProvider {
|
|||
public String getHelpTopic() {
|
||||
return "DataTypeEditors";
|
||||
}
|
||||
|
||||
public void selectField(String fieldName) {
|
||||
if (fieldName != null) {
|
||||
editorPanel.selectField(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -492,20 +492,14 @@ public class DataTypeManagerPlugin extends ProgramPlugin
|
|||
|
||||
@Override
|
||||
public void edit(DataType dt) {
|
||||
DataTypeManager dataTypeManager = dt.getDataTypeManager();
|
||||
if (dataTypeManager == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"DataType " + dt.getPathName() + " has no DataTypeManager! Make sure the " +
|
||||
"given DataType has been resolved by a DataTypeManager");
|
||||
}
|
||||
CategoryPath categoryPath = dt.getCategoryPath();
|
||||
if (categoryPath == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"DataType " + dt.getName() + " has no category path!");
|
||||
}
|
||||
editorManager.edit(dt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void edit(Structure dt, String fieldName) {
|
||||
editorManager.edit(dt, fieldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeManager getBuiltInDataTypesManager() {
|
||||
return dataTypeManagerHandler.getBuiltInDataTypesManager();
|
||||
|
|
|
@ -97,17 +97,8 @@ public class DataTypeEditorManager implements EditorListener {
|
|||
*/
|
||||
public void edit(DataType dataType) {
|
||||
|
||||
DataTypeManager dataTypeManager = dataType.getDataTypeManager();
|
||||
if (dataTypeManager == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Datatype " + dataType.getName() + " doesn't have a data type manager specified.");
|
||||
}
|
||||
|
||||
EditorProvider editor = getEditor(dataType);
|
||||
EditorProvider editor = reuseExistingEditor(dataType);
|
||||
if (editor != null) {
|
||||
ComponentProvider componentProvider = editor.getComponentProvider();
|
||||
plugin.getTool().showComponentProvider(componentProvider, true);
|
||||
componentProvider.toFront();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -124,13 +115,58 @@ public class DataTypeEditorManager implements EditorListener {
|
|||
else if (dataType instanceof FunctionDefinition) {
|
||||
editFunctionSignature((FunctionDefinition) dataType);
|
||||
}
|
||||
if (editor == null) {
|
||||
|
||||
if (editor != null) {
|
||||
editor.addEditorListener(this);
|
||||
editorList.add(editor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a data type editor for editing the given Structure. If the structure is is already
|
||||
* being edited then it is brought to the front. Otherwise, a new editor is created and
|
||||
* displayed.
|
||||
* @param structure the structure.
|
||||
* @param fieldName the optional name of the field to select in the editor.
|
||||
*/
|
||||
public void edit(Structure structure, String fieldName) {
|
||||
|
||||
StructureEditorProvider editor = (StructureEditorProvider) getEditor(structure);
|
||||
if (editor != null) {
|
||||
reuseExistingEditor(structure);
|
||||
editor.selectField(fieldName);
|
||||
return;
|
||||
}
|
||||
|
||||
editor = new StructureEditorProvider(plugin, structure,
|
||||
showStructureNumbersInHex());
|
||||
editor.selectField(fieldName);
|
||||
editor.addEditorListener(this);
|
||||
editorList.add(editor);
|
||||
}
|
||||
|
||||
private EditorProvider reuseExistingEditor(DataType dataType) {
|
||||
DataTypeManager dataTypeManager = dataType.getDataTypeManager();
|
||||
if (dataTypeManager == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Datatype " + dataType.getName() + " doesn't have a data type manager specified.");
|
||||
}
|
||||
|
||||
CategoryPath categoryPath = dataType.getCategoryPath();
|
||||
if (categoryPath == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"DataType " + dataType.getName() + " has no category path!");
|
||||
}
|
||||
|
||||
EditorProvider editor = getEditor(dataType);
|
||||
if (editor != null) {
|
||||
ComponentProvider componentProvider = editor.getComponentProvider();
|
||||
plugin.getTool().showComponentProvider(componentProvider, true);
|
||||
componentProvider.toFront();
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
private void installEditorActions() {
|
||||
|
||||
// composite editor actions
|
||||
|
|
|
@ -22,8 +22,7 @@ import javax.swing.tree.TreePath;
|
|||
|
||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManagerChangeListener;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
|
@ -88,14 +87,24 @@ public interface DataTypeManagerService extends DataTypeQueryService, DataTypeAr
|
|||
public boolean isEditable(DataType dt);
|
||||
|
||||
/**
|
||||
* Pop up an editor dialog for the given data type.
|
||||
* Pop up an editor window for the given data type.
|
||||
*
|
||||
* @param dt data type that either a Structure or a Union; built in types cannot be edited
|
||||
* @param dt the data type; built in types cannot be edited
|
||||
* @throws IllegalArgumentException if the given has not been resolved by a DataTypeManager;
|
||||
* in other words, if {@link DataType#getDataTypeManager()} returns null.
|
||||
* in other words, if {@link DataType#getDataTypeManager()} returns null
|
||||
*/
|
||||
public void edit(DataType dt);
|
||||
|
||||
/**
|
||||
* Pop up an editor window for the given structure.
|
||||
*
|
||||
* @param structure the structure
|
||||
* @param fieldName the optional structure field name to select in the editor window
|
||||
* @throws IllegalArgumentException if the given has not been resolved by a DataTypeManager;
|
||||
* in other words, if {@link DataType#getDataTypeManager()} returns null
|
||||
*/
|
||||
public void edit(Structure structure, String fieldName);
|
||||
|
||||
/**
|
||||
* Selects the given data type in the display of data types. A null <code>dataType</code>
|
||||
* value will clear the current selection.
|
||||
|
|
|
@ -99,6 +99,11 @@ public class TestDoubleDataTypeManagerService implements DataTypeManagerService
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void edit(Structure structure, String fieldName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeArchive(DataTypeManager dtm) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -17,14 +17,16 @@ package ghidra.app.plugin.core.decompile.actions;
|
|||
|
||||
import docking.ActionContext;
|
||||
import docking.action.MenuData;
|
||||
import ghidra.app.decompiler.ClangFieldToken;
|
||||
import ghidra.app.decompiler.ClangToken;
|
||||
import ghidra.app.decompiler.component.DecompilerPanel;
|
||||
import ghidra.app.decompiler.component.DecompilerUtils;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.UndefinedFunction;
|
||||
|
@ -74,9 +76,31 @@ public class EditDataTypeAction extends AbstractDecompilerAction {
|
|||
if (baseDtDTM != dataTypeManager) {
|
||||
baseDataType = baseDataType.clone(dataTypeManager);
|
||||
}
|
||||
final DataTypeManagerService service =
|
||||
|
||||
DataTypeManagerService service =
|
||||
context.getTool().getService(DataTypeManagerService.class);
|
||||
service.edit(baseDataType);
|
||||
|
||||
if (dataType instanceof Structure structure) {
|
||||
editStructure(service, structure, context);
|
||||
}
|
||||
else {
|
||||
service.edit(baseDataType);
|
||||
}
|
||||
}
|
||||
|
||||
private void editStructure(DataTypeManagerService service, Structure structure,
|
||||
DecompilerActionContext context) {
|
||||
|
||||
DecompilerPanel decompilerPanel = context.getDecompilerPanel();
|
||||
ClangToken tokenAtCursor = decompilerPanel.getTokenAtCursor();
|
||||
if (tokenAtCursor instanceof ClangFieldToken) {
|
||||
String fieldName = tokenAtCursor.getText();
|
||||
if (fieldName != null) {
|
||||
service.edit(structure, fieldName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
service.edit(structure);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue