GP-3871 Added option to remove quotes from string before being added to clipboard

This commit is contained in:
ghidragon 2024-04-09 18:14:24 -04:00
parent cb141a391d
commit baf5e11fc9
4 changed files with 60 additions and 15 deletions

View file

@ -283,7 +283,12 @@
<TH align="left"><B>Description</B></TH>
</TR>
<TR valign="middle">
<TD valign="top" width="200" align="left">Copy Strings Without Quotes</TD>
<TD valign="top" align="left">If selected, copying strings to the clipboard from
the listing, decompiler, or bytes viewer will remove outer quotes.</TD>
</TR>
<TR valign="middle">
<TD valign="top" width="200" align="left">Docking Windows On Top</TD>

View file

@ -29,6 +29,8 @@ import javax.swing.event.ChangeListener;
import docking.*;
import docking.action.*;
import docking.dnd.GClipboard;
import docking.dnd.StringTransferable;
import docking.tool.ToolConstants;
import generic.theme.GIcon;
import ghidra.app.CorePluginPackage;
import ghidra.app.context.ListingActionContext;
@ -37,12 +39,15 @@ import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.services.ClipboardContentProviderService;
import ghidra.app.services.ClipboardService;
import ghidra.app.util.ClipboardType;
import ghidra.framework.options.OptionsChangeListener;
import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.bean.opteditor.OptionsVetoException;
import ghidra.util.task.*;
//@formatter:off
@ -55,10 +60,12 @@ import ghidra.util.task.*;
servicesProvided = { ClipboardService.class }
)
//@formatter:on
public class ClipboardPlugin extends ProgramPlugin implements ClipboardOwner, ClipboardService {
public class ClipboardPlugin extends ProgramPlugin
implements ClipboardOwner, ClipboardService, OptionsChangeListener {
public static final String GROUP_NAME = "Clipboard";
public static final String TOOLBAR_GROUP_NAME = "ZClipboard";
private static final String REMOVE_QUOTES_OPTION = "Copy Strings Without Quotes";
//The provider that owns the clipboard content
private ClipboardContentProviderService clipboardOwnerProvider;
@ -76,9 +83,28 @@ public class ClipboardPlugin extends ProgramPlugin implements ClipboardOwner, Cl
};
private boolean isClipboardOwner;
private boolean removeQuotes;
public ClipboardPlugin(PluginTool tool) {
super(tool);
initOptions();
}
private void initOptions() {
ToolOptions options = tool.getOptions(ToolConstants.TOOL_OPTIONS);
options.registerOption(REMOVE_QUOTES_OPTION, false, null,
"If true, copying strings to the clipboard will remove outer quotes");
removeQuotes = options.getBoolean(REMOVE_QUOTES_OPTION, false);
options.addOptionsChangeListener(this);
}
@Override
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
Object newValue) throws OptionsVetoException {
if (optionName.equals(REMOVE_QUOTES_OPTION)) {
removeQuotes = options.getBoolean(REMOVE_QUOTES_OPTION, false);
}
}
@Override
@ -246,6 +272,10 @@ public class ClipboardPlugin extends ProgramPlugin implements ClipboardOwner, Cl
monitor.setMessage("Setting Clipboard Contents");
Clipboard systemClipboard = getSystemClipboard();
Transferable transferable = clipboardService.copy(monitor);
if (removeQuotes && transferable instanceof StringTransferable stringTransferable) {
stringTransferable.removeOuterQuotes();
}
if (transferable == null) {
return;
}

View file

@ -30,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.ActionContext;
import docking.ComponentProvider;
import docking.dnd.GenericDataFlavor;
import docking.dnd.StringTransferable;
import docking.widgets.fieldpanel.Layout;
import docking.widgets.fieldpanel.internal.*;
import generic.text.TextLayoutGraphics;
@ -750,7 +751,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier
// Inner Classes
//==================================================================================================
private static class LabelStringTransferable implements Transferable {
private static class LabelStringTransferable extends StringTransferable {
public static final DataFlavor labelStringFlavor = new GenericDataFlavor(
DataFlavor.javaJVMLocalObjectMimeType + "; class=java.lang.String",
@ -759,20 +760,18 @@ public class CodeBrowserClipboardProvider extends ByteCopier
private final DataFlavor[] flavors = { labelStringFlavor, DataFlavor.stringFlavor };
private final List<DataFlavor> flavorList = Arrays.asList(flavors);
private String symbolName;
LabelStringTransferable(String name) {
this.symbolName = name;
super(name);
}
@Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (flavor.equals(labelStringFlavor)) {
return symbolName;
return data;
}
if (flavor.equals(DataFlavor.stringFlavor)) {
return symbolName;
return data;
}
throw new UnsupportedFlavorException(flavor);
}
@ -788,7 +787,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier
}
}
private static class NonLabelStringTransferable implements Transferable {
private static class NonLabelStringTransferable extends StringTransferable {
public static final DataFlavor nonLabelStringFlavor = new GenericDataFlavor(
DataFlavor.javaJVMLocalObjectMimeType + "; class=java.lang.String",
@ -797,9 +796,11 @@ public class CodeBrowserClipboardProvider extends ByteCopier
private final DataFlavor[] flavors = { nonLabelStringFlavor, DataFlavor.stringFlavor };
private final List<DataFlavor> flavorList = Arrays.asList(flavors);
private String text;
NonLabelStringTransferable(String[] text) {
super(combine(text));
}
private static String combine(String[] text) {
StringBuilder buildy = new StringBuilder();
for (String string : text) {
if (buildy.length() > 0) {
@ -807,21 +808,21 @@ public class CodeBrowserClipboardProvider extends ByteCopier
}
buildy.append(string);
}
this.text = buildy.toString();
return buildy.toString();
}
NonLabelStringTransferable(String text) {
this.text = text;
super(text);
}
@Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (flavor.equals(nonLabelStringFlavor)) {
return text;
return data;
}
if (flavor.equals(DataFlavor.stringFlavor)) {
return text;
return data;
}
throw new UnsupportedFlavorException(flavor);
}

View file

@ -20,7 +20,7 @@ import java.io.IOException;
public class StringTransferable implements Transferable {
private String data = null;
protected String data = null;
private DataFlavor[] flavors = { DataFlavor.stringFlavor };
public StringTransferable(String data) {
@ -42,4 +42,13 @@ public class StringTransferable implements Transferable {
throws UnsupportedFlavorException, IOException {
return data;
}
public void removeOuterQuotes() {
if (data.length() < 2) {
return;
}
if (data.charAt(0) == '"' && data.charAt(data.length() - 1) == '"') {
data = data.substring(1, data.length() - 1);
}
}
}