Xref merge test fixes

This commit is contained in:
dragonmacher 2021-09-21 12:56:33 -04:00
parent ae17ea4cd9
commit 51af44f843
16 changed files with 440 additions and 294 deletions

View file

@ -60,7 +60,8 @@ public class CommentFieldSearcher extends ProgramDatabaseFieldSearcher {
return nextAddress;
}
private void findMatchesForCurrentAddress(Address address, List<ProgramLocation> currentMatches) {
private void findMatchesForCurrentAddress(Address address,
List<ProgramLocation> currentMatches) {
String comment = program.getListing().getComment(commentType, address);
if (comment == null) {
return;
@ -84,7 +85,7 @@ public class CommentFieldSearcher extends ProgramDatabaseFieldSearcher {
charOffset, rowIndex);
case CodeUnit.PLATE_COMMENT:
return new PlateFieldLocation(program, address, dataPath, rowIndex, charOffset,
comments, rowIndex - 1);
comments, rowIndex);
case CodeUnit.REPEATABLE_COMMENT:
return new RepeatableCommentFieldLocation(program, address, dataPath, comments,
rowIndex, charOffset, rowIndex); // TODO One of searchStrIndex parameters is wrong.

View file

@ -427,11 +427,9 @@ public class BytesFieldFactory extends FieldFactory {
ListingTextField btf = (ListingTextField) bf;
RowColLocation rcl = btf.dataToScreenLocation(tokenIndex, tokenOffset);
if (hasSamePath(bf, loc)) {
return new FieldLocation(index, fieldNum, rcl.row(), rcl.col());
}
return null;
}

View file

@ -20,6 +20,8 @@ import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import docking.widgets.fieldpanel.field.*;
import docking.widgets.fieldpanel.support.*;
import ghidra.app.util.HelpTopics;
@ -32,6 +34,7 @@ import ghidra.app.util.viewer.proxy.ProxyObj;
import ghidra.framework.options.Options;
import ghidra.framework.options.ToolOptions;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.program.util.*;
@ -141,21 +144,18 @@ public class PlateFieldFactory extends FieldFactory {
}
CodeUnit cu = (CodeUnit) proxy.getObject();
List<FieldElement> elements = new ArrayList<>(10);
boolean isClipped = false;
List<FieldElement> elements = new ArrayList<>();
String commentText = getCommentText(cu);
if ((commentText == null) || (commentText.isEmpty())) {
generateDefaultPlate(elements, cu);
if (StringUtils.isBlank(commentText)) {
getDefaultFieldElements(cu, elements);
}
else {
isClipped = generateFormattedPlateComment(elements, cu);
isClipped = getFormattedFieldElements(cu, elements);
}
addBlankLines(elements, cu);
if (elements.size() == 0) {
// no real or default comment
return null;
if (elements.isEmpty()) {
return null; // no real or default comments
}
if (isNestedDataAtSameAddressAsParent(proxy)) {
@ -170,6 +170,27 @@ public class PlateFieldFactory extends FieldFactory {
return new PlateListingTextField(proxy, textField);
}
private boolean getFormattedFieldElements(CodeUnit cu, List<FieldElement> elements) {
int numberBlankLines = getNumberBlankLines(cu, true);
addBlankLines(elements, numberBlankLines, cu);
String[] comments = cu.getCommentAsArray(CodeUnit.PLATE_COMMENT);
return generateFormattedPlateComment(elements, comments, cu.getProgram());
}
private void getDefaultFieldElements(CodeUnit cu, List<FieldElement> elements) {
int numberBlankLines = getNumberBlankLines(cu, true);
addBlankLines(elements, numberBlankLines, cu);
String defaultComment = getDefaultComment(cu);
if (defaultComment != null) {
generateDefaultPlate(elements, defaultComment);
}
}
private boolean isNestedDataAtSameAddressAsParent(ProxyObj<?> proxy) {
if (proxy instanceof DataProxy) {
DataProxy dp = (DataProxy) proxy;
@ -200,67 +221,39 @@ public class PlateFieldFactory extends FieldFactory {
return buffy.toString();
}
/**
/*
* Creates desired FieldElements and puts them in the given list. Returns true if any of the
* data is clipped because it is too long to display.
*
* @param elementList the list into which the created data will be placed.
* @param cu the code unit for which a plate comment will be generated
* @return true if the data is clipped
*/
private boolean generateFormattedPlateComment(List<FieldElement> elementList, CodeUnit cu) {
String[] comments = cu.getCommentAsArray(CodeUnit.PLATE_COMMENT);
if ((comments == null) || (comments.length == 0)) {
private boolean generateFormattedPlateComment(List<FieldElement> elements, String[] comments,
Program p) {
if (comments == null || comments.length == 0) {
return false;
}
Program program = cu.getProgram();
AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics());
for (int i = 0; i < comments.length; i++) {
elementList
.add(CommentUtils.parseTextForAnnotations(comments[i], program, prototype, i));
AttributedString asteriscs = getStarsString();
int row = elements.size();
// add top border
elements.add(new TextFieldElement(asteriscs, row++, 0));
int commentsStart = row;
for (String c : comments) {
FieldElement element = CommentUtils.parseTextForAnnotations(c, p, prototype, row++);
elements.add(element);
}
if (isWordWrap) {
elementList = FieldUtils.wordWrapList(new CompositeFieldElement(elementList), width);
elements = FieldUtils.wordWrapList(new CompositeFieldElement(elements), width);
}
return addBorder(elementList);
}
boolean isClipped = addSideBorders(elements, commentsStart);
private void addBlankLines(List<FieldElement> elementList, CodeUnit cu) {
AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics());
FieldElement blankLine = new TextFieldElement(prototype, 0, 0);
int numBlankLines = getNumberBlankLines(cu, elementList.size() > 0);
for (int i = 0; i < numBlankLines; i++) {
elementList.add(0, blankLine);
}
}
// add bottom border
elements.add(new TextFieldElement(asteriscs, row++, 0));
private int getNumberBlankLines(CodeUnit cu, boolean hasPlate) {
if (cu.getProgram().getListing().getFunctionAt(cu.getMinAddress()) != null) {
if (nLinesBeforeFunctions != 0) {
return nLinesBeforeFunctions;
}
}
if (hasPlate && nLinesBeforePlates != 0) {
return nLinesBeforePlates;
}
if (cu.getLabel() != null) {
return nLinesBeforeLabels;
}
return 0;
}
private boolean addBorder(List<FieldElement> elements) {
AttributedString asteriscs = getStarsString();
boolean isClipped = addSideBorders(elements);
elements.add(0, new TextFieldElement(asteriscs, 0, 0));
elements.add(new TextFieldElement(asteriscs, elements.size(), 0));
return isClipped;
}
@ -269,13 +262,17 @@ public class PlateFieldFactory extends FieldFactory {
* Text will be left justified between two '*' and padded based upon the
* available field width.
* @param elements the field elements that may get updated
* @param commentsStart the start index of comment elements in the element list
* @return formatted plate text line
*/
private boolean addSideBorders(List<FieldElement> elements) {
private boolean addSideBorders(List<FieldElement> elements, int commentsStart) {
boolean isClipped = false;
if (elements.size() == 1) {
// If there is only a single line comment, then center it
int n = elements.size() - commentsStart;
if (n == 1) {
FieldElement element = elements.get(0);
if (element.length() > 1 && element.charAt(0) == ' ') {
if (element.length() > 1 && element.charAt(0) == ' ') { // not sure why the space matters
FieldElementResult result = addSideBorder(element.substring(1), 1, true);
isClipped = result.isClipped();
elements.set(0, result.getFieldElement());
@ -283,8 +280,8 @@ public class PlateFieldFactory extends FieldFactory {
}
}
for (int i = 0; i < elements.size(); i++) {
FieldElementResult result = addSideBorder(elements.get(i), i + 1, false);
for (int i = commentsStart; i < elements.size(); i++) {
FieldElementResult result = addSideBorder(elements.get(i), i, false);
isClipped |= result.isClipped();
elements.set(i, result.getFieldElement());
}
@ -311,7 +308,7 @@ public class PlateFieldFactory extends FieldFactory {
int prePadding = center ? totalPadding / 2 : 0;
int postPadding = center ? (totalPadding + 1) / 2 : totalPadding;
StringBuffer buffy = new StringBuffer();
StringBuilder buffy = new StringBuilder();
buffy.append('*').append(' ');
addPadding(buffy, prePadding);
@ -335,21 +332,56 @@ public class PlateFieldFactory extends FieldFactory {
ellipsisLength > 0);
}
private void addPadding(StringBuffer buf, int count) {
private void addPadding(StringBuilder buf, int count) {
for (int i = 0; i < count; i++) {
buf.append(' ');
}
}
private void generateDefaultPlate(List<FieldElement> elementList, CodeUnit cu) {
String defaultComment = getDefaultComment(cu);
if (defaultComment != null) {
AttributedString as = new AttributedString(defaultComment, color, getMetrics());
elementList.add(new TextFieldElement(as, 0, 0));
addBorder(elementList);
private void addBlankLines(List<FieldElement> elements, int numberBlankLines, CodeUnit cu) {
AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics());
for (int row = 0; row < numberBlankLines; row++) {
elements.add(new TextFieldElement(prototype, row, 0));
}
}
private int getNumberBlankLines(CodeUnit cu, boolean hasPlate) {
if (cu.getProgram().getListing().getFunctionAt(cu.getMinAddress()) != null) {
if (nLinesBeforeFunctions != 0) {
return nLinesBeforeFunctions;
}
}
if (hasPlate && nLinesBeforePlates != 0) {
return nLinesBeforePlates;
}
if (cu.getLabel() != null) {
return nLinesBeforeLabels;
}
return 0;
}
private void generateDefaultPlate(List<FieldElement> elements, String defaultComment) {
if (defaultComment == null) {
return;
}
AttributedString asteriscs = getStarsString();
int row = elements.size();
// top border
elements.add(0, new TextFieldElement(asteriscs, row++, 0));
AttributedString as = new AttributedString(defaultComment, color, getMetrics());
elements.add(new TextFieldElement(as, row++, 0));
addSideBorders(elements, 1);
// bottom border
elements.add(new TextFieldElement(asteriscs, row++, 0));
}
private String getDefaultComment(CodeUnit cu) {
if (showFunctionPlates) {
@ -367,11 +399,6 @@ public class PlateFieldFactory extends FieldFactory {
return SUBROUTINE_PLATE_COMMENT;
}
// TODO handle case statements?
// if (showCasePlates) {
// return CASE_PLATE_COMMENT;
// }
if (showTransitionPlates) {
if (isDeadCode(cu)) {
return DEAD_CODE_PLATE_COMMENT;
@ -432,7 +459,7 @@ public class PlateFieldFactory extends FieldFactory {
int n = width / starWidth;
if (stars.length() != n) {
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
for (int i = 0; i < n; i++) {
buf.append('*');
}
@ -465,18 +492,18 @@ public class PlateFieldFactory extends FieldFactory {
((ListingTextField) listingField).screenToDataLocation(row, col);
//
// The 'row' value is an offset from the top of the plate comment, which has 0 or
// more blank lines at the top, followed by a line of asterisks.
// The 'row' value includes blank lines and header decoration lines. The 'commentRow' used
// below is the index into the list of comments. Calculate the comment beginning by
// removing the non-comment lines.
//
int fillerLineCount = getNumberOfLeadingFillerLines(listingField);
int commentRow = row - fillerLineCount;
if (commentRow >= comments.length) {
commentRow = -1; // clicked the bottom decoration line
if (commentRow >= comments.length || commentRow < 0) {
commentRow = -1; // clicked above the comment or the bottom decoration line
}
return new PlateFieldLocation(cu.getProgram(), ((CodeUnit) proxyObject).getMinAddress(),
cpath, dataLocation.row(), dataLocation.col(), comments, commentRow);
cpath, commentRow, dataLocation.col(), comments, commentRow);
}
private int getNumberOfLeadingFillerLines(ListingField listingField) {
@ -491,6 +518,7 @@ public class PlateFieldFactory extends FieldFactory {
@Override
public FieldLocation getFieldLocation(ListingField listingField, BigInteger index, int fieldNum,
ProgramLocation programLoc) {
if (!(programLoc instanceof CommentFieldLocation)) {
return null;
}
@ -507,8 +535,40 @@ public class PlateFieldFactory extends FieldFactory {
return null;
}
/*
Calculate the data row using the model row provided in the location, along with
compensating for any spacing and plate comment decorations. For example, for this
comment,
This is line one
This is line two
the plate comment may look like this
(blank line)
****************************
* This is line one
* This is line two
*****************************
*/
CodeUnit cu = (CodeUnit) obj;
String commentText = getCommentText(cu);
boolean hasComment = true;
if (StringUtils.isBlank(commentText)) {
String defaultComment = getDefaultComment(cu);
if (defaultComment == null) {
hasComment = false;
}
}
int commentRow = commentLocation.getRow();
int numberBlankLines = getNumberBlankLines(cu, hasComment);
int headerCount = hasComment ? 1 : 0;
int dataRow = commentRow + numberBlankLines + headerCount;
ListingTextField listingTextField = (ListingTextField) listingField;
RowColLocation location = listingTextField.dataToScreenLocation(commentLocation.getRow(),
RowColLocation location = listingTextField.dataToScreenLocation(dataRow,
commentLocation.getCharOffset());
return new FieldLocation(index, fieldNum, location.row(), location.col());
}
@ -614,7 +674,7 @@ public class PlateFieldFactory extends FieldFactory {
Address prevAddr = cu.getMinAddress().subtractNoWrap(1);
return cu.getProgram().getListing().getCodeUnitContaining(prevAddr);
}
catch (Exception e) {
catch (AddressOverflowException e) {
// we are just being lazy and not validating before doing the subtract--SOCK!
}
return null;
@ -638,7 +698,7 @@ public class PlateFieldFactory extends FieldFactory {
}
initialized = true;
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
sb.append("\n");
for (int i = 0; i < 19; i++) {
sb.append("|");
@ -725,14 +785,13 @@ public class PlateFieldFactory extends FieldFactory {
int getLeadingFillerLineCount() {
int count = 0;
for (Field field : subFields) {
String text = field.getText().trim();
for (String line : getLines()) {
count++;
if (text.isEmpty()) {
if (line.isEmpty()) {
continue; // skip leading blank lines
}
if (text.startsWith("*")) {
if (line.startsWith("*")) {
break;
}
}

View file

@ -551,7 +551,7 @@ public class XRefFieldFactory extends FieldFactory {
List<XrefFieldElement> elements = new ArrayList<>();
FunctionManager functionManager = program.getFunctionManager();
Function currentFunction = functionManager.getFunctionContaining(cu.getMinAddress());
int n = tooMany ? maxXRefs + 1 : totalXrefs;
int n = tooMany ? maxXRefs : totalXrefs;
int count = 0;
for (; count < xrefs.size() && count < n; count++) {
Reference ref = xrefs.get(count);

View file

@ -896,7 +896,8 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest
assertEquals("XREFs Field.Display Local Block", names.get(1));
assertEquals("XREFs Field.Display Namespace", names.get(2));
assertEquals("XREFs Field.Display Reference Type", names.get(3));
assertEquals("XREFs Field.Maximum Number of XREFs to Display", names.get(4));
assertEquals("XREFs Field.Group by Function", names.get(4));
assertEquals("XREFs Field.Maximum Number of XREFs to Display", names.get(5));
assertTrue(cb.goToField(addr("0x1003d9f"), "XRef", 0, 0));
@ -968,7 +969,9 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest
btf = (ListingTextField) cb.getCurrentField();
assertEquals(9, btf.getNumRows());
options.setInt(names.get(4), 3);
// note: the 'group by function' option is tested in the XrefFieldFactoryTest
options.setInt(names.get(5), 3);
cb.updateNow();
assertTrue(cb.goToField(addr("0x1003d9f"), "XRef", 0, 0));
btf = (ListingTextField) cb.getCurrentField();

View file

@ -212,25 +212,25 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
for (int i = 0; i < 22; i++) {
scrollbar.getUnitIncrement(1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001027"), codeBrowser.getAddressTopOfScreen());
for (int i = 0; i < 18; i++) {
scrollbar.getUnitIncrement(-1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001000"), codeBrowser.getAddressTopOfScreen());
for (int i = 0; i < 16; i++) {
scrollbar.getBlockIncrement(1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001136"), codeBrowser.getAddressTopOfScreen());
for (int i = 0; i < 16; i++) {
scrollbar.getBlockIncrement(-1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001000"), codeBrowser.getAddressTopOfScreen());
}
@ -333,25 +333,25 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
for (int i = 0; i < 20; i++) {
scrollbar.getUnitIncrement(1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001025"), codeBrowser.getAddressTopOfScreen());
for (int i = 0; i < 16; i++) {
scrollbar.getUnitIncrement(-1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001000"), codeBrowser.getAddressTopOfScreen());
for (int i = 0; i < 16; i++) {
scrollbar.getBlockIncrement(1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001136"), codeBrowser.getAddressTopOfScreen());
for (int i = 0; i < 16; i++) {
scrollbar.getBlockIncrement(-1);
}
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(addr("0x1001000"), codeBrowser.getAddressTopOfScreen());
}
@ -412,7 +412,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
codeBrowser.goToField(addr("0x1007000"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x1007001"), "Address", 0, 0);
assertEquals("01007001", codeBrowser.getCurrentFieldText());
@ -423,7 +423,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
codeBrowser.goToField(addr("0x1007000"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x1007000"), "Address", 0, 0);
for (int i = 0; i < 7; i++) {
@ -450,7 +450,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
codeBrowser.goToField(addr("0x1007000"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x1007008"), "Address", 0, 0);
assertEquals("01007008", codeBrowser.getCurrentFieldText());
codeBrowser.goToField(addr("0x1007010"), "Address", 0, 0);
@ -458,7 +458,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
codeBrowser.goToField(addr("0x1007000"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x1007000"), "Address", 0, 0);
codeBrowser.goToField(addr("0x1007008"), "Address", 0, 0);
assertEquals("01007000", codeBrowser.getCurrentFieldText());
@ -477,14 +477,14 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
codeBrowser.goToField(addr("0x1007000"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x1007023"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x100702a"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForPostedSwingRunnables();
waitForSwing();
waitForSwing();
codeBrowser.goToField(addr("0x100702b"), "Address", 0, 0);
assertEquals("0100702b", codeBrowser.getCurrentFieldText());
@ -525,6 +525,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
goTo(codeBrowser, addr("0x1007000"));
for (int i = 0; i < 300; i++) {
cursorRight(fp);
if (!codeBrowser.getCurrentFieldText().equals(cb2.getCurrentFieldText())) {
@ -533,11 +534,11 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
assertEquals(codeBrowser.getCurrentFieldText(), cb2.getCurrentFieldText());
if (!codeBrowser.getCurrentFieldLoction().equals(cb2.getCurrentFieldLoction())) {
System.err.println("location no equal at cursor move: " + i);
System.err.println("location not equal at cursor move: " + i);
}
assertEquals(codeBrowser.getCurrentFieldLoction(), cb2.getCurrentFieldLoction());
}
}
@Test
@ -561,13 +562,13 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
codeBrowser.goToField(addr("0x1007000"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x1007023"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
codeBrowser.goToField(addr("0x100702a"), "+", 0, 0);
click(codeBrowser, 1);
waitForPostedSwingRunnables();
waitForSwing();
// this should open the other structure
codeBrowser.goToField(addr("0x1007023"), "Address", 0, 0);
@ -809,7 +810,7 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
fieldOptions.setInt(name, 0);
}
}
waitForPostedSwingRunnables();
waitForSwing();
plugin.updateNow();
}

View file

@ -187,7 +187,7 @@ public class SearchTextPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(commentsCB);
assertSelected(commentsCB);
// verify that the case sensitive checkbox is not selected
// verify that the case sensitive checkbox is not selected
JCheckBox csCB = (JCheckBox) findButton(dialog.getComponent(), "Case Sensitive");
assertNotNull(csCB);
assertNotSelected(csCB);
@ -216,7 +216,7 @@ public class SearchTextPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testSearchOptions() throws Exception {
// verify that the search dialog allows for searching Functions,
// Comments, labels, instruction mnemonics and operands, defined data
// Comments, labels, instruction mnemonics and operands, defined data
// mnemonics and values.
SearchTextDialog dialog = getDialog();
JCheckBox cb = (JCheckBox) findButton(dialog.getComponent(), "Functions");
@ -419,6 +419,8 @@ public class SearchTextPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
loc = cbPlugin.getCurrentLocation();
assertEquals(getAddr(0x01004192), loc.getAddress());
assertTrue(loc instanceof CommentFieldLocation);
assertEquals("Search result not placed at the matching character position", 15,
((CommentFieldLocation) loc).getCharOffset());
assertEquals(CodeUnit.PLATE_COMMENT, ((CommentFieldLocation) loc).getCommentType());
pressButton(searchButton);
@ -667,7 +669,7 @@ public class SearchTextPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
//
// test marker stuff
//
//
AddressSet set = getAddressesFromModel(model);
MarkerService markerService = tool.getService(MarkerService.class);
MarkerSet markerSet = markerService.getMarkerSet("Search", program);

View file

@ -15,8 +15,7 @@
*/
package ghidra.app.util.viewer.field;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
@ -57,10 +56,6 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
private Program program;
private GoToService goToService;
public PlateFieldFactoryTest() {
super();
}
@Before
public void setUp() throws Exception {
@ -151,8 +146,9 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
cu.setCommentAsArray(CodeUnit.PLATE_COMMENT,
new String[] { "this is", "a plate comment" });
// create a reference to addr
program.getReferenceManager().addMemoryReference(getAddr(0x010023ee), addr,
RefType.DATA, SourceType.USER_DEFINED, 0);
program.getReferenceManager()
.addMemoryReference(getAddr(0x010023ee), addr,
RefType.DATA, SourceType.USER_DEFINED, 0);
}
finally {
program.endTransaction(transactionID, true);
@ -189,8 +185,9 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
cu.setCommentAsArray(CodeUnit.PLATE_COMMENT, new String[] { originalText });
// create a reference to addr
program.getReferenceManager().addMemoryReference(getAddr(0x010023ee), addr,
RefType.DATA, SourceType.USER_DEFINED, 0);
program.getReferenceManager()
.addMemoryReference(getAddr(0x010023ee), addr,
RefType.DATA, SourceType.USER_DEFINED, 0);
}
finally {
program.endTransaction(transactionID, true);
@ -247,7 +244,7 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
public void testShowTransitionPlates() throws Exception {
// no plate comment
assertTrue(!cb.goToField(getAddr(0x1001100), PlateFieldFactory.FIELD_NAME, 1, 1));
assertFalse(cb.goToField(getAddr(0x1001100), PlateFieldFactory.FIELD_NAME, 1, 1));
setBooleanOption(PlateFieldFactory.SHOW_TRANSITION_PLATES_OPTION, true);
@ -282,7 +279,7 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
public void testShowSubroutinePlates() throws Exception {
// no subroutine plate comment
assertTrue(!cb.goToField(getAddr(0x1001200), PlateFieldFactory.FIELD_NAME, 1, 1));
assertFalse(cb.goToField(getAddr(0x1001200), PlateFieldFactory.FIELD_NAME, 1, 1));
setBooleanOption(PlateFieldFactory.SHOW_SUBROUTINE_PLATES_OPTION, true);
@ -297,28 +294,13 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testLinesBeforeFunction() throws Exception {
assertTrue(!cb.goToField(getAddr(0x1001300), PlateFieldFactory.FIELD_NAME, 1, 1));
assertFalse(cb.goToField(getAddr(0x1001300), PlateFieldFactory.FIELD_NAME, 1, 1));
setIntOption(PlateFieldFactory.LINES_BEFORE_FUNCTIONS_OPTION, 2);
assertTrue(cb.goToField(getAddr(0x1001300), PlateFieldFactory.FIELD_NAME, 1, 1));
ListingTextField tf = (ListingTextField) cb.getCurrentField();
assertEquals(2, tf.getNumRows());
// list.add(cu.getMinAddress());
//
// ArrayList<Address> list = new ArrayList<Address>();
// Listing listing = program.getListing();
//
// FunctionIterator iter = listing.getFunctions(true);
// while (iter.hasNext()) {
// Function f = iter.next();
// CodeUnit cu = listing.getCodeUnitAt(f.getEntryPoint());
// assertTrue(cbPlugin.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 1));
// ListingTextField tf = (ListingTextField) cbPlugin.getCurrentField();
// assertEquals(5, tf.getNumRows());
// list.add(cu.getMinAddress());
// }
// assertEquals(66, list.size());
}
@Test
@ -354,7 +336,7 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
Listing listing = program.getListing();
CodeUnit cu = listing.getCodeUnitAt(getAddr(0x1001500));
assertTrue(!cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 1));
assertFalse(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 1));
createPlateComment(cu, "This is a plate comment");
@ -465,8 +447,9 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
int transactionID = program.startTransaction("test");
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
try {
program.getSymbolTable().createLabel(addr, testName.getMethodName(),
SourceType.USER_DEFINED);
program.getSymbolTable()
.createLabel(addr, testName.getMethodName(),
SourceType.USER_DEFINED);
cu.setComment(CodeUnit.PLATE_COMMENT,
"this is a comment\ngo to the address 0x010028de");
}

View file

@ -39,6 +39,7 @@ public class ClippingTextField implements TextField {
protected int startX;
private int width;
private int preferredWidth;
private int numDataRows;
private String fullText;
private boolean isClipped;
@ -49,28 +50,40 @@ public class ClippingTextField implements TextField {
/**
* Constructs a new ClippingTextField that allows the cursor beyond the end
* of the line. This is just a pass through constructor that makes the call:
* of the line.
*
* <pre>
* this(startX, width, new AttributedString[] { textElement }, hlFactory, true);
* </pre>
*
* @param startX
* The x position of the field
* @param width
* The width of the field
* @param textElement
* The AttributedStrings to display in the field.
* @param hlFactory
* The HighlightFactory object used to paint highlights.
* @param startX The x position of the field
* @param width The width of the field
* @param textElement The AttributedStrings to display in the field.
* @param hlFactory The HighlightFactory object used to paint highlights.
*/
public ClippingTextField(int startX, int width, FieldElement textElement,
HighlightFactory hlFactory) {
// default to one row
this(startX, width, textElement, 1, hlFactory);
}
/**
* Constructs a new ClippingTextField that allows the cursor beyond the end
* of the line.
*
* <p>This constructor allows clients to specify the number of data rows that have been
* converted into a single screen row.
*
* @param startX The x position of the field
* @param width The width of the field
* @param textElement The AttributedStrings to display in the field.
* @param numDataRows the number of data rows represented by this single screen row field
* @param hlFactory The HighlightFactory object used to paint highlights.
*/
public ClippingTextField(int startX, int width, FieldElement textElement, int numDataRows,
HighlightFactory hlFactory) {
this.textElement = textElement;
this.hlFactory = hlFactory;
this.startX = startX;
this.width = width;
this.numDataRows = numDataRows;
this.textElement = textElement;
this.hlFactory = hlFactory;
this.preferredWidth = textElement.getStringWidth();
clip(width);
@ -139,7 +152,7 @@ public class ClippingTextField implements TextField {
@Override
public int getNumDataRows() {
return 1;
return numDataRows;
}
@Override
@ -336,18 +349,13 @@ public class ClippingTextField implements TextField {
@Override
public RowColLocation screenToDataLocation(int screenRow, int screenColumn) {
return originalElement.getDataLocationForCharacterIndex(screenColumn);
}
@Override
public RowColLocation dataToScreenLocation(int dataRow, int dataColumn) {
int column = textElement.getCharacterIndexForDataLocation(dataRow, dataColumn);
if (column < 0) {
// place at the end if past the end
if (dataColumn >= textElement.length()) {
return new DefaultRowColLocation(0, textElement.length());
}
return new DefaultRowColLocation();
return new DefaultRowColLocation(0, textElement.length());
}
return new RowColLocation(0, column);
}

View file

@ -22,6 +22,7 @@ import java.util.List;
import javax.swing.JComponent;
import docking.widgets.fieldpanel.support.RowColLocation;
import generic.json.Json;
/**
* A FieldElement that is composed of other FieldElements. The elements are laid out horizontally.
@ -107,46 +108,6 @@ public class CompositeFieldElement implements FieldElement {
return heightBelow;
}
//==================================================================================================
// FontMetrics methods
//==================================================================================================
@Override
public int getStringWidth() {
if (textWidth == -1) {
textWidth = 0;
for (FieldElement fieldElement : fieldElements) {
textWidth += fieldElement.getStringWidth();
}
}
return textWidth;
}
@Override
public String getText() {
if (fullText == null) {
StringBuilder buffer = new StringBuilder();
for (FieldElement fieldElement : fieldElements) {
buffer.append(fieldElement.getText());
}
fullText = buffer.toString();
}
return fullText;
}
//==================================================================================================
// Paint methods
//==================================================================================================
@Override
public void paint(JComponent c, Graphics g, int x, int y) {
int xPos = x;
for (FieldElement fieldElement : fieldElements) {
fieldElement.paint(c, g, xPos, y);
xPos += fieldElement.getStringWidth();
}
}
@Override
public FieldElement replaceAll(char[] targets, char repacement) {
FieldElement[] newStrings = new FieldElement[fieldElements.length];
@ -191,16 +152,6 @@ public class CompositeFieldElement implements FieldElement {
return new CompositeFieldElement(newStrings);
}
private static class IndexedOffset {
int index;
int offset;
IndexedOffset(int index, int offset) {
this.index = index;
this.offset = offset;
}
}
@Override
public FieldElement getFieldElement(int column) {
IndexedOffset startPos = getIndexedOffsetForCharPosition(column);
@ -217,6 +168,46 @@ public class CompositeFieldElement implements FieldElement {
return getText();
}
@Override
public int getStringWidth() {
if (textWidth == -1) {
textWidth = 0;
for (FieldElement fieldElement : fieldElements) {
textWidth += fieldElement.getStringWidth();
}
}
return textWidth;
}
@Override
public String getText() {
if (fullText == null) {
StringBuilder buffer = new StringBuilder();
for (FieldElement fieldElement : fieldElements) {
buffer.append(fieldElement.getText());
}
fullText = buffer.toString();
}
return fullText;
}
@Override
public void paint(JComponent c, Graphics g, int x, int y) {
int xPos = x;
for (FieldElement fieldElement : fieldElements) {
fieldElement.paint(c, g, xPos, y);
xPos += fieldElement.getStringWidth();
}
}
/**
* Returns the number of sub-elements contained in this field
* @return the number of sub-elements contained in this field
*/
public int getNumElements() {
return fieldElements.length;
}
//==================================================================================================
// Location Info
//==================================================================================================
@ -229,6 +220,7 @@ public class CompositeFieldElement implements FieldElement {
@Override
public int getCharacterIndexForDataLocation(int dataRow, int dataColumn) {
int columnsSoFar = 0;
for (int i = fieldElements.length - 1; i >= 0; i--) {
columnsSoFar += fieldElements[i].length();
@ -242,4 +234,20 @@ public class CompositeFieldElement implements FieldElement {
return -1;
}
private static class IndexedOffset {
int index;
int offset;
IndexedOffset(int index, int offset) {
this.index = index;
this.offset = offset;
}
@Override
public String toString() {
return Json.toString(this);
}
}
}

View file

@ -342,12 +342,15 @@ public class CompositeVerticalLayoutTextField implements TextField {
}
private FieldRow getFieldRowFromDataRow(int dataRow) {
int currentRow = 0;
for (FieldRow row : fieldRows) {
if (currentRow >= dataRow) {
int length = row.field.getNumDataRows();
if (currentRow + length > dataRow) {
return row;
}
currentRow += row.field.getNumDataRows();
currentRow += length;
}
return fieldRows.get(fieldRows.size() - 1);
}

View file

@ -20,8 +20,9 @@ import java.util.*;
import docking.widgets.fieldpanel.support.HighlightFactory;
/**
* This class provides a TextField implementation that takes multiple AttributedStrings and places
* as many that will fit on a line without clipping before continuing to the next line.
* This class provides a TextField implementation that takes multiple AttributedString field
* elements and places as many that will fit on a line without clipping before continuing to the
* next line.
*/
public class FlowLayoutTextField extends VerticalLayoutTextField {
@ -67,27 +68,35 @@ public class FlowLayoutTextField extends VerticalLayoutTextField {
int currentIndex = 0;
while (currentIndex < elements.size()) {
int numberPerLine = getNumberOfElementsPerLine(elements, currentIndex, width);
subFields.add(createLine(elements, currentIndex, numberPerLine));
subFields.add(createLineFromElements(elements, currentIndex, numberPerLine));
currentIndex += numberPerLine;
}
return subFields;
}
private static CompositeFieldElement createLine(List<FieldElement> elements, int from,
int length) {
return new CompositeFieldElement(elements.subList(from, from + length));
@Override
protected TextField createFieldForLine(FieldElement element) {
CompositeFieldElement composite = (CompositeFieldElement) element;
int numDataRows = composite.getNumElements();
return new ClippingTextField(startX, width, element, numDataRows, hlFactory);
}
private static CompositeFieldElement createLineFromElements(List<FieldElement> elements,
int start, int length) {
return new CompositeFieldElement(elements.subList(start, start + length));
}
private static int getNumberOfElementsPerLine(List<FieldElement> elements, int start,
int width) {
int currentWidth = 0;
int count = 0;
for (FieldElement element : elements) {
for (int i = start; i < elements.size(); i++) {
FieldElement element = elements.get(i);
currentWidth += element.getStringWidth();
count++;
if (currentWidth > width) {
return Math.max(count - 1, 1);
int count = i - start;
return Math.max(count, 1);
}
}
return elements.size() - start;

View file

@ -16,7 +16,8 @@
package docking.widgets.fieldpanel.field;
import java.awt.*;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JComponent;
@ -26,6 +27,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.widgets.fieldpanel.internal.FieldBackgroundColorManager;
import docking.widgets.fieldpanel.internal.PaintContext;
import docking.widgets.fieldpanel.support.*;
import generic.json.Json;
/**
* This class provides a TextField implementation that takes multiple FieldElements and places
@ -33,7 +35,10 @@ import docking.widgets.fieldpanel.support.*;
*/
public class VerticalLayoutTextField implements TextField {
protected List<TextField> subFields; // list of fields for FieldElements
//
// The sub-fields of this text field. Each FieldRow has a Field, a screen row and a data row.
//
protected List<FieldRow> subFields;
protected int startX;
protected int width;
protected int preferredWidth;
@ -136,16 +141,16 @@ public class VerticalLayoutTextField implements TextField {
}
protected void calculateHeight() {
heightAbove = (subFields.get(0)).getHeightAbove();
for (Field field : subFields) {
height += field.getHeight();
heightAbove = (subFields.get(0)).field.getHeightAbove();
for (FieldRow fieldRow : subFields) {
height += fieldRow.field.getHeight();
}
}
private int calculatePreferredWidth() {
int widest = 0;
for (Field field : subFields) {
widest = Math.max(widest, field.getPreferredWidth());
for (FieldRow fieldRow : subFields) {
widest = Math.max(widest, fieldRow.field.getPreferredWidth());
}
return widest;
}
@ -197,20 +202,21 @@ public class VerticalLayoutTextField implements TextField {
@Override
public int getNumCols(int row) {
Field f = subFields.get(row);
Field f = getField(row);
return f.getNumCols(0);
}
@Override
public int getRow(int y) {
if (y < 0) {
if (y < -heightAbove) {
return 0;
}
int heightSoFar = 0;
int heightSoFar = -heightAbove;
int n = subFields.size();
for (int i = 0; i < n; i++) {
Field f = subFields.get(i);
Field f = getField(i);
heightSoFar += f.getHeight();
if (heightSoFar > y) {
return i;
@ -221,7 +227,7 @@ public class VerticalLayoutTextField implements TextField {
@Override
public int getCol(int row, int x) {
Field f = subFields.get(row);
Field f = getField(row);
return f.getCol(0, x);
}
@ -230,7 +236,7 @@ public class VerticalLayoutTextField implements TextField {
int y = -heightAbove;
for (int i = 0; i < row; i++) {
Field f = subFields.get(row);
Field f = getField(i);
y += f.getHeight();
}
return y;
@ -238,7 +244,7 @@ public class VerticalLayoutTextField implements TextField {
@Override
public int getX(int row, int col) {
Field f = subFields.get(row);
Field f = getField(row);
return f.getX(0, col);
}
@ -248,7 +254,7 @@ public class VerticalLayoutTextField implements TextField {
if ((row < 0) || (row >= subFields.size())) {
return false;
}
Field f = subFields.get(row);
Field f = getField(row);
return f.isValid(0, col);
}
@ -295,7 +301,7 @@ public class VerticalLayoutTextField implements TextField {
int translatedY = 0;
int extraSpace = rowSeparator.length();
for (int i = 0; i < n; i++) {
ClippingTextField subField = (ClippingTextField) subFields.get(i);
ClippingTextField subField = (ClippingTextField) getField(i);
int subFieldHeight = subField.getHeight();
int endY = startY + subFieldHeight;
@ -332,7 +338,7 @@ public class VerticalLayoutTextField implements TextField {
private void print(Graphics g, PaintContext context) {
int n = subFields.size();
for (int i = 0; i < n; i++) {
ClippingTextField clippingField = (ClippingTextField) subFields.get(i);
ClippingTextField clippingField = (ClippingTextField) getField(i);
clippingField.print(g, context);
@ -346,10 +352,10 @@ public class VerticalLayoutTextField implements TextField {
if ((row < 0) || (row >= subFields.size())) {
return null;
}
Field f = subFields.get(row);
Field f = getField(row);
Rectangle r = f.getCursorBounds(0, col);
for (int i = 0; i < row; i++) {
f = subFields.get(row);
f = getField(i);
r.y += f.getHeight();
}
return r;
@ -370,10 +376,11 @@ public class VerticalLayoutTextField implements TextField {
if ((topOfScreen < -heightAbove) || (topOfScreen > height - heightAbove)) {
return max;
}
int row = getRow(topOfScreen);
int y = getY(row);
int rowOffset = topOfScreen - y;
int rowHeight = (subFields.get(row)).getHeight();
int rowHeight = getField(row).getHeight();
if (direction > 0) { // if scrolling down
return rowHeight - rowOffset;
}
@ -399,14 +406,6 @@ public class VerticalLayoutTextField implements TextField {
isPrimary = state;
}
/**
* Returns the list of subfields in this field.
* @return the list of subfields in this field.
*/
public List<Field> getSubfields() {
return Collections.unmodifiableList(subFields);
}
@Override
public int getHeightAbove() {
return heightAbove;
@ -425,17 +424,17 @@ public class VerticalLayoutTextField implements TextField {
@Override
public FieldElement getFieldElement(int screenRow, int screenColumn) {
TextField f = subFields.get(screenRow);
TextField f = getField(screenRow);
int fieldRow = 0; // each field is on a single row
return f.getFieldElement(fieldRow, screenColumn);
}
protected List<TextField> layoutElements(List<FieldElement> textElements, int maxLines) {
List<TextField> newSubFields = new ArrayList<>();
protected List<FieldRow> layoutElements(List<FieldElement> textElements, int maxLines) {
List<FieldRow> newSubFields = new ArrayList<>();
boolean tooManyLines = textElements.size() > maxLines;
int currentRow = 0;
for (int i = 0; i < textElements.size() && i < maxLines; i++) {
FieldElement element = textElements.get(i);
if (tooManyLines && (i == maxLines - 1)) {
@ -444,9 +443,13 @@ public class VerticalLayoutTextField implements TextField {
elements[1] = new StrutFieldElement(500);
element = new CompositeFieldElement(elements);
}
TextField field = new ClippingTextField(startX, width, element, hlFactory);
newSubFields.add(field);
TextField field = createFieldForLine(element);
int modelRow = currentRow;
int screenRow = newSubFields.size();
newSubFields.add(new FieldRow(field, modelRow, screenRow));
isClipped |= field.isClipped();
currentRow += field.getNumRows();
}
isClipped |= tooManyLines;
@ -455,38 +458,36 @@ public class VerticalLayoutTextField implements TextField {
}
/**
* Translates the row and column to a String index and character offset into
* that string.
* @param screenRow the row containing the location.
* @param screenColumn the character position in the row of the location
* @return a MultiStringLocation containing the string index and position
* within that string.
* Create the text field for given field element
* @param element the element
* @return the field
*/
protected TextField createFieldForLine(FieldElement element) {
return new ClippingTextField(startX, width, element, hlFactory);
}
@Override
public RowColLocation screenToDataLocation(int screenRow, int screenColumn) {
screenRow = Math.min(screenRow, subFields.size() - 1);
screenRow = Math.max(screenRow, 0);
TextField field = subFields.get(screenRow);
TextField field = getField(screenRow);
screenColumn = Math.min(screenColumn, field.getText().length());
screenColumn = Math.max(screenColumn, 0);
int fieldRow = 0; // each field is on a single row
return field.screenToDataLocation(fieldRow, screenColumn);
int dataRow = getDataRow(field);
return field.screenToDataLocation(dataRow, screenColumn);
}
@Override
public RowColLocation dataToScreenLocation(int dataRow, int dataColumn) {
if (dataRow >= getNumRows()) {
TextField lastField = subFields.get(subFields.size());
return new DefaultRowColLocation(lastField.getText().length(), subFields.size() - 1);
}
TextField field = subFields.get(dataRow);
FieldRow fieldRow = getFieldRowFromDataRow(dataRow);
TextField field = fieldRow.field;
RowColLocation location = field.dataToScreenLocation(dataRow, dataColumn);
return location.withRow(dataRow);
int screenRow = fieldRow.screenRow;
return location.withRow(screenRow);
}
@Override
@ -517,7 +518,8 @@ public class VerticalLayoutTextField implements TextField {
}
int lastRow = n - 1;
int lastColumn = subFields.get(lastRow).getText().length();
TextField field = getField(lastRow);
int lastColumn = field.getText().length();
return new DefaultRowColLocation(lastRow, lastColumn);
}
@ -525,4 +527,54 @@ public class VerticalLayoutTextField implements TextField {
public boolean isClipped() {
return isClipped;
}
/**
* Returns the view's text lines of this field
* @return the lines
*/
protected List<String> getLines() {
return lines;
}
private TextField getField(int screenRow) {
return subFields.get(screenRow).field;
}
private FieldRow getFieldRowFromDataRow(int dataRow) {
int currentRow = 0;
for (FieldRow row : subFields) {
int length = row.field.getNumDataRows();
if (currentRow + length > dataRow) {
return row;
}
currentRow += length;
}
return subFields.get(subFields.size() - 1);
}
private int getDataRow(TextField field) {
for (FieldRow fieldRow : subFields) {
if (fieldRow.field == field) {
return fieldRow.dataRow;
}
}
return 0;
}
private class FieldRow {
private TextField field;
private int dataRow;
private int screenRow;
FieldRow(TextField field, int dataRow, int screenRow) {
this.field = field;
this.dataRow = dataRow;
this.screenRow = screenRow;
}
@Override
public String toString() {
return Json.toString(this);
}
}
}

View file

@ -47,6 +47,22 @@ public class FlowLayoutTextFieldTest extends AbstractGenericTest {
FontMetrics fm = tk.getFontMetrics(font);
List<FieldElement> elements = new ArrayList<>();
/*
Data Rows:
Hello
World
Supercalifragilisticexpialidocious
Wow!
Screen Rows:
Hello World
Supercalifra...
Wow
*/
elements.add(new TextFieldElement(new AttributedString("Hello ", Color.BLUE, fm), 0, 0));
elements.add(new TextFieldElement(
new AttributedString("World ", Color.RED, fm, true, Color.BLUE), 1, 0));
@ -95,17 +111,19 @@ public class FlowLayoutTextFieldTest extends AbstractGenericTest {
assertEquals(new RowColLocation(1, 0), textField.dataToScreenLocation(2, 0));
assertEquals(new RowColLocation(1, 4), textField.dataToScreenLocation(2, 4));
assertEquals(new RowColLocation(1, 15), textField.dataToScreenLocation(2, 15));
// Supercalifra (12 chars); ... (3 chars); Supercalifra... (15 chars)
assertEquals(new DefaultRowColLocation(1, 12), textField.dataToScreenLocation(2, 15));
assertEquals(new RowColLocation(2, 0), textField.dataToScreenLocation(3, 0));
assertEquals(new RowColLocation(2, 4), textField.dataToScreenLocation(3, 4));
assertEquals(new RowColLocation(0, 0), textField.dataToScreenLocation(0, 12));
assertEquals(new RowColLocation(0, 0), textField.dataToScreenLocation(0, 75));
assertEquals(new DefaultRowColLocation(0, 12), textField.dataToScreenLocation(0, 12));
assertEquals(new DefaultRowColLocation(0, 12), textField.dataToScreenLocation(0, 75));
}
@Test
public void testGetRowColumn() {
public void testTextOffsetToScreenLocation() {
assertEquals(new RowColLocation(0, 0), textField.textOffsetToScreenLocation(0));
assertEquals(new RowColLocation(0, 5), textField.textOffsetToScreenLocation(5));
assertEquals(new RowColLocation(0, 6), textField.textOffsetToScreenLocation(6));
@ -116,7 +134,8 @@ public class FlowLayoutTextFieldTest extends AbstractGenericTest {
assertEquals(new RowColLocation(1, 3), textField.textOffsetToScreenLocation(15));
assertEquals(new RowColLocation(1, 18), textField.textOffsetToScreenLocation(30));
assertEquals(new RowColLocation(2, 0), textField.textOffsetToScreenLocation(47));
assertEquals(new RowColLocation(2, 5), textField.textOffsetToScreenLocation(1000));
assertEquals(new DefaultRowColLocation(2, 5), textField.textOffsetToScreenLocation(1000));
}
}

View file

@ -324,7 +324,7 @@ public class CompositeVerticalLayoutTextFieldTest extends AbstractGenericTest {
assertRowCol(1, 5, field.dataToScreenLocation(1, 5));
// try accessing clipped rows
assertRowCol(1, 0, field.dataToScreenLocation(2, 0));
assertRowCol(1, 5, field.dataToScreenLocation(2, 0));
assertRowCol(1, 5, field.dataToScreenLocation(2, 5));
assertRowCol(1, 5, field.dataToScreenLocation(20, 50));
}

View file

@ -435,7 +435,7 @@ public class ClipboardPluginTest extends AbstractGhidraHeadedIntegrationTest {
String operandPrefix = "dword ptr [EBP + ";
String operandReferenceName = "destStr]";
OperandFieldLocation variableOperandReferenceLocation = new OperandFieldLocation(program,
addr("0100416c"), null, addr("0x8"), operandPrefix + operandReferenceName, 1, 9);
addr("0100416c"), null, addr("0x8"), operandPrefix + operandReferenceName, 0, 9);
codeBrowserPlugin.goTo(variableOperandReferenceLocation);
DockingAction pasteAction = getAction(codeBrowserClipboardProvider, PASTE_ACTION_NAME);
@ -1551,8 +1551,8 @@ public class ClipboardPluginTest extends AbstractGhidraHeadedIntegrationTest {
}
/*
* We remove the FieldPanel focus listeners for these tests, as when they lose focus,
* the selection mechanism does not work as expected. Focus changes can happen
* We remove the FieldPanel focus listeners for these tests, as when they lose focus,
* the selection mechanism does not work as expected. Focus changes can happen
* indeterminately during parallel batch testing.
*/
private void removeFieldPanelFocusListeners(Container c) {