diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java
index 216a85bbd6..dae9bddd46 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clipboard/CodeBrowserClipboardProvider.java
@@ -25,6 +25,7 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
import docking.ActionContext;
import docking.ComponentProvider;
@@ -346,12 +347,7 @@ public class CodeBrowserClipboardProvider extends ByteCopier
return createStringTransferable(g.getBuffer().toString());
}
catch (Exception e) {
- String msg = e.getMessage();
- if (msg == null) {
- msg = e.toString();
- }
-
- String message = "Copy failed: " + msg;
+ String message = "Copy failed: " + ExceptionUtils.getMessage(e);
Msg.error(this, message, e);
tool.setStatusInfo(message, true);
}
diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java
index f1f733145e..7df039ba46 100644
--- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java
+++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGClipboardProvider.java
@@ -18,6 +18,8 @@ package ghidra.app.plugin.core.functiongraph;
import java.awt.Rectangle;
import java.awt.datatransfer.Transferable;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
import docking.ActionContext;
import docking.widgets.fieldpanel.Layout;
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.framework.plugintool.PluginTool;
import ghidra.program.model.address.*;
+import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;
public class FGClipboardProvider extends CodeBrowserClipboardProvider {
@@ -82,11 +85,9 @@ public class FGClipboardProvider extends CodeBrowserClipboardProvider {
return createStringTransferable(g.getBuffer().toString());
}
catch (Exception e) {
- String msg = e.getMessage();
- if (msg == null) {
- msg = e.toString();
- }
- tool.setStatusInfo("Copy failed: " + msg, true);
+ String message = "Copy failed: " + ExceptionUtils.getMessage(e);
+ Msg.error(this, message, e);
+ tool.setStatusInfo(message, true);
}
return null;
diff --git a/Ghidra/Framework/Generic/src/main/java/generic/text/TextLayoutGraphics.java b/Ghidra/Framework/Generic/src/main/java/generic/text/TextLayoutGraphics.java
index 99764e93ca..f15a9f9d37 100644
--- a/Ghidra/Framework/Generic/src/main/java/generic/text/TextLayoutGraphics.java
+++ b/Ghidra/Framework/Generic/src/main/java/generic/text/TextLayoutGraphics.java
@@ -105,7 +105,7 @@ public class TextLayoutGraphics extends Graphics2D {
@Override
public void setFont(Font font) {
lastFont = font;
- fontMetrics = getFontMetrics(font);
+ fontMetrics = createFontMetrics(font);
}
/**
@@ -117,73 +117,79 @@ public class TextLayoutGraphics extends Graphics2D {
return;
}
- TextInfo[] sortedTextInfos = new TextInfo[textInfos.size()];
- textInfos.toArray(sortedTextInfos);
+ sortDataAndAssignRows();
- //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
+ // render the text into a string
int lastRow = 0;
- int lastXPos = 0; //The X co-ordinate of the end of the last string
- for (TextInfo sortedTextInfo : sortedTextInfos) {
- //Insert newlines as appropriate
- for (int j = lastRow; j < sortedTextInfo.row; j++) {
+ int currentX = 0; //The x coordinate of the end of the last string
+ for (TextInfo info : textInfos) {
+ // insert newlines as appropriate
+ for (int i = lastRow; i < info.row; i++) {
buffer.append('\n');
}
- //If we started a new row, reset the X position
- if (lastRow != sortedTextInfo.row) {
- lastXPos = 0;
+ // if we started a new row, reset the x position
+ if (lastRow != info.row) {
+ currentX = 0;
}
- lastRow = sortedTextInfo.row;
+ lastRow = info.row;
- //Insert spaces to account for distance past last field in row
- FontMetrics metrics = sortedTextInfo.fontMetrics;
+ // insert spaces to account for distance past last field in row
+ FontMetrics metrics = info.fontMetrics;
int spaceWidth = metrics.charWidth(' ');
+
if (spaceWidth == 0) {
// some environments report 0 for some fonts
spaceWidth = 4;
}
- int fillSpaces =
- Math.round((float) (sortedTextInfo.point.x - lastXPos) / (float) spaceWidth);
- //Account for the case where there's a very small amount of space between fields
- if (fillSpaces == 0 && sortedTextInfo.point.x > lastXPos) {
+ float spaceBetween = info.point.x - currentX;
+ int fillSpaces = Math.round(spaceBetween / spaceWidth);
+
+ // account for the case where there's a very small amount of space between fields
+ if (fillSpaces == 0 && info.point.x > currentX) {
fillSpaces = 1;
}
- for (int j = 0; j < fillSpaces; j++) {
+ for (int i = 0; i < fillSpaces; i++) {
buffer.append(' ');
}
- lastXPos = sortedTextInfo.point.x + metrics.stringWidth(sortedTextInfo.text);
+ int stringWidth = metrics.stringWidth(info.text);
+ currentX = info.point.x + stringWidth;
- //Append the text
- buffer.append(sortedTextInfo.text);
+ // append the text
+ buffer.append(info.text);
}
buffer.append('\n');
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() {
return buffer.toString();
}
diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java
index 45206a0ead..f8733adf4d 100644
--- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java
+++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java
@@ -759,6 +759,7 @@ public class HTMLUtilities {
//
// 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) {
@Override
public void paint(Graphics g) {
diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java b/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java
index c95425fd1e..d9fda2ff81 100644
--- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java
+++ b/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java
@@ -15,8 +15,8 @@
*/
package ghidra.util;
-import static ghidra.util.HTMLUtilities.HTML;
-import static org.junit.Assert.assertEquals;
+import static ghidra.util.HTMLUtilities.*;
+import static org.junit.Assert.*;
import java.awt.Color;
@@ -122,7 +122,7 @@ public class HTMLUtilitiesTest {
@Test
public void testFromHTML() {
String s = "Bold, italics, sized font!";
- String text = HTMLUtilities.fromHTML(s);
+ String text = Swing.runNow(() -> HTMLUtilities.fromHTML(s));
assertEquals("Bold, italics, sized font!", text);
}