diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java index 4469d7288c..f019ae5e88 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FieldFormatModel.java @@ -16,6 +16,7 @@ package ghidra.app.util.viewer.format; import java.util.*; +import java.util.stream.Collectors; import org.jdom2.Element; @@ -283,6 +284,13 @@ public class FieldFormatModel { } } + @Override + public String toString() { + return name + ":\n" + Arrays.stream(factories) + .map(f -> f.getClass().getSimpleName()) + .collect(Collectors.joining(",\n")); + } + /** * Saves this format to XML. * @return the XML element for the saved format @@ -324,10 +332,11 @@ public class FieldFormatModel { */ public void restoreFromXml(Element root) { List> list = root.getChildren("ROW"); - Iterator> rowIter = list.iterator(); - rows = new ArrayList<>(list.size()); - while (rowIter.hasNext()) { - Row row = createRow((Element) rowIter.next()); + Iterator> it = list.iterator(); + rows = new ArrayList<>(); + while (it.hasNext()) { + Element element = (Element) it.next(); + Row row = createRow(element); rows.add(row); } findWidth(); @@ -462,6 +471,7 @@ public class FieldFormatModel { row.fieldOptionsChanged(options, optionName, oldValue, newValue); } } + //================================================================================================== //Inner Classes //================================================================================================== @@ -564,6 +574,8 @@ class Row { @Override public String toString() { - return fields.toString(); + return fields.stream() + .map(f -> f.getClass().getSimpleName()) + .collect(Collectors.joining(",")); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java index 1d91e86858..10f47a33e7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/format/FormatManager.java @@ -116,7 +116,7 @@ public class FormatManager implements OptionsChangeListener { FormatManager newManager = new FormatManager(displayOptions, fieldOptions); SaveState saveState = new SaveState(); saveState(saveState); - newManager.readState(saveState); + newManager.readState(saveState, false); return newManager; } @@ -961,7 +961,10 @@ public class FormatManager implements OptionsChangeListener { */ public void saveState(SaveState saveState) { for (int i = 0; i < NUM_MODELS; i++) { - saveState.putXmlElement(models[i].getName(), models[i].saveToXml()); + FieldFormatModel model = models[i]; + String name = model.getName(); + Element element = model.saveToXml(); + saveState.putXmlElement(name, element); } } @@ -972,16 +975,30 @@ public class FormatManager implements OptionsChangeListener { * @param saveState the SaveState to read from. */ public void readState(SaveState saveState) { + readState(saveState, true); + } + + // Note: only for clients that manage their own exact formats; remove when + // checkForMissingNewCriticalFields() gets removed + @Deprecated(since = "12.2", forRemoval = true) + public void readState(SaveState saveState, boolean checkForMissingFields) { initialized = false; for (int i = 0; i < NUM_MODELS; i++) { - if (saveState.hasValue(models[i].getName())) { - models[i].restoreFromXml(saveState.getXmlElement(models[i].getName())); - // hack to make sure the new open/close variables field is present - // If missing, we are just going to reset it to the default format - checkForMissingNewCriticalFields(models[i]); + FieldFormatModel model = models[i]; + String name = model.getName(); + if (!saveState.hasValue(name)) { + Element element = getDefaultModel(i); + model.restoreFromXml(element); + continue; } - else { - models[i].restoreFromXml(getDefaultModel(i)); + + Element element = saveState.getXmlElement(name); + model.restoreFromXml(element); + + if (checkForMissingFields) { + // Hack to make sure the new open/close variables field is present. If missing, we + // are just going to reset it to the default format + checkForMissingNewCriticalFields(model); } } initialized = true; @@ -993,17 +1010,20 @@ public class FormatManager implements OptionsChangeListener { private void checkForMissingNewCriticalFields(FieldFormatModel model) { if (model.getName().equals("Variable")) { if (!hasField(model, "+")) { - model.restoreFromXml(getDefaultVariableFormat()); + Element element = getDefaultVariableFormat(); + model.restoreFromXml(element); } } if (model.getName().equals("Function")) { if (!hasField(model, "+")) { - model.restoreFromXml(getDefaultFunctionFormat()); + Element element = getDefaultFunctionFormat(); + model.restoreFromXml(element); } } if (model.getName().equals("Address Break")) { if (!hasField(model, "Collapsed Code")) { - model.restoreFromXml(getDefaultDividerFormat()); + Element element = getDefaultDividerFormat(); + model.restoreFromXml(element); } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/listing/ListingCodeComparisonView.java b/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/listing/ListingCodeComparisonView.java index 393750701b..f916d5748a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/listing/ListingCodeComparisonView.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/features/base/codecompare/listing/ListingCodeComparisonView.java @@ -177,7 +177,7 @@ public class ListingCodeComparisonView private void changeRightToMatchLeftFormat(FieldFormatModel model) { SaveState formatState = new SaveState(); displays.get(LEFT).getFormatManager().saveState(formatState); - displays.get(RIGHT).getFormatManager().readState(formatState); + displays.get(RIGHT).getFormatManager().readState(formatState, false); saveFormat(saveState); tool.setConfigChanged(true); diff --git a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/FunctionGraphCodeComparisonView.java b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/FunctionGraphCodeComparisonView.java index 579a054ab5..ea1bd8fe26 100644 --- a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/FunctionGraphCodeComparisonView.java +++ b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/functiongraph/FunctionGraphCodeComparisonView.java @@ -259,7 +259,7 @@ public class FunctionGraphCodeComparisonView extends CodeComparisonView { } FormatManager formatManager = new FormatManager(displayOptions, fieldOptions); - formatManager.readState(formatState); + formatManager.readState(formatState, false); leftController.updateMinimalFormatManager(formatManager); FgDisplay rightDisplay = displays.get(Side.RIGHT); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java index 6cb20d3354..b6ffe7914e 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FunctionGraphPlugin.java @@ -415,7 +415,7 @@ public class FunctionGraphPlugin extends ProgramPlugin ToolOptions fieldOptions = options.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS); userDefinedFormatManager = new FormatManager(displayOptions, fieldOptions); SaveState formatState = new SaveState(formatElement); - userDefinedFormatManager.readState(formatState); + userDefinedFormatManager.readState(formatState, false); connectedProvider.formatChanged(); } diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/SetFormatDialogComponentProvider.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/SetFormatDialogComponentProvider.java index 0a318b715a..ed37e6515e 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/SetFormatDialogComponentProvider.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/SetFormatDialogComponentProvider.java @@ -33,6 +33,8 @@ import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.AddressSetView; import ghidra.program.model.listing.Program; +import ghidra.util.Msg; +import ghidra.util.xml.XmlUtilities; public class SetFormatDialogComponentProvider extends DialogComponentProvider { @@ -164,7 +166,7 @@ public class SetFormatDialogComponentProvider extends DialogComponentProvider { // update the dialog's GUI (which will later be used as the new format if the // user presses OK) - listingFormatManager.readState(saveState); + listingFormatManager.readState(saveState, false); } } @@ -189,6 +191,8 @@ public class SetFormatDialogComponentProvider extends DialogComponentProvider { FieldFormatModel originalModel = defaultFormatManager.getModel(index); Element originalXML = originalModel.saveToXml(); + Msg.debug(this, XmlUtilities.toString(originalXML)); + // update the dialog's GUI (which will later be used as the new format if the // user presses OK) FormatManager listingFormatManager = listingPanel.getFormatManager(); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java index 045c1f47e5..cb5413f84c 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/mvc/FGController.java @@ -153,6 +153,14 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi } + /** + * The minimal format manager can also be called the 'user' format manager. We have a full + * format manager that the user cannot change. We also have a default format manager that the + * user cannot change. The minimal format manager can be updated by the user. + * + *
Even stranger, the minimal starts out as the default format. + * @return the minimal format + */ public FormatManager getMinimalFormatManager() { if (minimalFormatManager == null) { setMinimalFormatManager(createMinimalFormatManager()); @@ -173,7 +181,7 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi SaveState saveState = new SaveState(); newFormatManager.saveState(saveState); - minimalFormatManager.readState(saveState); + minimalFormatManager.readState(saveState, false); env.setUserDefinedFormat(minimalFormatManager); view.repaint(); }