mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 12:00:04 +02:00
Merge remote-tracking branch 'origin/GP-61-dragonmacher-clear-keybindings'
This commit is contained in:
commit
64da286d3d
15 changed files with 434 additions and 482 deletions
|
@ -39,7 +39,7 @@ public class GotoNextFunctionAction extends NavigatableContextAction {
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
|
|
||||||
public GotoNextFunctionAction(PluginTool tool, String owner) {
|
public GotoNextFunctionAction(PluginTool tool, String owner) {
|
||||||
super("Go to next function", owner);
|
super("Go To Next Function", owner);
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
|
|
||||||
MenuData menuData =
|
MenuData menuData =
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class GotoPreviousFunctionAction extends NavigatableContextAction {
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
|
|
||||||
public GotoPreviousFunctionAction(PluginTool tool, String owner) {
|
public GotoPreviousFunctionAction(PluginTool tool, String owner) {
|
||||||
super("Go to previous function", owner);
|
super("Go To Previous Function", owner);
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
|
|
||||||
MenuData menuData =
|
MenuData menuData =
|
||||||
|
|
|
@ -33,7 +33,8 @@ import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.DefaultLanguageService;
|
import ghidra.program.util.DefaultLanguageService;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.*;
|
import ghidra.util.task.ConsoleTaskMonitor;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utilities.util.FileUtilities;
|
import utilities.util.FileUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,11 +124,14 @@ public class TestProgramManager {
|
||||||
/**
|
/**
|
||||||
* Save a program to the cached program store. A SaveAs will be performed on the
|
* Save a program to the cached program store. A SaveAs will be performed on the
|
||||||
* program to its cached storage location.
|
* program to its cached storage location.
|
||||||
|
*
|
||||||
* @param progName program name
|
* @param progName program name
|
||||||
* @param program program object
|
* @param program program object
|
||||||
* @param replace if true any existing cached database with the same name will be replaced
|
* @param replace if true any existing cached database with the same name will be replaced
|
||||||
* @param monitor task monitor
|
* @param monitor task monitor
|
||||||
|
* @throws IOException if the database cannot be created
|
||||||
* @throws DuplicateNameException if already cached
|
* @throws DuplicateNameException if already cached
|
||||||
|
* @throws CancelledException if the save operation is cancelled
|
||||||
*/
|
*/
|
||||||
public void saveToCache(String progName, ProgramDB program, boolean replace,
|
public void saveToCache(String progName, ProgramDB program, boolean replace,
|
||||||
TaskMonitor monitor) throws IOException, DuplicateNameException, CancelledException {
|
TaskMonitor monitor) throws IOException, DuplicateNameException, CancelledException {
|
||||||
|
@ -205,7 +209,9 @@ public class TestProgramManager {
|
||||||
* the only reason to use this method vice openProgram().
|
* the only reason to use this method vice openProgram().
|
||||||
*
|
*
|
||||||
* @param project the project into which the file will be restored
|
* @param project the project into which the file will be restored
|
||||||
* @param programName the name of the program zip file without the ".gzf" extension.
|
* @param programName the name of the program zip file without the ".gzf" extension
|
||||||
|
* @return the file
|
||||||
|
* @throws FileNotFoundException if the file cannot be found
|
||||||
*/
|
*/
|
||||||
public DomainFile addProgramToProject(Project project, String programName)
|
public DomainFile addProgramToProject(Project project, String programName)
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
|
@ -221,6 +227,8 @@ public class TestProgramManager {
|
||||||
*
|
*
|
||||||
* @param folder the folder into which the domain file will be inserted
|
* @param folder the folder into which the domain file will be inserted
|
||||||
* @param programName the name of the program zip file without the ".gzf" extension.
|
* @param programName the name of the program zip file without the ".gzf" extension.
|
||||||
|
* @return the file
|
||||||
|
* @throws FileNotFoundException if the file cannot be found
|
||||||
*/
|
*/
|
||||||
public DomainFile addProgramToProject(DomainFolder folder, String programName)
|
public DomainFile addProgramToProject(DomainFolder folder, String programName)
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
|
@ -234,7 +242,7 @@ public class TestProgramManager {
|
||||||
int oneUp = 0;
|
int oneUp = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
DomainFile df = folder.createFile(name, gzf, TaskMonitorAdapter.DUMMY_MONITOR);
|
DomainFile df = folder.createFile(name, gzf, TaskMonitor.DUMMY);
|
||||||
AbstractGenericTest.waitForPostedSwingRunnables();
|
AbstractGenericTest.waitForPostedSwingRunnables();
|
||||||
DomainObject dobj = df.getDomainObject(this, true, false, null);
|
DomainObject dobj = df.getDomainObject(this, true, false, null);
|
||||||
try {
|
try {
|
||||||
|
@ -281,7 +289,7 @@ public class TestProgramManager {
|
||||||
DBHandle dbh = null;
|
DBHandle dbh = null;
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
dbh = db.open(TaskMonitorAdapter.DUMMY_MONITOR);
|
dbh = db.open(TaskMonitor.DUMMY);
|
||||||
program = new ProgramDB(dbh, DBConstants.UPDATE, null, this);
|
program = new ProgramDB(dbh, DBConstants.UPDATE, null, this);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +320,7 @@ public class TestProgramManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg.info(this, message + (endTime - startTime));
|
Msg.info(this, message + (endTime - startTime));
|
||||||
dbh = db.open(TaskMonitorAdapter.DUMMY_MONITOR);
|
dbh = db.open(TaskMonitor.DUMMY);
|
||||||
program = new ProgramDB(dbh, DBConstants.UPDATE, null, this);
|
program = new ProgramDB(dbh, DBConstants.UPDATE, null, this);
|
||||||
dbh = null;
|
dbh = null;
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -341,7 +349,7 @@ public class TestProgramManager {
|
||||||
File gzf = AbstractGenericTest.findTestDataFile(programName + ".gzf");
|
File gzf = AbstractGenericTest.findTestDataFile(programName + ".gzf");
|
||||||
if (gzf != null && gzf.exists()) {
|
if (gzf != null && gzf.exists()) {
|
||||||
Msg.info(this, "Unpacking: " + gzf);
|
Msg.info(this, "Unpacking: " + gzf);
|
||||||
db = new PrivateDatabase(dbDir, gzf, TaskMonitorAdapter.DUMMY_MONITOR);
|
db = new PrivateDatabase(dbDir, gzf, TaskMonitor.DUMMY);
|
||||||
testPrograms.put(programName, db);
|
testPrograms.put(programName, db);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
@ -451,12 +459,12 @@ public class TestProgramManager {
|
||||||
|
|
||||||
private void upgradeDatabase(PrivateDatabase db) throws Exception {
|
private void upgradeDatabase(PrivateDatabase db) throws Exception {
|
||||||
|
|
||||||
DBHandle dbh = db.openForUpdate(TaskMonitorAdapter.DUMMY_MONITOR);
|
DBHandle dbh = db.openForUpdate(TaskMonitor.DUMMY);
|
||||||
try {
|
try {
|
||||||
ProgramDB program =
|
ProgramDB program =
|
||||||
new ProgramDB(dbh, DBConstants.UPGRADE, TaskMonitorAdapter.DUMMY_MONITOR, this);
|
new ProgramDB(dbh, DBConstants.UPGRADE, TaskMonitor.DUMMY, this);
|
||||||
if (dbh != null) {
|
if (dbh != null) {
|
||||||
dbh.save(null, null, TaskMonitorAdapter.DUMMY_MONITOR);
|
dbh.save(null, null, TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
dbh = null;
|
dbh = null;
|
||||||
program.release(this);
|
program.release(this);
|
||||||
|
|
|
@ -19,19 +19,20 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.actions.DockingToolActions;
|
import docking.actions.*;
|
||||||
import docking.actions.KeyEntryDialog;
|
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||||
import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin;
|
import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.test.TestEnv;
|
import ghidra.test.TestEnv;
|
||||||
|
import util.CollectionUtils;
|
||||||
|
|
||||||
public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
|
@ -91,6 +92,39 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(acceleratorKey.getKeyCode(), KeyEvent.VK_Q);
|
assertEquals(acceleratorKey.getKeyCode(), KeyEvent.VK_Q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClearDefaultKeyBinding() throws Exception {
|
||||||
|
|
||||||
|
DockingAction boundAction = getBoundAction_Shared();
|
||||||
|
showDialog(boundAction);
|
||||||
|
|
||||||
|
assertEquals("OPEN_BRACKET", keyEntryField.getText());
|
||||||
|
triggerBackspaceKey(keyEntryField);
|
||||||
|
|
||||||
|
pressDialogOK();
|
||||||
|
KeyStroke ks = boundAction.getKeyBinding();
|
||||||
|
assertNull(ks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClearDefaultKeyBinding_SharedKeybinding() throws Exception {
|
||||||
|
|
||||||
|
DockingAction boundAction = getBoundAction_Shared();
|
||||||
|
showDialog(boundAction);
|
||||||
|
|
||||||
|
KeyStroke oldKs = boundAction.getKeyBinding();
|
||||||
|
assertEquals("OPEN_BRACKET", keyEntryField.getText());
|
||||||
|
triggerBackspaceKey(keyEntryField);
|
||||||
|
|
||||||
|
pressDialogOK();
|
||||||
|
KeyStroke ks = boundAction.getKeyBinding();
|
||||||
|
assertNull(ks);
|
||||||
|
|
||||||
|
ToolActions toolActions = (ToolActions) tool.getToolActions();
|
||||||
|
Action toolAction = toolActions.getAction(oldKs);
|
||||||
|
assertNull("Shared actions' keybinding not cleared", toolAction);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCollision() throws Exception {
|
public void testCollision() throws Exception {
|
||||||
// make sure we get a collision for a value that is already bound
|
// make sure we get a collision for a value that is already bound
|
||||||
|
@ -185,6 +219,13 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
return (DockingAction) getInstanceField("action", goToPlugin);
|
return (DockingAction) getInstanceField("action", goToPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DockingAction getBoundAction_Shared() {
|
||||||
|
Set<DockingActionIf> sharedActions =
|
||||||
|
getActionsByOwnerAndName(tool, "Shared", "Define Array");
|
||||||
|
assertFalse(sharedActions.isEmpty());
|
||||||
|
return (DockingAction) CollectionUtils.any(sharedActions);
|
||||||
|
}
|
||||||
|
|
||||||
private void pressDialogOK() {
|
private void pressDialogOK() {
|
||||||
JButton okButton = (JButton) getInstanceField("okButton", keyEntryDialog);
|
JButton okButton = (JButton) getInstanceField("okButton", keyEntryDialog);
|
||||||
pressButton(okButton);
|
pressButton(okButton);
|
||||||
|
|
|
@ -21,6 +21,8 @@ import java.awt.Color;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import generic.stl.Pair;
|
import generic.stl.Pair;
|
||||||
|
@ -182,11 +184,11 @@ public class ToolPluginOptionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
options = saveAndLoadOptions();
|
options = saveAndLoadOptions();
|
||||||
verifyStringOptionsStillChanged_UsingTheOptionsAPI(options, changedOption);
|
verifyStringOptionsStillChanged_UsingTheOptionsAPI(options, changedOption);
|
||||||
|
|
||||||
options.registerOption(NEW_TEST_OPTION_NAME, "default", null, null);
|
options.registerOption(NEW_TEST_OPTION_NAME, "default", null, "description");
|
||||||
options = saveAndLoadOptions();
|
options = saveAndLoadOptions();
|
||||||
verifyStringOptionsStillChanged_UsingTheOptionsAPI(options, changedOption);
|
verifyStringOptionsStillChanged_UsingTheOptionsAPI(options, changedOption);
|
||||||
|
|
||||||
options.registerOption(NEW_TEST_OPTION_NAME, "default", null, null);
|
options.registerOption(NEW_TEST_OPTION_NAME, "default", null, "description");
|
||||||
options = saveAndLoadOptions();
|
options = saveAndLoadOptions();
|
||||||
verifyStringOptionsStillChanged_UsingTheOptionsAPI(options, changedOption);
|
verifyStringOptionsStillChanged_UsingTheOptionsAPI(options, changedOption);
|
||||||
|
|
||||||
|
@ -198,6 +200,28 @@ public class ToolPluginOptionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
verifyUnusedOptionNoLongerHasEntry(options, changedOption.first);
|
verifyUnusedOptionNoLongerHasEntry(options, changedOption.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClearingKeyBindingOption() {
|
||||||
|
|
||||||
|
Options options = loadKeyBindingOptions();
|
||||||
|
|
||||||
|
String optionName = clearKeyBinding(options);
|
||||||
|
|
||||||
|
options = saveAndLoadOptions();
|
||||||
|
verifyKeyBindingIsStillCleared(options, optionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccessingOptionWithoutRegistering() {
|
||||||
|
|
||||||
|
ToolOptions options = loadSearchOptions();
|
||||||
|
String defaultValue = "default";
|
||||||
|
Option option =
|
||||||
|
options.getOption(NEW_TEST_OPTION_NAME, OptionType.STRING_TYPE, defaultValue);
|
||||||
|
assertNotNull("unregistered option was not created on access", option);
|
||||||
|
assertEquals(defaultValue, option.getValue(defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetFileOptionToNull() {
|
public void testSetFileOptionToNull() {
|
||||||
//
|
//
|
||||||
|
@ -309,12 +333,24 @@ public class ToolPluginOptionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
return tool.getOptions("Search");
|
return tool.getOptions("Search");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Options loadKeyBindingOptions() {
|
||||||
|
return tool.getOptions("Key Bindings");
|
||||||
|
}
|
||||||
|
|
||||||
private Pair<String, String> changeStringTestOption(Options options) {
|
private Pair<String, String> changeStringTestOption(Options options) {
|
||||||
options.registerOption(NEW_TEST_OPTION_NAME, "HEY", null, null);
|
options.registerOption(NEW_TEST_OPTION_NAME, "HEY", null, "description");
|
||||||
options.setString(NEW_TEST_OPTION_NAME, TEST_OPTION_STRING_VALUE);
|
options.setString(NEW_TEST_OPTION_NAME, TEST_OPTION_STRING_VALUE);
|
||||||
return new Pair<>(NEW_TEST_OPTION_NAME, TEST_OPTION_STRING_VALUE);
|
return new Pair<>(NEW_TEST_OPTION_NAME, TEST_OPTION_STRING_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String clearKeyBinding(Options options) {
|
||||||
|
String keyBindingName = "Go To Next Function (CodeBrowserPlugin)";
|
||||||
|
KeyStroke ks = options.getKeyStroke(keyBindingName, null);
|
||||||
|
assertNotNull(ks);
|
||||||
|
options.setKeyStroke(keyBindingName, null);
|
||||||
|
return keyBindingName;
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyStringOptionStillChanged_WithoutUsingOptionsAPI(Options options,
|
private void verifyStringOptionStillChanged_WithoutUsingOptionsAPI(Options options,
|
||||||
String optionName) {
|
String optionName) {
|
||||||
assertTrue("Options does not have an entry for test option", options.contains(optionName));
|
assertTrue("Options does not have an entry for test option", options.contains(optionName));
|
||||||
|
@ -340,6 +376,11 @@ public class ToolPluginOptionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void verifyKeyBindingIsStillCleared(Options options, String optionName) {
|
||||||
|
KeyStroke ksValue = options.getKeyStroke(optionName, null);
|
||||||
|
assertNull(ksValue);
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> getDiffs(Map<String, Object> initialValues,
|
private List<String> getDiffs(Map<String, Object> initialValues,
|
||||||
Map<String, Object> latestValues) {
|
Map<String, Object> latestValues) {
|
||||||
List<String> diffs = new ArrayList<>();
|
List<String> diffs = new ArrayList<>();
|
||||||
|
@ -354,20 +395,4 @@ public class ToolPluginOptionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
return diffs;
|
return diffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private OptionsPanel showSearchOptions() {
|
|
||||||
// List<DockingActionIf> actions = tool.getDockingActionsByFullActionName("Tool Options... (Tool)");
|
|
||||||
// assertEquals(1, actions.size());
|
|
||||||
//
|
|
||||||
// performAction(actions.get(0), false);
|
|
||||||
//
|
|
||||||
// OptionsDialog dialog = waitForDialogComponent(null, OptionsDialog.class, DEFAULT_WINDOW_TIMEOUT);
|
|
||||||
//
|
|
||||||
// OptionsPanel optionsPanel = (OptionsPanel) getInstanceField("panel", dialog);
|
|
||||||
// GTree tree = (GTree) getInstanceField("gTree", optionsPanel);
|
|
||||||
// tree.setSelectedNodeByNamePath(new String[] { "Options", "Search" });
|
|
||||||
// waitForTree(tree);
|
|
||||||
//
|
|
||||||
// return optionsPanel;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import java.util.Random;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGTest;
|
||||||
import ghidra.framework.data.ProjectFileManager;
|
import ghidra.framework.data.ProjectFileManager;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
@ -35,12 +35,12 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.test.ProjectTestUtils;
|
import ghidra.test.ProjectTestUtils;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.VersionException;
|
import ghidra.util.exception.VersionException;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utilities.util.FileUtilities;
|
import utilities.util.FileUtilities;
|
||||||
|
|
||||||
public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private String TEMP = AbstractGenericTest.getTestDirectoryPath();
|
private String TEMP = AbstractGTest.getTestDirectoryPath();
|
||||||
private static Random RAND = new Random();
|
private static Random RAND = new Random();
|
||||||
|
|
||||||
private ProjectLocator projectLocator;
|
private ProjectLocator projectLocator;
|
||||||
|
@ -60,20 +60,22 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
userDir = new File(projectLocator.getProjectDir(), ProjectFileManager.USER_FOLDER_NAME);
|
userDir = new File(projectLocator.getProjectDir(), ProjectFileManager.USER_FOLDER_NAME);
|
||||||
|
|
||||||
ProgramBuilder builder = new ProgramBuilder("Test", ProgramBuilder._TOY);
|
ProgramBuilder builder = new ProgramBuilder("Test", ProgramBuilder._TOY);
|
||||||
df = project.getProjectData().getRootFolder().createFile("test", builder.getProgram(),
|
df = project.getProjectData()
|
||||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
.getRootFolder()
|
||||||
|
.createFile("test", builder.getProgram(),
|
||||||
|
TaskMonitor.DUMMY);
|
||||||
builder.dispose();
|
builder.dispose();
|
||||||
|
|
||||||
Program program = null;
|
Program program = null;
|
||||||
try {
|
try {
|
||||||
program =
|
program =
|
||||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
catch (VersionException e) {
|
catch (VersionException e) {
|
||||||
assertTrue(e.isUpgradable());
|
assertTrue(e.isUpgradable());
|
||||||
program =
|
program =
|
||||||
(Program) df.getDomainObject(this, true, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, true, false, TaskMonitor.DUMMY);
|
||||||
program.save("upgrade", TaskMonitorAdapter.DUMMY_MONITOR);
|
program.save("upgrade", TaskMonitor.DUMMY);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.release(this);
|
program.release(this);
|
||||||
|
@ -141,27 +143,27 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
DomainFile df2;
|
DomainFile df2;
|
||||||
|
|
||||||
Program program =
|
Program program =
|
||||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
try {
|
try {
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
assertTrue(program.canSave());
|
assertTrue(program.canSave());
|
||||||
|
|
||||||
// Modify program content - no user data should be saved
|
// Modify program content - no user data should be saved
|
||||||
change(program);
|
change(program);
|
||||||
assertTrue(program.isChanged());
|
assertTrue(program.isChanged());
|
||||||
program.save("save", TaskMonitorAdapter.DUMMY_MONITOR);
|
program.save("save", TaskMonitor.DUMMY);
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
assertFalse("User data directory should be empty", userDataSubDir.isDirectory());
|
assertFalse("User data directory should be empty", userDataSubDir.isDirectory());
|
||||||
|
|
||||||
// Modify user data content
|
// Modify user data content
|
||||||
ProgramUserData userData = program.getProgramUserData();
|
ProgramUserData userData = program.getProgramUserData();
|
||||||
change(userData, "STRING", space.getAddress(0), "Str0");
|
change(userData, "STRING", space.getAddress(0), "Str0");
|
||||||
change(userData, "STRING", space.getAddress(10), "Str10");
|
change(userData, "STRING", space.getAddress(10), "Str10");
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
|
|
||||||
String newName = df.getName() + ".1";
|
String newName = df.getName() + ".1";
|
||||||
df2 = df.getParent().createFile(newName, program, TaskMonitorAdapter.DUMMY_MONITOR);
|
df2 = df.getParent().createFile(newName, program, TaskMonitor.DUMMY);
|
||||||
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -169,9 +171,9 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
program =
|
program =
|
||||||
(Program) df2.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df2.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
try {
|
try {
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
|
|
||||||
// Verify user data content
|
// Verify user data content
|
||||||
ProgramUserData userData = program.getProgramUserData();
|
ProgramUserData userData = program.getProgramUserData();
|
||||||
|
@ -180,7 +182,7 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals("Str0", map.getString(space.getAddress(0)));
|
assertEquals("Str0", map.getString(space.getAddress(0)));
|
||||||
assertEquals("Str10", map.getString(space.getAddress(10)));
|
assertEquals("Str10", map.getString(space.getAddress(10)));
|
||||||
assertNull(map.getString(space.getAddress(20)));
|
assertNull(map.getString(space.getAddress(20)));
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.release(this);
|
program.release(this);
|
||||||
|
@ -203,17 +205,17 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
int ver;
|
int ver;
|
||||||
|
|
||||||
Program program =
|
Program program =
|
||||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
try {
|
try {
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
assertTrue(program.canSave());
|
assertTrue(program.canSave());
|
||||||
|
|
||||||
// Modify program content - no user data should be saved
|
// Modify program content - no user data should be saved
|
||||||
change(program);
|
change(program);
|
||||||
assertTrue(program.isChanged());
|
assertTrue(program.isChanged());
|
||||||
program.save("save", TaskMonitorAdapter.DUMMY_MONITOR);
|
program.save("save", TaskMonitor.DUMMY);
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
assertFalse("User data directory should be empty", userDataSubDir.isDirectory());
|
assertFalse("User data directory should be empty", userDataSubDir.isDirectory());
|
||||||
|
|
||||||
ver = getLatestDbVersion(dbDir);
|
ver = getLatestDbVersion(dbDir);
|
||||||
|
@ -222,7 +224,7 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
ProgramUserData userData = program.getProgramUserData();
|
ProgramUserData userData = program.getProgramUserData();
|
||||||
change(userData, "STRING", space.getAddress(0), "Str0");
|
change(userData, "STRING", space.getAddress(0), "Str0");
|
||||||
change(userData, "STRING", space.getAddress(10), "Str10");
|
change(userData, "STRING", space.getAddress(10), "Str10");
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -234,9 +236,9 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
getLatestDbVersion(dbDir));
|
getLatestDbVersion(dbDir));
|
||||||
|
|
||||||
program =
|
program =
|
||||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
try {
|
try {
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
|
|
||||||
// Verify user data content
|
// Verify user data content
|
||||||
ProgramUserData userData = program.getProgramUserData();
|
ProgramUserData userData = program.getProgramUserData();
|
||||||
|
@ -245,21 +247,21 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals("Str0", map.getString(space.getAddress(0)));
|
assertEquals("Str0", map.getString(space.getAddress(0)));
|
||||||
assertEquals("Str10", map.getString(space.getAddress(10)));
|
assertEquals("Str10", map.getString(space.getAddress(10)));
|
||||||
assertNull(map.getString(space.getAddress(20)));
|
assertNull(map.getString(space.getAddress(20)));
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
|
|
||||||
// Modify user data content
|
// Modify user data content
|
||||||
change(userData, "STRING", space.getAddress(10), "Str10a");
|
change(userData, "STRING", space.getAddress(10), "Str10a");
|
||||||
change(userData, "STRING", space.getAddress(20), "Str20a");
|
change(userData, "STRING", space.getAddress(20), "Str20a");
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.release(this);
|
program.release(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
program =
|
program =
|
||||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
try {
|
try {
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
|
|
||||||
// Verify user data content
|
// Verify user data content
|
||||||
ProgramUserData userData = program.getProgramUserData();
|
ProgramUserData userData = program.getProgramUserData();
|
||||||
|
@ -268,7 +270,7 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals("Str0", map.getString(space.getAddress(0)));
|
assertEquals("Str0", map.getString(space.getAddress(0)));
|
||||||
assertEquals("Str10a", map.getString(space.getAddress(10)));
|
assertEquals("Str10a", map.getString(space.getAddress(10)));
|
||||||
assertEquals("Str20a", map.getString(space.getAddress(20)));
|
assertEquals("Str20a", map.getString(space.getAddress(20)));
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.release(this);
|
program.release(this);
|
||||||
|
@ -287,7 +289,7 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
// TODO: Multi-user repository connect case not tested
|
// TODO: Multi-user repository connect case not tested
|
||||||
|
|
||||||
Program program =
|
Program program =
|
||||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
space = program.getAddressFactory().getDefaultAddressSpace();
|
space = program.getAddressFactory().getDefaultAddressSpace();
|
||||||
try {
|
try {
|
||||||
// Create user data content
|
// Create user data content
|
||||||
|
@ -307,9 +309,9 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
df = project.getProjectData().getFile("/test");
|
df = project.getProjectData().getFile("/test");
|
||||||
|
|
||||||
program =
|
program =
|
||||||
(Program) df.getDomainObject(this, false, false, TaskMonitorAdapter.DUMMY_MONITOR);
|
(Program) df.getDomainObject(this, false, false, TaskMonitor.DUMMY);
|
||||||
try {
|
try {
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
|
|
||||||
// Verify user data content
|
// Verify user data content
|
||||||
ProgramUserData userData = program.getProgramUserData();
|
ProgramUserData userData = program.getProgramUserData();
|
||||||
|
@ -318,7 +320,7 @@ public class ProgramUserDataTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals("Str0", map.getString(space.getAddress(0)));
|
assertEquals("Str0", map.getString(space.getAddress(0)));
|
||||||
assertEquals("Str10", map.getString(space.getAddress(10)));
|
assertEquals("Str10", map.getString(space.getAddress(10)));
|
||||||
assertNull(map.getString(space.getAddress(20)));
|
assertNull(map.getString(space.getAddress(20)));
|
||||||
assertTrue(!program.isChanged());
|
assertFalse(program.isChanged());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.release(this);
|
program.release(this);
|
||||||
|
|
|
@ -43,10 +43,6 @@ public class OptionsTest extends AbstractGenericTest {
|
||||||
|
|
||||||
private ToolOptions options;
|
private ToolOptions options;
|
||||||
|
|
||||||
public OptionsTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
options = new ToolOptions("Test");
|
options = new ToolOptions("Test");
|
||||||
|
|
|
@ -399,17 +399,14 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyBindingData newKeyBindingData = (KeyBindingData) evt.getNewValue();
|
KeyBindingData newKeyBindingData = (KeyBindingData) evt.getNewValue();
|
||||||
KeyStroke newKeyStroke = null;
|
KeyStroke newKs = null;
|
||||||
if (newKeyBindingData != null) {
|
if (newKeyBindingData != null) {
|
||||||
newKeyStroke = newKeyBindingData.getKeyBinding();
|
newKs = newKeyBindingData.getKeyBinding();
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyStroke optKeyStroke = keyBindingOptions.getKeyStroke(action.getFullName(), null);
|
KeyStroke currentKs = keyBindingOptions.getKeyStroke(action.getFullName(), null);
|
||||||
if (newKeyStroke == null) {
|
if (!Objects.equals(currentKs, newKs)) {
|
||||||
keyBindingOptions.removeOption(action.getFullName());
|
keyBindingOptions.setKeyStroke(action.getFullName(), newKs);
|
||||||
}
|
|
||||||
else if (!newKeyStroke.equals(optKeyStroke)) {
|
|
||||||
keyBindingOptions.setKeyStroke(action.getFullName(), newKeyStroke);
|
|
||||||
keyBindingsChanged();
|
keyBindingsChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_SameDefaultKeyBindings() {
|
public void testSharedKeyBinding_SameDefaultKeyBindings() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action2);
|
tool.addAction(action2);
|
||||||
|
@ -81,8 +81,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_OptionsChange() {
|
public void testSharedKeyBinding_OptionsChange() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action2);
|
tool.addAction(action2);
|
||||||
|
@ -99,8 +99,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_DifferentDefaultKeyBindings() {
|
public void testSharedKeyBinding_DifferentDefaultKeyBindings() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_DIFFERENT_THAN_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_DIFFERENT_THAN_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action2);
|
tool.addAction(action2);
|
||||||
|
@ -115,8 +115,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_NoDefaultKeyBindings() {
|
public void testSharedKeyBinding_NoDefaultKeyBindings() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, null);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, null);
|
||||||
TestAction action2 = new TestAction(OWNER_2, null);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, null);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action2);
|
tool.addAction(action2);
|
||||||
|
@ -130,8 +130,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_OneDefaultOneUndefinedDefaultKeyBinding() {
|
public void testSharedKeyBinding_OneDefaultOneUndefinedDefaultKeyBinding() {
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, null);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, null);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action2);
|
tool.addAction(action2);
|
||||||
|
@ -146,8 +146,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_RemoveAction() {
|
public void testSharedKeyBinding_RemoveAction() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action2);
|
tool.addAction(action2);
|
||||||
|
@ -166,7 +166,7 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_AddSameActionTwice() {
|
public void testSharedKeyBinding_AddSameActionTwice() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
|
|
||||||
|
@ -188,8 +188,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_OnlyOneEntryInOptions() {
|
public void testSharedKeyBinding_OnlyOneEntryInOptions() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action2);
|
tool.addAction(action2);
|
||||||
|
@ -205,8 +205,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_AddActionAfterOptionHasChanged() {
|
public void testSharedKeyBinding_AddActionAfterOptionHasChanged() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
KeyStroke newKs = KeyStroke.getKeyStroke(KeyEvent.VK_Z, 0);
|
KeyStroke newKs = KeyStroke.getKeyStroke(KeyEvent.VK_Z, 0);
|
||||||
|
@ -223,8 +223,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_AddActionAfterOptionHasChanged_RepeatAddRemove() {
|
public void testSharedKeyBinding_AddActionAfterOptionHasChanged_RepeatAddRemove() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
KeyStroke newKs = KeyStroke.getKeyStroke(KeyEvent.VK_Z, 0);
|
KeyStroke newKs = KeyStroke.getKeyStroke(KeyEvent.VK_Z, 0);
|
||||||
|
@ -248,8 +248,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_SameDefaultKeyBindings_LocalAction() {
|
public void testSharedKeyBinding_SameDefaultKeyBindings_LocalAction() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
DummyComponentProvider provider = new DummyComponentProvider();
|
DummyComponentProvider provider = new DummyComponentProvider();
|
||||||
tool.addLocalAction(provider, action1);
|
tool.addLocalAction(provider, action1);
|
||||||
|
@ -264,8 +264,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_RemoveAction_LocalAction() {
|
public void testSharedKeyBinding_RemoveAction_LocalAction() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
DummyComponentProvider provider = new DummyComponentProvider();
|
DummyComponentProvider provider = new DummyComponentProvider();
|
||||||
tool.addLocalAction(provider, action1);
|
tool.addLocalAction(provider, action1);
|
||||||
|
@ -285,8 +285,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSharedKeyBinding_RemoveComonentActions() {
|
public void testSharedKeyBinding_RemoveComonentActions() {
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action2 = new TestAction(OWNER_2, DEFAULT_KS_1);
|
SharedNameAction action2 = new SharedNameAction(OWNER_2, DEFAULT_KS_1);
|
||||||
|
|
||||||
DummyComponentProvider provider = new DummyComponentProvider();
|
DummyComponentProvider provider = new DummyComponentProvider();
|
||||||
tool.addLocalAction(provider, action1);
|
tool.addLocalAction(provider, action1);
|
||||||
|
@ -313,8 +313,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
// same name and owner.
|
// same name and owner.
|
||||||
//
|
//
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action1Copy = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1Copy = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action1Copy);
|
tool.addAction(action1Copy);
|
||||||
|
@ -342,8 +342,8 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
// same name and owner.
|
// same name and owner.
|
||||||
//
|
//
|
||||||
|
|
||||||
TestAction action1 = new TestAction(OWNER_1, DEFAULT_KS_1);
|
SharedNameAction action1 = new SharedNameAction(OWNER_1, DEFAULT_KS_1);
|
||||||
TestAction action1Copy = new TestAction(OWNER_1, DEFAULT_KS_DIFFERENT_THAN_1);
|
SharedNameAction action1Copy = new SharedNameAction(OWNER_1, DEFAULT_KS_DIFFERENT_THAN_1);
|
||||||
|
|
||||||
tool.addAction(action1);
|
tool.addAction(action1);
|
||||||
tool.addAction(action1Copy);
|
tool.addAction(action1Copy);
|
||||||
|
@ -484,7 +484,7 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
spyLogger.assertLogMessage("shared", "key", "binding", "actions", "different", "default");
|
spyLogger.assertLogMessage("shared", "key", "binding", "actions", "different", "default");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertKeyBinding(TestAction action, KeyStroke expectedKs) {
|
private void assertKeyBinding(SharedNameAction action, KeyStroke expectedKs) {
|
||||||
assertEquals(expectedKs, action.getKeyBinding());
|
assertEquals(expectedKs, action.getKeyBinding());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,9 +492,9 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
private class TestAction extends DockingAction {
|
private class SharedNameAction extends DockingAction {
|
||||||
|
|
||||||
public TestAction(String owner, KeyStroke ks) {
|
public SharedNameAction(String owner, KeyStroke ks) {
|
||||||
super(SHARED_NAME, owner, KeyBindingType.SHARED);
|
super(SHARED_NAME, owner, KeyBindingType.SHARED);
|
||||||
setKeyBindingData(new KeyBindingData(ks));
|
setKeyBindingData(new KeyBindingData(ks));
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,8 +116,8 @@ public abstract class AbstractOptions implements Options {
|
||||||
"Attempted to register an unsupported object: " + defaultValue.getClass());
|
"Attempted to register an unsupported object: " + defaultValue.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
registerOption(optionName, OptionType.getOptionType(defaultValue), defaultValue, help,
|
OptionType type = OptionType.getOptionType(defaultValue);
|
||||||
description);
|
registerOption(optionName, type, defaultValue, help, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,16 +150,41 @@ public abstract class AbstractOptions implements Options {
|
||||||
valueMap.put(optionName, option);
|
valueMap.put(optionName, option);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!currentOption.isRegistered()) {
|
|
||||||
Option option =
|
Option newOption = null;
|
||||||
|
if (currentOption.isRegistered()) {
|
||||||
|
// Registered again
|
||||||
|
newOption =
|
||||||
|
copyRegisteredOption(currentOption, type, description, defaultValue, help, editor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// option was accessed, but not registered
|
||||||
|
newOption =
|
||||||
createRegisteredOption(optionName, type, description, help, defaultValue, editor);
|
createRegisteredOption(optionName, type, description, help, defaultValue, editor);
|
||||||
option.setCurrentValue(currentOption.getCurrentValue());
|
|
||||||
valueMap.put(optionName, option);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We probably don't need to do anything special if we are re-registering an
|
copyCurrentValue(currentOption, newOption);
|
||||||
// option, which is what the below code handles.
|
valueMap.put(optionName, newOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyCurrentValue(Option currentOption, Option newOption) {
|
||||||
|
|
||||||
|
Object currentValue = currentOption.getCurrentValue();
|
||||||
|
OptionType type = currentOption.getOptionType();
|
||||||
|
if (!isNullable(type) && currentValue == null) {
|
||||||
|
return; // not allowed to be null
|
||||||
|
}
|
||||||
|
|
||||||
|
// null is allowed; null can represent a valid 'cleared' state
|
||||||
|
newOption.setCurrentValue(currentValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Option copyRegisteredOption(Option currentOption, OptionType type,
|
||||||
|
String description, Object defaultValue, HelpLocation help, PropertyEditor editor) {
|
||||||
|
|
||||||
|
// We probably don't need to do anything special if we are re-registering an option,
|
||||||
|
// which is what the below code handles
|
||||||
String oldDescription = currentOption.getDescription();
|
String oldDescription = currentOption.getDescription();
|
||||||
HelpLocation oldHelp = currentOption.getHelpLocation();
|
HelpLocation oldHelp = currentOption.getHelpLocation();
|
||||||
Object oldDefaultValue = currentOption.getDefaultValue();
|
Object oldDefaultValue = currentOption.getDefaultValue();
|
||||||
|
@ -170,13 +195,9 @@ public abstract class AbstractOptions implements Options {
|
||||||
Object newDefaultValue = oldDefaultValue == null ? defaultValue : oldDefaultValue;
|
Object newDefaultValue = oldDefaultValue == null ? defaultValue : oldDefaultValue;
|
||||||
PropertyEditor newEditor = oldEditor == null ? editor : oldEditor;
|
PropertyEditor newEditor = oldEditor == null ? editor : oldEditor;
|
||||||
|
|
||||||
Option newOption = createRegisteredOption(optionName, type, newDescripiton, newHelpLocation,
|
String optionName = currentOption.getName();
|
||||||
|
return createRegisteredOption(optionName, type, newDescripiton, newHelpLocation,
|
||||||
newDefaultValue, newEditor);
|
newDefaultValue, newEditor);
|
||||||
Object currentValue = currentOption.getCurrentValue();
|
|
||||||
if (currentValue != null) {
|
|
||||||
newOption.setCurrentValue(currentValue);
|
|
||||||
}
|
|
||||||
valueMap.put(optionName, newOption);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -249,6 +270,10 @@ public abstract class AbstractOptions implements Options {
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionType type = option.getOptionType();
|
OptionType type = option.getOptionType();
|
||||||
|
return isNullable(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isNullable(OptionType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
// objects can be null
|
// objects can be null
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,10 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.framework.options;
|
package ghidra.framework.options;
|
||||||
|
|
||||||
|
import java.beans.PropertyEditor;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
|
import utilities.util.reflection.ReflectionUtilities;
|
||||||
import java.beans.PropertyEditor;
|
|
||||||
|
|
||||||
public abstract class Option {
|
public abstract class Option {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -68,24 +69,20 @@ public abstract class Option {
|
||||||
return helpLocation;
|
return helpLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasValue() {
|
|
||||||
return defaultValue != null || getCurrentValue() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description == null ? "Unregistered Option" : description;
|
return description == null ? "Unregistered Option" : description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getValue(Object passedInDefaultValue) {
|
public Object getValue(Object passedInDefaultValue) {
|
||||||
Object value = getCurrentValue();
|
Object value = getCurrentValue();
|
||||||
if (value != null) {
|
if (value == null && defaultValue == null) {
|
||||||
return value;
|
// Assume that both values being null is an indication that there is no value
|
||||||
}
|
// to use. Otherwise, a null current value implies that the user has cleared
|
||||||
if (defaultValue != null) {
|
// the default value.
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
return passedInDefaultValue;
|
return passedInDefaultValue;
|
||||||
}
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isRegistered() {
|
public boolean isRegistered() {
|
||||||
return isRegistered;
|
return isRegistered;
|
||||||
|
@ -97,11 +94,7 @@ public abstract class Option {
|
||||||
|
|
||||||
public boolean isDefault() {
|
public boolean isDefault() {
|
||||||
Object value = getCurrentValue();
|
Object value = getCurrentValue();
|
||||||
if (value == null) {
|
return Objects.equals(value, defaultValue);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value.equals(defaultValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -125,46 +118,12 @@ public abstract class Option {
|
||||||
Throwable throwable = new Throwable();
|
Throwable throwable = new Throwable();
|
||||||
StackTraceElement[] stackTrace = throwable.getStackTrace();
|
StackTraceElement[] stackTrace = throwable.getStackTrace();
|
||||||
|
|
||||||
String information = getInceptionInformationFromTheFirstClassThatIsNotUs(stackTrace);
|
StackTraceElement[] filteredTrace =
|
||||||
inceptionInformation = information;
|
ReflectionUtilities.filterStackTrace(stackTrace, "option", "OptionsManager");
|
||||||
}
|
inceptionInformation = filteredTrace[0].toString();
|
||||||
|
|
||||||
private String getInceptionInformationFromTheFirstClassThatIsNotUs(
|
|
||||||
StackTraceElement[] stackTrace) {
|
|
||||||
|
|
||||||
// To find our creation point we can use a simple algorithm: find the name of our class,
|
|
||||||
// which is in the first stack trace element and then keep walking backwards until that
|
|
||||||
// name is not ours.
|
|
||||||
//
|
|
||||||
String myClassName = getClass().getName();
|
|
||||||
int myClassNameStartIndex = -1;
|
|
||||||
for (int i = 1; i < stackTrace.length; i++) { // start at 1, because we are the first item
|
|
||||||
StackTraceElement stackTraceElement = stackTrace[i];
|
|
||||||
String elementClassName = stackTraceElement.getClassName();
|
|
||||||
if (myClassName.equals(elementClassName)) {
|
|
||||||
myClassNameStartIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, go backwards until we find a non-options class in the stack, in order
|
|
||||||
// to remove infrastructure code from the client that called the options API.
|
|
||||||
int creatorIndex = myClassNameStartIndex;
|
|
||||||
for (int i = myClassNameStartIndex; i < stackTrace.length; i++) { // start at 1, because we are the first item
|
|
||||||
StackTraceElement stackTraceElement = stackTrace[i];
|
|
||||||
String elementClassName = stackTraceElement.getClassName();
|
|
||||||
|
|
||||||
if (elementClassName.toLowerCase().indexOf("option") == -1) {
|
|
||||||
creatorIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stackTrace[creatorIndex].toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OptionType getOptionType() {
|
public OptionType getOptionType() {
|
||||||
return optionType;
|
return optionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@ import ghidra.util.exception.AssertException;
|
||||||
* The Options Dialog shows the hierarchy in tree format.
|
* The Options Dialog shows the hierarchy in tree format.
|
||||||
*/
|
*/
|
||||||
public class ToolOptions extends AbstractOptions {
|
public class ToolOptions extends AbstractOptions {
|
||||||
|
private static final String CLASS_ATTRIBUTE = "CLASS";
|
||||||
|
private static final String NAME_ATTRIBUTE = "NAME";
|
||||||
|
private static final String WRAPPED_OPTION_NAME = "WRAPPED_OPTION";
|
||||||
|
private static final String CLEARED_VALUE_ELEMENT_NAME = "CLEARED_VALUE";
|
||||||
public static final Set<Class<?>> PRIMITIVE_CLASSES = buildPrimitiveClassSet();
|
public static final Set<Class<?>> PRIMITIVE_CLASSES = buildPrimitiveClassSet();
|
||||||
public static final Set<Class<?>> WRAPPABLE_CLASSES = buildWrappableClassSet();
|
public static final Set<Class<?>> WRAPPABLE_CLASSES = buildWrappableClassSet();
|
||||||
|
|
||||||
|
@ -81,34 +85,57 @@ public class ToolOptions extends AbstractOptions {
|
||||||
* @param root XML that contains the set of options to restore
|
* @param root XML that contains the set of options to restore
|
||||||
*/
|
*/
|
||||||
public ToolOptions(Element root) {
|
public ToolOptions(Element root) {
|
||||||
this(root.getAttributeValue("NAME"));
|
this(root.getAttributeValue(NAME_ATTRIBUTE));
|
||||||
|
|
||||||
SaveState saveState = new SaveState(root);
|
SaveState saveState = new SaveState(root);
|
||||||
|
|
||||||
|
readNonWrappedOptions(saveState);
|
||||||
|
|
||||||
|
try {
|
||||||
|
readWrappedOptions(root);
|
||||||
|
}
|
||||||
|
catch (ReflectiveOperationException exc) {
|
||||||
|
Msg.error(this, "Unexpected Exception: " + exc.getMessage(), exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readNonWrappedOptions(SaveState saveState) {
|
||||||
for (String optionName : saveState.getNames()) {
|
for (String optionName : saveState.getNames()) {
|
||||||
Object object = saveState.getObject(optionName);
|
Object object = saveState.getObject(optionName);
|
||||||
Option option =
|
Option option =
|
||||||
createUnregisteredOption(optionName, OptionType.getOptionType(object), null);
|
createUnregisteredOption(optionName, OptionType.getOptionType(object), null);
|
||||||
option.doSetCurrentValue(object); // use doSet versus set so that it is not registered
|
option.doSetCurrentValue(object); // use doSet versus set so that it is not registered
|
||||||
valueMap.put(optionName, option);
|
valueMap.put(optionName, option);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<?> iter = root.getChildren("WRAPPED_OPTION").iterator();
|
private void readWrappedOptions(Element root) throws ReflectiveOperationException {
|
||||||
while (iter.hasNext()) {
|
|
||||||
try {
|
Iterator<?> it = root.getChildren(WRAPPED_OPTION_NAME).iterator();
|
||||||
Element elem = (Element) iter.next();
|
while (it.hasNext()) {
|
||||||
String optionName = elem.getAttributeValue("NAME");
|
|
||||||
Class<?> c = Class.forName(elem.getAttributeValue("CLASS"));
|
Element element = (Element) it.next();
|
||||||
|
List<?> children = element.getChildren();
|
||||||
|
if (children.isEmpty()) {
|
||||||
|
continue; // shouldn't happen
|
||||||
|
}
|
||||||
|
|
||||||
|
String optionName = element.getAttributeValue(NAME_ATTRIBUTE);
|
||||||
|
Class<?> c = Class.forName(element.getAttributeValue(CLASS_ATTRIBUTE));
|
||||||
Constructor<?> constructor = c.getDeclaredConstructor();
|
Constructor<?> constructor = c.getDeclaredConstructor();
|
||||||
WrappedOption wo = (WrappedOption) constructor.newInstance();
|
WrappedOption wo = (WrappedOption) constructor.newInstance();
|
||||||
wo.readState(new SaveState(elem));
|
|
||||||
Option option = createUnregisteredOption(optionName, wo.getOptionType(), null);
|
Option option = createUnregisteredOption(optionName, wo.getOptionType(), null);
|
||||||
option.doSetCurrentValue(wo.getObject());// use doSet versus set so that it is not registered
|
|
||||||
valueMap.put(optionName, option);
|
valueMap.put(optionName, option);
|
||||||
|
|
||||||
|
Element child = (Element) children.get(0);
|
||||||
|
String elementName = child.getName();
|
||||||
|
if (CLEARED_VALUE_ELEMENT_NAME.equals(elementName)) {
|
||||||
|
// a signal that the default option value has been cleared
|
||||||
|
option.doSetCurrentValue(null); // use doSet so that it is not registered
|
||||||
}
|
}
|
||||||
catch (Exception exc) {
|
else {
|
||||||
Msg.error(this, "Unexpected Exception: " + exc.getMessage(), exc);
|
wo.readState(new SaveState(element));
|
||||||
|
option.doSetCurrentValue(wo.getObject()); // use doSet so that it is not registered
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,8 +149,20 @@ public class ToolOptions extends AbstractOptions {
|
||||||
* @return the xml root element
|
* @return the xml root element
|
||||||
*/
|
*/
|
||||||
public Element getXmlRoot(boolean includeDefaultBindings) {
|
public Element getXmlRoot(boolean includeDefaultBindings) {
|
||||||
|
|
||||||
SaveState saveState = new SaveState(XML_ELEMENT_NAME);
|
SaveState saveState = new SaveState(XML_ELEMENT_NAME);
|
||||||
|
|
||||||
|
writeNonWrappedOptions(includeDefaultBindings, saveState);
|
||||||
|
|
||||||
|
Element root = saveState.saveToXml();
|
||||||
|
root.setAttribute(NAME_ATTRIBUTE, name);
|
||||||
|
|
||||||
|
writeWrappedOptions(includeDefaultBindings, root);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeNonWrappedOptions(boolean includeDefaultBindings, SaveState saveState) {
|
||||||
for (String optionName : valueMap.keySet()) {
|
for (String optionName : valueMap.keySet()) {
|
||||||
Option optionValue = valueMap.get(optionName);
|
Option optionValue = valueMap.get(optionName);
|
||||||
if (includeDefaultBindings || !optionValue.isDefault()) {
|
if (includeDefaultBindings || !optionValue.isDefault()) {
|
||||||
|
@ -133,29 +172,45 @@ public class ToolOptions extends AbstractOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Element root = saveState.saveToXml();
|
private void writeWrappedOptions(boolean includeDefaultBindings, Element root) {
|
||||||
root.setAttribute("NAME", name);
|
|
||||||
|
|
||||||
for (String optionName : valueMap.keySet()) {
|
for (String optionName : valueMap.keySet()) {
|
||||||
Option optionValue = valueMap.get(optionName);
|
Option option = valueMap.get(optionName);
|
||||||
if (includeDefaultBindings || !optionValue.isDefault()) {
|
if (includeDefaultBindings || !option.isDefault()) {
|
||||||
Object value = optionValue.getValue(null);
|
|
||||||
if (value != null && !isSupportedBySaveState(value)) {
|
Object value = option.getCurrentValue();
|
||||||
WrappedOption wrappedOption = wrapOption(value);
|
if (isSupportedBySaveState(value)) {
|
||||||
SaveState ss = new SaveState("WRAPPED_OPTION");
|
// handled above
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
WrappedOption wrappedOption = wrapOption(option);
|
||||||
|
if (wrappedOption == null) {
|
||||||
|
// cannot write an option without a value to determine its type
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveState ss = new SaveState(WRAPPED_OPTION_NAME);
|
||||||
|
Element elem = null;
|
||||||
|
if (value == null) {
|
||||||
|
// Handle the null case ourselves, not using the wrapped option (and when
|
||||||
|
// reading from xml) so that the logic does not need to in each wrapped option
|
||||||
|
elem = ss.saveToXml();
|
||||||
|
elem.addContent(new Element(CLEARED_VALUE_ELEMENT_NAME));
|
||||||
|
}
|
||||||
|
else {
|
||||||
wrappedOption.writeState(ss);
|
wrappedOption.writeState(ss);
|
||||||
Element elem = ss.saveToXml();
|
elem = ss.saveToXml();
|
||||||
elem.setAttribute("NAME", optionName);
|
}
|
||||||
elem.setAttribute("CLASS", wrappedOption.getClass().getName());
|
|
||||||
|
elem.setAttribute(NAME_ATTRIBUTE, optionName);
|
||||||
|
elem.setAttribute(CLASS_ATTRIBUTE, wrappedOption.getClass().getName());
|
||||||
root.addContent(elem);
|
root.addContent(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSupportedBySaveState(Object obj) {
|
private boolean isSupportedBySaveState(Object obj) {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -170,7 +225,19 @@ public class ToolOptions extends AbstractOptions {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private WrappedOption wrapOption(Object value) {
|
private WrappedOption wrapOption(Option option) {
|
||||||
|
|
||||||
|
Object value = null;
|
||||||
|
value = option.getCurrentValue();
|
||||||
|
if (value == null) {
|
||||||
|
value = option.getDefaultValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
// nothing to wrap
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (value instanceof CustomOption) {
|
if (value instanceof CustomOption) {
|
||||||
return new WrappedCustomOption((CustomOption) value);
|
return new WrappedCustomOption((CustomOption) value);
|
||||||
}
|
}
|
||||||
|
@ -232,44 +299,6 @@ public class ToolOptions extends AbstractOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private class NotifyListenersRunnable implements Runnable {
|
|
||||||
private String optionName;
|
|
||||||
private Object oldValue;
|
|
||||||
private Object newValue;
|
|
||||||
private boolean vetoed;
|
|
||||||
|
|
||||||
NotifyListenersRunnable(String optionName, Object oldValue, Object newValue) {
|
|
||||||
this.optionName = optionName;
|
|
||||||
this.oldValue = oldValue;
|
|
||||||
this.newValue = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
List<OptionsChangeListener> notifiedListeners = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
for (OptionsChangeListener listener : listeners) {
|
|
||||||
listener.optionsChanged(ToolOptions.this, optionName, oldValue, newValue);
|
|
||||||
notifiedListeners.add(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (OptionsVetoException e) {
|
|
||||||
vetoed = true;
|
|
||||||
for (OptionsChangeListener notifiedListener : notifiedListeners) {
|
|
||||||
notifiedListener.optionsChanged(ToolOptions.this, optionName, newValue,
|
|
||||||
oldValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean wasVetoed() {
|
|
||||||
return vetoed;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds all the options name/value pairs to this Options.
|
* Adds all the options name/value pairs to this Options.
|
||||||
* @param newOptions the new options into which the current options values will be placed
|
* @param newOptions the new options into which the current options values will be placed
|
||||||
|
@ -356,6 +385,8 @@ public class ToolOptions extends AbstractOptions {
|
||||||
ToolOption(String name, OptionType type, String description, HelpLocation helpLocation,
|
ToolOption(String name, OptionType type, String description, HelpLocation helpLocation,
|
||||||
Object defaultValue, boolean isRegistered, PropertyEditor editor) {
|
Object defaultValue, boolean isRegistered, PropertyEditor editor) {
|
||||||
super(name, type, description, helpLocation, defaultValue, isRegistered, editor);
|
super(name, type, description, helpLocation, defaultValue, isRegistered, editor);
|
||||||
|
|
||||||
|
this.currentValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -385,7 +416,44 @@ public class ToolOptions extends AbstractOptions {
|
||||||
protected boolean notifyOptionChanged(String optionName, Object oldValue, Object newValue) {
|
protected boolean notifyOptionChanged(String optionName, Object oldValue, Object newValue) {
|
||||||
NotifyListenersRunnable runnable =
|
NotifyListenersRunnable runnable =
|
||||||
new NotifyListenersRunnable(optionName, oldValue, newValue);
|
new NotifyListenersRunnable(optionName, oldValue, newValue);
|
||||||
SystemUtilities.runSwingNow(runnable);
|
Swing.runNow(runnable);
|
||||||
return !runnable.wasVetoed();
|
return !runnable.wasVetoed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class NotifyListenersRunnable implements Runnable {
|
||||||
|
private String optionName;
|
||||||
|
private Object oldValue;
|
||||||
|
private Object newValue;
|
||||||
|
private boolean vetoed;
|
||||||
|
|
||||||
|
NotifyListenersRunnable(String optionName, Object oldValue, Object newValue) {
|
||||||
|
this.optionName = optionName;
|
||||||
|
this.oldValue = oldValue;
|
||||||
|
this.newValue = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<OptionsChangeListener> notifiedListeners = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
for (OptionsChangeListener listener : listeners) {
|
||||||
|
listener.optionsChanged(ToolOptions.this, optionName, oldValue, newValue);
|
||||||
|
notifiedListeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OptionsVetoException e) {
|
||||||
|
vetoed = true;
|
||||||
|
for (OptionsChangeListener notifiedListener : notifiedListeners) {
|
||||||
|
notifiedListener.optionsChanged(ToolOptions.this, optionName, newValue,
|
||||||
|
oldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasVetoed() {
|
||||||
|
return vetoed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,7 @@ import ghidra.util.SystemUtilities;
|
||||||
import ghidra.util.exception.ClosedException;
|
import ghidra.util.exception.ClosedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Database implementation of {@link Option}
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class OptionsDB extends AbstractOptions {
|
class OptionsDB extends AbstractOptions {
|
||||||
|
|
||||||
|
@ -42,8 +41,6 @@ class OptionsDB extends AbstractOptions {
|
||||||
private Table propertyTable;
|
private Table propertyTable;
|
||||||
private DomainObjectAdapterDB domainObj;
|
private DomainObjectAdapterDB domainObj;
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
OptionsDB(DomainObjectAdapterDB domainObj) {
|
OptionsDB(DomainObjectAdapterDB domainObj) {
|
||||||
super("");
|
super("");
|
||||||
this.domainObj = domainObj;
|
this.domainObj = domainObj;
|
||||||
|
@ -59,7 +56,7 @@ class OptionsDB extends AbstractOptions {
|
||||||
* the corresponding oldPath properties will be removed.
|
* the corresponding oldPath properties will be removed.
|
||||||
* @throws IllegalStateException if list has been manipulated since construction
|
* @throws IllegalStateException if list has been manipulated since construction
|
||||||
* @throws IllegalArgumentException if invalid property alterations are provided
|
* @throws IllegalArgumentException if invalid property alterations are provided
|
||||||
* @throws IOException
|
* @throws IOException if there is an exception moving or deleting a property
|
||||||
*/
|
*/
|
||||||
synchronized void performAlterations(Map<String, String> propertyAlterations)
|
synchronized void performAlterations(Map<String, String> propertyAlterations)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@ -108,7 +105,7 @@ class OptionsDB extends AbstractOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// move records
|
// move records
|
||||||
ArrayList<Record> list = new ArrayList<Record>();
|
ArrayList<Record> list = new ArrayList<>();
|
||||||
rec = propertyTable.getRecord(new StringField(oldPath));
|
rec = propertyTable.getRecord(new StringField(oldPath));
|
||||||
if (rec != null) {
|
if (rec != null) {
|
||||||
propertyTable.deleteRecord(new StringField(oldPath));
|
propertyTable.deleteRecord(new StringField(oldPath));
|
||||||
|
@ -182,7 +179,7 @@ class OptionsDB extends AbstractOptions {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized List<String> getOptionNames() {
|
public synchronized List<String> getOptionNames() {
|
||||||
Set<String> names = new HashSet<String>(valueMap.keySet());
|
Set<String> names = new HashSet<>(valueMap.keySet());
|
||||||
names.addAll(aliasMap.keySet());
|
names.addAll(aliasMap.keySet());
|
||||||
try {
|
try {
|
||||||
if (propertyTable != null) {
|
if (propertyTable != null) {
|
||||||
|
@ -196,7 +193,7 @@ class OptionsDB extends AbstractOptions {
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
domainObj.dbError(e);
|
domainObj.dbError(e);
|
||||||
}
|
}
|
||||||
List<String> optionNames = new ArrayList<String>(names);
|
List<String> optionNames = new ArrayList<>(names);
|
||||||
Collections.sort(optionNames);
|
Collections.sort(optionNames);
|
||||||
return optionNames;
|
return optionNames;
|
||||||
}
|
}
|
||||||
|
@ -253,16 +250,6 @@ class OptionsDB extends AbstractOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Property getProperty(String propertyName) {
|
|
||||||
// Record rec = getPropertyRecord(propertyName);
|
|
||||||
// if (rec == null) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// int propertyOrdinal = rec.getByteValue(TYPE_COL);
|
|
||||||
// OptionType propertyType = OptionType.values()[propertyOrdinal];
|
|
||||||
// return createProperty(propertyName, propertyType, null);
|
|
||||||
// }
|
|
||||||
|
|
||||||
class DBOption extends Option {
|
class DBOption extends Option {
|
||||||
private Object value = null;
|
private Object value = null;
|
||||||
private boolean isCached = false;
|
private boolean isCached = false;
|
||||||
|
@ -270,6 +257,8 @@ class OptionsDB extends AbstractOptions {
|
||||||
protected DBOption(String name, OptionType type, String description, HelpLocation help,
|
protected DBOption(String name, OptionType type, String description, HelpLocation help,
|
||||||
Object defaultValue, boolean isRegistered, PropertyEditor editor) {
|
Object defaultValue, boolean isRegistered, PropertyEditor editor) {
|
||||||
super(name, type, description, help, defaultValue, isRegistered, editor);
|
super(name, type, description, help, defaultValue, isRegistered, editor);
|
||||||
|
|
||||||
|
getCurrentValue(); // initialize our defaults
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -123,19 +123,9 @@ public class KeyBindingsPanel extends JPanel {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newKeyStroke != null) {
|
|
||||||
options.setKeyStroke(fullActionName, newKeyStroke);
|
options.setKeyStroke(fullActionName, newKeyStroke);
|
||||||
}
|
|
||||||
else {
|
|
||||||
options.removeOption(fullActionName);
|
|
||||||
}
|
|
||||||
originalValues.put(fullActionName, newKeyStroke);
|
originalValues.put(fullActionName, newKeyStroke);
|
||||||
keyStrokesByFullName.put(fullActionName, newKeyStroke);
|
keyStrokesByFullName.put(fullActionName, newKeyStroke);
|
||||||
|
|
||||||
List<DockingActionIf> actions = actionsByFullName.get(fullActionName);
|
|
||||||
for (DockingActionIf action : actions) {
|
|
||||||
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKeyStroke));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
|
|
|
@ -57,7 +57,6 @@ import ghidra.program.util.*;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database implementation for Program.
|
* Database implementation for Program.
|
||||||
|
@ -199,10 +198,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
|
|
||||||
private OverlaySpaceAdapterDB overlaySpaceAdapter;
|
private OverlaySpaceAdapterDB overlaySpaceAdapter;
|
||||||
|
|
||||||
private HashMap<String, AddressSetPropertyMapDB> addrSetPropertyMap = new HashMap<>();
|
private Map<String, AddressSetPropertyMapDB> addrSetPropertyMap = new HashMap<>();
|
||||||
private HashMap<String, IntRangeMapDB> intRangePropertyMap = new HashMap<>();
|
private Map<String, IntRangeMapDB> intRangePropertyMap = new HashMap<>();
|
||||||
|
|
||||||
private HashSet<Long> changedFunctionIDs = new HashSet<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new ProgramDB
|
* Constructs a new ProgramDB
|
||||||
|
@ -232,12 +229,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
int id = startTransaction("create program");
|
int id = startTransaction("create program");
|
||||||
|
|
||||||
createDatabase();
|
createDatabase();
|
||||||
if (createManagers(CREATE, TaskMonitorAdapter.DUMMY_MONITOR) != null) {
|
if (createManagers(CREATE, TaskMonitor.DUMMY) != null) {
|
||||||
throw new AssertException("Unexpected version exception on create");
|
throw new AssertException("Unexpected version exception on create");
|
||||||
}
|
}
|
||||||
listing = new ListingDB();
|
listing = new ListingDB();
|
||||||
changeSet = new ProgramDBChangeSet(addrMap, NUM_UNDOS);
|
changeSet = new ProgramDBChangeSet(addrMap, NUM_UNDOS);
|
||||||
initManagers(CREATE, TaskMonitorAdapter.DUMMY_MONITOR);
|
initManagers(CREATE, TaskMonitor.DUMMY);
|
||||||
propertiesCreate();
|
propertiesCreate();
|
||||||
programUserData = new ProgramUserDataDB(this);
|
programUserData = new ProgramUserDataDB(this);
|
||||||
endTransaction(id, true);
|
endTransaction(id, true);
|
||||||
|
@ -273,7 +270,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
* @throws IOException if an error accessing the database occurs.
|
* @throws IOException if an error accessing the database occurs.
|
||||||
* @throws VersionException if database version does not match implementation, UPGRADE may be possible.
|
* @throws VersionException if database version does not match implementation, UPGRADE may be possible.
|
||||||
* @throws CancelledException if instantiation is canceled by monitor
|
* @throws CancelledException if instantiation is canceled by monitor
|
||||||
* @throws LanguageNotFoundException
|
* @throws LanguageNotFoundException if a language cannot be found for this program
|
||||||
*/
|
*/
|
||||||
public ProgramDB(DBHandle dbh, int openMode, TaskMonitor monitor, Object consumer)
|
public ProgramDB(DBHandle dbh, int openMode, TaskMonitor monitor, Object consumer)
|
||||||
throws IOException, VersionException, LanguageNotFoundException, CancelledException {
|
throws IOException, VersionException, LanguageNotFoundException, CancelledException {
|
||||||
|
@ -281,7 +278,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
super(dbh, "Untitled", 500, 1000, consumer);
|
super(dbh, "Untitled", 500, 1000, consumer);
|
||||||
|
|
||||||
if (monitor == null) {
|
if (monitor == null) {
|
||||||
monitor = TaskMonitorAdapter.DUMMY;
|
monitor = TaskMonitor.DUMMY;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
|
@ -369,7 +366,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
/**
|
/**
|
||||||
* Initialize program compiler specification.
|
* Initialize program compiler specification.
|
||||||
* During a language upgrade this will provide a temporary spec until setLanguage is complete.
|
* During a language upgrade this will provide a temporary spec until setLanguage is complete.
|
||||||
* @throws CompilerSpecNotFoundException
|
* @throws CompilerSpecNotFoundException if the compiler spec cannot be found
|
||||||
*/
|
*/
|
||||||
private void initCompilerSpec() throws CompilerSpecNotFoundException {
|
private void initCompilerSpec() throws CompilerSpecNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
@ -399,8 +396,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
* @param openMode one of:
|
* @param openMode one of:
|
||||||
* READ_ONLY: the original database will not be modified
|
* READ_ONLY: the original database will not be modified
|
||||||
* UPDATE: the database can be written to.
|
* UPDATE: the database can be written to.
|
||||||
* UPGRADE: the database is upgraded to the lastest schema as it is opened.
|
* UPGRADE: the database is upgraded to the latest schema as it is opened.
|
||||||
* @throws LanguageNotFoundException
|
* @throws LanguageNotFoundException if a language cannot be found for this program
|
||||||
* @return VersionException if language upgrade required
|
* @return VersionException if language upgrade required
|
||||||
*/
|
*/
|
||||||
private VersionException checkLanguageVersion(int openMode) throws LanguageNotFoundException {
|
private VersionException checkLanguageVersion(int openMode) throws LanguageNotFoundException {
|
||||||
|
@ -409,7 +406,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
|
|
||||||
Language newLanguage = language;
|
Language newLanguage = language;
|
||||||
|
|
||||||
Language oldLanguage = OldLanguageFactory.getOldLanguageFactory().getOldLanguage(
|
Language oldLanguage = OldLanguageFactory.getOldLanguageFactory()
|
||||||
|
.getOldLanguage(
|
||||||
languageID, languageVersion);
|
languageID, languageVersion);
|
||||||
if (oldLanguage == null) {
|
if (oldLanguage == null) {
|
||||||
// Assume minor version behavior - old language does not exist for current major version
|
// Assume minor version behavior - old language does not exist for current major version
|
||||||
|
@ -420,7 +418,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
|
|
||||||
// Ensure that we can upgrade the language
|
// Ensure that we can upgrade the language
|
||||||
languageUpgradeTranslator =
|
languageUpgradeTranslator =
|
||||||
LanguageTranslatorFactory.getLanguageTranslatorFactory().getLanguageTranslator(
|
LanguageTranslatorFactory.getLanguageTranslatorFactory()
|
||||||
|
.getLanguageTranslator(
|
||||||
oldLanguage, newLanguage);
|
oldLanguage, newLanguage);
|
||||||
if (languageUpgradeTranslator == null) {
|
if (languageUpgradeTranslator == null) {
|
||||||
|
|
||||||
|
@ -451,12 +450,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Language specified by languageName was not found. Check for
|
* Language specified by languageName was not found. Check for
|
||||||
* valid language translation/migration. Old langauge version specified by
|
* valid language translation/migration. Old language version specified by
|
||||||
* languageVersion.
|
* languageVersion.
|
||||||
* @param openMode one of:
|
* @param openMode one of:
|
||||||
* READ_ONLY: the original database will not be modified
|
* READ_ONLY: the original database will not be modified
|
||||||
* UPDATE: the database can be written to.
|
* UPDATE: the database can be written to.
|
||||||
* UPGRADE: the database is upgraded to the lastest schema as it is opened.
|
* UPGRADE: the database is upgraded to the latest schema as it is opened.
|
||||||
* @return true if language upgrade required
|
* @return true if language upgrade required
|
||||||
* @throws LanguageNotFoundException if a suitable replacement language not found
|
* @throws LanguageNotFoundException if a suitable replacement language not found
|
||||||
*/
|
*/
|
||||||
|
@ -464,7 +463,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
throws LanguageNotFoundException {
|
throws LanguageNotFoundException {
|
||||||
|
|
||||||
languageUpgradeTranslator =
|
languageUpgradeTranslator =
|
||||||
LanguageTranslatorFactory.getLanguageTranslatorFactory().getLanguageTranslator(
|
LanguageTranslatorFactory.getLanguageTranslatorFactory()
|
||||||
|
.getLanguageTranslator(
|
||||||
languageID, languageVersion);
|
languageID, languageVersion);
|
||||||
if (languageUpgradeTranslator == null) {
|
if (languageUpgradeTranslator == null) {
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -514,10 +514,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
changed = origChangeState;
|
changed = origChangeState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the program user data
|
|
||||||
* @param programUserData
|
|
||||||
*/
|
|
||||||
void setProgramUserData(ProgramUserDataDB programUserData) {
|
void setProgramUserData(ProgramUserDataDB programUserData) {
|
||||||
this.programUserData = programUserData;
|
this.programUserData = programUserData;
|
||||||
}
|
}
|
||||||
|
@ -571,9 +567,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
return memoryManager;
|
return memoryManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the namespace manager
|
|
||||||
*/
|
|
||||||
public NamespaceManager getNamespaceManager() {
|
public NamespaceManager getNamespaceManager() {
|
||||||
return (NamespaceManager) managers[NAMESPACE_MGR];
|
return (NamespaceManager) managers[NAMESPACE_MGR];
|
||||||
}
|
}
|
||||||
|
@ -583,16 +576,10 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
return (ReferenceManager) managers[REF_MGR];
|
return (ReferenceManager) managers[REF_MGR];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the CodeManager
|
|
||||||
*/
|
|
||||||
public CodeManager getCodeManager() {
|
public CodeManager getCodeManager() {
|
||||||
return (CodeManager) managers[CODE_MGR];
|
return (CodeManager) managers[CODE_MGR];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the TreeManager
|
|
||||||
*/
|
|
||||||
public TreeManager getTreeManager() {
|
public TreeManager getTreeManager() {
|
||||||
return (TreeManager) managers[TREE_MGR];
|
return (TreeManager) managers[TREE_MGR];
|
||||||
}
|
}
|
||||||
|
@ -655,6 +642,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
format = pl.getString(EXECUTABLE_FORMAT, (String) null);
|
format = pl.getString(EXECUTABLE_FORMAT, (String) null);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// handled below
|
||||||
}
|
}
|
||||||
return format == null ? UNKNOWN : format;
|
return format == null ? UNKNOWN : format;
|
||||||
}
|
}
|
||||||
|
@ -674,6 +662,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
format = pl.getString(EXECUTABLE_MD5, (String) null);
|
format = pl.getString(EXECUTABLE_MD5, (String) null);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// handled below
|
||||||
}
|
}
|
||||||
return format == null ? UNKNOWN : format;
|
return format == null ? UNKNOWN : format;
|
||||||
}
|
}
|
||||||
|
@ -693,6 +682,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
format = pl.getString(EXECUTABLE_SHA256, (String) null);
|
format = pl.getString(EXECUTABLE_SHA256, (String) null);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
// handled below
|
||||||
}
|
}
|
||||||
return format == null ? UNKNOWN : format;
|
return format == null ? UNKNOWN : format;
|
||||||
}
|
}
|
||||||
|
@ -910,6 +900,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
* Notification that a program tree was changed.
|
* Notification that a program tree was changed.
|
||||||
* @param id the id of the program tree that was changed.
|
* @param id the id of the program tree that was changed.
|
||||||
* @param type the type of change
|
* @param type the type of change
|
||||||
|
* @param affectedObj the object that was changed
|
||||||
* @param oldValue old value depends on the type of the change
|
* @param oldValue old value depends on the type of the change
|
||||||
* @param newValue old value depends on the type of the change
|
* @param newValue old value depends on the type of the change
|
||||||
*/
|
*/
|
||||||
|
@ -960,7 +951,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
* @param symbol the symbol that was changed.
|
* @param symbol the symbol that was changed.
|
||||||
* @param type the type of change
|
* @param type the type of change
|
||||||
* @param addr the address of the symbol that changed
|
* @param addr the address of the symbol that changed
|
||||||
* @param affectedObj
|
* @param affectedObj the object that was changed
|
||||||
* @param oldValue old value depends on the type of the change
|
* @param oldValue old value depends on the type of the change
|
||||||
* @param newValue old value depends on the type of the change
|
* @param newValue old value depends on the type of the change
|
||||||
*/
|
*/
|
||||||
|
@ -1023,10 +1014,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
fireEvent(new ProgramChangeRecord(type, addr, addr, null, oldValue, newValue));
|
fireEvent(new ProgramChangeRecord(type, addr, addr, null, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashSet<Long> getChangedFunctionTagIDs() {
|
|
||||||
return this.changedFunctionIDs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRegisterValuesChanged(Register register, Address start, Address end) {
|
public void setRegisterValuesChanged(Register register, Address start, Address end) {
|
||||||
if (recordChanges) {
|
if (recordChanges) {
|
||||||
|
@ -1043,27 +1030,11 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
new ProgramChangeRecord(DOCR_REGISTER_VALUES_CHANGED, start, end, null, null, null));
|
new ProgramChangeRecord(DOCR_REGISTER_VALUES_CHANGED, start, end, null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state this Program as having changed and generate
|
|
||||||
* the event. Any or all parameters may be null.
|
|
||||||
* @param type event type
|
|
||||||
* @param oldValue original value
|
|
||||||
* @param newValue new value
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setChanged(int type, Object oldValue, Object newValue) {
|
public void setChanged(int type, Object oldValue, Object newValue) {
|
||||||
setChanged(type, (Address) null, (Address) null, oldValue, newValue);
|
setChanged(type, (Address) null, (Address) null, oldValue, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state this Program as having changed and generate
|
|
||||||
* the event. Any or all parameters may be null.
|
|
||||||
* @param type event type
|
|
||||||
* @param start starting address that is affected by the event
|
|
||||||
* @param end ending address that is affected by the event
|
|
||||||
* @param oldValue original value
|
|
||||||
* @param newValue new value
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setChanged(int type, Address start, Address end, Object oldValue, Object newValue) {
|
public void setChanged(int type, Address start, Address end, Object oldValue, Object newValue) {
|
||||||
|
|
||||||
|
@ -1084,37 +1055,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
fireEvent(new ProgramChangeRecord(type, newstart, newend, null, oldValue, newValue));
|
fireEvent(new ProgramChangeRecord(type, newstart, newend, null, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state of a Program as having changed and generate
|
|
||||||
* the event. Any or all parameters may be null.
|
|
||||||
* NOTE: ChangeSet data will not be updated since this a very generic
|
|
||||||
* change not related to a specific address.
|
|
||||||
* @param type event type
|
|
||||||
* @param affectedObj object that is the subject of the event
|
|
||||||
* @param oldValue original value or an Object that is related to
|
|
||||||
* the event
|
|
||||||
* @param newValue new value or an Object that is related to the
|
|
||||||
* the event
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setObjChanged(int type, Object affectedObj, Object oldValue, Object newValue) {
|
public void setObjChanged(int type, Object affectedObj, Object oldValue, Object newValue) {
|
||||||
changed = true;
|
changed = true;
|
||||||
fireEvent(new ProgramChangeRecord(type, null, null, affectedObj, oldValue, newValue));
|
fireEvent(new ProgramChangeRecord(type, null, null, affectedObj, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state of a Program as having changed and generate
|
|
||||||
* the event. Any or all parameters may be null.
|
|
||||||
* NOTE: ChangeSet data will not be updated since this a very generic
|
|
||||||
* change not related to a specific address.
|
|
||||||
* @param type event type
|
|
||||||
* @param subType event sub-type
|
|
||||||
* @param affectedObj object that is the subject of the event
|
|
||||||
* @param oldValue original value or an Object that is related to
|
|
||||||
* the event
|
|
||||||
* @param newValue new value or an Object that is related to the
|
|
||||||
* the event
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setObjChanged(int type, int subType, Object affectedObj, Object oldValue,
|
public void setObjChanged(int type, int subType, Object affectedObj, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
|
@ -1123,17 +1069,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
new ProgramChangeRecord(type, subType, null, null, affectedObj, oldValue, newValue));
|
new ProgramChangeRecord(type, subType, null, null, affectedObj, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state of a Program as having changed and generate
|
|
||||||
* the event. Any or all parameters may be null.
|
|
||||||
* @param type event type
|
|
||||||
* @param addr program address affected
|
|
||||||
* @param affectedObj object that is the subject of the event
|
|
||||||
* @param oldValue original value or an Object that is related to
|
|
||||||
* the event
|
|
||||||
* @param newValue new value or an Object that is related to the
|
|
||||||
* the event
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setObjChanged(int type, Address addr, Object affectedObj, Object oldValue,
|
public void setObjChanged(int type, Address addr, Object affectedObj, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
|
@ -1144,18 +1079,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
fireEvent(new ProgramChangeRecord(type, addr, addr, affectedObj, oldValue, newValue));
|
fireEvent(new ProgramChangeRecord(type, addr, addr, affectedObj, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state of a Program as having changed and generate
|
|
||||||
* the event. Any or all parameters may be null.
|
|
||||||
* @param type event type
|
|
||||||
* @param subType event sub-type
|
|
||||||
* @param addr program address affected
|
|
||||||
* @param affectedObj object that is the subject of the event
|
|
||||||
* @param oldValue original value or an Object that is related to
|
|
||||||
* the event
|
|
||||||
* @param newValue new value or an Object that is related to the
|
|
||||||
* the event
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setObjChanged(int type, int subType, Address addr, Object affectedObj,
|
public void setObjChanged(int type, int subType, Address addr, Object affectedObj,
|
||||||
Object oldValue, Object newValue) {
|
Object oldValue, Object newValue) {
|
||||||
|
@ -1167,17 +1090,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
new ProgramChangeRecord(type, subType, addr, addr, affectedObj, oldValue, newValue));
|
new ProgramChangeRecord(type, subType, addr, addr, affectedObj, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state of a Program as having changed and generate
|
|
||||||
* the event. Any or all parameters may be null.
|
|
||||||
* @param type event type
|
|
||||||
* @param addrSet set of program addresses affected
|
|
||||||
* @param affectedObj object that is the subject of the event
|
|
||||||
* @param oldValue original value or an Object that is related to
|
|
||||||
* the event
|
|
||||||
* @param newValue new value or an Object that is related to the
|
|
||||||
* the event
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setObjChanged(int type, AddressSetView addrSet, Object affectedObj, Object oldValue,
|
public void setObjChanged(int type, AddressSetView addrSet, Object affectedObj, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
|
@ -1188,9 +1100,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
fireEvent(new ProgramChangeRecord(type, null, null, affectedObj, oldValue, newValue));
|
fireEvent(new ProgramChangeRecord(type, null, null, affectedObj, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateChanges over range
|
|
||||||
*/
|
|
||||||
private void updateChangeSet(Address start, Address end) {
|
private void updateChangeSet(Address start, Address end) {
|
||||||
ProgramDBChangeSet pcs = (ProgramDBChangeSet) changeSet;
|
ProgramDBChangeSet pcs = (ProgramDBChangeSet) changeSet;
|
||||||
if (start != null) {
|
if (start != null) {
|
||||||
|
@ -1201,23 +1110,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method updateChanges over address set
|
|
||||||
*/
|
|
||||||
private void updateChangeSet(AddressSetView addrSet) {
|
private void updateChangeSet(AddressSetView addrSet) {
|
||||||
if (addrSet != null) {
|
if (addrSet != null) {
|
||||||
((ProgramDBChangeSet) changeSet).add(addrSet);
|
((ProgramDBChangeSet) changeSet).add(addrSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state of a Program as having changed and generate
|
|
||||||
* the DOCR_CODE_UNIT_PROPERTY_CHANGED event.
|
|
||||||
* @param propertyName
|
|
||||||
* @param codeUnitAddr address of the code unit with the property change
|
|
||||||
* @param oldValue old value for the property
|
|
||||||
* @param newValue new value for the property
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setPropertyChanged(String propertyName, Address codeUnitAddr, Object oldValue,
|
public void setPropertyChanged(String propertyName, Address codeUnitAddr, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
|
@ -1228,13 +1126,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
fireEvent(new CodeUnitPropertyChangeRecord(propertyName, codeUnitAddr, oldValue, newValue));
|
fireEvent(new CodeUnitPropertyChangeRecord(propertyName, codeUnitAddr, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the state of a Program as having changed and generate
|
|
||||||
* the DOCR_CODE_UNIT_PROPERTY_RANGE_REMOVED event.
|
|
||||||
* @param propertyName name of the property
|
|
||||||
* @param start start of range of the property being removed
|
|
||||||
* @param end end of the range of the property being removed
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setPropertyRangeRemoved(String propertyName, Address start, Address end) {
|
public void setPropertyRangeRemoved(String propertyName, Address start, Address end) {
|
||||||
if (recordChanges) {
|
if (recordChanges) {
|
||||||
|
@ -1244,25 +1135,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
fireEvent(new CodeUnitPropertyChangeRecord(propertyName, start, end));
|
fireEvent(new CodeUnitPropertyChangeRecord(propertyName, start, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify program of a user data change
|
|
||||||
* @param propertyName
|
|
||||||
* @param codeUnitAddr
|
|
||||||
* @param oldValue
|
|
||||||
* @param newValue
|
|
||||||
*/
|
|
||||||
void userDataChanged(String propertyName, Address codeUnitAddr, Object oldValue,
|
void userDataChanged(String propertyName, Address codeUnitAddr, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
// Do not update change set!
|
// Do not update change set!
|
||||||
fireEvent(new CodeUnitUserDataChangeRecord(propertyName, codeUnitAddr, oldValue, newValue));
|
fireEvent(new CodeUnitUserDataChangeRecord(propertyName, codeUnitAddr, oldValue, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notification of property change
|
|
||||||
* @param propertyName
|
|
||||||
* @param oldValue
|
|
||||||
* @param newValue
|
|
||||||
*/
|
|
||||||
protected void userDataChanged(String propertyName, Object oldValue, Object newValue) {
|
protected void userDataChanged(String propertyName, Object oldValue, Object newValue) {
|
||||||
fireEvent(new UserDataChangeRecord(propertyName, name, name));
|
fireEvent(new UserDataChangeRecord(propertyName, name, name));
|
||||||
}
|
}
|
||||||
|
@ -1309,6 +1187,9 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
* Creates a new OverlayAddressSpace with the given name and base AddressSpace
|
* Creates a new OverlayAddressSpace with the given name and base AddressSpace
|
||||||
* @param overlaySpaceName the name of the overlay space to create
|
* @param overlaySpaceName the name of the overlay space to create
|
||||||
* @param templateSpace the base AddressSpace to overlay
|
* @param templateSpace the base AddressSpace to overlay
|
||||||
|
* @param minOffset the min offset of the space
|
||||||
|
* @param maxOffset the max offset of the space
|
||||||
|
* @return the new space
|
||||||
* @throws DuplicateNameException if an AddressSpace already exists with the given name.
|
* @throws DuplicateNameException if an AddressSpace already exists with the given name.
|
||||||
* @throws LockException if the program is shared and not checked out exclusively.
|
* @throws LockException if the program is shared and not checked out exclusively.
|
||||||
* @throws MemoryConflictException if image base override is active
|
* @throws MemoryConflictException if image base override is active
|
||||||
|
@ -1526,8 +1407,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
* <li>LanguageMinorVersion</li>
|
* <li>LanguageMinorVersion</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* @param openMode program open mode
|
* @param openMode program open mode
|
||||||
* @return version exception if the current version is out of date and can be upgraded.
|
* @return version exception if the current version is out of date and can be upgraded
|
||||||
* @throws IOException
|
* @throws IOException if there is an exception at the database level
|
||||||
* @throws VersionException if the data is newer than this version of Ghidra and can not be
|
* @throws VersionException if the data is newer than this version of Ghidra and can not be
|
||||||
* upgraded or opened.
|
* upgraded or opened.
|
||||||
*/
|
*/
|
||||||
|
@ -1617,12 +1498,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
table.putRecord(record);
|
table.putRecord(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Perform more complex upgrades which require all language version translation to
|
* Perform more complex upgrades which require all language version translation to be completed
|
||||||
* be completed
|
|
||||||
* @param monitor
|
|
||||||
* @throws IOException
|
|
||||||
* @throws CancelledException
|
|
||||||
*/
|
*/
|
||||||
private void postUpgrade(int oldVersion, TaskMonitor monitor)
|
private void postUpgrade(int oldVersion, TaskMonitor monitor)
|
||||||
throws CancelledException, IOException {
|
throws CancelledException, IOException {
|
||||||
|
@ -1646,16 +1523,13 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
|
|
||||||
public int getStoredVersion() throws IOException {
|
public int getStoredVersion() throws IOException {
|
||||||
Record record = table.getRecord(new StringField(PROGRAM_DB_VERSION));
|
Record record = table.getRecord(new StringField(PROGRAM_DB_VERSION));
|
||||||
|
|
||||||
// DB Version was added in 2.1 release (27-May-04)
|
|
||||||
// if record does not exist return 1;
|
|
||||||
|
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
String s = record.getString(0);
|
String s = record.getString(0);
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(s);
|
return Integer.parseInt(s);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
|
// return 1 for invalid value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1705,12 +1579,10 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* External function pointers had previously been wrapped in a function. This should know be
|
* External function pointers had previously been wrapped in a function. This should know be
|
||||||
* handled by creating an external function which corresponds to the pointers external location
|
* handled by creating an external function which corresponds to the pointers external location
|
||||||
* reference.
|
* reference.
|
||||||
* @param monitor
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
private void checkFunctionWrappedPointers(TaskMonitor monitor)
|
private void checkFunctionWrappedPointers(TaskMonitor monitor)
|
||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
|
@ -1795,11 +1667,11 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
}
|
}
|
||||||
catch (VersionException e) {
|
catch (VersionException e) {
|
||||||
if (!e.isUpgradable()) {
|
if (!e.isUpgradable()) {
|
||||||
// Attempt to instatiate the old function manager which may be used for upgrades
|
// Attempt to instantiate the old function manager which may be used for upgrades
|
||||||
try {
|
try {
|
||||||
oldFunctionMgr = new OldFunctionManager(dbh, this, addrMap);
|
oldFunctionMgr = new OldFunctionManager(dbh, this, addrMap);
|
||||||
if (openMode != UPGRADE) {
|
if (openMode != UPGRADE) {
|
||||||
// Indicate that program is upgradeable
|
// Indicate that program is upgradable
|
||||||
oldFunctionMgr = null;
|
oldFunctionMgr = null;
|
||||||
versionExc = (new VersionException(true)).combine(versionExc);
|
versionExc = (new VersionException(true)).combine(versionExc);
|
||||||
}
|
}
|
||||||
|
@ -1810,6 +1682,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (VersionException e1) {
|
catch (VersionException e1) {
|
||||||
|
// TODO why does this happen? should we log this?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2058,12 +1931,14 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves all information stored in the given range to the new location.
|
* Moves all information stored in the given range to the new location
|
||||||
* @param fromAddr the first address in the range to be moved.
|
*
|
||||||
* @param toAddr the address to move to.
|
* @param fromAddr the first address in the range to be moved
|
||||||
* @param length the number of addresses to move.
|
* @param toAddr the address to move to
|
||||||
* @param monitor the task monitor to use while deleting information in the given range.
|
* @param length the number of addresses to move
|
||||||
* @throws RollbackException if the user cancelled the operation via the task monitor.
|
* @param monitor the task monitor to use while deleting information in the given range
|
||||||
|
* @throws AddressOverflowException if there is a problem moving address ranges
|
||||||
|
* @throws RollbackException if the user cancelled the operation via the task monitor
|
||||||
*/
|
*/
|
||||||
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
|
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
|
||||||
throws AddressOverflowException, RollbackException {
|
throws AddressOverflowException, RollbackException {
|
||||||
|
@ -2103,23 +1978,6 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
return globalNamespace;
|
return globalNamespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void updateCompilerSpec(Language currLanguage, CompilerSpecID currCompilerSpecID, TaskMonitor monitor) {
|
|
||||||
// try {
|
|
||||||
// compilerSpec = currLanguage.getCompilerSpecByID(currCompilerSpecID);
|
|
||||||
// if (compilerSpec == null) {
|
|
||||||
// throw new IllegalArgumentException("Language "
|
|
||||||
// + currLanguage.getLanguageDescription().getDescription()
|
|
||||||
// + " does not have a compiler spec " + currCompilerSpecID);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (CompilerSpecNotFoundException e) {
|
|
||||||
// throw new IllegalArgumentException("Language "
|
|
||||||
// + currLanguage.getLanguageDescription().getDescription()
|
|
||||||
// + " does not have a compiler spec " + currCompilerSpecID);
|
|
||||||
// }
|
|
||||||
// this.compilerSpecID = currCompilerSpecID;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLanguage(Language newLanguage, CompilerSpecID newCompilerSpecID,
|
public void setLanguage(Language newLanguage, CompilerSpecID newCompilerSpecID,
|
||||||
boolean forceRedisassembly, TaskMonitor monitor)
|
boolean forceRedisassembly, TaskMonitor monitor)
|
||||||
|
@ -2129,7 +1987,8 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LanguageTranslator languageTranslator =
|
LanguageTranslator languageTranslator =
|
||||||
LanguageTranslatorFactory.getLanguageTranslatorFactory().getLanguageTranslator(language,
|
LanguageTranslatorFactory.getLanguageTranslatorFactory()
|
||||||
|
.getLanguageTranslator(language,
|
||||||
newLanguage);
|
newLanguage);
|
||||||
if (languageTranslator == null) {
|
if (languageTranslator == null) {
|
||||||
throw new IncompatibleLanguageException("Language translation not supported");
|
throw new IncompatibleLanguageException("Language translation not supported");
|
||||||
|
@ -2255,13 +2114,9 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Repair damaged context prior to language upgrade.
|
* Repair damaged context prior to language upgrade. It is assumed that the context has
|
||||||
* It is assumed that the context has already been upgrade and that the original
|
* already been upgrade and that the original prototypes and instructions are still intact.
|
||||||
* prototypes and instructions are still intact.
|
|
||||||
* @param translator optional language translator
|
|
||||||
* @param monitor
|
|
||||||
* @throws CancelledException
|
|
||||||
*/
|
*/
|
||||||
private void repairContext(int oldLanguageVersion, int oldLanguageMinorVersion,
|
private void repairContext(int oldLanguageVersion, int oldLanguageMinorVersion,
|
||||||
LanguageTranslator translator, TaskMonitor monitor) throws CancelledException {
|
LanguageTranslator translator, TaskMonitor monitor) throws CancelledException {
|
||||||
|
@ -2271,15 +2126,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Repair damaged ARM/THUMB context prior to language upgrade. With the release of Ghidra 5.2
|
* Repair damaged ARM/THUMB context prior to language upgrade. With the release of Ghidra 5.2
|
||||||
* (which corresponds to the ARM language version of 1.6) the stored context register
|
* (which corresponds to the ARM language version of 1.6) the stored context register
|
||||||
* value is write-protected where instructions exist.
|
* value is write-protected where instructions exist.
|
||||||
* It is assumed that the context has already been upgrade and that the original
|
* It is assumed that the context has already been upgrade and that the original
|
||||||
* prototypes and instructions are still intact.
|
* prototypes and instructions are still intact.
|
||||||
* @param translator optional language translator
|
|
||||||
* @param monitor
|
|
||||||
* @throws CancelledException
|
|
||||||
*/
|
*/
|
||||||
private void repairARMContext(int oldLanguageVersion, int oldLanguageMinorVersion,
|
private void repairARMContext(int oldLanguageVersion, int oldLanguageMinorVersion,
|
||||||
LanguageTranslator translator, TaskMonitor monitor) throws CancelledException {
|
LanguageTranslator translator, TaskMonitor monitor) throws CancelledException {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue