mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-28 23:21:46 +00:00
BitFields - additional refinements
This commit is contained in:
parent
286d2a6258
commit
3f1ffb276f
@ -271,6 +271,10 @@ public class BitFieldEditorPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.isConsumed()) {
|
||||
return;
|
||||
}
|
||||
e.consume();
|
||||
selectionActive = false;
|
||||
if (e.getButton() == MouseEvent.BUTTON1 && bitOffsetInput.isEnabled()) {
|
||||
bitSizeModel.setValue(1L); // must change size first
|
||||
@ -282,10 +286,12 @@ public class BitFieldEditorPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (!selectionActive) {
|
||||
if (!selectionActive || e.isConsumed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.consume();
|
||||
|
||||
Point p = e.getPoint();
|
||||
int bitOffset = placementComponent.getBitOffset(p);
|
||||
if (bitOffset == lastBit) {
|
||||
@ -314,7 +320,10 @@ public class BitFieldEditorPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
selectionActive = false;
|
||||
if (selectionActive && !e.isConsumed()) {
|
||||
e.consume();
|
||||
selectionActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -649,22 +658,19 @@ public class BitFieldEditorPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent mwe) {
|
||||
if (!isEnabled()) {
|
||||
if (!isEnabled() || mwe.getModifiersEx() != 0 || mwe.isConsumed()) {
|
||||
return;
|
||||
}
|
||||
if (mwe.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) {
|
||||
// TODO: should we handle other modes?
|
||||
return;
|
||||
}
|
||||
mwe.consume();
|
||||
SpinnerNumberModel m = (SpinnerNumberModel) getModel();
|
||||
if (mwe.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) {
|
||||
// TODO: Handle other mouse wheel modes
|
||||
return;
|
||||
}
|
||||
Long value =
|
||||
mwe.getUnitsToScroll() > 0 ? (Long) m.getPreviousValue() : (Long) m.getNextValue();
|
||||
if (value != null) {
|
||||
setValue(value);
|
||||
mwe.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package ghidra.app.plugin.core.compositeeditor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
@ -32,11 +32,11 @@ import resources.icons.ColorIcon;
|
||||
public class BitFieldPlacementComponent extends JPanel {
|
||||
|
||||
private static final int CELL_HEIGHT = 25;
|
||||
private static final int BIT_WIDTH = 10;
|
||||
// private static final int BIT_WIDTHx = 10;
|
||||
private static final int ZERO_BIT_WIDTH = 3;
|
||||
private static final int BIT_SEPARATOR_THICKNESS = 1;
|
||||
private static final int BYTE_SEPARATOR_THICKNESS = 2;
|
||||
private static final int BYTE_WIDTH = 8 * (BIT_WIDTH + BIT_SEPARATOR_THICKNESS);
|
||||
// private static final int BYTE_WIDTHx = 8 * (BIT_WIDTH + BIT_SEPARATOR_THICKNESS);
|
||||
private static final int SCROLLBAR_THICKNESS = 10;
|
||||
private static final int MY_HEIGHT = (2 * CELL_HEIGHT) + (3 * BYTE_SEPARATOR_THICKNESS);
|
||||
|
||||
@ -52,6 +52,9 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
private static final Color NON_BITFIELD_COMPONENT_COLOR = new Color(0xb8b8ff);
|
||||
private static final Color INTERIOR_LINE_COLOR = new Color(0xcfcfcf);
|
||||
|
||||
private int bitWidth = 10;
|
||||
private int byteWidth = getByteWidth(bitWidth);
|
||||
|
||||
private final Composite composite;
|
||||
private final boolean bigEndian;
|
||||
|
||||
@ -116,6 +119,63 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
setSize(getPreferredSize());
|
||||
setMinimumSize(getPreferredSize());
|
||||
ToolTipManager.sharedInstance().registerComponent(this);
|
||||
addMouseWheelListener(new MyMouseWheelListener());
|
||||
}
|
||||
|
||||
private class MyMouseWheelListener implements MouseWheelListener {
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (e.getModifiersEx() != InputEvent.SHIFT_DOWN_MASK || e.isConsumed()) {
|
||||
return;
|
||||
}
|
||||
if (e.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) {
|
||||
// TODO: should we handle other modes?
|
||||
return;
|
||||
}
|
||||
e.consume();
|
||||
|
||||
Point p = e.getPoint();
|
||||
int index = getBitIndex(p.x);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int w = bitWidth + e.getWheelRotation();
|
||||
if (w >= 10) {
|
||||
Rectangle visibleRect = getVisibleRect();
|
||||
double offsetX = p.getX() - visibleRect.getX();
|
||||
|
||||
setBitWidth(w);
|
||||
|
||||
Rectangle bitRec = bitFieldAllocation.bitAttributes[index].rectangle;
|
||||
int x = (int) (bitRec.getCenterX() - offsetX);
|
||||
Rectangle r =
|
||||
new Rectangle(x, visibleRect.y, visibleRect.width, visibleRect.height);
|
||||
|
||||
scrollRectToVisible(r);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int getByteWidth(int bitWidth) {
|
||||
return 8 * (bitWidth + BIT_SEPARATOR_THICKNESS);
|
||||
}
|
||||
|
||||
public int getBitWidth() {
|
||||
return bitWidth;
|
||||
}
|
||||
|
||||
public void setBitWidth(int width) {
|
||||
|
||||
bitWidth = width;
|
||||
byteWidth = getByteWidth(bitWidth);
|
||||
if (bitFieldAllocation != null) {
|
||||
bitFieldAllocation.layoutBits();
|
||||
}
|
||||
updatePreferredSize();
|
||||
repaint();
|
||||
}
|
||||
|
||||
private int getPreferredHeight() {
|
||||
@ -124,11 +184,10 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
|
||||
private int getPreferredWidth() {
|
||||
if (bitFieldAllocation == null) {
|
||||
return 10;
|
||||
return byteWidth;
|
||||
}
|
||||
|
||||
int extraLineSpace = BYTE_SEPARATOR_THICKNESS - BIT_SEPARATOR_THICKNESS;
|
||||
return (allocationByteSize * BYTE_WIDTH) + BYTE_SEPARATOR_THICKNESS + extraLineSpace;
|
||||
return (allocationByteSize * byteWidth) + BYTE_SEPARATOR_THICKNESS + extraLineSpace;
|
||||
}
|
||||
|
||||
public boolean isBigEndian() {
|
||||
@ -140,7 +199,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
}
|
||||
|
||||
int getBitOffset(Point point) {
|
||||
int bitWidthWithLine = BIT_WIDTH + BIT_SEPARATOR_THICKNESS;
|
||||
int bitWidthWithLine = bitWidth + BIT_SEPARATOR_THICKNESS;
|
||||
int cellIndex = (point.x - BYTE_SEPARATOR_THICKNESS) / bitWidthWithLine;
|
||||
return (8 * allocationByteSize) - cellIndex - 1;
|
||||
}
|
||||
@ -321,6 +380,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
if (bitFieldAllocation == null) {
|
||||
return null;
|
||||
}
|
||||
// TODO: binary search could be used for very large structures
|
||||
for (BitAttributes attrs : bitFieldAllocation.bitAttributes) {
|
||||
if (attrs.rectangle != null && attrs.rectangle.contains(p)) {
|
||||
return attrs;
|
||||
@ -329,6 +389,21 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
return null;
|
||||
}
|
||||
|
||||
int getBitIndex(int x) {
|
||||
if (bitFieldAllocation == null) {
|
||||
return -1;
|
||||
}
|
||||
// TODO: binary search could be used for very large structures
|
||||
for (int i = 0; i < bitFieldAllocation.bitAttributes.length; i++) {
|
||||
BitAttributes attrs = bitFieldAllocation.bitAttributes[i];
|
||||
if (attrs.rectangle != null && x >= attrs.rectangle.x &&
|
||||
x < (attrs.rectangle.x + attrs.rectangle.width)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rectangle which fully encompasses specified component.
|
||||
* @param dtc data type component
|
||||
@ -342,7 +417,6 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
|
||||
if (extendToByteBoundary) {
|
||||
// compute rectangle which extends to byte boundary
|
||||
int byteWidth = 8 * (BIT_WIDTH + BIT_SEPARATOR_THICKNESS);
|
||||
int offset = (dtc.getOffset() - allocationByteOffset);
|
||||
if (!bigEndian) {
|
||||
offset = allocationByteSize - offset - dtc.getLength();
|
||||
@ -371,7 +445,10 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
@Override
|
||||
public String getToolTipText(MouseEvent e) {
|
||||
BitAttributes attrs = getBitAttributes(e.getPoint());
|
||||
return attrs != null ? attrs.getTip() : null;
|
||||
String dtcInfo = attrs != null ? (attrs.getTip() + "<BR>") : "";
|
||||
return "<HTML><div style=\"text-align:center\">" + dtcInfo +
|
||||
"<div style=\"color: gray;font-style: italic\">(Shift-wheel to zoom)</div></div></HTML>";
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -412,12 +489,12 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
// start close to the left clip bounds
|
||||
Rectangle clipBounds = g.getClipBounds();
|
||||
int maxX = clipBounds.x + clipBounds.width - 1;
|
||||
int startIndex = clipBounds.x / BYTE_WIDTH;
|
||||
x += startIndex * BYTE_WIDTH;
|
||||
int startIndex = clipBounds.x / byteWidth;
|
||||
x += startIndex * byteWidth;
|
||||
|
||||
for (int i = startIndex; i < byteSize; i++) {
|
||||
// last byte header needs to slightly wider
|
||||
int w = BYTE_WIDTH;
|
||||
int w = byteWidth;
|
||||
if (i == (byteSize - 1)) {
|
||||
w += BYTE_SEPARATOR_THICKNESS - BIT_SEPARATOR_THICKNESS;
|
||||
}
|
||||
@ -433,7 +510,6 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
private void paintByte(Graphics g, int x, int y, int width, int byteIndex, int baseOffset) {
|
||||
|
||||
Color curColor = g.getColor();
|
||||
Font curFont = g.getFont();
|
||||
|
||||
int offset = byteIndex;
|
||||
if (!bigEndian) {
|
||||
@ -445,8 +521,6 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
g.fillRect(x, y, width - BYTE_SEPARATOR_THICKNESS, CELL_HEIGHT); // byte fill
|
||||
|
||||
g.setColor(TEXT_COLOR);
|
||||
Font textFont = getFont().deriveFont(Font.BOLD);
|
||||
g.setFont(textFont);
|
||||
|
||||
String offsetStr = Integer.toString(offset);
|
||||
FontMetrics fontMetrics = g.getFontMetrics();
|
||||
@ -455,7 +529,6 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
g.drawString(offsetStr, textX, textY);
|
||||
|
||||
g.setColor(curColor);
|
||||
g.setFont(curFont);
|
||||
}
|
||||
|
||||
private void paintBits(Graphics2D g, int y) {
|
||||
@ -480,9 +553,9 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
// start close to the left clip bounds
|
||||
Rectangle clipBounds = g.getClipBounds();
|
||||
int maxX = clipBounds.x + clipBounds.width - 1;
|
||||
int bitWidth = bitAttributes[0].rectangle.width;
|
||||
int width = bitAttributes[0].rectangle.width;
|
||||
int startIndex = clipBounds.x / (bitAttributes[0].rectangle.width);
|
||||
x += startIndex * bitWidth;
|
||||
x += startIndex * width;
|
||||
|
||||
int bitIndex;
|
||||
for (bitIndex = startIndex; bitIndex < bitAttributes.length; bitIndex++) {
|
||||
@ -500,16 +573,16 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
}
|
||||
if (prevDtc == null) {
|
||||
prevDtc = dtc;
|
||||
dtcRectangle = new Rectangle(attrs.rectangle);
|
||||
dtcRectangle = new Rectangle(attrs.rectangle.intersection(clipBounds));
|
||||
}
|
||||
dtcRectangle.add(attrs.rectangle);
|
||||
dtcRectangle.add(attrs.rectangle.intersection(clipBounds));
|
||||
|
||||
if (attrs.unallocated) {
|
||||
paintDit(g, attrs.rectangle);
|
||||
}
|
||||
|
||||
prevAttrs = attrs;
|
||||
x += bitWidth;
|
||||
x += width;
|
||||
}
|
||||
if (prevDtc != null) {
|
||||
paintComponentLabel(g, prevDtc, dtcRectangle);
|
||||
@ -687,7 +760,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
private void layoutBits() {
|
||||
int x = BYTE_SEPARATOR_THICKNESS;
|
||||
int y = (2 * BYTE_SEPARATOR_THICKNESS) + CELL_HEIGHT;
|
||||
int width = BIT_WIDTH + BIT_SEPARATOR_THICKNESS;
|
||||
int width = bitWidth + BIT_SEPARATOR_THICKNESS;
|
||||
for (BitAttributes attrs : bitAttributes) {
|
||||
attrs.layout(x, y, width, CELL_HEIGHT);
|
||||
x += width;
|
||||
@ -872,7 +945,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
}
|
||||
// little-endian: place strip on right-side of bit
|
||||
// big-endian: place strip on left-side of bit
|
||||
int xStrip = bigEndian ? rectangle.x : (rectangle.x + BIT_WIDTH - ZERO_BIT_WIDTH);
|
||||
int xStrip = bigEndian ? rectangle.x : (rectangle.x + bitWidth - ZERO_BIT_WIDTH);
|
||||
int xLine =
|
||||
bigEndian ? (xStrip + ZERO_BIT_WIDTH) : (xStrip - BIT_SEPARATOR_THICKNESS);
|
||||
g.setColor(c);
|
||||
@ -881,7 +954,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
g.fillRect(xLine, rectangle.y, BIT_SEPARATOR_THICKNESS, CELL_HEIGHT);
|
||||
}
|
||||
else {
|
||||
g.fillRect(rectangle.x, rectangle.y, BIT_WIDTH, CELL_HEIGHT);
|
||||
g.fillRect(rectangle.x, rectangle.y, bitWidth, CELL_HEIGHT);
|
||||
if (conflict != null && conflict.dtc.isZeroBitFieldComponent()) {
|
||||
conflict.paint(g, null, false);
|
||||
}
|
||||
@ -901,7 +974,7 @@ public class BitFieldPlacementComponent extends JPanel {
|
||||
lineColor = INTERIOR_LINE_COLOR;
|
||||
}
|
||||
g.setColor(lineColor);
|
||||
g.fillRect(rectangle.x + BIT_WIDTH, rectangle.y, BIT_SEPARATOR_THICKNESS,
|
||||
g.fillRect(rectangle.x + bitWidth, rectangle.y, BIT_SEPARATOR_THICKNESS,
|
||||
CELL_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
@ -377,13 +377,16 @@ class StructureDB extends CompositeDB implements Structure {
|
||||
int endIndex = startIndex;
|
||||
if (startIndex < components.size()) {
|
||||
// some shifting of components may be required
|
||||
int endBitOffset = startBitOffset + effectiveBitSize - 1;
|
||||
endIndex = Collections.binarySearch(components, new Integer(endBitOffset),
|
||||
int endBitOffset = startBitOffset;
|
||||
if (effectiveBitSize != 0) {
|
||||
endBitOffset += effectiveBitSize - 1;
|
||||
}
|
||||
endIndex = Collections.binarySearch(components, Integer.valueOf(endBitOffset),
|
||||
bitOffsetComparator);
|
||||
if (endIndex < 0) {
|
||||
endIndex = -endIndex - 1;
|
||||
}
|
||||
else {
|
||||
else if (effectiveBitSize != 0) {
|
||||
hasConflict = true;
|
||||
}
|
||||
}
|
||||
|
@ -574,13 +574,16 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
int endIndex = startIndex;
|
||||
if (startIndex < components.size()) {
|
||||
// some shifting of components may be required
|
||||
int endBitOffset = startBitOffset + effectiveBitSize - 1;
|
||||
endIndex = Collections.binarySearch(components, new Integer(endBitOffset),
|
||||
int endBitOffset = startBitOffset;
|
||||
if (effectiveBitSize != 0) {
|
||||
endBitOffset += effectiveBitSize - 1;
|
||||
}
|
||||
endIndex = Collections.binarySearch(components, Integer.valueOf(endBitOffset),
|
||||
bitOffsetComparator);
|
||||
if (endIndex < 0) {
|
||||
endIndex = -endIndex - 1;
|
||||
}
|
||||
else {
|
||||
else if (effectiveBitSize != 0) {
|
||||
hasConflict = true;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user