mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1717 - Fixed Plate Comment rending bugs
This commit is contained in:
parent
c3c20d9e0f
commit
087529c448
5 changed files with 247 additions and 253 deletions
|
@ -21,11 +21,7 @@ import javax.lang.model.element.*;
|
||||||
import javax.lang.model.type.*;
|
import javax.lang.model.type.*;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
import db.DBHandle;
|
|
||||||
import ghidra.util.database.DBCachedDomainObjectAdapter;
|
|
||||||
import ghidra.util.database.DBOpenMode;
|
|
||||||
import ghidra.util.database.annot.DBAnnotatedField;
|
import ghidra.util.database.annot.DBAnnotatedField;
|
||||||
import ghidra.util.task.TaskMonitor;
|
|
||||||
|
|
||||||
public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
final VariableElement field;
|
final VariableElement field;
|
||||||
|
@ -127,31 +123,8 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
return codecElem;
|
return codecElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
class A extends DBCachedDomainObjectAdapter {
|
|
||||||
|
|
||||||
protected A(DBHandle dbh, DBOpenMode openMode, TaskMonitor monitor, String name,
|
|
||||||
int timeInterval, int bufSize, Object consumer) {
|
|
||||||
super(dbh, openMode, monitor, name, timeInterval, bufSize, consumer);
|
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChangeable() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void checkCodecTypes(TypeElement objectType) {
|
protected void checkCodecTypes(TypeElement objectType) {
|
||||||
|
|
||||||
//experiment(new Blargh(null, null));
|
|
||||||
|
|
||||||
TypeElement codecType = getCodecTypeElement();
|
TypeElement codecType = getCodecTypeElement();
|
||||||
if (codecType == null) {
|
if (codecType == null) {
|
||||||
ctx.messager.printMessage(Kind.ERROR,
|
ctx.messager.printMessage(Kind.ERROR,
|
||||||
|
@ -169,13 +142,13 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
// 3) FieldType is non-abstract
|
// 3) FieldType is non-abstract
|
||||||
// 4) The codec has an appropriate constructor
|
// 4) The codec has an appropriate constructor
|
||||||
|
|
||||||
for (Element enc : codecType.getEnclosedElements()) {
|
// for (Element enc : codecType.getEnclosedElements()) {
|
||||||
if (enc.getKind() == ElementKind.CONSTRUCTOR) {
|
// if (enc.getKind() == ElementKind.CONSTRUCTOR) {
|
||||||
ExecutableElement exe = (ExecutableElement) enc;
|
// ExecutableElement exe = (ExecutableElement) enc;
|
||||||
ExecutableType exeType = (ExecutableType) exe.asType();
|
// ExecutableType exeType = (ExecutableType) exe.asType();
|
||||||
//throw new RuntimeException();
|
// //throw new RuntimeException();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Map<String, TypeMirror> args = ctx.getArguments(codecType, ctx.DB_FIELD_CODEC_ELEM);
|
Map<String, TypeMirror> args = ctx.getArguments(codecType, ctx.DB_FIELD_CODEC_ELEM);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -28,29 +27,33 @@ import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||||
public interface ListingField extends Field {
|
public interface ListingField extends Field {
|
||||||
/**
|
/**
|
||||||
* Returns the FieldFactory that generated this Field
|
* Returns the FieldFactory that generated this Field
|
||||||
|
* @return the FieldFactory that generated this Field
|
||||||
*/
|
*/
|
||||||
public FieldFactory getFieldFactory();
|
public FieldFactory getFieldFactory();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the height above the imaginary base line used for alignment of
|
* Returns the height above the imaginary base line used for alignment of fields.
|
||||||
* fields.
|
|
||||||
*/
|
*/
|
||||||
int getHeightAbove();
|
@Override
|
||||||
|
public int getHeightAbove();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the height below the imaginary base line used for alignment of
|
* Returns the height below the imaginary base line used for alignment of fields.
|
||||||
* fields.
|
|
||||||
*/
|
*/
|
||||||
int getHeightBelow();
|
@Override
|
||||||
|
public int getHeightBelow();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the fieldModel that has the FieldFactory that generated this field.
|
* Returns the fieldModel that has the FieldFactory that generated this field.
|
||||||
|
* @return the fieldModel that has the FieldFactory that generated this field.
|
||||||
*/
|
*/
|
||||||
public FieldFormatModel getFieldModel();
|
public FieldFormatModel getFieldModel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object that the fieldFactory used to generate the information
|
* Returns the object that the fieldFactory used to generate the information in this field.
|
||||||
* in this field.
|
* @return the object that the fieldFactory used to generate the information in this field.
|
||||||
*/
|
*/
|
||||||
public ProxyObj getProxy();
|
public ProxyObj<?> getProxy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object that was clicked on a Field for the given FieldLocation. This may be the
|
* Returns the object that was clicked on a Field for the given FieldLocation. This may be the
|
||||||
|
@ -59,5 +62,5 @@ public interface ListingField extends Field {
|
||||||
* @param fieldLocation The location that was clicked.
|
* @param fieldLocation The location that was clicked.
|
||||||
* @return the object that was clicked
|
* @return the object that was clicked
|
||||||
*/
|
*/
|
||||||
public Object getClickedObject( FieldLocation fieldLocation );
|
public Object getClickedObject(FieldLocation fieldLocation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,31 +57,31 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
*/
|
*/
|
||||||
private static final int CONTENT_PADDING = 4;
|
private static final int CONTENT_PADDING = 4;
|
||||||
private static final String ELLIPSIS = "...";
|
private static final String ELLIPSIS = "...";
|
||||||
final static String FUNCTION_PLATE_COMMENT = " FUNCTION";
|
public final static String FUNCTION_PLATE_COMMENT = "FUNCTION";
|
||||||
final static String THUNK_FUNCTION_PLATE_COMMENT = " THUNK FUNCTION";
|
private static final String THUNK_FUNCTION_PLATE_COMMENT = "THUNK FUNCTION";
|
||||||
final static String POINTER_TO_EXTERNAL_FUNCTION_COMMENT = " POINTER to EXTERNAL FUNCTION";
|
private static final String POINTER_TO_EXTERNAL_FUNCTION_COMMENT =
|
||||||
final static String POINTER_TO_NONEXTERNAL_FUNCTION_COMMENT = " POINTER to FUNCTION";
|
"POINTER to EXTERNAL FUNCTION";
|
||||||
final static String CASE_PLATE_COMMENT = " CASE";
|
private static final String POINTER_TO_NONEXTERNAL_FUNCTION_COMMENT = "POINTER to FUNCTION";
|
||||||
final static String EXT_ENTRY_PLATE_COMMENT = " EXTERNAL ENTRY";
|
static final String EXT_ENTRY_PLATE_COMMENT = "EXTERNAL ENTRY";
|
||||||
final static String DEAD_CODE_PLATE_COMMENT = " DEAD";
|
static final String DEAD_CODE_PLATE_COMMENT = "DEAD";
|
||||||
final static String SUBROUTINE_PLATE_COMMENT = " SUBROUTINE";
|
static final String SUBROUTINE_PLATE_COMMENT = "SUBROUTINE";
|
||||||
final static String DEFAULT_PLATE_COMMENT = " ";
|
static final String DEFAULT_PLATE_COMMENT = " ";
|
||||||
|
|
||||||
final static String GROUP_TITLE = "Format Code";
|
private static final String GROUP_TITLE = "Format Code";
|
||||||
final static String SHOW_SUBROUTINE_PLATES_OPTION =
|
static final String SHOW_SUBROUTINE_PLATES_OPTION =
|
||||||
GROUP_TITLE + Options.DELIMITER + " Show Subroutine Plates";
|
GROUP_TITLE + Options.DELIMITER + "Show Subroutine Plates";
|
||||||
final static String SHOW_FUNCTION_PLATES_OPTION =
|
static final String SHOW_FUNCTION_PLATES_OPTION =
|
||||||
GROUP_TITLE + Options.DELIMITER + " Show Function Plates";
|
GROUP_TITLE + Options.DELIMITER + "Show Function Plates";
|
||||||
final static String SHOW_TRANSITION_PLATES_OPTION =
|
static final String SHOW_TRANSITION_PLATES_OPTION =
|
||||||
GROUP_TITLE + Options.DELIMITER + " Show Transition Plates";
|
GROUP_TITLE + Options.DELIMITER + "Show Transition Plates";
|
||||||
final static String SHOW_EXT_ENTRY_PLATES_OPTION =
|
static final String SHOW_EXT_ENTRY_PLATES_OPTION =
|
||||||
GROUP_TITLE + Options.DELIMITER + " Show External Entry Plates";
|
GROUP_TITLE + Options.DELIMITER + "Show External Entry Plates";
|
||||||
|
|
||||||
final static String LINES_BEFORE_FUNCTIONS_OPTION =
|
static final String LINES_BEFORE_FUNCTIONS_OPTION =
|
||||||
GROUP_TITLE + Options.DELIMITER + "Lines Before Functions";
|
GROUP_TITLE + Options.DELIMITER + "Lines Before Functions";
|
||||||
final static String LINES_BEFORE_LABELS_OPTION =
|
static final String LINES_BEFORE_LABELS_OPTION =
|
||||||
GROUP_TITLE + Options.DELIMITER + "Lines Before Labels";
|
GROUP_TITLE + Options.DELIMITER + "Lines Before Labels";
|
||||||
final static String LINES_BEFORE_PLATES_OPTION =
|
static final String LINES_BEFORE_PLATES_OPTION =
|
||||||
GROUP_TITLE + Options.DELIMITER + "Lines Before Plates";
|
GROUP_TITLE + Options.DELIMITER + "Lines Before Plates";
|
||||||
|
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
|
@ -91,7 +91,6 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
private boolean showSubroutinePlates;
|
private boolean showSubroutinePlates;
|
||||||
private boolean showTransitionPlates;
|
private boolean showTransitionPlates;
|
||||||
private boolean showExternalPlates;
|
private boolean showExternalPlates;
|
||||||
// private boolean showCasePlates;
|
|
||||||
|
|
||||||
private boolean showExternalFunctionPointerPlates;
|
private boolean showExternalFunctionPointerPlates;
|
||||||
private boolean showNonExternalFunctionPointerPlates;
|
private boolean showNonExternalFunctionPointerPlates;
|
||||||
|
@ -101,9 +100,6 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
private int nLinesBeforePlates;
|
private int nLinesBeforePlates;
|
||||||
private boolean isWordWrap;
|
private boolean isWordWrap;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public PlateFieldFactory() {
|
public PlateFieldFactory() {
|
||||||
super(FIELD_NAME);
|
super(FIELD_NAME);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +116,6 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||||
init(fieldOptions);
|
init(fieldOptions);
|
||||||
|
|
||||||
// showCasePlates = fieldOptions.getBoolean(name, SHOW_CASE_PLATES_OPTION, false);
|
|
||||||
isWordWrap = fieldOptions.getBoolean(ENABLE_WORD_WRAP_MSG, false);
|
isWordWrap = fieldOptions.getBoolean(ENABLE_WORD_WRAP_MSG, false);
|
||||||
showExternalPlates = fieldOptions.getBoolean(SHOW_EXT_ENTRY_PLATES_OPTION, false);
|
showExternalPlates = fieldOptions.getBoolean(SHOW_EXT_ENTRY_PLATES_OPTION, false);
|
||||||
showFunctionPlates = fieldOptions.getBoolean(SHOW_FUNCTION_PLATES_OPTION, true);
|
showFunctionPlates = fieldOptions.getBoolean(SHOW_FUNCTION_PLATES_OPTION, true);
|
||||||
|
@ -239,17 +234,16 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
// add top border
|
// add top border
|
||||||
elements.add(new TextFieldElement(asteriscs, row++, 0));
|
elements.add(new TextFieldElement(asteriscs, row++, 0));
|
||||||
|
|
||||||
int commentsStart = row;
|
// add and word wrap the comments
|
||||||
|
List<FieldElement> commentsList = new ArrayList<>();
|
||||||
for (String c : comments) {
|
for (String c : comments) {
|
||||||
FieldElement element = CommentUtils.parseTextForAnnotations(c, p, prototype, row++);
|
commentsList.add(CommentUtils.parseTextForAnnotations(c, p, prototype, row++));
|
||||||
elements.add(element);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWordWrap) {
|
if (isWordWrap) {
|
||||||
elements = FieldUtils.wordWrapList(new CompositeFieldElement(elements), width);
|
commentsList = FieldUtils.wordWrapList(new CompositeFieldElement(commentsList), width);
|
||||||
}
|
}
|
||||||
|
boolean isClipped = addSideBorders(commentsList);
|
||||||
boolean isClipped = addSideBorders(elements, commentsStart);
|
elements.addAll(commentsList);
|
||||||
|
|
||||||
// add bottom border
|
// add bottom border
|
||||||
elements.add(new TextFieldElement(asteriscs, row++, 0));
|
elements.add(new TextFieldElement(asteriscs, row++, 0));
|
||||||
|
@ -257,33 +251,13 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
return isClipped;
|
return isClipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean addSideBorders(List<FieldElement> comments) {
|
||||||
* Generate a text line for the plate text.
|
|
||||||
* 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, int commentsStart) {
|
|
||||||
boolean isClipped = false;
|
boolean isClipped = false;
|
||||||
|
|
||||||
// If there is only a single line comment, then center it
|
for (int i = 0; i < comments.size(); i++) {
|
||||||
int n = elements.size() - commentsStart;
|
FieldElementResult result = addSideBorder(comments.get(i), i, false);
|
||||||
if (n == 1) {
|
|
||||||
FieldElement element = elements.get(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());
|
|
||||||
return isClipped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = commentsStart; i < elements.size(); i++) {
|
|
||||||
FieldElementResult result = addSideBorder(elements.get(i), i, false);
|
|
||||||
isClipped |= result.isClipped();
|
isClipped |= result.isClipped();
|
||||||
elements.set(i, result.getFieldElement());
|
comments.set(i, result.getFieldElement());
|
||||||
}
|
}
|
||||||
return isClipped;
|
return isClipped;
|
||||||
}
|
}
|
||||||
|
@ -341,7 +315,7 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
private void addBlankLines(List<FieldElement> elements, int numberBlankLines, CodeUnit cu) {
|
private void addBlankLines(List<FieldElement> elements, int numberBlankLines, CodeUnit cu) {
|
||||||
AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics());
|
AttributedString prototype = new AttributedString(EMPTY_STRING, color, getMetrics());
|
||||||
for (int row = 0; row < numberBlankLines; row++) {
|
for (int row = 0; row < numberBlankLines; row++) {
|
||||||
elements.add(new TextFieldElement(prototype, row, 0));
|
elements.add(0, new TextFieldElement(prototype, row, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,14 +343,16 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
AttributedString asteriscs = getStarsString();
|
AttributedString asteriscs = getStarsString();
|
||||||
int row = elements.size();
|
int row = elements.size(); // blank lines
|
||||||
|
|
||||||
// top border
|
// top border
|
||||||
elements.add(0, new TextFieldElement(asteriscs, row++, 0));
|
elements.add(new TextFieldElement(asteriscs, row++, 0));
|
||||||
|
|
||||||
|
int commentRow = row++;
|
||||||
AttributedString as = new AttributedString(defaultComment, color, getMetrics());
|
AttributedString as = new AttributedString(defaultComment, color, getMetrics());
|
||||||
elements.add(new TextFieldElement(as, row++, 0));
|
TextFieldElement commentElement = new TextFieldElement(as, commentRow, 0);
|
||||||
addSideBorders(elements, 1);
|
FieldElementResult result = addSideBorder(commentElement, commentRow, true);
|
||||||
|
elements.add(result.getFieldElement());
|
||||||
|
|
||||||
// bottom border
|
// bottom border
|
||||||
elements.add(new TextFieldElement(asteriscs, row++, 0));
|
elements.add(new TextFieldElement(asteriscs, row++, 0));
|
||||||
|
@ -470,13 +446,15 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProgramLocation getProgramLocation(int row, int col, ListingField listingField) {
|
public ProgramLocation getProgramLocation(int row, int col, ListingField listingField) {
|
||||||
Object proxyObject = listingField.getProxy().getObject();
|
|
||||||
// if on a function, get the code unit there.
|
// if on a function, get the code unit there.
|
||||||
|
Object proxyObject = listingField.getProxy().getObject();
|
||||||
if (proxyObject instanceof Function) {
|
if (proxyObject instanceof Function) {
|
||||||
Function func = (Function) proxyObject;
|
Function func = (Function) proxyObject;
|
||||||
Listing listing = func.getProgram().getListing();
|
Listing listing = func.getProgram().getListing();
|
||||||
proxyObject = listing.getCodeUnitAt(func.getEntryPoint());
|
proxyObject = listing.getCodeUnitAt(func.getEntryPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(proxyObject instanceof CodeUnit)) {
|
if (!(proxyObject instanceof CodeUnit)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -698,12 +676,6 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
}
|
}
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("\n");
|
|
||||||
for (int i = 0; i < 19; i++) {
|
|
||||||
sb.append("|");
|
|
||||||
}
|
|
||||||
|
|
||||||
HelpLocation help = new HelpLocation(HelpTopics.CODE_BROWSER, "Format_Code");
|
HelpLocation help = new HelpLocation(HelpTopics.CODE_BROWSER, "Format_Code");
|
||||||
options.getOptions(GROUP_TITLE).setOptionsHelpLocation(help);
|
options.getOptions(GROUP_TITLE).setOptionsHelpLocation(help);
|
||||||
|
|
||||||
|
@ -719,8 +691,6 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
"Toggle for whether a plate comment should be displayed for subroutines.");
|
"Toggle for whether a plate comment should be displayed for subroutines.");
|
||||||
options.registerOption(SHOW_FUNCTION_PLATES_OPTION, true, help,
|
options.registerOption(SHOW_FUNCTION_PLATES_OPTION, true, help,
|
||||||
"Toggle for whether a plate comment should be displayed for functions.");
|
"Toggle for whether a plate comment should be displayed for functions.");
|
||||||
// options.registerOption(SHOW_CASE_PLATES_OPTION,false, help,
|
|
||||||
// "Toggle for whether a plate comment should be displayed for a case statement.");
|
|
||||||
options.registerOption(SHOW_TRANSITION_PLATES_OPTION, false, help,
|
options.registerOption(SHOW_TRANSITION_PLATES_OPTION, false, help,
|
||||||
"Toggle for whether a plate comment should be displayed for a change " +
|
"Toggle for whether a plate comment should be displayed for a change " +
|
||||||
"in the flow type between instructions, when data follows " +
|
"in the flow type between instructions, when data follows " +
|
||||||
|
@ -747,9 +717,9 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
private class PlateListingTextField extends ListingTextField {
|
class PlateListingTextField extends ListingTextField {
|
||||||
|
|
||||||
protected PlateListingTextField(ProxyObj<?> proxy, PlateFieldTextField field) {
|
PlateListingTextField(ProxyObj<?> proxy, PlateFieldTextField field) {
|
||||||
super(PlateFieldFactory.this, proxy, field);
|
super(PlateFieldFactory.this, proxy, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,12 +728,12 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PlateFieldTextField extends VerticalLayoutTextField {
|
class PlateFieldTextField extends VerticalLayoutTextField {
|
||||||
|
|
||||||
private boolean isCommentClipped;
|
private boolean isCommentClipped;
|
||||||
private String commentText;
|
private String commentText;
|
||||||
|
|
||||||
public PlateFieldTextField(List<FieldElement> textElements, PlateFieldFactory factory,
|
PlateFieldTextField(List<FieldElement> textElements, PlateFieldFactory factory,
|
||||||
ProxyObj<?> proxy, int startX, int width, String commentText,
|
ProxyObj<?> proxy, int startX, int width, String commentText,
|
||||||
boolean isCommentClipped) {
|
boolean isCommentClipped) {
|
||||||
super(textElements, startX, width, Integer.MAX_VALUE,
|
super(textElements, startX, width, Integer.MAX_VALUE,
|
||||||
|
@ -779,9 +749,16 @@ public class PlateFieldFactory extends FieldFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTextWithLineSeparators() {
|
public String getTextWithLineSeparators() {
|
||||||
|
// note: this is the comment text which will be blank for default plate comments
|
||||||
return commentText;
|
return commentText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getLines() {
|
||||||
|
// open up access for testing
|
||||||
|
return super.getLines();
|
||||||
|
}
|
||||||
|
|
||||||
int getLeadingFillerLineCount() {
|
int getLeadingFillerLineCount() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,7 @@ import static org.junit.Assert.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.SwingUtilities;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import docking.widgets.table.GTable;
|
import docking.widgets.table.GTable;
|
||||||
|
@ -36,6 +35,8 @@ import ghidra.app.plugin.core.navigation.NextPrevAddressPlugin;
|
||||||
import ghidra.app.plugin.core.table.TableComponentProvider;
|
import ghidra.app.plugin.core.table.TableComponentProvider;
|
||||||
import ghidra.app.plugin.core.table.TableServicePlugin;
|
import ghidra.app.plugin.core.table.TableServicePlugin;
|
||||||
import ghidra.app.services.GoToService;
|
import ghidra.app.services.GoToService;
|
||||||
|
import ghidra.app.util.viewer.field.PlateFieldFactory.PlateFieldTextField;
|
||||||
|
import ghidra.app.util.viewer.field.PlateFieldFactory.PlateListingTextField;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
|
@ -44,7 +45,6 @@ import ghidra.program.model.address.AddressSet;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.test.*;
|
import ghidra.test.*;
|
||||||
import ghidra.util.exception.AssertException;
|
|
||||||
import ghidra.util.table.GhidraProgramTableModel;
|
import ghidra.util.table.GhidraProgramTableModel;
|
||||||
|
|
||||||
public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
@ -116,15 +116,8 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Address addr = symbol.getAddress();
|
Address addr = symbol.getAddress();
|
||||||
Function function = program.getFunctionManager().getFunctionAt(addr);
|
Function function = program.getFunctionManager().getFunctionAt(addr);
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(function.getEntryPoint());
|
CodeUnit cu = program.getListing().getCodeUnitAt(function.getEntryPoint());
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
try {
|
tx(program, () -> cu.setComment(CodeUnit.PLATE_COMMENT, null));
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT, null);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
program.flushEvents();
|
|
||||||
waitForPostedSwingRunnables();
|
|
||||||
|
|
||||||
goToService.goTo(addr);
|
goToService.goTo(addr);
|
||||||
|
|
||||||
|
@ -140,21 +133,17 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
public void testExistingPlateComment() throws Exception {
|
public void testExistingPlateComment() throws Exception {
|
||||||
Symbol symbol = getUniqueSymbol(program, "entry");
|
Symbol symbol = getUniqueSymbol(program, "entry");
|
||||||
Address addr = symbol.getAddress();
|
Address addr = symbol.getAddress();
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
try {
|
tx(program, () -> {
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
||||||
cu.setCommentAsArray(CodeUnit.PLATE_COMMENT,
|
cu.setCommentAsArray(CodeUnit.PLATE_COMMENT,
|
||||||
new String[] { "this is", "a plate comment" });
|
new String[] { "this is", "a plate comment" });
|
||||||
// create a reference to addr
|
// create a reference to addr
|
||||||
program.getReferenceManager()
|
ReferenceManager rm = program.getReferenceManager();
|
||||||
.addMemoryReference(getAddr(0x010023ee), addr,
|
rm.addMemoryReference(getAddr(0x010023ee), addr, RefType.DATA, SourceType.USER_DEFINED,
|
||||||
RefType.DATA, SourceType.USER_DEFINED, 0);
|
0);
|
||||||
}
|
});
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
program.flushEvents();
|
|
||||||
waitForPostedSwingRunnables();
|
|
||||||
cb.updateNow();
|
cb.updateNow();
|
||||||
|
|
||||||
Function function = program.getFunctionManager().getFunctionAt(addr);
|
Function function = program.getFunctionManager().getFunctionAt(addr);
|
||||||
|
@ -180,21 +169,16 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
String originalText =
|
String originalText =
|
||||||
"this is a plate comment that is meant to be longer than the available " +
|
"this is a plate comment that is meant to be longer than the available " +
|
||||||
"width, as to trigger clipping";
|
"width, as to trigger clipping";
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
try {
|
tx(program, () -> {
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
||||||
cu.setCommentAsArray(CodeUnit.PLATE_COMMENT, new String[] { originalText });
|
cu.setCommentAsArray(CodeUnit.PLATE_COMMENT, new String[] { originalText });
|
||||||
// create a reference to addr
|
// create a reference to addr
|
||||||
program.getReferenceManager()
|
program.getReferenceManager()
|
||||||
.addMemoryReference(getAddr(0x010023ee), addr,
|
.addMemoryReference(getAddr(0x010023ee), addr,
|
||||||
RefType.DATA, SourceType.USER_DEFINED, 0);
|
RefType.DATA, SourceType.USER_DEFINED, 0);
|
||||||
}
|
});
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
program.flushEvents();
|
|
||||||
waitForPostedSwingRunnables();
|
|
||||||
cb.updateNow();
|
cb.updateNow();
|
||||||
|
|
||||||
goToService.goTo(addr);
|
goToService.goTo(addr);
|
||||||
|
@ -217,17 +201,13 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
Symbol symbol = getUniqueSymbol(program, "entry");
|
Symbol symbol = getUniqueSymbol(program, "entry");
|
||||||
Address addr = symbol.getAddress();
|
Address addr = symbol.getAddress();
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
try {
|
tx(program, () -> {
|
||||||
CreateFunctionCmd cmd = new CreateFunctionCmd(addr);
|
CreateFunctionCmd cmd = new CreateFunctionCmd(addr);
|
||||||
cmd.applyTo(program);
|
cmd.applyTo(program);
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT, null);
|
cu.setComment(CodeUnit.PLATE_COMMENT, null);
|
||||||
}
|
});
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
program.flushEvents();
|
|
||||||
waitForPostedSwingRunnables();
|
|
||||||
cb.updateNow();
|
cb.updateNow();
|
||||||
|
|
||||||
goToService.goTo(addr);
|
goToService.goTo(addr);
|
||||||
|
@ -263,7 +243,7 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
new DisassembleCommand(addr, new AddressSet(addr, getAddr(0x01004e39)), true);
|
new DisassembleCommand(addr, new AddressSet(addr, getAddr(0x01004e39)), true);
|
||||||
tool.execute(cmd, program);
|
tool.execute(cmd, program);
|
||||||
program.flushEvents();
|
program.flushEvents();
|
||||||
waitForPostedSwingRunnables();
|
waitForSwing();
|
||||||
|
|
||||||
setBooleanOption(PlateFieldFactory.SHOW_TRANSITION_PLATES_OPTION, true);
|
setBooleanOption(PlateFieldFactory.SHOW_TRANSITION_PLATES_OPTION, true);
|
||||||
assertTrue(cb.goToField(addr, PlateFieldFactory.FIELD_NAME, 1, 1));
|
assertTrue(cb.goToField(addr, PlateFieldFactory.FIELD_NAME, 1, 1));
|
||||||
|
@ -292,7 +272,7 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLinesBeforeFunction() throws Exception {
|
public void testLinesBeforeFunction_WithoutPlateComment() throws Exception {
|
||||||
|
|
||||||
assertFalse(cb.goToField(getAddr(0x1001300), PlateFieldFactory.FIELD_NAME, 1, 1));
|
assertFalse(cb.goToField(getAddr(0x1001300), PlateFieldFactory.FIELD_NAME, 1, 1));
|
||||||
|
|
||||||
|
@ -303,6 +283,35 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertEquals(2, tf.getNumRows());
|
assertEquals(2, tf.getNumRows());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLinesBeforeFunction_WithPlateComment() throws Exception {
|
||||||
|
|
||||||
|
setBooleanOption(PlateFieldFactory.SHOW_FUNCTION_PLATES_OPTION, true);
|
||||||
|
setIntOption(PlateFieldFactory.LINES_BEFORE_FUNCTIONS_OPTION, 2);
|
||||||
|
assertTrue(cb.goToField(getAddr(0x1001300), PlateFieldFactory.FIELD_NAME, 1, 1));
|
||||||
|
ListingTextField tf = (ListingTextField) cb.getCurrentField();
|
||||||
|
assertEquals(5, tf.getNumRows());
|
||||||
|
|
||||||
|
assertPrecedingBlankLines((PlateListingTextField) tf, 2);
|
||||||
|
int textRow = 3;
|
||||||
|
assertCentered((PlateListingTextField) tf, textRow,
|
||||||
|
PlateFieldFactory.FUNCTION_PLATE_COMMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultPlateCommentGetsCentered_Function() throws Exception {
|
||||||
|
|
||||||
|
setBooleanOption(PlateFieldFactory.SHOW_FUNCTION_PLATES_OPTION, true);
|
||||||
|
assertTrue(cb.goToField(getAddr(0x1001300), PlateFieldFactory.FIELD_NAME, 1, 1));
|
||||||
|
ListingTextField tf = (ListingTextField) cb.getCurrentField();
|
||||||
|
assertTrue(tf.getText().indexOf(PlateFieldFactory.FUNCTION_PLATE_COMMENT) >= 0);
|
||||||
|
assertEquals(3, tf.getNumRows());
|
||||||
|
|
||||||
|
int textRow = 1;
|
||||||
|
assertCentered((PlateListingTextField) tf, textRow,
|
||||||
|
PlateFieldFactory.FUNCTION_PLATE_COMMENT);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLinesBeforeLabels() throws Exception {
|
public void testLinesBeforeLabels() throws Exception {
|
||||||
|
|
||||||
|
@ -332,7 +341,7 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLinesBeforePlates() throws Exception {
|
public void testLinesBeforePlates_NonDefaultComment() throws Exception {
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
|
||||||
CodeUnit cu = listing.getCodeUnitAt(getAddr(0x1001500));
|
CodeUnit cu = listing.getCodeUnitAt(getAddr(0x1001500));
|
||||||
|
@ -349,20 +358,27 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 1));
|
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 1));
|
||||||
tf = (ListingTextField) cb.getCurrentField();
|
tf = (ListingTextField) cb.getCurrentField();
|
||||||
assertEquals(5, tf.getNumRows());
|
assertEquals(5, tf.getNumRows());
|
||||||
|
assertPrecedingBlankLines((PlateListingTextField) tf, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createPlateComment(CodeUnit cu, String text) {
|
@Test
|
||||||
int transactionID = program.startTransaction("test");
|
public void testLinesBeforePlates_DefaultPlateComment() throws Exception {
|
||||||
try {
|
Listing listing = program.getListing();
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT, text);
|
|
||||||
}
|
CodeUnit cu = listing.getCodeUnitAt(getAddr(0x1001500));
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
setBooleanOption(PlateFieldFactory.SHOW_FUNCTION_PLATES_OPTION, true);
|
||||||
}
|
|
||||||
program.flushEvents();
|
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 1));
|
||||||
waitForPostedSwingRunnables();
|
ListingTextField tf = (ListingTextField) cb.getCurrentField();
|
||||||
cb.updateNow();
|
assertEquals(3, tf.getNumRows());
|
||||||
|
|
||||||
|
setIntOption(PlateFieldFactory.LINES_BEFORE_PLATES_OPTION, 2);
|
||||||
|
|
||||||
|
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 1));
|
||||||
|
tf = (ListingTextField) cb.getCurrentField();
|
||||||
|
assertEquals(5, tf.getNumRows());
|
||||||
|
assertPrecedingBlankLines((PlateListingTextField) tf, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -419,15 +435,11 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
// add a plate comment that has an address in it
|
// add a plate comment that has an address in it
|
||||||
Address addr = getAddr(0x01002911);
|
Address addr = getAddr(0x01002911);
|
||||||
|
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
||||||
try {
|
tx(program, () -> {
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT,
|
cu.setComment(CodeUnit.PLATE_COMMENT,
|
||||||
"this is a comment\ngo to the address 0x010028de");
|
"this is a comment\ngo to the address 0x010028de");
|
||||||
}
|
});
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 2, 23));
|
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 2, 23));
|
||||||
click(cb, 2);
|
click(cb, 2);
|
||||||
|
|
||||||
|
@ -444,18 +456,14 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
// add a plate comment that has an address in it
|
// add a plate comment that has an address in it
|
||||||
Address addr = getAddr(0x01002911);
|
Address addr = getAddr(0x01002911);
|
||||||
|
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
CodeUnit cu = program.getListing().getCodeUnitAt(addr);
|
||||||
try {
|
tx(program, () -> {
|
||||||
program.getSymbolTable()
|
program.getSymbolTable()
|
||||||
.createLabel(addr, testName.getMethodName(),
|
.createLabel(addr, testName.getMethodName(),
|
||||||
SourceType.USER_DEFINED);
|
SourceType.USER_DEFINED);
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT,
|
cu.setComment(CodeUnit.PLATE_COMMENT,
|
||||||
"this is a comment\ngo to the address 0x010028de");
|
"this is a comment\ngo to the address 0x010028de");
|
||||||
}
|
});
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int nonCommentHeader = precedingBlankLines + 1; // +1 for the '***' line
|
int nonCommentHeader = precedingBlankLines + 1; // +1 for the '***' line
|
||||||
int row = nonCommentHeader + 1; // 1 is the second comment row
|
int row = nonCommentHeader + 1; // 1 is the second comment row
|
||||||
|
@ -469,14 +477,9 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
@Test
|
@Test
|
||||||
public void testNavigationOnLabel() throws Exception {
|
public void testNavigationOnLabel() throws Exception {
|
||||||
// add a plate comment that has "entry" in it
|
// add a plate comment that has "entry" in it
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(getAddr(0x0100292b));
|
CodeUnit cu = program.getListing().getCodeUnitAt(getAddr(0x0100292b));
|
||||||
try {
|
tx(program, () -> cu.setComment(CodeUnit.PLATE_COMMENT, "go to entry"));
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT, "go to entry");
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 8));
|
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 8));
|
||||||
click(cb, 2);
|
click(cb, 2);
|
||||||
|
|
||||||
|
@ -487,57 +490,31 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
@Test
|
@Test
|
||||||
public void testNavigationOnLabelWildcard() throws Exception {
|
public void testNavigationOnLabelWildcard() throws Exception {
|
||||||
// add a plate comment that has "entry" in it
|
// add a plate comment that has "entry" in it
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
CodeUnit cu = program.getListing().getCodeUnitAt(getAddr(0x01001100));
|
CodeUnit cu = program.getListing().getCodeUnitAt(getAddr(0x01001100));
|
||||||
try {
|
tx(program, () -> {
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT, "go to FUN*");
|
cu.setComment(CodeUnit.PLATE_COMMENT, "go to FUN*");
|
||||||
}
|
});
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 8));
|
assertTrue(cb.goToField(cu.getMinAddress(), PlateFieldFactory.FIELD_NAME, 1, 8));
|
||||||
click(cb, 2);
|
click(cb, 2);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
// should get the query results dialog that shows all the default function labels.
|
// should get the query results dialog that shows all the default function labels.
|
||||||
List<TableComponentProvider<?>> providers = waitForResultsTable();
|
List<TableComponentProvider<?>> providers = waitFor(() -> {
|
||||||
|
|
||||||
|
List<TableComponentProvider<?>> currentProviders = getNavigationResultsTables();
|
||||||
|
if (!currentProviders.isEmpty()) {
|
||||||
|
return currentProviders;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
assertEquals(1, providers.size());
|
assertEquals(1, providers.size());
|
||||||
GhidraProgramTableModel<?> model = waitForModel(providers.get(0));
|
GhidraProgramTableModel<?> model = waitForModel(providers.get(0));
|
||||||
assertEquals("01001300", model.getValueAt(0, 0).toString());
|
assertEquals("01001300", model.getValueAt(0, 0).toString());
|
||||||
assertEquals("01001500", model.getValueAt(1, 0).toString());
|
assertEquals("01001500", model.getValueAt(1, 0).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TableComponentProvider<?>> waitForResultsTable() {
|
|
||||||
|
|
||||||
List<TableComponentProvider<?>> providers = getNavigationResultsTables();
|
|
||||||
|
|
||||||
waitForSwing();
|
|
||||||
int nWaits = 0;
|
|
||||||
while (providers.isEmpty() && nWaits < 200) {
|
|
||||||
sleep(DEFAULT_WAIT_DELAY);
|
|
||||||
providers = getNavigationResultsTables();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nWaits >= 200) {
|
|
||||||
throw new AssertException("Timed out waiting for table model to load");
|
|
||||||
}
|
|
||||||
|
|
||||||
return providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<TableComponentProvider<?>> getNavigationResultsTables() {
|
|
||||||
TableServicePlugin plugin = getPlugin(tool, TableServicePlugin.class);
|
|
||||||
|
|
||||||
List<TableComponentProvider<?>> providers = new ArrayList<>();
|
|
||||||
runSwing(() -> {
|
|
||||||
TableComponentProvider<?>[] managedComponents = plugin.getManagedComponents();
|
|
||||||
for (TableComponentProvider<?> tableComponentProvider : managedComponents) {
|
|
||||||
providers.add(tableComponentProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClickOnAsterisks() throws Exception {
|
public void testClickOnAsterisks() throws Exception {
|
||||||
// click on first row of asterisks in the plate comment
|
// click on first row of asterisks in the plate comment
|
||||||
|
@ -554,6 +531,71 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(tf.getText().startsWith("*****"));
|
assertTrue(tf.getText().startsWith("*****"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertPrecedingBlankLines(PlateListingTextField tf, int n) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Example: (this may have blank lines before the plate comment)
|
||||||
|
|
||||||
|
|
||||||
|
***************************************************************
|
||||||
|
* FUNCTION *
|
||||||
|
***************************************************************
|
||||||
|
|
||||||
|
*/
|
||||||
|
PlateFieldTextField plateTextField = tf.getPlateTextField();
|
||||||
|
List<String> lines = plateTextField.getLines();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
String line = lines.get(i);
|
||||||
|
assertTrue(StringUtils.isBlank(line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCentered(PlateListingTextField tf, int textRow, String commentText) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Example: (this may have blank lines before the plate comment)
|
||||||
|
|
||||||
|
|
||||||
|
***************************************************************
|
||||||
|
* FUNCTION *
|
||||||
|
***************************************************************
|
||||||
|
|
||||||
|
*/
|
||||||
|
PlateFieldTextField plateTextField = tf.getPlateTextField();
|
||||||
|
List<String> lines = plateTextField.getLines();
|
||||||
|
|
||||||
|
String lineText = lines.get(textRow);
|
||||||
|
lineText = lineText.replaceAll("\\*", "");
|
||||||
|
int textIndex = lineText.indexOf(commentText);
|
||||||
|
int textEnd = textIndex + commentText.length();
|
||||||
|
String pre = lineText.substring(0, textIndex);
|
||||||
|
String post = lineText.substring(textEnd + 1);
|
||||||
|
int spacesBefore = StringUtils.countMatches(pre, ' ');
|
||||||
|
int spacesAfter = StringUtils.countMatches(post, ' ');
|
||||||
|
int diff = Math.abs(spacesBefore - spacesAfter);
|
||||||
|
assertTrue(diff < 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TableComponentProvider<?>> getNavigationResultsTables() {
|
||||||
|
TableServicePlugin plugin = getPlugin(tool, TableServicePlugin.class);
|
||||||
|
|
||||||
|
List<TableComponentProvider<?>> providers = new ArrayList<>();
|
||||||
|
runSwing(() -> {
|
||||||
|
TableComponentProvider<?>[] managedComponents = plugin.getManagedComponents();
|
||||||
|
for (TableComponentProvider<?> tableComponentProvider : managedComponents) {
|
||||||
|
providers.add(tableComponentProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return providers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createPlateComment(CodeUnit cu, String text) {
|
||||||
|
tx(program, () -> {
|
||||||
|
cu.setComment(CodeUnit.PLATE_COMMENT, text);
|
||||||
|
});
|
||||||
|
cb.updateNow();
|
||||||
|
}
|
||||||
|
|
||||||
private GhidraProgramTableModel<?> waitForModel(TableComponentProvider<?> provider)
|
private GhidraProgramTableModel<?> waitForModel(TableComponentProvider<?> provider)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
GThreadedTablePanel<?> panel =
|
GThreadedTablePanel<?> panel =
|
||||||
|
@ -570,21 +612,20 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBooleanOption(final String name, final boolean value) throws Exception {
|
private void setBooleanOption(final String name, final boolean value) throws Exception {
|
||||||
SwingUtilities.invokeAndWait(() -> fieldOptions.setBoolean(name, value));
|
runSwing(() -> fieldOptions.setBoolean(name, value));
|
||||||
waitForPostedSwingRunnables();
|
waitForSwing();
|
||||||
cb.updateNow();
|
cb.updateNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIntOption(final String name, final int value) throws Exception {
|
private void setIntOption(final String name, final int value) throws Exception {
|
||||||
SwingUtilities.invokeAndWait(() -> fieldOptions.setInt(name, value));
|
runSwing(() -> fieldOptions.setInt(name, value));
|
||||||
waitForPostedSwingRunnables();
|
waitForSwing();
|
||||||
cb.updateNow();
|
cb.updateNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetOptions() {
|
private void resetOptions() {
|
||||||
List<String> names = fieldOptions.getOptionNames();
|
List<String> names = fieldOptions.getOptionNames();
|
||||||
for (int i = 0; i < names.size(); i++) {
|
for (String name : names) {
|
||||||
String name = names.get(i);
|
|
||||||
if (!name.startsWith("Format Code")) {
|
if (!name.startsWith("Format Code")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -595,7 +636,7 @@ public class PlateFieldFactoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
fieldOptions.setInt(name, 0);
|
fieldOptions.setInt(name, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitForPostedSwingRunnables();
|
waitForSwing();
|
||||||
cb.updateNow();
|
cb.updateNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ public interface Field {
|
||||||
* the given data
|
* the given data
|
||||||
* @param row the text row
|
* @param row the text row
|
||||||
* @param col the character position
|
* @param col the character position
|
||||||
* @return tru if valid
|
* @return true if valid
|
||||||
*/
|
*/
|
||||||
public boolean isValid(int row, int col);
|
public boolean isValid(int row, int col);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue