Merge remote-tracking branch 'origin/GP-1-dragonmacher-escape-confirmation'

This commit is contained in:
Ryan Kurtz 2025-04-21 14:12:54 -04:00
commit a810c384f4
11 changed files with 227 additions and 64 deletions

View file

@ -65,7 +65,6 @@ public class CreateInternalStructureAction extends CompositeEditorTableAction {
createStructure(); createStructure();
} }
requestTableFocus();
Swing.runLater(() -> { Swing.runLater(() -> {
provider.toFront(); provider.toFront();
provider.requestFocus(); provider.requestFocus();

View file

@ -32,7 +32,7 @@ public class AllHistoryAction extends ListingContextAction {
super("Show All History", owner); super("Show All History", owner);
this.tool = tool; this.tool = tool;
setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_SEARCH, "Label History..." }, setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_SEARCH, "Label History..." },
null, "Search")); null, "search 1"));
setKeyBindingData(new KeyBindingData(KeyEvent.VK_H, 0)); setKeyBindingData(new KeyBindingData(KeyEvent.VK_H, 0));
addToWindowWhen(ListingActionContext.class); addToWindowWhen(ListingActionContext.class);

View file

@ -43,6 +43,10 @@ public enum Combiner {
this.function = function; this.function = function;
} }
public boolean isMerge() {
return this != REPLACE;
}
public String getName() { public String getName() {
return name; return name;
} }

View file

@ -249,8 +249,9 @@ public class MemoryMatchTableModel extends AddressBasedTableModel<MemoryMatch> {
byteString = HTMLUtilities.colorString(color, byteString); byteString = HTMLUtilities.colorString(color, byteString);
} }
b.append(byteString); b.append(byteString);
if (i == max) if (i == max) {
break; break;
}
b.append(" "); b.append(" ");
} }

View file

@ -274,6 +274,10 @@ class MemorySearchControlPanel extends JPanel {
searchButton.setSelectedStateByClientData(combiner); searchButton.setSelectedStateByClientData(combiner);
} }
void setSearchCombiner(Combiner combiner) {
searchButton.setSelectedStateByClientData(combiner);
}
private void adjustLocationForCaretPosition(Point location) { private void adjustLocationForCaretPosition(Point location) {
JTextField textField = searchInputField.getTextField(); JTextField textField = searchInputField.getTextField();
Caret caret = textField.getCaret(); Caret caret = textField.getCaret();
@ -460,5 +464,4 @@ class MemorySearchControlPanel extends JPanel {
Component getDefaultFocusComponent() { Component getDefaultFocusComponent() {
return searchInputField; return searchInputField;
} }
} }

View file

@ -149,6 +149,7 @@ public class MemorySearchPlugin extends Plugin implements MemorySearchService {
saveState.putBoolean(SHOW_OPTIONS_PANEL, showOptionsPanel); saveState.putBoolean(SHOW_OPTIONS_PANEL, showOptionsPanel);
saveState.putBoolean(SHOW_SCAN_PANEL, showOptionsPanel); saveState.putBoolean(SHOW_SCAN_PANEL, showOptionsPanel);
} }
//================================================================================================== //==================================================================================================
// MemorySearchService methods // MemorySearchService methods
//================================================================================================== //==================================================================================================
@ -205,10 +206,9 @@ public class MemorySearchPlugin extends Plugin implements MemorySearchService {
Msg.showWarn(this, null, "Search Failed!", "No valid start address!"); Msg.showWarn(this, null, "Search Failed!", "No valid start address!");
return; return;
} }
MemorySearcher searcher = new MemorySearcher(source, lastByteMatcher, addresses, 1); MemorySearcher searcher = new MemorySearcher(source, lastByteMatcher, addresses, 1);
MemoryMatch match = searcher.findOnce(start, forward, monitor); MemoryMatch match = searcher.findOnce(start, forward, monitor);
Swing.runLater(() -> navigateToMatch(match)); Swing.runLater(() -> navigateToMatch(match));
} }

View file

@ -31,6 +31,8 @@ import docking.action.ToggleDockingAction;
import docking.action.builder.ActionBuilder; import docking.action.builder.ActionBuilder;
import docking.action.builder.ToggleActionBuilder; import docking.action.builder.ToggleActionBuilder;
import docking.util.GGlassPaneMessage; import docking.util.GGlassPaneMessage;
import docking.widgets.OptionDialog;
import docking.widgets.OptionDialogBuilder;
import generic.theme.GIcon; import generic.theme.GIcon;
import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.NavigatableActionContext;
import ghidra.app.nav.Navigatable; import ghidra.app.nav.Navigatable;
@ -38,6 +40,7 @@ import ghidra.app.nav.NavigatableRemovalListener;
import ghidra.app.util.HelpTopics; import ghidra.app.util.HelpTopics;
import ghidra.features.base.memsearch.bytesource.AddressableByteSource; import ghidra.features.base.memsearch.bytesource.AddressableByteSource;
import ghidra.features.base.memsearch.bytesource.SearchRegion; import ghidra.features.base.memsearch.bytesource.SearchRegion;
import ghidra.features.base.memsearch.combiner.Combiner;
import ghidra.features.base.memsearch.matcher.ByteMatcher; import ghidra.features.base.memsearch.matcher.ByteMatcher;
import ghidra.features.base.memsearch.scan.Scanner; import ghidra.features.base.memsearch.scan.Scanner;
import ghidra.features.base.memsearch.searcher.*; import ghidra.features.base.memsearch.searcher.*;
@ -145,7 +148,6 @@ public class MemorySearchProvider extends ComponentProviderAdapter
navigatable.addNavigatableListener(this); navigatable.addNavigatableListener(this);
program.addCloseListener(this); program.addCloseListener(this);
updateTitle(); updateTitle();
} }
public void setSearchInput(String input) { public void setSearchInput(String input) {
@ -539,9 +541,43 @@ public class MemorySearchProvider extends ComponentProviderAdapter
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
super.actionPerformed(context); super.actionPerformed(context);
updateSubTitle(); updateSubTitle();
resultsPanel.itemDeleted();
} }
}); });
}
@Override
public void closeComponent() {
doClose(false);
}
private void doClose(boolean force) {
if (force) {
super.closeComponent();
return;
}
if (!canClose()) {
return;
}
super.closeComponent();
}
private boolean canClose() {
boolean hasUserChanges = resultsPanel.hasUserChanges();
if (!hasUserChanges) {
return true;
}
String message = "Close dialog and lost custom search results?";
OptionDialogBuilder builder = new OptionDialogBuilder("Close Results Window?", message);
int choice = builder.addOption("Yes")
.addCancel()
.setDefaultButton("Yes")
.setMessageType(OptionDialog.QUESTION_MESSAGE)
.show(resultsPanel);
return choice == OptionDialog.OPTION_ONE;
} }
@Override @Override
@ -551,6 +587,7 @@ public class MemorySearchProvider extends ComponentProviderAdapter
} }
private void dispose() { private void dispose() {
if (glassPaneMessage != null) { if (glassPaneMessage != null) {
glassPaneMessage.hide(); glassPaneMessage.hide();
glassPaneMessage = null; glassPaneMessage = null;
@ -583,12 +620,12 @@ public class MemorySearchProvider extends ComponentProviderAdapter
@Override @Override
public void navigatableRemoved(Navigatable nav) { public void navigatableRemoved(Navigatable nav) {
closeComponent(); doClose(true);
} }
@Override @Override
public void domainObjectClosed(DomainObject dobj) { public void domainObjectClosed(DomainObject dobj) {
closeComponent(); doClose(true);
} }
Navigatable getNavigatable() { Navigatable getNavigatable() {
@ -638,12 +675,20 @@ public class MemorySearchProvider extends ComponentProviderAdapter
return resultsPanel.getTableModel().getModelData(); return resultsPanel.getTableModel().getModelData();
} }
public MemorySearchResultsPanel getResultsPanel() {
return resultsPanel;
}
public void setSettings(SearchSettings settings) { public void setSettings(SearchSettings settings) {
String converted = searchPanel.convertInput(model.getSettings(), settings); String converted = searchPanel.convertInput(model.getSettings(), settings);
model.setSettings(settings); model.setSettings(settings);
searchPanel.setSearchInput(converted); searchPanel.setSearchInput(converted);
} }
public void setSearchCombiner(Combiner combiner) {
searchPanel.setSearchCombiner(combiner);
}
public boolean isSearchSelection() { public boolean isSearchSelection() {
return model.isSearchSelectionOnly(); return model.isSearchSelectionOnly();
} }

View file

@ -41,7 +41,7 @@ import ghidra.util.task.*;
* in a table. This panel also includes most of the search logic as it has direct access to the * in a table. This panel also includes most of the search logic as it has direct access to the
* table for showing the results. * table for showing the results.
*/ */
class MemorySearchResultsPanel extends JPanel { public class MemorySearchResultsPanel extends JPanel {
private GhidraThreadedTablePanel<MemoryMatch> threadedTablePanel; private GhidraThreadedTablePanel<MemoryMatch> threadedTablePanel;
private GhidraTableFilterPanel<MemoryMatch> tableFilterPanel; private GhidraTableFilterPanel<MemoryMatch> tableFilterPanel;
private GhidraTable table; private GhidraTable table;
@ -49,6 +49,9 @@ class MemorySearchResultsPanel extends JPanel {
private MemorySearchProvider provider; private MemorySearchProvider provider;
private SearchMarkers markers; private SearchMarkers markers;
private boolean hasDeleted;
private boolean hasCombined;
MemorySearchResultsPanel(MemorySearchProvider provider, SearchMarkers markers) { MemorySearchResultsPanel(MemorySearchProvider provider, SearchMarkers markers) {
super(new BorderLayout()); super(new BorderLayout());
this.provider = provider; this.provider = provider;
@ -73,6 +76,14 @@ class MemorySearchResultsPanel extends JPanel {
markers.loadMarkers(provider.getTitle(), tableModel.getModelData()); markers.loadMarkers(provider.getTitle(), tableModel.getModelData());
} }
void itemDeleted() {
hasDeleted = true;
}
boolean hasUserChanges() {
return hasDeleted || hasCombined;
}
void providerActivated() { void providerActivated() {
markers.makeActiveMarkerSet(); markers.makeActiveMarkerSet();
} }
@ -109,7 +120,13 @@ class MemorySearchResultsPanel extends JPanel {
} }
private MemoryMatchTableLoader createLoader(MemorySearcher searcher, Combiner combiner) { private MemoryMatchTableLoader createLoader(MemorySearcher searcher, Combiner combiner) {
if (hasResults()) { if (!hasResults()) {
hasDeleted = false;
return new NewSearchTableLoader(searcher);
}
// We have existing results. Will they be merged?
if (combiner.isMerge()) {
// If we have existing results, the combiner determines how the new search results get // If we have existing results, the combiner determines how the new search results get
// combined with the existing results. // combined with the existing results.
@ -118,11 +135,14 @@ class MemorySearchResultsPanel extends JPanel {
// and only the new results are kept. In this case, it is preferred to use the same // and only the new results are kept. In this case, it is preferred to use the same
// loader as if doing an initial search because you get incremental loading and also // loader as if doing an initial search because you get incremental loading and also
// don't need to copy the existing results to feed to a combiner. // don't need to copy the existing results to feed to a combiner.
if (combiner != Combiner.REPLACE) { hasCombined = true;
List<MemoryMatch> previousResults = tableModel.getModelData(); List<MemoryMatch> previousResults = tableModel.getModelData();
return new CombinedMatchTableLoader(searcher, previousResults, combiner); return new CombinedMatchTableLoader(searcher, previousResults, combiner);
} }
}
// We have results, but we are going to replace them. A new load of data means any previous
// manual deletes are now irrelevant
hasDeleted = false;
return new NewSearchTableLoader(searcher); return new NewSearchTableLoader(searcher);
} }
@ -146,7 +166,7 @@ class MemorySearchResultsPanel extends JPanel {
} }
} }
GhidraTable getTable() { public GhidraTable getTable() {
return table; return table;
} }

View file

@ -24,12 +24,17 @@ import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import docking.action.DockingActionIf;
import docking.widgets.OptionDialog;
import docking.widgets.fieldpanel.support.Highlight; import docking.widgets.fieldpanel.support.Highlight;
import docking.widgets.table.GTable;
import ghidra.GhidraOptions; import ghidra.GhidraOptions;
import ghidra.app.services.MarkerSet; import ghidra.app.services.MarkerSet;
import ghidra.app.util.viewer.field.BytesFieldFactory; import ghidra.app.util.viewer.field.BytesFieldFactory;
import ghidra.features.base.memsearch.bytesource.ProgramSearchRegion; import ghidra.features.base.memsearch.bytesource.ProgramSearchRegion;
import ghidra.features.base.memsearch.combiner.Combiner;
import ghidra.features.base.memsearch.format.SearchFormat; import ghidra.features.base.memsearch.format.SearchFormat;
import ghidra.features.base.memsearch.gui.MemorySearchResultsPanel;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@ -259,15 +264,13 @@ public class MemSearchHexTest extends AbstractMemSearchTest {
@Test @Test
public void testHexSearchAll2() throws Exception { public void testHexSearchAll2() throws Exception {
// enter search string for multiple byte match
// enter search string for multiple byte match
setInput("ff 15"); setInput("ff 15");
performSearchAll(); performSearchAll();
waitForSearch(5); waitForSearch(5);
List<Address> addrs = addrs(0x01002d1f, 0x01002d41, 0x01002d4a, 0x01002d5e, 0x010029bd); List<Address> addrs = addrs(0x01002d1f, 0x01002d41, 0x01002d4a, 0x01002d5e, 0x010029bd);
checkMarkerSet(addrs); checkMarkerSet(addrs);
} }
@ -552,4 +555,113 @@ public class MemSearchHexTest extends AbstractMemSearchTest {
assertEquals(addr(0x01002d0b), currentAddress()); assertEquals(addr(0x01002d0b), currentAddress());
} }
@Test
public void testPromptToClose_NoChanges() {
search("ff 15", 5);
triggerEscape(searchProvider.getComponent());
assertProviderClosed();
}
@Test
public void testPromptToClose_DeletedRows() {
search("ff 15", 5);
deleteRow(0);
triggerEscape(searchProvider.getComponent());
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
pressButtonByText(dialog, "Yes");
assertProviderClosed();
}
@Test
public void testPromptToClose_DeletedRows_Cancel() {
search("ff 15", 5);
deleteRow(0);
triggerEscape(searchProvider.getComponent());
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
pressButtonByText(dialog, "No");
assertProviderVisible();
}
@Test
public void testPromptToClose_MergedData() {
//
// Search then perform a new search that will be combined with the initial search results.
// This new merged search will trigger the requirement to prompt the user before closing,
// since the new set of data is non-trivial to create.
//
search("ff 15", 5);
// perform a new search and use the existing results
runSwing(() -> searchProvider.setSearchCombiner(Combiner.UNION));
search("8b f?", 9);
triggerEscape(searchProvider.getComponent());
OptionDialog confirmDialog = waitForDialogComponent(OptionDialog.class);
pressButtonByText(confirmDialog, "Yes");
assertProviderClosed();
}
@Test
public void testPromptToClose_DeletedRows_NewSearch() {
//
// Search. Delete a row. This would trigger a prompt when closing the dialog. Perform a
// new search. This new non-merged search will clear the requirement to prompt the user
// before closing.
//
search("ff 15", 5);
deleteRow(0);
search("8b f?", 4);
triggerEscape(searchProvider.getComponent());
assertProviderClosed();
}
private void assertProviderVisible() {
assertTrue(runSwing(() -> searchProvider.isVisible()));
}
private void assertProviderClosed() {
assertFalse(runSwing(() -> searchProvider.isVisible()));
}
private void search(String input, int expectedMatchCount) {
setInput(input);
performSearchAll();
waitForSearch(expectedMatchCount);
}
private void deleteRow(int row) {
int resultCount = getResultCount();
runSwing(() -> {
MemorySearchResultsPanel panel = searchProvider.getResultsPanel();
GTable table = panel.getTable();
table.selectRow(row);
});
DockingActionIf removeAction = getAction(memorySearchPlugin, "Remove Items");
performAction(removeAction);
assertEquals(resultCount - 1, getResultCount());
}
private int getResultCount() {
return runSwing(() -> searchProvider.getSearchResults().size());
}
} }

View file

@ -22,11 +22,9 @@ import java.awt.Window;
import org.junit.*; import org.junit.*;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.marker.MarkerManagerPlugin; import ghidra.app.plugin.core.marker.MarkerManagerPlugin;
import ghidra.app.plugin.core.programtree.ProgramTreePlugin; import ghidra.app.plugin.core.programtree.ProgramTreePlugin;
import ghidra.app.services.ProgramManager;
import ghidra.features.base.memsearch.gui.MemorySearchPlugin; import ghidra.features.base.memsearch.gui.MemorySearchPlugin;
import ghidra.features.base.memsearch.gui.MemorySearchProvider; import ghidra.features.base.memsearch.gui.MemorySearchProvider;
import ghidra.features.base.memsearch.mnemonic.MnemonicSearchPlugin; import ghidra.features.base.memsearch.mnemonic.MnemonicSearchPlugin;
@ -35,7 +33,6 @@ import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramSelection;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.TestEnv; import ghidra.test.TestEnv;
import ghidra.util.Swing; import ghidra.util.Swing;
@ -45,9 +42,9 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
private PluginTool tool; private PluginTool tool;
private ProgramDB program; private ProgramDB program;
private MnemonicSearchPlugin plugin; private MnemonicSearchPlugin plugin;
private DockingActionIf searchMnemonicOperandsNoConstAction; private DockingActionIf includeOperandsExcludeConstAction;
private DockingActionIf searchMnemonicNoOperandsNoConstAction; private DockingActionIf excludeOperandsAction;
private DockingActionIf searchMnemonicOperandsConstAction; private DockingActionIf includeOperandsAction;
private CodeBrowserPlugin cb; private CodeBrowserPlugin cb;
private MemorySearchProvider searchProvider; private MemorySearchProvider searchProvider;
@ -63,16 +60,12 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
plugin = env.getPlugin(MnemonicSearchPlugin.class); plugin = env.getPlugin(MnemonicSearchPlugin.class);
cb = env.getPlugin(CodeBrowserPlugin.class); cb = env.getPlugin(CodeBrowserPlugin.class);
program = (ProgramDB) buildProgram(); program = (ProgramDB) buildProgram();
env.showTool(program);
ProgramManager pm = tool.getService(ProgramManager.class); excludeOperandsAction = getAction(plugin, "Exclude Operands");
pm.openProgram(program.getDomainFile()); includeOperandsAction = getAction(plugin, "Include Operands");
includeOperandsExcludeConstAction =
searchMnemonicOperandsNoConstAction =
getAction(plugin, "Include Operands (except constants)"); getAction(plugin, "Include Operands (except constants)");
searchMnemonicNoOperandsNoConstAction = getAction(plugin, "Exclude Operands");
searchMnemonicOperandsConstAction = getAction(plugin, "Include Operands");
env.showTool();
} }
private Program buildProgram() throws Exception { private Program buildProgram() throws Exception {
@ -93,29 +86,19 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
@Test @Test
public void testSearchMnemonicOperandsNoConst() { public void testSearchMnemonicOperandsNoConst() {
ProgramSelection sel = new ProgramSelection(addr(0x01004062), addr(0x0100406a)); makeSelection(tool, program, addr(0x01004062), addr(0x0100406a));
tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", sel, program)); performAction(includeOperandsExcludeConstAction, cb.getProvider(), true);
performAction(searchMnemonicOperandsNoConstAction, cb.getProvider(), true);
searchProvider = waitForComponentProvider(MemorySearchProvider.class); searchProvider = waitForComponentProvider(MemorySearchProvider.class);
assertNotNull(searchProvider);
assertEquals( assertEquals(
"01010101 10001011 11101100 10000001 11101100 ........ ........ ........ ........", "01010101 10001011 11101100 10000001 11101100 ........ ........ ........ ........",
getInput()); getInput());
} }
@Test @Test
public void testSearchMnemonicNoOperandsNoConst() { public void testSearchMnemonicNoOperandsNoConst() {
ProgramSelection sel = new ProgramSelection(addr(0x01004062), addr(0x0100406a)); makeSelection(tool, program, addr(0x01004062), addr(0x0100406a));
tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", sel, program)); performAction(excludeOperandsAction, cb.getProvider(), true);
performAction(searchMnemonicNoOperandsNoConstAction, cb.getProvider(), true);
searchProvider = waitForComponentProvider(MemorySearchProvider.class); searchProvider = waitForComponentProvider(MemorySearchProvider.class);
assertNotNull(searchProvider);
assertEquals( assertEquals(
"01010... 10001011 11...... 10000001 11101... ........ ........ ........ ........", "01010... 10001011 11...... 10000001 11101... ........ ........ ........ ........",
getInput()); getInput());
@ -124,16 +107,10 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
@Test @Test
public void testSearchMnemonicOperandsConst() { public void testSearchMnemonicOperandsConst() {
ProgramSelection sel = new ProgramSelection(addr(0x01004062), addr(0x0100406a));
tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", sel, program));
performAction(searchMnemonicOperandsConstAction, cb.getProvider(), true);
performAction(searchMnemonicOperandsConstAction, cb.getProvider(), true);
makeSelection(tool, program, addr(0x01004062), addr(0x0100406a));
performAction(includeOperandsAction, cb.getProvider(), true);
searchProvider = waitForComponentProvider(MemorySearchProvider.class); searchProvider = waitForComponentProvider(MemorySearchProvider.class);
assertNotNull(searchProvider);
assertEquals( assertEquals(
"01010101 10001011 11101100 10000001 11101100 00000100 00000001 00000000 00000000", "01010101 10001011 11101100 10000001 11101100 00000100 00000001 00000000 00000000",
getInput()); getInput());
@ -142,7 +119,6 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
/** /**
* Tests that when multiple regions are selected, the user is notified via * Tests that when multiple regions are selected, the user is notified via
* pop-up that this is not acceptable. * pop-up that this is not acceptable.
*
*/ */
@Test @Test
public void testMultipleSelection() { public void testMultipleSelection() {
@ -158,7 +134,7 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
makeSelection(tool, program, addrSet); makeSelection(tool, program, addrSet);
// Now invoke the menu option we want to test. // Now invoke the menu option we want to test.
performAction(searchMnemonicOperandsConstAction, cb.getProvider(), false); performAction(includeOperandsAction, cb.getProvider(), false);
// Here's the main assert: If the code recognizes that we have multiple selection, the // Here's the main assert: If the code recognizes that we have multiple selection, the
// MemSearchDialog will NOT be displayed (an error message pops up instead). So verify that // MemSearchDialog will NOT be displayed (an error message pops up instead). So verify that
@ -172,7 +148,7 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
return program.getMinAddress().getNewAddress(offset); return program.getMinAddress().getNewAddress(offset);
} }
protected String getInput() { private String getInput() {
return Swing.runNow(() -> searchProvider.getSearchInput()); return Swing.runNow(() -> searchProvider.getSearchInput());
} }
} }

View file

@ -76,8 +76,11 @@ public class ProjectDataDeleteAction extends FrontendProjectTreeAction {
String message = getMessage(fileCount, files); String message = getMessage(fileCount, files);
OptionDialogBuilder builder = new OptionDialogBuilder("Confirm Delete", message); OptionDialogBuilder builder = new OptionDialogBuilder("Confirm Delete", message);
builder.addOption("OK").addCancel().setMessageType(OptionDialog.QUESTION_MESSAGE); int choice = builder.addOption("OK")
return builder.show(parent) != OptionDialog.CANCEL_OPTION; .addCancel()
.setMessageType(OptionDialog.QUESTION_MESSAGE)
.show(parent);
return choice != OptionDialog.CANCEL_OPTION;
} }
private String getMessage(int fileCount, Set<DomainFile> selectedFiles) { private String getMessage(int fileCount, Set<DomainFile> selectedFiles) {