mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
Merge remote-tracking branch 'origin/GP-4289_ghidragon_wrap_operands_on_semicolon--SQUASHED'
This commit is contained in:
commit
77aa79caf1
@ -932,7 +932,12 @@
|
||||
from the <I><A href="#Listing_Display">Listing Display</A></I> options panel; select
|
||||
<I>Underline</I> from the <I>Screen Element</I> list.</P>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
<P><B>Wrap on Semicolons -</B> Option to wrap operand fields on semicolons. Some processors
|
||||
have multiple sub instructions encoded at the same address. Normally, these are shown on
|
||||
one line and the additional instructions are all shown within the operand field and
|
||||
separated by semicolons. With this option on, each follow on instruction will be displayed
|
||||
on its own line within the operand field.
|
||||
</P> </BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Pcode_Field"></A>PCode Field</H3>
|
||||
|
||||
|
@ -55,7 +55,8 @@ public class PcodeFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
public PcodeFieldFactory(String name, FieldFormatModel model,
|
||||
ListingHighlightProvider highlightProvider, Options displayOptions, Options fieldOptions) {
|
||||
ListingHighlightProvider highlightProvider, Options displayOptions,
|
||||
Options fieldOptions) {
|
||||
|
||||
super(name, model, highlightProvider, displayOptions, fieldOptions);
|
||||
setWidth(300);
|
||||
@ -67,7 +68,8 @@ public class PcodeFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldFactory newInstance(FieldFormatModel myModel, ListingHighlightProvider highlightProvider,
|
||||
public FieldFactory newInstance(FieldFormatModel myModel,
|
||||
ListingHighlightProvider highlightProvider,
|
||||
ToolOptions options, ToolOptions fieldOptions) {
|
||||
return new PcodeFieldFactory(FIELD_NAME, myModel, highlightProvider, options, fieldOptions);
|
||||
}
|
||||
@ -81,7 +83,7 @@ public class PcodeFieldFactory extends FieldFactory {
|
||||
}
|
||||
Instruction instr = (Instruction) obj;
|
||||
|
||||
ArrayList<TextFieldElement> elements = new ArrayList<>();
|
||||
List<FieldElement> elements = new ArrayList<>();
|
||||
|
||||
List<AttributedString> pcodeListing = formatter.formatOps(instr.getProgram().getLanguage(),
|
||||
instr.getProgram().getAddressFactory(), Arrays.asList(instr.getPcode(true)));
|
||||
@ -91,9 +93,8 @@ public class PcodeFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
if (elements.size() > 0) {
|
||||
FieldElement[] textElements = elements.toArray(new FieldElement[elements.size()]);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, textElements,
|
||||
startX + varWidth, width, Integer.MAX_VALUE, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements,
|
||||
startX + varWidth, width, hlProvider);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -50,7 +50,8 @@ public class AssignedVariableFieldFactory extends FieldFactory {
|
||||
* @param displayOptions the Options for display properties.
|
||||
* @param fieldOptions the Options for field specific properties.
|
||||
*/
|
||||
private AssignedVariableFieldFactory(FieldFormatModel model, ListingHighlightProvider hsProvider,
|
||||
private AssignedVariableFieldFactory(FieldFormatModel model,
|
||||
ListingHighlightProvider hsProvider,
|
||||
Options displayOptions, Options fieldOptions) {
|
||||
super(FIELD_NAME, model, hsProvider, displayOptions, fieldOptions);
|
||||
}
|
||||
@ -70,7 +71,7 @@ public class AssignedVariableFieldFactory extends FieldFactory {
|
||||
}
|
||||
CodeUnit cu = (CodeUnit) obj;
|
||||
|
||||
ArrayList<FieldElement> elemenetList = new ArrayList<>();
|
||||
ArrayList<FieldElement> elements = new ArrayList<>();
|
||||
|
||||
Function f = cu.getProgram().getFunctionManager().getFunctionContaining(cu.getMinAddress());
|
||||
if (f != null) {
|
||||
@ -89,19 +90,16 @@ public class AssignedVariableFieldFactory extends FieldFactory {
|
||||
buf.append(var.getName());
|
||||
AttributedString as = new AttributedString(buf.toString(),
|
||||
FunctionColors.VARIABLE_ASSIGNED, getMetrics());
|
||||
elemenetList.add(new TextFieldElement(as, 0, 0));
|
||||
elements.add(new TextFieldElement(as, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elemenetList.size() == 0) {
|
||||
if (elements.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FieldElement[] elements = new FieldElement[elemenetList.size()];
|
||||
elemenetList.toArray(elements);
|
||||
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements, startX + varWidth,
|
||||
width, elements.length + 1, hlProvider);
|
||||
width, hlProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,7 +132,8 @@ public class AssignedVariableFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldFactory newInstance(FieldFormatModel formatModel, ListingHighlightProvider hsProvider,
|
||||
public FieldFactory newInstance(FieldFormatModel formatModel,
|
||||
ListingHighlightProvider hsProvider,
|
||||
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||
return new AssignedVariableFieldFactory(formatModel, hsProvider, displayOptions,
|
||||
fieldOptions);
|
||||
|
@ -292,11 +292,7 @@ public class EolCommentFieldFactory extends FieldFactory {
|
||||
elementList.addAll(elements);
|
||||
}
|
||||
|
||||
FieldElement[] fieldElements = elementList.toArray(new FieldElement[elementList.size()]);
|
||||
if (fieldElements.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fieldElements, x, width,
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elementList, x, width,
|
||||
maxDisplayLines, hlProvider);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
package ghidra.app.util.viewer.field;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.fieldpanel.field.AttributedString;
|
||||
import docking.widgets.fieldpanel.field.FieldElement;
|
||||
@ -70,16 +72,16 @@ public class FunctionRepeatableCommentFieldFactory extends FieldFactory {
|
||||
Function f = (Function) obj;
|
||||
Program program = f.getProgram();
|
||||
String[] commentArr = f.getRepeatableCommentAsArray();
|
||||
FieldElement[] fields = new FieldElement[commentArr.length];
|
||||
List<FieldElement> fields = new ArrayList<>();
|
||||
AttributedString prototype =
|
||||
new AttributedString("prototype", CommentColors.REPEATABLE, getMetrics());
|
||||
for (int i = 0; i < commentArr.length; i++) {
|
||||
fields[i] = CommentUtils.parseTextForAnnotations(commentArr[i], program, prototype, i);
|
||||
fields.add(CommentUtils.parseTextForAnnotations(commentArr[i], program, prototype, i));
|
||||
}
|
||||
|
||||
if (commentArr.length > 0) {
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fields, x, width,
|
||||
Integer.MAX_VALUE, hlProvider);
|
||||
hlProvider);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ package ghidra.app.util.viewer.field;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.fieldpanel.field.*;
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
@ -52,7 +54,8 @@ public class InstructionMaskValueFieldFactory extends FieldFactory {
|
||||
* @param displayOptions the Options for display properties.
|
||||
* @param fieldOptions the Options for field specific properties.
|
||||
*/
|
||||
private InstructionMaskValueFieldFactory(FieldFormatModel model, ListingHighlightProvider hsProvider,
|
||||
private InstructionMaskValueFieldFactory(FieldFormatModel model,
|
||||
ListingHighlightProvider hsProvider,
|
||||
Options displayOptions, Options fieldOptions) {
|
||||
super(FIELD_NAME, model, hsProvider, displayOptions, fieldOptions);
|
||||
}
|
||||
@ -88,21 +91,21 @@ public class InstructionMaskValueFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
try {
|
||||
FieldElement[] fieldElements = new FieldElement[2 * (operandCount + 1)];
|
||||
fieldElements[0] =
|
||||
getLine("M[m]: ", instructionMask.getBytes(), MaskColors.BITS, proxy, varWidth);
|
||||
fieldElements[1] =
|
||||
getLine("V[m]: ", instructionMask.applyMask(instr), MaskColors.VALUE, proxy,
|
||||
varWidth);
|
||||
List<FieldElement> elements = new ArrayList<>();
|
||||
elements.add(
|
||||
getLine("M[m]: ", instructionMask.getBytes(), MaskColors.BITS, proxy, varWidth));
|
||||
elements.add(getLine("V[m]: ", instructionMask.applyMask(instr), MaskColors.VALUE,
|
||||
proxy, varWidth));
|
||||
|
||||
for (int i = 0; i < operandCount; i++) {
|
||||
fieldElements[2 * (i + 1)] = getLine("M[" + i + "]: ", operandMasks[i].getBytes(),
|
||||
MaskColors.BITS, proxy, varWidth);
|
||||
fieldElements[2 * (i + 1) + 1] = getLine("V[" + i + "]: ",
|
||||
operandMasks[i].applyMask(instr), MaskColors.VALUE, proxy, varWidth);
|
||||
elements.add(getLine("M[" + i + "]: ", operandMasks[i].getBytes(), MaskColors.BITS,
|
||||
proxy, varWidth));
|
||||
elements.add(getLine("V[" + i + "]: ", operandMasks[i].applyMask(instr),
|
||||
MaskColors.VALUE, proxy, varWidth));
|
||||
}
|
||||
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fieldElements,
|
||||
startX + varWidth, width, fieldElements.length, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements,
|
||||
startX + varWidth, width, hlProvider);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
return null;
|
||||
@ -165,7 +168,8 @@ public class InstructionMaskValueFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldFactory newInstance(FieldFormatModel formatModel, ListingHighlightProvider hsProvider,
|
||||
public FieldFactory newInstance(FieldFormatModel formatModel,
|
||||
ListingHighlightProvider hsProvider,
|
||||
ToolOptions toolOptions, ToolOptions fieldOptions) {
|
||||
return new InstructionMaskValueFieldFactory(formatModel, hsProvider, toolOptions,
|
||||
fieldOptions);
|
||||
|
@ -181,8 +181,7 @@ public class LabelFieldFactory extends FieldFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
FieldElement[] textElements = new FieldElement[length];
|
||||
int nextPos = 0;
|
||||
List<FieldElement> elements = new ArrayList<>(length);
|
||||
|
||||
if (hasOffcuts) {
|
||||
for (Address offcut : offcuts) {
|
||||
@ -193,7 +192,7 @@ public class LabelFieldFactory extends FieldFactory {
|
||||
inspector.getOffcutSymbolColor(),
|
||||
getMetrics(inspector.getOffcutSymbolStyle()), false, null);
|
||||
}
|
||||
textElements[nextPos++] = new TextFieldElement(as, nextPos, 0);
|
||||
elements.add(new TextFieldElement(as, elements.size(), 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,11 +205,11 @@ public class LabelFieldFactory extends FieldFactory {
|
||||
ColorAndStyle c = inspector.getColorAndStyle(symbol);
|
||||
AttributedString as = new AttributedString(icon, checkLabelString(symbol, prog),
|
||||
c.getColor(), getMetrics(c.getStyle()), false, null);
|
||||
textElements[nextPos++] = new TextFieldElement(as, nextPos, 0);
|
||||
elements.add(new TextFieldElement(as, elements.size(), 0));
|
||||
}
|
||||
|
||||
return ListingTextField.createMultilineTextField(this, proxy, textElements, x, width,
|
||||
Integer.MAX_VALUE, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements, x, width,
|
||||
hlProvider);
|
||||
}
|
||||
|
||||
private String getOffsetText(CodeUnit cu, Address currAddr, Address offcutAddress) {
|
||||
|
@ -125,10 +125,10 @@ public class ListingTextField implements ListingField, TextField {
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the given array of text, each on its own line.
|
||||
* Displays the given List of text elements, each on its own line.
|
||||
* @param factory the field factory that generated this field
|
||||
* @param proxy the object used to populate this field
|
||||
* @param textElements the array of elements for the field.
|
||||
* @param textElements the list of text elements
|
||||
* Each of these holds text, attributes and location information.
|
||||
* @param startX the starting X position of the field
|
||||
* @param width the width of the field
|
||||
@ -137,18 +137,36 @@ public class ListingTextField implements ListingField, TextField {
|
||||
* @return the text field.
|
||||
*/
|
||||
public static ListingTextField createMultilineTextField(FieldFactory factory, ProxyObj<?> proxy,
|
||||
FieldElement[] textElements, int startX, int width, int maxLines,
|
||||
List<FieldElement> textElements, int startX, int width, int maxLines,
|
||||
ListingHighlightProvider provider) {
|
||||
|
||||
ListingFieldHighlightFactoryAdapter hlFactory =
|
||||
new ListingFieldHighlightFactoryAdapter(provider);
|
||||
List<FieldElement> list = Arrays.asList(textElements);
|
||||
TextField field =
|
||||
new VerticalLayoutTextField(list, startX, width, maxLines, hlFactory);
|
||||
new VerticalLayoutTextField(textElements, startX, width, maxLines, hlFactory);
|
||||
ListingTextField listingField = new ListingTextField(factory, proxy, field, hlFactory);
|
||||
return listingField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the given List of text elements, each on its own line with no max line restriction
|
||||
* @param factory the field factory that generated this field
|
||||
* @param proxy the object used to populate this field
|
||||
* @param textElements the list of text elements
|
||||
* Each of these holds text, attributes and location information.
|
||||
* @param startX the starting X position of the field
|
||||
* @param width the width of the field
|
||||
* @param provider the highlight provider
|
||||
* @return the text field.
|
||||
*/
|
||||
public static ListingTextField createMultilineTextField(FieldFactory factory, ProxyObj<?> proxy,
|
||||
List<FieldElement> textElements, int startX, int width,
|
||||
ListingHighlightProvider provider) {
|
||||
|
||||
return ListingTextField.createMultilineTextField(factory, proxy, textElements, startX,
|
||||
width, Integer.MAX_VALUE, provider);
|
||||
}
|
||||
|
||||
protected ListingTextField(FieldFactory factory, ProxyObj<?> proxy, TextField field,
|
||||
ListingFieldHighlightFactoryAdapter hlFactory) {
|
||||
this.factory = factory;
|
||||
|
@ -56,7 +56,8 @@ public class MemoryBlockStartFieldFactory extends FieldFactory {
|
||||
* @param displayOptions the Options for display properties.
|
||||
* @param fieldOptions the Options for field specific properties.
|
||||
*/
|
||||
private MemoryBlockStartFieldFactory(FieldFormatModel model, ListingHighlightProvider hlProvider,
|
||||
private MemoryBlockStartFieldFactory(FieldFormatModel model,
|
||||
ListingHighlightProvider hlProvider,
|
||||
Options displayOptions, Options fieldOptions) {
|
||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||
}
|
||||
@ -85,7 +86,7 @@ public class MemoryBlockStartFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
// Convert the text to field elements.
|
||||
FieldElement[] elements = createFieldElements(attributedStrings);
|
||||
List<FieldElement> elements = createFieldElements(attributedStrings);
|
||||
|
||||
// And put the elements in a text field.
|
||||
ListingTextField ltf = ListingTextField.createMultilineTextField(this, proxy, elements,
|
||||
@ -227,7 +228,7 @@ public class MemoryBlockStartFieldFactory extends FieldFactory {
|
||||
return lines;
|
||||
}
|
||||
|
||||
private FieldElement[] createFieldElements(List<AttributedString> attributedStrings) {
|
||||
private List<FieldElement> createFieldElements(List<AttributedString> attributedStrings) {
|
||||
List<FieldElement> elements = new ArrayList<>();
|
||||
int lineNum = 0;
|
||||
for (AttributedString line : attributedStrings) {
|
||||
@ -235,11 +236,6 @@ public class MemoryBlockStartFieldFactory extends FieldFactory {
|
||||
elements.add(blockElement);
|
||||
lineNum++;
|
||||
}
|
||||
|
||||
// Convert to an array
|
||||
FieldElement[] elementsArray = new FieldElement[elements.size()];
|
||||
elements.toArray(elementsArray);
|
||||
|
||||
return elementsArray;
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,8 @@ public class OperandFieldFactory extends OperandFieldHelper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldFactory newInstance(FieldFormatModel formatModel, ListingHighlightProvider hsProvider,
|
||||
public FieldFactory newInstance(FieldFormatModel formatModel,
|
||||
ListingHighlightProvider hsProvider,
|
||||
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||
return new OperandFieldFactory(formatModel, hsProvider, displayOptions, fieldOptions);
|
||||
}
|
||||
|
@ -48,14 +48,17 @@ import ghidra.util.HelpLocation;
|
||||
*/
|
||||
abstract class OperandFieldHelper extends FieldFactory {
|
||||
|
||||
private final static String ENABLE_WORD_WRAP_MSG =
|
||||
private final static String ENABLE_WORD_WRAP_OPTION =
|
||||
GhidraOptions.OPERAND_GROUP_TITLE + Options.DELIMITER + FieldUtils.WORD_WRAP_OPTION_NAME;
|
||||
private final static String MAX_DISPLAY_LINES_MSG =
|
||||
private final static String MAX_DISPLAY_LINES_OPTION =
|
||||
GhidraOptions.OPERAND_GROUP_TITLE + Options.DELIMITER + "Maximum Lines To Display";
|
||||
private final static String UNDERLINE_OPTION =
|
||||
GhidraOptions.OPERAND_GROUP_TITLE + Options.DELIMITER + "Underline References";
|
||||
private final static String SPACE_AFTER_SEPARATOR_OPTION =
|
||||
GhidraOptions.OPERAND_GROUP_TITLE + Options.DELIMITER + "Add Space After Separator";
|
||||
private final static String WRAP_ON_SEMICOLON_OPTION =
|
||||
GhidraOptions.OPERAND_GROUP_TITLE + Options.DELIMITER + "Wrap on Semicolons";
|
||||
private final static OperandFieldElement LINE_BREAK = new OperandFieldElement(null, 0, 0, 0);
|
||||
|
||||
public enum UNDERLINE_CHOICE {
|
||||
Hidden, All, None
|
||||
@ -75,6 +78,7 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
private boolean isWordWrap = false;
|
||||
private int maxDisplayLines = 2;
|
||||
private boolean spaceAfterSeparator = false;
|
||||
private boolean wrapOnSemicolon = false;
|
||||
|
||||
protected BrowserCodeUnitFormat codeUnitFormat;
|
||||
private ChangeListener codeUnitFormatListener = e -> OperandFieldHelper.this.model.update();
|
||||
@ -102,9 +106,9 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
setOptions(displayOptions);
|
||||
|
||||
HelpLocation hl = new HelpLocation("CodeBrowserPlugin", "Operands_Field");
|
||||
fieldOptions.registerOption(ENABLE_WORD_WRAP_MSG, false, hl,
|
||||
fieldOptions.registerOption(ENABLE_WORD_WRAP_OPTION, false, hl,
|
||||
"Enables word wrapping of strings in the operands field.");
|
||||
fieldOptions.registerOption(MAX_DISPLAY_LINES_MSG, 2, hl,
|
||||
fieldOptions.registerOption(MAX_DISPLAY_LINES_OPTION, 2, hl,
|
||||
"The maximum number of lines used to display the strings in the operands field.");
|
||||
fieldOptions.registerOption(UNDERLINE_OPTION, UNDERLINE_CHOICE.Hidden, hl,
|
||||
"Select 'All' to underline any operand field that has a reference; " +
|
||||
@ -112,16 +116,16 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
"select 'None' for no underlines.");
|
||||
fieldOptions.registerOption(SPACE_AFTER_SEPARATOR_OPTION, false, hl,
|
||||
"Add space between separator and next operand");
|
||||
fieldOptions.registerOption(WRAP_ON_SEMICOLON_OPTION, false, hl,
|
||||
"Wrap operand field on semicolons");
|
||||
|
||||
setMaximumLinesToDisplay(fieldOptions.getInt(MAX_DISPLAY_LINES_MSG, 2), fieldOptions);
|
||||
isWordWrap = fieldOptions.getBoolean(ENABLE_WORD_WRAP_MSG, false);
|
||||
|
||||
setMaximumLinesToDisplay(fieldOptions.getInt(MAX_DISPLAY_LINES_OPTION, 2), fieldOptions);
|
||||
isWordWrap = fieldOptions.getBoolean(ENABLE_WORD_WRAP_OPTION, false);
|
||||
underlineChoice = fieldOptions.getEnum(UNDERLINE_OPTION, UNDERLINE_CHOICE.Hidden);
|
||||
|
||||
spaceAfterSeparator = fieldOptions.getBoolean(SPACE_AFTER_SEPARATOR_OPTION, false);
|
||||
wrapOnSemicolon = fieldOptions.getBoolean(WRAP_ON_SEMICOLON_OPTION, false);
|
||||
|
||||
inspector = new SymbolInspector(displayOptions, null);
|
||||
fieldOptions.getOptions(GhidraOptions.OPERAND_GROUP_TITLE).setOptionsHelpLocation(hl);
|
||||
|
||||
// Create code unit format and associated options - listen for changes
|
||||
codeUnitFormat = new BrowserCodeUnitFormat(fieldOptions, true);
|
||||
@ -141,22 +145,29 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
Object newValue) {
|
||||
|
||||
boolean updateModel = false;
|
||||
if (optionName.equals(MAX_DISPLAY_LINES_MSG)) {
|
||||
setMaximumLinesToDisplay(((Integer) newValue).intValue(), options);
|
||||
updateModel = true;
|
||||
}
|
||||
else if (optionName.equals(ENABLE_WORD_WRAP_MSG)) {
|
||||
isWordWrap = ((Boolean) newValue).booleanValue();
|
||||
updateModel = true;
|
||||
}
|
||||
else if (optionName.equals(UNDERLINE_OPTION)) {
|
||||
underlineChoice = (UNDERLINE_CHOICE) newValue;
|
||||
updateModel = true;
|
||||
}
|
||||
else if (optionName.equals(SPACE_AFTER_SEPARATOR_OPTION)) {
|
||||
spaceAfterSeparator = ((Boolean) newValue).booleanValue();
|
||||
updateModel = true;
|
||||
switch (optionName) {
|
||||
case MAX_DISPLAY_LINES_OPTION:
|
||||
setMaximumLinesToDisplay(((Integer) newValue).intValue(), options);
|
||||
updateModel = true;
|
||||
break;
|
||||
case ENABLE_WORD_WRAP_OPTION:
|
||||
isWordWrap = ((Boolean) newValue).booleanValue();
|
||||
updateModel = true;
|
||||
break;
|
||||
case UNDERLINE_OPTION:
|
||||
underlineChoice = (UNDERLINE_CHOICE) newValue;
|
||||
updateModel = true;
|
||||
break;
|
||||
case SPACE_AFTER_SEPARATOR_OPTION:
|
||||
spaceAfterSeparator = ((Boolean) newValue).booleanValue();
|
||||
updateModel = true;
|
||||
break;
|
||||
case WRAP_ON_SEMICOLON_OPTION:
|
||||
wrapOnSemicolon = ((Boolean) newValue).booleanValue();
|
||||
updateModel = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (updateModel) {
|
||||
model.update();
|
||||
}
|
||||
@ -165,19 +176,18 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
private void setMaximumLinesToDisplay(int maxLines, Options options) {
|
||||
if (maxLines < 1) {
|
||||
maxLines = 1;
|
||||
options.setInt(MAX_DISPLAY_LINES_MSG, maxLines);
|
||||
options.setInt(MAX_DISPLAY_LINES_OPTION, maxLines);
|
||||
}
|
||||
this.maxDisplayLines = maxLines;
|
||||
}
|
||||
|
||||
FieldLocation getFieldLocation(BigInteger index, int fieldNum, ListingField bf, int opIndex,
|
||||
int column) {
|
||||
if (bf instanceof ListingTextField) {
|
||||
ListingTextField btf = (ListingTextField) bf;
|
||||
RowColLocation rcl = btf.dataToScreenLocation(opIndex, column);
|
||||
FieldLocation getFieldLocation(BigInteger index, int fieldNum, ListingField field,
|
||||
int opIndex, int column) {
|
||||
if (field instanceof ListingTextField listingField) {
|
||||
RowColLocation rcl = listingField.dataToScreenLocation(opIndex, column);
|
||||
return new FieldLocation(index, fieldNum, rcl.row(), rcl.col());
|
||||
}
|
||||
else if (bf instanceof ImageFactoryField) {
|
||||
else if (field instanceof ImageFactoryField) {
|
||||
return new FieldLocation(index, fieldNum, 0, 0);
|
||||
}
|
||||
return null;
|
||||
@ -435,14 +445,50 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
characterOffset = 0;
|
||||
}
|
||||
|
||||
// There may be operands with no representation objects, so we don't want to create a composite field element.
|
||||
// There may be operands with no representation objects, so we don't want to create a
|
||||
// composite field element.
|
||||
if (elements.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (wrapOnSemicolon) {
|
||||
List<FieldElement> lines = breakIntoLines(elements);
|
||||
if (lines.size() == 1) {
|
||||
return ListingTextField.createSingleLineTextField(this, proxy,
|
||||
lines.get(0), startX + varWidth, width, hlProvider);
|
||||
}
|
||||
return ListingTextField.createMultilineTextField(this, proxy, lines, startX, width,
|
||||
hlProvider);
|
||||
}
|
||||
return ListingTextField.createSingleLineTextField(this, proxy,
|
||||
new CompositeFieldElement(elements), startX + varWidth, width, hlProvider);
|
||||
}
|
||||
|
||||
private List<FieldElement> breakIntoLines(List<OperandFieldElement> elements) {
|
||||
// This method groups all elements between LINE_BREAK elements into composite elements
|
||||
// where each composite element will be display on its own line.
|
||||
//
|
||||
// It does this by collecting elements in the lineElements list until it find a LINE_BREAK
|
||||
List<FieldElement> fieldElements = new ArrayList<>();
|
||||
List<OperandFieldElement> lineElements = new ArrayList<>();
|
||||
|
||||
for (OperandFieldElement operandFieldElement : elements) {
|
||||
if (operandFieldElement == LINE_BREAK) {
|
||||
if (!lineElements.isEmpty()) {
|
||||
fieldElements.add(new CompositeFieldElement(lineElements));
|
||||
lineElements.clear();
|
||||
}
|
||||
}
|
||||
else {
|
||||
lineElements.add(operandFieldElement);
|
||||
}
|
||||
}
|
||||
if (!lineElements.isEmpty()) {
|
||||
fieldElements.add(new CompositeFieldElement(lineElements));
|
||||
lineElements.clear();
|
||||
}
|
||||
return fieldElements;
|
||||
}
|
||||
|
||||
private int addElementsForOperand(Instruction inst, List<OperandFieldElement> elements,
|
||||
int opIndex, OperandRepresentationList opRepList, int characterOffset) {
|
||||
int subOpIndex = 0;
|
||||
@ -493,7 +539,11 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
|
||||
AttributedString as = new AttributedString(opElem.toString(), attributes.colorAttribute,
|
||||
getMetrics(attributes.styleAttribute), underline, ListingColors.UNDERLINE);
|
||||
|
||||
elements.add(new OperandFieldElement(as, opIndex, subOpIndex, characterOffset));
|
||||
if (wrapOnSemicolon && opElem instanceof Character c && c == ';') {
|
||||
elements.add(LINE_BREAK);
|
||||
}
|
||||
return characterOffset + as.length();
|
||||
}
|
||||
|
||||
@ -742,5 +792,4 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
operandSubIndex, column);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -449,26 +449,26 @@ public class PostCommentFieldFactory extends FieldFactory {
|
||||
(comments.length == 0 || alwaysShowAutomatic) ? autoComment.length : 0;
|
||||
AttributedString prototypeString =
|
||||
new AttributedString("prototype", color, getMetrics());
|
||||
FieldElement[] fields =
|
||||
new FieldElement[comments.length + nLinesAfterBlocks + nLinesAutoComment];
|
||||
if (fields.length > 0) {
|
||||
int commentLineCount = comments.length + nLinesAfterBlocks + nLinesAutoComment;
|
||||
List<FieldElement> elements = new ArrayList<>(commentLineCount);
|
||||
if (commentLineCount > 0) {
|
||||
for (int i = 0; i < nLinesAutoComment; i++) {
|
||||
AttributedString as = new AttributedString(autoComment[i],
|
||||
CommentColors.AUTO, getMetrics(automaticCommentStyle), false, null);
|
||||
fields[i] = new TextFieldElement(as, i, 0);
|
||||
elements.add(new TextFieldElement(as, i, 0));
|
||||
}
|
||||
for (int i = 0; i < comments.length; i++) {
|
||||
int index = nLinesAutoComment + i;
|
||||
fields[index] = CommentUtils.parseTextForAnnotations(comments[i],
|
||||
instr.getProgram(), prototypeString, index);
|
||||
elements.add(CommentUtils.parseTextForAnnotations(comments[i],
|
||||
instr.getProgram(), prototypeString, index));
|
||||
}
|
||||
for (int i = fields.length - nLinesAfterBlocks; i < fields.length; i++) {
|
||||
for (int i = commentLineCount - nLinesAfterBlocks; i < commentLineCount; i++) {
|
||||
// add blank lines for end-of-block
|
||||
AttributedString as = new AttributedString("", color, getMetrics());
|
||||
fields[i] = new TextFieldElement(as, i, 0);
|
||||
elements.add(new TextFieldElement(as, i, 0));
|
||||
}
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fields, xStart,
|
||||
width, Integer.MAX_VALUE, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements, xStart,
|
||||
width, hlProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -516,10 +516,9 @@ public class PostCommentFieldFactory extends FieldFactory {
|
||||
fields.add(new TextFieldElement(as, fields.size(), 0));
|
||||
}
|
||||
}
|
||||
FieldElement[] elements = fields.toArray(new FieldElement[fields.size()]);
|
||||
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements, xStart, width,
|
||||
Integer.MAX_VALUE, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fields, xStart, width,
|
||||
hlProvider);
|
||||
}
|
||||
|
||||
private void init(Options options) {
|
||||
|
@ -386,10 +386,8 @@ public class PreCommentFieldFactory extends FieldFactory {
|
||||
fields = FieldUtils.wrap(fields, width);
|
||||
}
|
||||
|
||||
FieldElement[] elements = fields.toArray(new FieldElement[fields.size()]);
|
||||
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements, xStart, width,
|
||||
Integer.MAX_VALUE, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fields, xStart, width,
|
||||
hlProvider);
|
||||
}
|
||||
|
||||
private void init(Options options) {
|
||||
|
@ -199,14 +199,14 @@ public class RegisterFieldFactory extends FieldFactory {
|
||||
return setRegisters;
|
||||
}
|
||||
|
||||
private FieldElement[] getFieldElements(String[] registerStrings) {
|
||||
FieldElement[] fieldElements = new FieldElement[registerStrings.length];
|
||||
private List<FieldElement> getFieldElements(String[] registerStrings) {
|
||||
List<FieldElement> elements = new ArrayList<>(registerStrings.length);
|
||||
for (int i = 0; i < registerStrings.length; i++) {
|
||||
AttributedString str =
|
||||
new AttributedString(registerStrings[i], ListingColors.REGISTER, getMetrics());
|
||||
fieldElements[i] = new TextFieldElement(str, i, 0);
|
||||
elements.add(new TextFieldElement(str, i, 0));
|
||||
}
|
||||
return fieldElements;
|
||||
return elements;
|
||||
}
|
||||
|
||||
private ListingTextField getTextField(String[] registerStrings, ProxyObj<?> proxy, int xStart) {
|
||||
@ -214,9 +214,9 @@ public class RegisterFieldFactory extends FieldFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
FieldElement[] fieldElements = getFieldElements(registerStrings);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fieldElements, xStart, width,
|
||||
Integer.MAX_VALUE, hlProvider);
|
||||
List<FieldElement> elements = getFieldElements(registerStrings);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements, xStart, width,
|
||||
hlProvider);
|
||||
}
|
||||
|
||||
private class RegComparator implements Comparator<Register> {
|
||||
|
@ -55,7 +55,8 @@ public class RegisterTransitionFieldFactory extends FieldFactory {
|
||||
* @param displayOptions the Options for display properties.
|
||||
* @param fieldOptions the Options for field specific properties.
|
||||
*/
|
||||
private RegisterTransitionFieldFactory(FieldFormatModel model, ListingHighlightProvider hsProvider,
|
||||
private RegisterTransitionFieldFactory(FieldFormatModel model,
|
||||
ListingHighlightProvider hsProvider,
|
||||
Options displayOptions, Options fieldOptions) {
|
||||
super(FIELD_NAME, model, hsProvider, displayOptions, fieldOptions);
|
||||
initOptions(displayOptions, fieldOptions);
|
||||
@ -118,22 +119,22 @@ public class RegisterTransitionFieldFactory extends FieldFactory {
|
||||
if (stackDepthStr != null) {
|
||||
numElements++;
|
||||
}
|
||||
FieldElement[] fieldElements = new FieldElement[numElements];
|
||||
List<FieldElement> elements = new ArrayList<>(numElements);
|
||||
for (int i = 0; i < numRegisters; i++) {
|
||||
Register register = transitionRegisters.get(i);
|
||||
AttributedString str = new AttributedString(
|
||||
"assume " + register.getName() + " = " +
|
||||
getValueString(register, context, curAddress),
|
||||
ListingColors.REGISTER, getMetrics());
|
||||
fieldElements[i] = new TextFieldElement(str, i, 0);
|
||||
elements.add(new TextFieldElement(str, i, 0));
|
||||
}
|
||||
if (stackDepthStr != null) {
|
||||
AttributedString str =
|
||||
new AttributedString(stackDepthStr, ListingColors.REGISTER, getMetrics());
|
||||
fieldElements[numRegisters] = new TextFieldElement(str, numRegisters, 0);
|
||||
elements.add(new TextFieldElement(str, numRegisters, 0));
|
||||
}
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fieldElements,
|
||||
startX + varWidth, width, Integer.MAX_VALUE, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements,
|
||||
startX + varWidth, width, hlProvider);
|
||||
}
|
||||
|
||||
private String getValueString(Register register, ProgramContext context, Address curAddress) {
|
||||
@ -242,7 +243,8 @@ public class RegisterTransitionFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldFactory newInstance(FieldFormatModel fieldFormatModel, ListingHighlightProvider hsProvider,
|
||||
public FieldFactory newInstance(FieldFormatModel fieldFormatModel,
|
||||
ListingHighlightProvider hsProvider,
|
||||
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||
return new RegisterTransitionFieldFactory(fieldFormatModel, hsProvider, displayOptions,
|
||||
fieldOptions);
|
||||
|
@ -16,6 +16,8 @@
|
||||
package ghidra.app.util.viewer.field;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.fieldpanel.field.*;
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
@ -78,14 +80,15 @@ public class SpaceFieldFactory extends FieldFactory {
|
||||
else if (n < 0) {
|
||||
n = -n;
|
||||
}
|
||||
FieldElement[] fes = new FieldElement[n];
|
||||
|
||||
List<FieldElement> elements = new ArrayList<>(n);
|
||||
AttributedString as = new AttributedString("", Colors.FOREGROUND, getMetrics());
|
||||
for (int i = 0; i < n; i++) {
|
||||
fes[i] = new TextFieldElement(as, 0, 0);
|
||||
elements.add(new TextFieldElement(as, 0, 0));
|
||||
}
|
||||
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fes, startX + varWidth,
|
||||
width, n + 1, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements,
|
||||
startX + varWidth, width, hlProvider);
|
||||
|
||||
}
|
||||
return null;
|
||||
|
@ -16,6 +16,8 @@
|
||||
package ghidra.app.util.viewer.field;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.fieldpanel.field.*;
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
@ -69,15 +71,15 @@ public class VariableCommentFieldFactory extends AbstractVariableFieldFactory {
|
||||
String comment = sv.getComment();
|
||||
String[] comments = StringUtilities.toLines(comment);
|
||||
if ((comments != null) && (comments.length > 0)) {
|
||||
FieldElement[] fields = new FieldElement[comments.length];
|
||||
List<FieldElement> elements = new ArrayList<>(comments.length);
|
||||
for (int i = 0; i < comments.length; i++) {
|
||||
AttributedString as =
|
||||
new AttributedString(comments[i], getColor(sv), getMetrics(sv));
|
||||
fields[i] = new TextFieldElement(as, i, 0);
|
||||
elements.add(new TextFieldElement(as, i, 0));
|
||||
}
|
||||
|
||||
return ListingTextField.createMultilineTextField(this, proxy, fields, startX + varWidth,
|
||||
width, Integer.MAX_VALUE, hlProvider);
|
||||
return ListingTextField.createMultilineTextField(this, proxy, elements,
|
||||
startX + varWidth, width, hlProvider);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -745,7 +745,7 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest
|
||||
loadProgram();
|
||||
Options options = tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS);
|
||||
List<String> names = getOptionNames(options, "Operands Field");
|
||||
assertEquals(15, names.size());
|
||||
assertEquals(16, names.size());
|
||||
assertEquals("Operands Field.Add Space After Separator", names.get(0));
|
||||
assertEquals("Operands Field.Always Show Primary Reference", names.get(1));
|
||||
assertEquals("Operands Field.Display Abbreviated Default Label Names", names.get(2));
|
||||
@ -761,6 +761,7 @@ public class CodeBrowserOptionsTest extends AbstractGhidraHeadedIntegrationTest
|
||||
assertEquals("Operands Field.Show Block Names", names.get(12));
|
||||
assertEquals("Operands Field.Show Offcut Information", names.get(13));
|
||||
assertEquals("Operands Field.Underline References", names.get(14));
|
||||
assertEquals("Operands Field.Wrap on Semicolons", names.get(15));
|
||||
|
||||
NamespaceWrappedOption namespaceOption =
|
||||
(NamespaceWrappedOption) options.getCustomOption(names.get(3),
|
||||
|
@ -492,11 +492,19 @@ public class VerticalLayoutTextField implements TextField {
|
||||
@Override
|
||||
public RowColLocation dataToScreenLocation(int dataRow, int dataColumn) {
|
||||
|
||||
FieldRow fieldRow = getFieldRowFromDataRow(dataRow);
|
||||
TextField field = fieldRow.field;
|
||||
RowColLocation location = field.dataToScreenLocation(dataRow, dataColumn);
|
||||
int screenRow = fieldRow.screenRow;
|
||||
return location.withRow(screenRow);
|
||||
// search each line looking for a match for the given row and column
|
||||
for (int i = 0; i < subFields.size(); i++) {
|
||||
FieldRow row = subFields.get(i);
|
||||
RowColLocation loc = row.field.dataToScreenLocation(dataRow, dataColumn);
|
||||
|
||||
// A DefaultRowColLocation means that the line did not have an exact match for
|
||||
// the dataRow and dataColumn, so need to keep looking at each line.
|
||||
if (!(loc instanceof DefaultRowColLocation)) {
|
||||
return new RowColLocation(i, loc.col());
|
||||
}
|
||||
}
|
||||
// We did not find a match for the given row and column, so return a default location of 0,0
|
||||
return new DefaultRowColLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,7 +92,7 @@ public class VerticalLayoutTextFieldTest extends AbstractGenericTest {
|
||||
assertEquals(new RowColLocation(2, 0), field.dataToScreenLocation(2, 0));
|
||||
assertEquals(new RowColLocation(2, 4), field.dataToScreenLocation(2, 4));
|
||||
assertEquals(new RowColLocation(2, 12), field.dataToScreenLocation(2, 12));
|
||||
assertEquals(new DefaultRowColLocation(2, 12), field.dataToScreenLocation(2, 15));
|
||||
assertEquals(new DefaultRowColLocation(0, 0), field.dataToScreenLocation(2, 15));
|
||||
|
||||
assertEquals(new RowColLocation(3, 0), field.dataToScreenLocation(3, 0));
|
||||
assertEquals(new RowColLocation(3, 4), field.dataToScreenLocation(3, 4));
|
||||
|
Loading…
Reference in New Issue
Block a user