mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-1-dragonmacher-escape-confirmation'
This commit is contained in:
commit
a810c384f4
11 changed files with 227 additions and 64 deletions
|
@ -65,7 +65,6 @@ public class CreateInternalStructureAction extends CompositeEditorTableAction {
|
|||
createStructure();
|
||||
}
|
||||
|
||||
requestTableFocus();
|
||||
Swing.runLater(() -> {
|
||||
provider.toFront();
|
||||
provider.requestFocus();
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -32,7 +32,7 @@ public class AllHistoryAction extends ListingContextAction {
|
|||
super("Show All History", owner);
|
||||
this.tool = tool;
|
||||
setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_SEARCH, "Label History..." },
|
||||
null, "Search"));
|
||||
null, "search 1"));
|
||||
|
||||
setKeyBindingData(new KeyBindingData(KeyEvent.VK_H, 0));
|
||||
addToWindowWhen(ListingActionContext.class);
|
||||
|
|
|
@ -43,6 +43,10 @@ public enum Combiner {
|
|||
this.function = function;
|
||||
}
|
||||
|
||||
public boolean isMerge() {
|
||||
return this != REPLACE;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -249,8 +249,9 @@ public class MemoryMatchTableModel extends AddressBasedTableModel<MemoryMatch> {
|
|||
byteString = HTMLUtilities.colorString(color, byteString);
|
||||
}
|
||||
b.append(byteString);
|
||||
if (i == max)
|
||||
if (i == max) {
|
||||
break;
|
||||
}
|
||||
b.append(" ");
|
||||
}
|
||||
|
||||
|
|
|
@ -274,6 +274,10 @@ class MemorySearchControlPanel extends JPanel {
|
|||
searchButton.setSelectedStateByClientData(combiner);
|
||||
}
|
||||
|
||||
void setSearchCombiner(Combiner combiner) {
|
||||
searchButton.setSelectedStateByClientData(combiner);
|
||||
}
|
||||
|
||||
private void adjustLocationForCaretPosition(Point location) {
|
||||
JTextField textField = searchInputField.getTextField();
|
||||
Caret caret = textField.getCaret();
|
||||
|
@ -460,5 +464,4 @@ class MemorySearchControlPanel extends JPanel {
|
|||
Component getDefaultFocusComponent() {
|
||||
return searchInputField;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -149,6 +149,7 @@ public class MemorySearchPlugin extends Plugin implements MemorySearchService {
|
|||
saveState.putBoolean(SHOW_OPTIONS_PANEL, showOptionsPanel);
|
||||
saveState.putBoolean(SHOW_SCAN_PANEL, showOptionsPanel);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// MemorySearchService methods
|
||||
//==================================================================================================
|
||||
|
@ -205,10 +206,9 @@ public class MemorySearchPlugin extends Plugin implements MemorySearchService {
|
|||
Msg.showWarn(this, null, "Search Failed!", "No valid start address!");
|
||||
return;
|
||||
}
|
||||
|
||||
MemorySearcher searcher = new MemorySearcher(source, lastByteMatcher, addresses, 1);
|
||||
|
||||
MemoryMatch match = searcher.findOnce(start, forward, monitor);
|
||||
|
||||
Swing.runLater(() -> navigateToMatch(match));
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ import docking.action.ToggleDockingAction;
|
|||
import docking.action.builder.ActionBuilder;
|
||||
import docking.action.builder.ToggleActionBuilder;
|
||||
import docking.util.GGlassPaneMessage;
|
||||
import docking.widgets.OptionDialog;
|
||||
import docking.widgets.OptionDialogBuilder;
|
||||
import generic.theme.GIcon;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
|
@ -38,6 +40,7 @@ import ghidra.app.nav.NavigatableRemovalListener;
|
|||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.features.base.memsearch.bytesource.AddressableByteSource;
|
||||
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.scan.Scanner;
|
||||
import ghidra.features.base.memsearch.searcher.*;
|
||||
|
@ -145,7 +148,6 @@ public class MemorySearchProvider extends ComponentProviderAdapter
|
|||
navigatable.addNavigatableListener(this);
|
||||
program.addCloseListener(this);
|
||||
updateTitle();
|
||||
|
||||
}
|
||||
|
||||
public void setSearchInput(String input) {
|
||||
|
@ -539,9 +541,43 @@ public class MemorySearchProvider extends ComponentProviderAdapter
|
|||
public void actionPerformed(ActionContext context) {
|
||||
super.actionPerformed(context);
|
||||
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
|
||||
|
@ -551,6 +587,7 @@ public class MemorySearchProvider extends ComponentProviderAdapter
|
|||
}
|
||||
|
||||
private void dispose() {
|
||||
|
||||
if (glassPaneMessage != null) {
|
||||
glassPaneMessage.hide();
|
||||
glassPaneMessage = null;
|
||||
|
@ -583,12 +620,12 @@ public class MemorySearchProvider extends ComponentProviderAdapter
|
|||
|
||||
@Override
|
||||
public void navigatableRemoved(Navigatable nav) {
|
||||
closeComponent();
|
||||
doClose(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void domainObjectClosed(DomainObject dobj) {
|
||||
closeComponent();
|
||||
doClose(true);
|
||||
}
|
||||
|
||||
Navigatable getNavigatable() {
|
||||
|
@ -638,12 +675,20 @@ public class MemorySearchProvider extends ComponentProviderAdapter
|
|||
return resultsPanel.getTableModel().getModelData();
|
||||
}
|
||||
|
||||
public MemorySearchResultsPanel getResultsPanel() {
|
||||
return resultsPanel;
|
||||
}
|
||||
|
||||
public void setSettings(SearchSettings settings) {
|
||||
String converted = searchPanel.convertInput(model.getSettings(), settings);
|
||||
model.setSettings(settings);
|
||||
searchPanel.setSearchInput(converted);
|
||||
}
|
||||
|
||||
public void setSearchCombiner(Combiner combiner) {
|
||||
searchPanel.setSearchCombiner(combiner);
|
||||
}
|
||||
|
||||
public boolean isSearchSelection() {
|
||||
return model.isSearchSelectionOnly();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* table for showing the results.
|
||||
*/
|
||||
class MemorySearchResultsPanel extends JPanel {
|
||||
public class MemorySearchResultsPanel extends JPanel {
|
||||
private GhidraThreadedTablePanel<MemoryMatch> threadedTablePanel;
|
||||
private GhidraTableFilterPanel<MemoryMatch> tableFilterPanel;
|
||||
private GhidraTable table;
|
||||
|
@ -49,6 +49,9 @@ class MemorySearchResultsPanel extends JPanel {
|
|||
private MemorySearchProvider provider;
|
||||
private SearchMarkers markers;
|
||||
|
||||
private boolean hasDeleted;
|
||||
private boolean hasCombined;
|
||||
|
||||
MemorySearchResultsPanel(MemorySearchProvider provider, SearchMarkers markers) {
|
||||
super(new BorderLayout());
|
||||
this.provider = provider;
|
||||
|
@ -73,6 +76,14 @@ class MemorySearchResultsPanel extends JPanel {
|
|||
markers.loadMarkers(provider.getTitle(), tableModel.getModelData());
|
||||
}
|
||||
|
||||
void itemDeleted() {
|
||||
hasDeleted = true;
|
||||
}
|
||||
|
||||
boolean hasUserChanges() {
|
||||
return hasDeleted || hasCombined;
|
||||
}
|
||||
|
||||
void providerActivated() {
|
||||
markers.makeActiveMarkerSet();
|
||||
}
|
||||
|
@ -109,7 +120,13 @@ class MemorySearchResultsPanel extends JPanel {
|
|||
}
|
||||
|
||||
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
|
||||
// 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
|
||||
// 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.
|
||||
if (combiner != Combiner.REPLACE) {
|
||||
List<MemoryMatch> previousResults = tableModel.getModelData();
|
||||
return new CombinedMatchTableLoader(searcher, previousResults, combiner);
|
||||
}
|
||||
hasCombined = true;
|
||||
List<MemoryMatch> previousResults = tableModel.getModelData();
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -146,7 +166,7 @@ class MemorySearchResultsPanel extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
GhidraTable getTable() {
|
||||
public GhidraTable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,17 @@ import java.util.List;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import docking.action.DockingActionIf;
|
||||
import docking.widgets.OptionDialog;
|
||||
import docking.widgets.fieldpanel.support.Highlight;
|
||||
import docking.widgets.table.GTable;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.services.MarkerSet;
|
||||
import ghidra.app.util.viewer.field.BytesFieldFactory;
|
||||
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.gui.MemorySearchResultsPanel;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
@ -259,15 +264,13 @@ public class MemSearchHexTest extends AbstractMemSearchTest {
|
|||
|
||||
@Test
|
||||
public void testHexSearchAll2() throws Exception {
|
||||
// enter search string for multiple byte match
|
||||
|
||||
// enter search string for multiple byte match
|
||||
setInput("ff 15");
|
||||
performSearchAll();
|
||||
|
||||
waitForSearch(5);
|
||||
|
||||
List<Address> addrs = addrs(0x01002d1f, 0x01002d41, 0x01002d4a, 0x01002d5e, 0x010029bd);
|
||||
|
||||
checkMarkerSet(addrs);
|
||||
}
|
||||
|
||||
|
@ -552,4 +555,113 @@ public class MemSearchHexTest extends AbstractMemSearchTest {
|
|||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,11 +22,9 @@ import java.awt.Window;
|
|||
import org.junit.*;
|
||||
|
||||
import docking.action.DockingActionIf;
|
||||
import ghidra.app.events.ProgramSelectionPluginEvent;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
import ghidra.app.plugin.core.marker.MarkerManagerPlugin;
|
||||
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.MemorySearchProvider;
|
||||
import ghidra.features.base.memsearch.mnemonic.MnemonicSearchPlugin;
|
||||
|
@ -35,7 +33,6 @@ import ghidra.program.database.ProgramBuilder;
|
|||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.Swing;
|
||||
|
@ -45,9 +42,9 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
|
|||
private PluginTool tool;
|
||||
private ProgramDB program;
|
||||
private MnemonicSearchPlugin plugin;
|
||||
private DockingActionIf searchMnemonicOperandsNoConstAction;
|
||||
private DockingActionIf searchMnemonicNoOperandsNoConstAction;
|
||||
private DockingActionIf searchMnemonicOperandsConstAction;
|
||||
private DockingActionIf includeOperandsExcludeConstAction;
|
||||
private DockingActionIf excludeOperandsAction;
|
||||
private DockingActionIf includeOperandsAction;
|
||||
private CodeBrowserPlugin cb;
|
||||
private MemorySearchProvider searchProvider;
|
||||
|
||||
|
@ -63,16 +60,12 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
|
|||
plugin = env.getPlugin(MnemonicSearchPlugin.class);
|
||||
cb = env.getPlugin(CodeBrowserPlugin.class);
|
||||
program = (ProgramDB) buildProgram();
|
||||
env.showTool(program);
|
||||
|
||||
ProgramManager pm = tool.getService(ProgramManager.class);
|
||||
pm.openProgram(program.getDomainFile());
|
||||
|
||||
searchMnemonicOperandsNoConstAction =
|
||||
excludeOperandsAction = getAction(plugin, "Exclude Operands");
|
||||
includeOperandsAction = getAction(plugin, "Include Operands");
|
||||
includeOperandsExcludeConstAction =
|
||||
getAction(plugin, "Include Operands (except constants)");
|
||||
searchMnemonicNoOperandsNoConstAction = getAction(plugin, "Exclude Operands");
|
||||
searchMnemonicOperandsConstAction = getAction(plugin, "Include Operands");
|
||||
|
||||
env.showTool();
|
||||
}
|
||||
|
||||
private Program buildProgram() throws Exception {
|
||||
|
@ -93,29 +86,19 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
|
|||
|
||||
@Test
|
||||
public void testSearchMnemonicOperandsNoConst() {
|
||||
ProgramSelection sel = new ProgramSelection(addr(0x01004062), addr(0x0100406a));
|
||||
tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", sel, program));
|
||||
|
||||
performAction(searchMnemonicOperandsNoConstAction, cb.getProvider(), true);
|
||||
makeSelection(tool, program, addr(0x01004062), addr(0x0100406a));
|
||||
performAction(includeOperandsExcludeConstAction, cb.getProvider(), true);
|
||||
searchProvider = waitForComponentProvider(MemorySearchProvider.class);
|
||||
|
||||
assertNotNull(searchProvider);
|
||||
assertEquals(
|
||||
"01010101 10001011 11101100 10000001 11101100 ........ ........ ........ ........",
|
||||
getInput());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchMnemonicNoOperandsNoConst() {
|
||||
ProgramSelection sel = new ProgramSelection(addr(0x01004062), addr(0x0100406a));
|
||||
tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", sel, program));
|
||||
|
||||
performAction(searchMnemonicNoOperandsNoConstAction, cb.getProvider(), true);
|
||||
|
||||
makeSelection(tool, program, addr(0x01004062), addr(0x0100406a));
|
||||
performAction(excludeOperandsAction, cb.getProvider(), true);
|
||||
searchProvider = waitForComponentProvider(MemorySearchProvider.class);
|
||||
assertNotNull(searchProvider);
|
||||
|
||||
assertEquals(
|
||||
"01010... 10001011 11...... 10000001 11101... ........ ........ ........ ........",
|
||||
getInput());
|
||||
|
@ -124,16 +107,10 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
|
|||
|
||||
@Test
|
||||
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);
|
||||
assertNotNull(searchProvider);
|
||||
|
||||
assertEquals(
|
||||
"01010101 10001011 11101100 10000001 11101100 00000100 00000001 00000000 00000000",
|
||||
getInput());
|
||||
|
@ -142,7 +119,6 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
|
|||
/**
|
||||
* Tests that when multiple regions are selected, the user is notified via
|
||||
* pop-up that this is not acceptable.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testMultipleSelection() {
|
||||
|
@ -158,7 +134,7 @@ public class MnemonicSearchPluginTest extends AbstractGhidraHeadedIntegrationTes
|
|||
makeSelection(tool, program, addrSet);
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
}
|
||||
|
||||
protected String getInput() {
|
||||
private String getInput() {
|
||||
return Swing.runNow(() -> searchProvider.getSearchInput());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -76,8 +76,11 @@ public class ProjectDataDeleteAction extends FrontendProjectTreeAction {
|
|||
|
||||
String message = getMessage(fileCount, files);
|
||||
OptionDialogBuilder builder = new OptionDialogBuilder("Confirm Delete", message);
|
||||
builder.addOption("OK").addCancel().setMessageType(OptionDialog.QUESTION_MESSAGE);
|
||||
return builder.show(parent) != OptionDialog.CANCEL_OPTION;
|
||||
int choice = builder.addOption("OK")
|
||||
.addCancel()
|
||||
.setMessageType(OptionDialog.QUESTION_MESSAGE)
|
||||
.show(parent);
|
||||
return choice != OptionDialog.CANCEL_OPTION;
|
||||
}
|
||||
|
||||
private String getMessage(int fileCount, Set<DomainFile> selectedFiles) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue