* implemented hex-viewer feature * added support for opening lib (.so) files * removed unused class * fix formatting * fixed error when opening an empty file * fixed a slight inaccuracy in synchronizing highlights * defaulted little endian to false * synchronize hex editor with theme and use smali font * fixed wrong displayed values * applied code formatting * fixed selection color in preview panel * Changed Smali Editor font entry in settings less confusing
This commit is contained in:
@@ -21,6 +21,7 @@ import jadx.core.utils.ListUtils;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.xmlgen.ResContainer;
|
||||
import jadx.gui.ui.TabbedPane;
|
||||
import jadx.gui.ui.codearea.BinaryContentPanel;
|
||||
import jadx.gui.ui.codearea.CodeContentPanel;
|
||||
import jadx.gui.ui.panel.ContentPanel;
|
||||
import jadx.gui.ui.panel.ImagePanel;
|
||||
@@ -131,6 +132,12 @@ public class JResource extends JLoadableNode {
|
||||
if (resFile.getType() == ResourceType.IMG) {
|
||||
return new ImagePanel(tabbedPane, this);
|
||||
}
|
||||
if (resFile.getType() == ResourceType.LIB) {
|
||||
return new BinaryContentPanel(tabbedPane, this, false);
|
||||
}
|
||||
if (getSyntaxByExtension(resFile.getDeobfName()) == null) {
|
||||
return new BinaryContentPanel(tabbedPane, this);
|
||||
}
|
||||
return new CodeContentPanel(tabbedPane, this);
|
||||
}
|
||||
|
||||
@@ -272,7 +279,6 @@ public class JResource extends JLoadableNode {
|
||||
switch (type) {
|
||||
case CODE:
|
||||
case FONT:
|
||||
case LIB:
|
||||
case MEDIA:
|
||||
return false;
|
||||
|
||||
@@ -280,6 +286,7 @@ public class JResource extends JLoadableNode {
|
||||
case XML:
|
||||
case ARSC:
|
||||
case IMG:
|
||||
case LIB:
|
||||
case UNKNOWN:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package jadx.gui.ui.codearea;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.LineNumbersMode;
|
||||
import jadx.gui.treemodel.JNode;
|
||||
import jadx.gui.ui.TabbedPane;
|
||||
|
||||
public class BinaryContentPanel extends AbstractCodeContentPanel {
|
||||
private final transient CodePanel textCodePanel;
|
||||
private final transient CodePanel hexCodePanel;
|
||||
private final transient HexConfigurationPanel hexConfigurationPanel;
|
||||
private final transient JTabbedPane areaTabbedPane;
|
||||
|
||||
public BinaryContentPanel(TabbedPane panel, JNode jnode) {
|
||||
this(panel, jnode, true);
|
||||
}
|
||||
|
||||
public BinaryContentPanel(TabbedPane panel, JNode jnode, boolean supportsText) {
|
||||
super(panel, jnode);
|
||||
setLayout(new BorderLayout());
|
||||
setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
if (supportsText) {
|
||||
textCodePanel = new CodePanel(new CodeArea(this, jnode));
|
||||
} else {
|
||||
textCodePanel = null;
|
||||
}
|
||||
HexArea hexArea = new HexArea(this, jnode);
|
||||
hexConfigurationPanel = new HexConfigurationPanel(hexArea.getConfiguration());
|
||||
hexArea.setConfigurationPanel(hexConfigurationPanel);
|
||||
hexCodePanel = new CodePanel(hexArea);
|
||||
areaTabbedPane = buildTabbedPane();
|
||||
add(areaTabbedPane);
|
||||
|
||||
getSelectedPanel().load();
|
||||
}
|
||||
|
||||
private JTabbedPane buildTabbedPane() {
|
||||
JSplitPane hexSplitPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, hexCodePanel, hexConfigurationPanel);
|
||||
hexSplitPanel.setResizeWeight(0.8);
|
||||
|
||||
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.BOTTOM);
|
||||
tabbedPane.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
|
||||
if (textCodePanel != null) {
|
||||
tabbedPane.add(textCodePanel, "Text");
|
||||
}
|
||||
tabbedPane.add(hexSplitPanel, "Hex");
|
||||
tabbedPane.addChangeListener(e -> {
|
||||
getSelectedPanel().load();
|
||||
});
|
||||
return tabbedPane;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractCodeArea getCodeArea() {
|
||||
if (textCodePanel != null) {
|
||||
return textCodePanel.getCodeArea();
|
||||
} else {
|
||||
return hexCodePanel.getCodeArea();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadSettings() {
|
||||
if (textCodePanel != null) {
|
||||
textCodePanel.loadSettings();
|
||||
}
|
||||
hexCodePanel.loadSettings();
|
||||
updateUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JadxSettings getSettings() {
|
||||
JadxSettings settings = super.getSettings();
|
||||
settings.setLineNumbersMode(LineNumbersMode.NORMAL);
|
||||
return settings;
|
||||
}
|
||||
|
||||
private CodePanel getSelectedPanel() {
|
||||
Component selectedComponent = areaTabbedPane.getSelectedComponent();
|
||||
CodePanel selectedPanel;
|
||||
if (selectedComponent instanceof CodePanel) {
|
||||
selectedPanel = (CodePanel) selectedComponent;
|
||||
} else if (selectedComponent instanceof JSplitPane) {
|
||||
selectedPanel = (CodePanel) ((JSplitPane) selectedComponent).getLeftComponent();
|
||||
} else {
|
||||
throw new RuntimeException("tabbedPane.getSelectedComponent returned a Component "
|
||||
+ "of unexpected type " + selectedComponent);
|
||||
}
|
||||
return selectedPanel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package jadx.gui.ui.codearea;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Font;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.CaretEvent;
|
||||
import javax.swing.event.CaretListener;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.fife.ui.rsyntaxtextarea.Theme;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.ICodeInfo;
|
||||
import jadx.gui.treemodel.JNode;
|
||||
import jadx.gui.ui.panel.ContentPanel;
|
||||
import jadx.gui.utils.UiUtils;
|
||||
|
||||
public class HexArea extends AbstractCodeArea {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HexArea.class);
|
||||
|
||||
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
||||
|
||||
private final HexAreaConfiguration config;
|
||||
private final JNode binaryNode;
|
||||
private final HexPreviewPanel hexPreviewPanel;
|
||||
private HexConfigurationPanel hexConfigurationPanel;
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
public HexArea(ContentPanel contentPanel, JNode node) {
|
||||
super(contentPanel, node);
|
||||
binaryNode = node;
|
||||
config = new HexAreaConfiguration();
|
||||
hexPreviewPanel = new HexPreviewPanel(config);
|
||||
|
||||
initView();
|
||||
applyTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ICodeInfo getCodeInfo() {
|
||||
return ICodeInfo.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
byte[] bytes = binaryNode.getCodeInfo().getCodeStr().getBytes(StandardCharsets.UTF_8);
|
||||
setBytes(bytes);
|
||||
if (getBytes().length > 0) {
|
||||
// We set the caret after the first byte to prevent it from being highlighted
|
||||
setCaretPosition(2);
|
||||
} else {
|
||||
setCaretPosition(0);
|
||||
}
|
||||
setLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadSettings() {
|
||||
super.loadSettings();
|
||||
applyTheme();
|
||||
}
|
||||
|
||||
private void applyTheme() {
|
||||
Font font = getContentPanel().getTabbedPane().getMainWindow().getSettings().getSmaliFont();
|
||||
setFont(font);
|
||||
|
||||
Theme theme = contentPanel.getTabbedPane().getMainWindow().getEditorTheme();
|
||||
if (hexPreviewPanel != null) {
|
||||
hexPreviewPanel.applyTheme(theme, font);
|
||||
}
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
addCaretListener(new HexCaretListener());
|
||||
setLayout(new BorderLayout());
|
||||
setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
hexPreviewPanel.setFont(getFont());
|
||||
add(hexPreviewPanel, BorderLayout.EAST);
|
||||
}
|
||||
|
||||
private void setBytes(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
|
||||
String text;
|
||||
if (bytes.length > 0) {
|
||||
byte[] hexChars = new byte[bytes.length * 4 - 2];
|
||||
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
hexChars[j * 4] = HEX_ARRAY[v >>> 4];
|
||||
hexChars[j * 4 + 1] = HEX_ARRAY[v & 0x0F];
|
||||
if (j != bytes.length - 1) {
|
||||
hexChars[j * 4 + 2] = ' ';
|
||||
hexChars[j * 4 + 3] = (byte) ((j % config.bytesPerLine == config.bytesPerLine - 1) ? '\n' : ' ');
|
||||
}
|
||||
}
|
||||
text = new String(hexChars, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
text = "";
|
||||
}
|
||||
setText(text);
|
||||
hexPreviewPanel.setBytes(bytes);
|
||||
hexConfigurationPanel.setBytes(bytes);
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void setConfigurationPanel(HexConfigurationPanel hexConfigurationPanel) {
|
||||
this.hexConfigurationPanel = hexConfigurationPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyAsStyledText() {
|
||||
String text = getSelectedText();
|
||||
if (text != null && !StringUtils.isEmpty(text)) {
|
||||
text = text
|
||||
.replace(" ", "")
|
||||
.replace("\n", "");
|
||||
UiUtils.copyToClipboard(text);
|
||||
}
|
||||
}
|
||||
|
||||
public HexAreaConfiguration getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
private class HexCaretListener implements CaretListener {
|
||||
private boolean isListening = true;
|
||||
private int previousCaretDot = -1;
|
||||
|
||||
@Override
|
||||
public void caretUpdate(CaretEvent caretEvent) {
|
||||
int dot = caretEvent.getDot();
|
||||
int mark = caretEvent.getMark();
|
||||
|
||||
if (!isListening) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dot % 2 == 1) {
|
||||
if (previousCaretDot > dot) {
|
||||
if (mark == dot) {
|
||||
mark--;
|
||||
}
|
||||
dot--;
|
||||
} else {
|
||||
if (mark == dot) {
|
||||
mark++;
|
||||
}
|
||||
dot++;
|
||||
}
|
||||
|
||||
isListening = false;
|
||||
HexArea.this.setCaretPosition(mark);
|
||||
HexArea.this.moveCaretPosition(dot);
|
||||
isListening = true;
|
||||
}
|
||||
|
||||
if (previousCaretDot != dot) {
|
||||
onTextCursorMoved(dot, mark);
|
||||
}
|
||||
|
||||
previousCaretDot = dot;
|
||||
}
|
||||
|
||||
private void onTextCursorMoved(int dot, int mark) {
|
||||
hexConfigurationPanel.setOffset(dot / 4);
|
||||
|
||||
int startIndex = Math.min(dot, mark);
|
||||
int endIndex = Math.max(dot, mark);
|
||||
int startOffset = startIndex / 4;
|
||||
int endOffset = endIndex / 4;
|
||||
if (startIndex % 4 == 2 && endIndex == startIndex + 2) {
|
||||
// Highlighted an empty space
|
||||
hexPreviewPanel.clearHighlights();
|
||||
return;
|
||||
}
|
||||
if (startOffset < endOffset && startIndex % 4 == 2) {
|
||||
startOffset++;
|
||||
}
|
||||
if (endOffset > startOffset && endIndex % 4 == 0) {
|
||||
endOffset--;
|
||||
}
|
||||
hexPreviewPanel.highlightBytes(startOffset, endOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package jadx.gui.ui.codearea;
|
||||
|
||||
public class HexAreaConfiguration {
|
||||
public int bytesPerLine = 16;
|
||||
|
||||
public boolean littleEndian = false;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package jadx.gui.ui.codearea;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
public class HexConfigurationPanel extends JPanel {
|
||||
private final List<ValueFormatter> formatters = new ArrayList<>();
|
||||
|
||||
private final HexAreaConfiguration config;
|
||||
|
||||
private byte[] bytes = null;
|
||||
private Integer offset = null;
|
||||
|
||||
private int row = 0;
|
||||
|
||||
public HexConfigurationPanel(HexAreaConfiguration configuration) {
|
||||
this.config = configuration;
|
||||
|
||||
setLayout(new GridBagLayout());
|
||||
addValueFormat("Signed 8 bit", 1, b -> Integer.toString(b.get()));
|
||||
addValueFormat("Unsigned 8 bit", 1, b -> Integer.toString(b.get() & 0xFF));
|
||||
addValueFormat("Signed 16 bit", 2, b -> Short.toString(b.getShort()));
|
||||
addValueFormat("Unsigned 16 bit", 2, b -> Integer.toString(b.getShort() & 0xFFFF));
|
||||
addValueFormat("Float 32 bit", 4, b -> Float.toString(b.getFloat()));
|
||||
addValueFormat("Signed 32 bit", 4, b -> Integer.toString(b.getInt()));
|
||||
addValueFormat("Unsigned 32 bit", 4, b -> Integer.toUnsignedString(b.getInt()));
|
||||
addValueFormat("Signed 64 bit", 8, b -> Long.toString(b.getLong()));
|
||||
addValueFormat("Float 64 bit", 8, b -> Double.toString(b.getDouble()));
|
||||
addValueFormat("Unsigned 64 bit", 8, b -> Long.toUnsignedString(b.getLong()));
|
||||
addValueFormat("Hexadecimal", 1, b -> Integer.toString(b.get(), 16));
|
||||
addValueFormat("Octal", 1, b -> Integer.toString(b.get(), 8));
|
||||
addValueFormat("Binary", 1, b -> Integer.toString(b.get(), 2));
|
||||
|
||||
GridBagConstraints constraints;
|
||||
constraints = getConstraints();
|
||||
constraints.gridwidth = 2;
|
||||
JCheckBox littleEndianCheckBox = new JCheckBox("Little endian", false);
|
||||
littleEndianCheckBox.addItemListener(ev -> {
|
||||
config.littleEndian = ev.getStateChange() == ItemEvent.SELECTED;
|
||||
reloadOffset();
|
||||
});
|
||||
add(littleEndianCheckBox, constraints);
|
||||
|
||||
// Workaround to force widgets to start from the top (otherwise centered)
|
||||
constraints = getConstraints();
|
||||
constraints.weighty = 1;
|
||||
add(new JLabel(" "), constraints);
|
||||
}
|
||||
|
||||
public void setOffset(int offset) {
|
||||
this.offset = offset;
|
||||
reloadOffset();
|
||||
}
|
||||
|
||||
public void setBytes(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
private void reloadOffset() {
|
||||
if (bytes == null || offset == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < formatters.size(); i++) {
|
||||
ValueFormatter formatter = formatters.get(i);
|
||||
if (canDisplay(offset, formatter.dataSize)) {
|
||||
ByteBuffer buffer = decodeByteArray(offset, formatter.dataSize);
|
||||
String value = formatter.function.apply(buffer);
|
||||
((JTextField) getComponent(i * 2 + 1)).setText(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GridBagConstraints getConstraints() {
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.insets = new Insets(5, 5, 5, 5);
|
||||
constraints.gridy = row;
|
||||
row++;
|
||||
return constraints;
|
||||
}
|
||||
|
||||
private void addValueFormat(String name, int dataSize, Function<ByteBuffer, String> formatter) {
|
||||
formatters.add(new ValueFormatter(dataSize, formatter));
|
||||
|
||||
GridBagConstraints constraints = getConstraints();
|
||||
constraints.gridx = 0;
|
||||
constraints.anchor = GridBagConstraints.WEST;
|
||||
add(new JLabel(name), constraints);
|
||||
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
constraints.gridx = 1;
|
||||
|
||||
JTextField textField = new JTextField();
|
||||
textField.setEditable(false);
|
||||
|
||||
add(textField, constraints);
|
||||
}
|
||||
|
||||
private boolean canDisplay(int offset, int size) {
|
||||
return offset + size <= bytes.length;
|
||||
}
|
||||
|
||||
private ByteBuffer decodeByteArray(int offset, int size) {
|
||||
byte[] chunk = sliceBytes(offset, size);
|
||||
if (config.littleEndian) {
|
||||
ArrayUtils.reverse(chunk);
|
||||
}
|
||||
return ByteBuffer.wrap(chunk);
|
||||
}
|
||||
|
||||
private byte[] sliceBytes(int offset, int size) {
|
||||
byte[] slice = new byte[size];
|
||||
System.arraycopy(bytes, offset, slice, 0, size);
|
||||
return slice;
|
||||
}
|
||||
|
||||
private static class ValueFormatter {
|
||||
public final int dataSize;
|
||||
public final Function<ByteBuffer, String> function;
|
||||
|
||||
public ValueFormatter(int dataSize, Function<ByteBuffer, String> function) {
|
||||
this.dataSize = dataSize;
|
||||
this.function = function;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package jadx.gui.ui.codearea;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.border.MatteBorder;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.DefaultHighlighter;
|
||||
import javax.swing.text.Highlighter;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxScheme;
|
||||
import org.fife.ui.rsyntaxtextarea.Theme;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HexPreviewPanel extends JTextArea {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HexPreviewPanel.class);
|
||||
|
||||
private final HexAreaConfiguration config;
|
||||
|
||||
private byte[] bytes = new byte[0];
|
||||
|
||||
private Color highlightColor = Color.YELLOW;
|
||||
private boolean hasHighlight = false;
|
||||
|
||||
public HexPreviewPanel(HexAreaConfiguration configuration) {
|
||||
super(0, configuration.bytesPerLine);
|
||||
|
||||
this.config = configuration;
|
||||
initView();
|
||||
}
|
||||
|
||||
public void setBytes(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
char c = (char) bytes[i];
|
||||
if (c <= 0x1f || (c & (1 << 7)) != 0) {
|
||||
sb.append('.');
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
if (i != bytes.length - 1 && i % config.bytesPerLine == config.bytesPerLine - 1) {
|
||||
sb.append('\n');
|
||||
}
|
||||
}
|
||||
setText(sb.toString());
|
||||
}
|
||||
|
||||
public void clearHighlights() {
|
||||
hasHighlight = false;
|
||||
getHighlighter().removeAllHighlights();
|
||||
}
|
||||
|
||||
public void highlightBytes(int startOffset, int endOffset) {
|
||||
if (hasHighlight) {
|
||||
getHighlighter().removeAllHighlights();
|
||||
}
|
||||
|
||||
// Include line breaks in the index
|
||||
startOffset += startOffset / config.bytesPerLine;
|
||||
endOffset += endOffset / config.bytesPerLine;
|
||||
|
||||
Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(highlightColor);
|
||||
try {
|
||||
getHighlighter().addHighlight(startOffset, endOffset + 1, painter);
|
||||
} catch (BadLocationException e) {
|
||||
LOG.error("Unable to highlight bytes " + startOffset + ":" + endOffset, e);
|
||||
}
|
||||
hasHighlight = true;
|
||||
}
|
||||
|
||||
public void setHighlightColor(Color highlightColor) {
|
||||
this.highlightColor = highlightColor;
|
||||
}
|
||||
|
||||
public void setBorderColor(Color borderColor) {
|
||||
setBorder(new MatteBorder(0, 2, 0, 0, borderColor));
|
||||
}
|
||||
|
||||
public void applyTheme(Theme theme, Font font) {
|
||||
setBackground(theme.bgColor);
|
||||
setHighlightColor(theme.selectionBG);
|
||||
setBorderColor(theme.gutterBorderColor);
|
||||
setDisabledTextColor(theme.scheme.getStyle(SyntaxScheme.IDENTIFIER).foreground);
|
||||
setFont(font);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
setEnabled(false);
|
||||
setEditable(false);
|
||||
}
|
||||
}
|
||||
@@ -199,7 +199,7 @@ preferences.cfg=CFG-Grafiken für Methoden generieren (im 'dot'-Format)
|
||||
preferences.raw_cfg=RAW CFG-Grafiken generieren
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Schrift ändern
|
||||
preferences.smali_font=Schrifteditor
|
||||
#preferences.smali_font=
|
||||
preferences.laf_theme=Thema
|
||||
preferences.theme=Thema ändern
|
||||
preferences.start_jobs=Autom. Hintergrunddekompilierung starten
|
||||
|
||||
@@ -199,7 +199,7 @@ preferences.cfg=Generate methods CFG graphs (in 'dot' format)
|
||||
preferences.raw_cfg=Generate RAW CFG graphs
|
||||
preferences.integerFormat=Integer format
|
||||
preferences.font=Editor font
|
||||
preferences.smali_font=Smali Editor font
|
||||
preferences.smali_font=Monospaced font (Smali/Hex)
|
||||
preferences.laf_theme=Theme
|
||||
preferences.theme=Editor theme
|
||||
preferences.start_jobs=Auto start background decompilation
|
||||
|
||||
@@ -199,7 +199,7 @@ preferences.cfg=메소드 CFG 그래프 생성 ('dot' 포맷)
|
||||
preferences.raw_cfg=RAW CFG 그래프 생성
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=에디터 글씨체
|
||||
preferences.smali_font=Smali 에디터 글씨체
|
||||
#preferences.smali_font=
|
||||
preferences.laf_theme=테마
|
||||
preferences.theme=에디터 테마
|
||||
preferences.start_jobs=백그라운드에서 디컴파일 자동 시작
|
||||
|
||||
@@ -199,7 +199,7 @@ preferences.cfg=Gera gráficos de métodos CFG no formato de pontos ('dot')
|
||||
preferences.raw_cfg=Gera gráficos CFG no formato RAW
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Fonte do editor
|
||||
preferences.smali_font=Fonte do editor de smali
|
||||
#preferences.smali_font=
|
||||
preferences.laf_theme=Tema
|
||||
preferences.theme=Tema do editor
|
||||
preferences.start_jobs=Inicializar descompilação automaticamente em segundo-plano
|
||||
|
||||
@@ -199,7 +199,7 @@ preferences.cfg=Методы генерации графиков CFG (в "dot"
|
||||
preferences.raw_cfg=Генерировать необработанные графики CFG
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Шрифт редактора Java
|
||||
preferences.smali_font=Шрифт редактора smali
|
||||
#preferences.smali_font=
|
||||
preferences.laf_theme=Тема приложения
|
||||
preferences.theme=Тема редактора
|
||||
preferences.start_jobs=Автоматическая декомпиляция
|
||||
|
||||
@@ -199,7 +199,7 @@ preferences.cfg=生成方法的 CFG 图('.dot')
|
||||
preferences.raw_cfg=生成原始的 CFG 图
|
||||
preferences.integerFormat=数值格式化
|
||||
preferences.font=编辑器字体
|
||||
preferences.smali_font=Smali编辑器字体
|
||||
#preferences.smali_font=
|
||||
preferences.laf_theme=主题
|
||||
preferences.theme=编辑器主题
|
||||
preferences.start_jobs=自动进行后台反编译
|
||||
|
||||
@@ -199,7 +199,7 @@ preferences.cfg=產生方法 CFG 圖表 ('dot' 格式)
|
||||
preferences.raw_cfg=產生 RAW CFG 圖表
|
||||
preferences.integerFormat=整數模式
|
||||
preferences.font=編輯器字型
|
||||
preferences.smali_font=Smali 編輯器字型
|
||||
#preferences.smali_font=
|
||||
preferences.laf_theme=主題
|
||||
preferences.theme=編輯器主題
|
||||
preferences.start_jobs=自動開始背景反編譯
|
||||
|
||||
Reference in New Issue
Block a user