mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
f553f5a534
5 changed files with 110 additions and 106 deletions
|
@ -25,6 +25,7 @@ import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.ComponentProvider;
|
import docking.ComponentProvider;
|
||||||
|
@ -346,12 +347,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier
|
||||||
return createStringTransferable(g.getBuffer().toString());
|
return createStringTransferable(g.getBuffer().toString());
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
String msg = e.getMessage();
|
String message = "Copy failed: " + ExceptionUtils.getMessage(e);
|
||||||
if (msg == null) {
|
|
||||||
msg = e.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String message = "Copy failed: " + msg;
|
|
||||||
Msg.error(this, message, e);
|
Msg.error(this, message, e);
|
||||||
tool.setStatusInfo(message, true);
|
tool.setStatusInfo(message, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ package ghidra.app.plugin.core.functiongraph;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.widgets.fieldpanel.Layout;
|
import docking.widgets.fieldpanel.Layout;
|
||||||
import docking.widgets.fieldpanel.internal.EmptyLayoutBackgroundColorManager;
|
import docking.widgets.fieldpanel.internal.EmptyLayoutBackgroundColorManager;
|
||||||
|
@ -32,6 +34,7 @@ import ghidra.app.plugin.core.functiongraph.mvc.FGData;
|
||||||
import ghidra.app.util.viewer.listingpanel.ListingModel;
|
import ghidra.app.util.viewer.listingpanel.ListingModel;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class FGClipboardProvider extends CodeBrowserClipboardProvider {
|
public class FGClipboardProvider extends CodeBrowserClipboardProvider {
|
||||||
|
@ -82,11 +85,9 @@ public class FGClipboardProvider extends CodeBrowserClipboardProvider {
|
||||||
return createStringTransferable(g.getBuffer().toString());
|
return createStringTransferable(g.getBuffer().toString());
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
String msg = e.getMessage();
|
String message = "Copy failed: " + ExceptionUtils.getMessage(e);
|
||||||
if (msg == null) {
|
Msg.error(this, message, e);
|
||||||
msg = e.toString();
|
tool.setStatusInfo(message, true);
|
||||||
}
|
|
||||||
tool.setStatusInfo("Copy failed: " + msg, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -26,28 +26,55 @@ import java.text.AttributedCharacterIterator;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Graphics used to render copied text data. This class is not a true graphics object, but is
|
* Graphics used to render copied text data. This class is not a true graphics object, but is
|
||||||
* instead used to grab text being painted so that clients can later use that text.
|
* instead used to grab text being painted so that clients can later use that text.
|
||||||
*/
|
*/
|
||||||
public class TextLayoutGraphics extends Graphics2D {
|
public class TextLayoutGraphics extends Graphics2D {
|
||||||
|
|
||||||
private static final Component COMPONENT = new JPanel();
|
|
||||||
|
|
||||||
private int transX;
|
private int transX;
|
||||||
private int transY;
|
private int transY;
|
||||||
private Shape clip;
|
private Shape clip;
|
||||||
private StringBuilder buffer = new StringBuilder();
|
private StringBuilder buffer = new StringBuilder();
|
||||||
private Font lastFont = new Font("SansSerif", Font.PLAIN, 12);
|
private Font lastFont = new Font("SansSerif", Font.PLAIN, 12);
|
||||||
private FontMetrics fontMetrics = getFontMetricsForFont(lastFont);
|
private FontMetrics fontMetrics = createFontMetrics(lastFont);
|
||||||
|
|
||||||
private List<TextInfo> textInfos = new ArrayList<>();
|
private List<TextInfo> textInfos = new ArrayList<>();
|
||||||
|
|
||||||
@SuppressWarnings("deprecation") // Java still uses it, so we still use it
|
private Comparator<TextInfo> pointComparator = (o1, o2) -> {
|
||||||
private static FontMetrics getFontMetricsForFont(Font font) {
|
TextInfo t1 = o1;
|
||||||
return Toolkit.getDefaultToolkit().getFontMetrics(font);
|
TextInfo t2 = o2;
|
||||||
|
|
||||||
|
int diff = t1.point.y - t2.point.y;
|
||||||
|
if (diff != 0) {
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff = t1.point.x - t2.point.x;
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
};
|
||||||
|
|
||||||
|
private Comparator<TextInfo> rowComparator = (o1, o2) -> {
|
||||||
|
TextInfo t1 = o1;
|
||||||
|
TextInfo t2 = o2;
|
||||||
|
|
||||||
|
int diff = t1.row - t2.row;
|
||||||
|
if (diff != 0) {
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff = t1.point.x - t2.point.x;
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
};
|
||||||
|
|
||||||
|
private static FontMetrics createFontMetrics(Font font) {
|
||||||
|
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||||
|
Graphics g = image.getGraphics();
|
||||||
|
FontMetrics fm = g.getFontMetrics(font);
|
||||||
|
g.dispose();
|
||||||
|
return fm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -71,13 +98,14 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
newTextInfo.point = new Point(x + transX, y + transY);
|
newTextInfo.point = new Point(x + transX, y + transY);
|
||||||
newTextInfo.text = str;
|
newTextInfo.text = str;
|
||||||
newTextInfo.font = lastFont;
|
newTextInfo.font = lastFont;
|
||||||
|
newTextInfo.fontMetrics = fontMetrics;
|
||||||
textInfos.add(newTextInfo);
|
textInfos.add(newTextInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFont(Font font) {
|
public void setFont(Font font) {
|
||||||
lastFont = font;
|
lastFont = font;
|
||||||
fontMetrics = getFontMetrics(font);
|
fontMetrics = createFontMetrics(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,101 +117,79 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Comparator<TextInfo> pointComparator = (o1, o2) -> {
|
sortDataAndAssignRows();
|
||||||
TextInfo t1 = o1;
|
|
||||||
TextInfo t2 = o2;
|
|
||||||
|
|
||||||
int diff = t1.point.y - t2.point.y;
|
// render the text into a string
|
||||||
if (diff != 0) {
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff = t1.point.x - t2.point.x;
|
|
||||||
|
|
||||||
return diff;
|
|
||||||
};
|
|
||||||
|
|
||||||
Comparator<TextInfo> rowComparator = (o1, o2) -> {
|
|
||||||
TextInfo t1 = o1;
|
|
||||||
TextInfo t2 = o2;
|
|
||||||
|
|
||||||
int diff = t1.row - t2.row;
|
|
||||||
if (diff != 0) {
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff = t1.point.x - t2.point.x;
|
|
||||||
|
|
||||||
return diff;
|
|
||||||
};
|
|
||||||
|
|
||||||
TextInfo[] sortedTextInfos = new TextInfo[textInfos.size()];
|
|
||||||
textInfos.toArray(sortedTextInfos);
|
|
||||||
|
|
||||||
//Sort the text by y position, then by x position
|
|
||||||
Arrays.sort(sortedTextInfos, pointComparator);
|
|
||||||
|
|
||||||
//Group the text into rows based on font height and y position
|
|
||||||
//TODO - Ideally, it would be nice if there was a good way to group text that
|
|
||||||
// varied in height in a nice way
|
|
||||||
int lastPos = sortedTextInfos[0].point.y;
|
|
||||||
int curRow = 0;
|
|
||||||
for (int i = 0; i < sortedTextInfos.length; i++) {
|
|
||||||
if (sortedTextInfos[i].point.y != lastPos) {
|
|
||||||
curRow++;
|
|
||||||
lastPos = sortedTextInfos[i].point.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
sortedTextInfos[i].row = curRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sort the text by row, then by x position
|
|
||||||
Arrays.sort(sortedTextInfos, rowComparator);
|
|
||||||
|
|
||||||
//Render the text into a string
|
|
||||||
int lastRow = 0;
|
int lastRow = 0;
|
||||||
int lastXPos = 0; //The X co-ordinate of the end of the last string
|
int currentX = 0; //The x coordinate of the end of the last string
|
||||||
for (TextInfo sortedTextInfo : sortedTextInfos) {
|
for (TextInfo info : textInfos) {
|
||||||
//Insert newlines as appropriate
|
// insert newlines as appropriate
|
||||||
for (int j = lastRow; j < sortedTextInfo.row; j++) {
|
for (int i = lastRow; i < info.row; i++) {
|
||||||
buffer.append('\n');
|
buffer.append('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we started a new row, reset the X position
|
// if we started a new row, reset the x position
|
||||||
if (lastRow != sortedTextInfo.row) {
|
if (lastRow != info.row) {
|
||||||
lastXPos = 0;
|
currentX = 0;
|
||||||
}
|
}
|
||||||
lastRow = sortedTextInfo.row;
|
lastRow = info.row;
|
||||||
|
|
||||||
//Insert spaces to account for distance past last field in row
|
// insert spaces to account for distance past last field in row
|
||||||
FontMetrics metrics = COMPONENT.getFontMetrics(sortedTextInfo.font);
|
FontMetrics metrics = info.fontMetrics;
|
||||||
int spaceWidth = metrics.charWidth(' ');
|
int spaceWidth = metrics.charWidth(' ');
|
||||||
|
|
||||||
if (spaceWidth == 0) {
|
if (spaceWidth == 0) {
|
||||||
// some environments report 0 for some fonts
|
// some environments report 0 for some fonts
|
||||||
spaceWidth = 4;
|
spaceWidth = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fillSpaces =
|
float spaceBetween = info.point.x - currentX;
|
||||||
Math.round((float) (sortedTextInfo.point.x - lastXPos) / (float) spaceWidth);
|
int fillSpaces = Math.round(spaceBetween / spaceWidth);
|
||||||
//Account for the case where there's a very small amount of space between fields
|
|
||||||
if (fillSpaces == 0 && sortedTextInfo.point.x > lastXPos) {
|
// account for the case where there's a very small amount of space between fields
|
||||||
|
if (fillSpaces == 0 && info.point.x > currentX) {
|
||||||
fillSpaces = 1;
|
fillSpaces = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < fillSpaces; j++) {
|
for (int i = 0; i < fillSpaces; i++) {
|
||||||
buffer.append(' ');
|
buffer.append(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
lastXPos = sortedTextInfo.point.x + metrics.stringWidth(sortedTextInfo.text);
|
int stringWidth = metrics.stringWidth(info.text);
|
||||||
|
currentX = info.point.x + stringWidth;
|
||||||
|
|
||||||
//Append the text
|
// append the text
|
||||||
buffer.append(sortedTextInfo.text);
|
buffer.append(info.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.append('\n');
|
buffer.append('\n');
|
||||||
textInfos.clear();
|
textInfos.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sortDataAndAssignRows() {
|
||||||
|
|
||||||
|
// sort the text by y position, then by x position
|
||||||
|
textInfos.sort(pointComparator);
|
||||||
|
|
||||||
|
// Group the text into rows based on font height and y position
|
||||||
|
//TODO - Ideally, it would be nice if there was a good way to group text that
|
||||||
|
// varied in height in a nice way
|
||||||
|
int lastPos = textInfos.get(0).point.y;
|
||||||
|
int row = 0;
|
||||||
|
for (TextInfo info : textInfos) {
|
||||||
|
if (info.point.y != lastPos) {
|
||||||
|
row++;
|
||||||
|
lastPos = info.point.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.row = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the text by row, then by x position
|
||||||
|
textInfos.sort(rowComparator);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String getBuffer() {
|
public String getBuffer() {
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
@ -231,7 +237,7 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Stubs
|
// Stubs
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
@ -387,7 +393,7 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
|
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -419,7 +425,7 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPaint(Paint paint) {
|
public void setPaint(Paint paint) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -440,7 +446,7 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRenderingHints(Map<?, ?> hints) {
|
public void setRenderingHints(Map<?, ?> hints) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -456,22 +462,22 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(double tx, double ty) {
|
public void translate(double tx, double ty) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rotate(double theta) {
|
public void rotate(double theta) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rotate(double theta, double x, double y) {
|
public void rotate(double theta, double x, double y) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void scale(double sx, double sy) {
|
public void scale(double sx, double sy) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -486,7 +492,7 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTransform(AffineTransform Tx) {
|
public void setTransform(AffineTransform Tx) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -538,11 +544,11 @@ public class TextLayoutGraphics extends Graphics2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextInfo {
|
class TextInfo {
|
||||||
public String text;
|
String text;
|
||||||
public Point point;
|
Font font;
|
||||||
public Font font;
|
FontMetrics fontMetrics;
|
||||||
|
Point point;
|
||||||
public int row;
|
int row;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
@ -759,6 +759,7 @@ public class HTMLUtilities {
|
||||||
//
|
//
|
||||||
// Use the label's builtin handling of HTML text via the HTMLEditorKit
|
// Use the label's builtin handling of HTML text via the HTMLEditorKit
|
||||||
//
|
//
|
||||||
|
Swing.assertSwingThread("This method must be called on the Swing thread");
|
||||||
JLabel label = new JLabel(text) {
|
JLabel label = new JLabel(text) {
|
||||||
@Override
|
@Override
|
||||||
public void paint(Graphics g) {
|
public void paint(Graphics g) {
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.util;
|
package ghidra.util;
|
||||||
|
|
||||||
import static ghidra.util.HTMLUtilities.HTML;
|
import static ghidra.util.HTMLUtilities.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public class HTMLUtilitiesTest {
|
||||||
@Test
|
@Test
|
||||||
public void testFromHTML() {
|
public void testFromHTML() {
|
||||||
String s = "<HTML><b>Bold</b>, <i>italics</i>, <font size='3'>sized font!</font>";
|
String s = "<HTML><b>Bold</b>, <i>italics</i>, <font size='3'>sized font!</font>";
|
||||||
String text = HTMLUtilities.fromHTML(s);
|
String text = Swing.runNow(() -> HTMLUtilities.fromHTML(s));
|
||||||
assertEquals("Bold, italics, sized font!", text);
|
assertEquals("Bold, italics, sized font!", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue