AS1/2 debugger

debugger listening only when really debugging started
fail to listen message
break reason displayed
This commit is contained in:
Jindra Petřík
2015-11-21 19:12:42 +01:00
parent 6d7ebb2619
commit 1237762e60
32 changed files with 1355 additions and 626 deletions

1
.gitignore vendored
View File

@@ -7,6 +7,7 @@
*.conflict~
*.identcache
*.recompiled.swf
run_test_*.swf
Thumbs.db
/build/
/reports/

Binary file not shown.

View File

@@ -52,7 +52,7 @@ auxiliary.show.customizer.message=<message>
<action name="rebuild">
<target>clean</target>
<target>build</target>
</action>
</action>
<action name="debug">
<script>../../nbproject/ide-targets.xml</script>
<target>debug-nb</target>
@@ -137,7 +137,7 @@ auxiliary.show.customizer.message=<message>
<arity>
<one-file-only/>
</arity>
</context>
</context>
</action>
<action name="debug.test.single">
<script>nbproject/ide-file-targets.xml</script>
@@ -147,7 +147,7 @@ auxiliary.show.customizer.message=<message>
<folder>test</folder>
<pattern>\.java$</pattern>
<format>java-name</format>
<arity>
<arity>
<one-file-only/>
</arity>
</context>
@@ -181,7 +181,7 @@ auxiliary.show.customizer.message=<message>
<one-file-only/>
</arity>
</context>
</action>
</action>
</ide-actions>
<export>
<type>folder</type>
@@ -219,7 +219,7 @@ auxiliary.show.customizer.message=<message>
</source-file>
<source-file>
<location>nbproject/ide-file-targets.xml</location>
</source-file>
</source-file>
</items>
<context-menu>
<ide-action name="build"/>
@@ -236,7 +236,7 @@ auxiliary.show.customizer.message=<message>
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
<compilation-unit>
<package-root>src</package-root>
<classpath mode="compile">../../lib/LZMA.jar;../../lib/avi.jar;../../lib/gif.jar;../../lib/gnujpdf.jar;../../lib/jl1.0.1.jar;../../lib/jpacker.jar;../../lib/nellymoser.jar;../../lib/sfntly.jar;../../lib/ttf.jar;../../lib/cmykjpeg.jar;../../src</classpath>
<classpath mode="compile">../../lib/LZMA.jar;../../lib/avi.jar;../../lib/gif.jar;../../lib/gnujpdf.jar;../../lib/jl1.0.1.jar;../../lib/jpacker.jar;../../lib/nellymoser.jar;../../lib/sfntly.jar;../../lib/ttf.jar;../../lib/cmykjpeg.jar;../../src;../../lib/flashdebugger.jar</classpath>
<built-to>build</built-to>
<built-to>reports</built-to>
<built-to>dist</built-to>

View File

@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash;
import SevenZip.Compression.LZMA.Decoder;
import SevenZip.Compression.LZMA.Encoder;
import com.jpexs.debugger.flash.SWD;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.CachedDecompilation;
import com.jpexs.decompiler.flash.abc.ClassPath;
@@ -77,6 +78,7 @@ import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DebugIDTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
@@ -157,6 +159,7 @@ import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -171,10 +174,15 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
@@ -1094,12 +1102,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
}
/*preload shape tags
for (Tag tag : tags) {
if (tag instanceof ShapeTag) {
((ShapeTag) tag).getShapes();
}
}*/
getASMs(true); // Add scriptNames to ASMs
}
@Override
@@ -1473,11 +1476,14 @@ public final class SWF implements SWFContainerItem, Timelined {
TreeItem realItem = treeItem instanceof TagScript ? ((TagScript) treeItem).getTag() : treeItem;
if (realItem instanceof ASMSource && (exportAll || exportNode)) {
String npath = path;
String exPath = path;
int ppos = 1;
while (asmsToExport.containsKey(npath)) {
ppos++;
npath = path + (exportFileNames ? "[" + ppos + "]" : "_" + ppos);
exPath = path + "[" + ppos + "]";
}
((ASMSource) realItem).setScriptName(exPath);
asmsToExport.put(npath, (ASMSource) realItem);
}
@@ -3143,6 +3149,8 @@ public final class SWF implements SWFContainerItem, Timelined {
int pos = 0;
boolean hasEnabled = false;
for (int i = 0; i < tags.size(); i++) {
Tag t = tags.get(i);
if (t instanceof MetadataTag) {
@@ -3152,23 +3160,183 @@ public final class SWF implements SWFContainerItem, Timelined {
pos = i + 1;
}
if (version >= 6 && (t instanceof EnableDebugger2Tag)) {
return;
hasEnabled = true;
break;
}
if (version == 5 && (t instanceof EnableDebuggerTag)) {
return;
hasEnabled = true;
break;
}
if (version < 5 && (t instanceof ProtectTag)) {
return;
hasEnabled = true;
break;
}
}
if (version >= 6) {
tags.add(pos, new EnableDebugger2Tag(this));
} else if (version == 5) {
tags.add(pos, new EnableDebuggerTag(this));
} else {
tags.add(pos, new ProtectTag(this));
if (!hasEnabled) {
if (version >= 6) {
tags.add(pos, new EnableDebugger2Tag(this));
} else if (version == 5) {
tags.add(pos, new EnableDebuggerTag(this));
} else {
tags.add(pos, new ProtectTag(this));
}
}
addDebugId();
}
public DebugIDTag getDebugId() {
for (Tag t : tags) {
if (t instanceof DebugIDTag) {
return (DebugIDTag) t;
}
}
return null;
}
public DebugIDTag addDebugId() {
DebugIDTag r = getDebugId();
if (r == null) {
for (int i = 0; i < tags.size(); i++) {
Tag t = tags.get(i);
if ((t instanceof EnableDebuggerTag) || (t instanceof EnableDebugger2Tag)) {
r = new DebugIDTag(this);
tags.add(i + 1, r);
new Random().nextBytes(r.debugId);
break;
}
}
}
return r;
}
public boolean generateSwdFile(File file, Map<String, Set<Integer>> breakpoints) throws IOException {
DebugIDTag dit = getDebugId();
if (dit == null) {
return false;
}
List<SWD.DebugItem> items = new ArrayList<>();
Map<String, ASMSource> asms = getASMs(true);
try {
items.add(new SWD.DebugId(dit.debugId));
Random rnd = new Random();
//Map<String, Integer> moduleIds = new HashMap<>();
List<SWD.DebugOffset> swdOffsets = new ArrayList<>();
List<SWD.DebugBreakpoint> swfBps = new ArrayList<>();
int moduleId = 0;
List<String> names = new ArrayList<>(asms.keySet());
Collections.sort(names);
//Collections.reverse(names);
for (String name : names) {
moduleId++;
CachedScript cs;
try {
cs = SWF.getCached(asms.get(name), asms.get(name).getActions());
} catch (InterruptedException ex) {
return false;
}
String txt = cs.text.replace("\r", "");
int line = 1;
Map<Integer, Integer> lineToOffset = new HashMap<>();
Map<Integer, String> regNames = new HashMap<>();
for (int pos = 0; pos < txt.length(); pos++) {
Highlighting h = Highlighting.searchPos(cs.hilights, pos);
if (h != null) {
int firstLineOffset = (int) h.getProperties().firstLineOffset;
if (firstLineOffset != -1) {
if (h.getProperties().declaration && h.getProperties().regIndex > -1) {
regNames.put(h.getProperties().regIndex, h.getProperties().localName);
/*List<Integer> curRegIndexes = new ArrayList<>(regNames.keySet());
List<String> curRegNames = new ArrayList<>();
for (int i = 0; i < curRegIndexes.size(); i++) {
curRegNames.add(regNames.get(i));
}
items.add(new SWD.DebugRegisters((int) h.getProperties().firstLineOffset, curRegIndexes, curRegNames));*/
}
}
if (firstLineOffset != -1 && !lineToOffset.containsKey(line)) {
lineToOffset.put(line, firstLineOffset);
}
}
if (txt.charAt(pos) == '\n') {
line++;
}
}
Map<Integer, Integer> offSetToLine = new TreeMap<>();
for (Map.Entry<Integer, Integer> en : lineToOffset.entrySet()) {
offSetToLine.put(en.getValue(), en.getKey());
}
//final String NONAME = "[No instance name assigned]";
String sname = name;
int bitmap = SWD.bitmapAction;
/* Matcher m;
int bitmap = SWD.bitmapAction;
m = Pattern.compile("^\\\\frame_([0-9]+)\\\\DoAction$").matcher(sname);
if (m.matches()) {
//TODO: scenes?, layers?
sname = "Actions for Scene 1: Frame " + m.group(1) + " of Layer Name Layer 1";
} else if ((m = Pattern.compile("^\\\\__Packages\\\\(.*)$").matcher(sname)).matches()) {
sname = m.group(1).replace("\\", ".") + ": .\\" + m.group(1) + ".as";
} else {
continue; //FIXME!
}
m = Pattern.compile("^\\\\DefineSprite_([0-9])+\\\\frame_([0-9]+)\\\\DoAction$").matcher(sname);
if (m.matches()) {
//TODO: layers?
//sname = "Actions for Symbol " + m.group(1) + ": Frame " + m.group(2) + " of Layer Name Layer 1";
continue; //FIXME!
}
//TODO: handle onxxx together ?
m = Pattern.compile("^\\\\DefineButton2?_([0-9]+)\\\\on\\(.*$").matcher(sname);
if (m.matches()) {
//bitmap = SWD.bitmapOnAction;
//sname = "Actions for " + NONAME + " (Symbol " + m.group(1) + ")";
continue; //FIXME!
}
//TODO: handle onClipEvent together ?
m = Pattern.compile("^\\\\frame_([0-9]+)\\\\PlaceObject[2-3]?_([0-9]+)_[^\\\\]*\\\\onClipEvent\\(.*$").matcher(sname);
if (m.matches()) {
//bitmap = SWD.bitmapOnClipAction;
//sname = "Actions for " + NONAME + " (Symbol " + m.group(2) + ")";
continue; //FIXME!
}//*/
items.add(new SWD.DebugScript(moduleId, bitmap, sname, txt));
for (int ofs : offSetToLine.keySet()) {
items.add(new SWD.DebugOffset(moduleId, offSetToLine.get(ofs), ofs));
}
if (breakpoints.containsKey(name)) {
Set<Integer> bplines = breakpoints.get(name);
for (int bpline : bplines) {
if (lineToOffset.containsKey(bpline)) {
items.add(new SWD.DebugBreakpoint(moduleId, bpline));
}
}
}
//moduleId++;
}
//items.addAll(swdOffsets);
//items.addAll(swfBps);
} catch (Throwable t) {
Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "message", t);
return false;
}
SWD swd = new SWD(7, items);
try (FileOutputStream fis = new FileOutputStream(file)) {
swd.saveTo(fis);
}
return true;
}
public boolean enableTelemetry(String password) {

View File

@@ -897,7 +897,7 @@ public class SWFInputStream implements AutoCloseable {
InflaterInputStream dis = new InflaterInputStream(new ByteArrayInputStream(data, offset, length));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int c = 0;
int c;
while ((c = dis.read(buf)) > 0) {
baos.write(buf, 0, c);
}
@@ -1202,11 +1202,7 @@ public class SWFInputStream implements AutoCloseable {
break;
case DoActionTag.ID:
case DoInitActionTag.ID:
if (isAS3) {
doParse = false;
} else {
doParse = true;
}
doParse = !isAS3;
break;
case ShowFrameTag.ID:
case PlaceObjectTag.ID:
@@ -1233,7 +1229,7 @@ public class SWFInputStream implements AutoCloseable {
}
}
if (parseTags && doParse && parallel1 && tag instanceof TagStub) {
if (parseTags && doParse && parallel1 && tag instanceof TagStub && executor != null) {
Future<Tag> future = executor.submit(new TagResolutionTask((TagStub) tag, di, level, parallel1, skipUnusualTags, lazy));
futureResults.add(future);
} else {
@@ -1262,7 +1258,9 @@ public class SWFInputStream implements AutoCloseable {
}
}
executor.shutdown();
if (executor != null) {
executor.shutdown();
}
}
return tags;
}
@@ -1670,7 +1668,7 @@ public class SWFInputStream implements AutoCloseable {
* @throws IOException
*/
public Action readAction() throws IOException {
int actionCode = -1;
int actionCode;
try {
actionCode = readUI8("actionCode");

View File

@@ -61,6 +61,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
private String file;
@Override
public long getLineOffset() {
return getOffset();
}
public void setFileLine(String file, int line) {
this.file = file;
this.line = line;

View File

@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator;
import com.jpexs.decompiler.flash.action.model.ActionItem;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
@@ -109,6 +110,8 @@ public abstract class Action implements GraphSourceItem {
private boolean ignored = false;
public long fileOffset = -1;
/**
* Action type identifier
*/
@@ -121,6 +124,11 @@ public abstract class Action implements GraphSourceItem {
private long address;
@Override
public long getLineOffset() {
return fileOffset;
}
/**
* Names of ActionScript properties
*/
@@ -937,11 +945,12 @@ public abstract class Action implements GraphSourceItem {
this.ignored = ignored;
}
public static List<GraphTargetItem> actionsPartToTree(HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException {
public static List<GraphTargetItem> actionsPartToTree(Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException {
if (start < actions.size() && (end > 0) && (start > 0)) {
logger.log(Level.FINE, "Entering {0}-{1}{2}", new Object[]{start, end, actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : ""});
}
ActionLocalData localData = new ActionLocalData(registerNames, variables, functions);
localData.lineStartAction = fi.getVal();
List<GraphTargetItem> output = new ArrayList<>();
int ip = start;
boolean isWhile = false;
@@ -964,6 +973,10 @@ public abstract class Action implements GraphSourceItem {
ip++;
continue;
}
if (stack.isEmpty()) {
localData.lineStartAction = action;
fi.setVal(action);
}
if (action instanceof GraphSourceItemContainer) {
GraphSourceItemContainer cnt = (GraphSourceItemContainer) action;
//List<GraphTargetItem> out=actionsPartToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(),new HashMap<String, GraphTargetItem>(), new TranslateStack(), src, ip+1,endip-1 , version);

View File

@@ -79,7 +79,11 @@ public class ActionGraphSource extends GraphSource {
@Override
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
return Action.actionsPartToTree(registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path);
Reference<GraphSourceItem> fi = new Reference<>(localData.lineStartInstruction);
List<GraphTargetItem> r = Action.actionsPartToTree(fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path);
localData.lineStartInstruction = fi.getVal();
return r;
}
private List<Long> posCache = null;

View File

@@ -796,6 +796,7 @@ public class ActionListReader {
if ((a = sis.readAction()) == null) {
break;
}
a.fileOffset = ip;
int actionLengthWithHeader = a.getTotalActionLength();

View File

@@ -524,6 +524,10 @@ public class Configuration {
@ConfigurationName("gui.avm2.splitPane.vars.dividerLocationPercent")
public static final ConfigurationItem<Double> guiAvm2VarsSplitPaneDividerLocationPercent = null;
@ConfigurationDefaultDouble(0.7)
@ConfigurationName("gui.action.splitPane.vars.dividerLocationPercent")
public static final ConfigurationItem<Double> guiActionVarsSplitPaneDividerLocationPercent = null;
@ConfigurationDefaultBoolean(true)
@ConfigurationCategory("script")
public static final ConfigurationItem<Boolean> debugHalt = null;

View File

@@ -184,7 +184,7 @@ public class HighlightedTextWriter extends GraphTextWriter {
ndata.merge(data);
ndata.offset = src.getOffset() + pos;
if (itemPos.startLineItem != null) {
ndata.firstLineOffset = itemPos.startLineItem.getOffset();
ndata.firstLineOffset = itemPos.startLineItem.getLineOffset();
}
h = new Highlighting(sb.length() - newLineCount, ndata, HighlightType.OFFSET, str);
instructionHilights.add(h);

View File

@@ -84,6 +84,13 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
private boolean isSingleFrame;
private String scriptName = "-";
@Override
public String getScriptName() {
return scriptName;
}
/**
* Constructor
*
@@ -108,6 +115,11 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
readData(sis, data, 0, false, false, false);
}
@Override
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
buttonId = sis.readUI16("buttonId");

View File

@@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
@@ -54,6 +55,14 @@ public class DoActionTag extends Tag implements ASMSource {
@HideInRawEdit
public ByteArrayRange actionBytes;
@Internal
private String scriptName = "-";
@Override
public String getScriptName() {
return scriptName;
}
/**
* Constructor
*
@@ -87,6 +96,11 @@ public class DoActionTag extends Tag implements ASMSource {
readData(sis, data, 0, false, false, false);
}
@Override
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
actionBytes = sis.readByteRangeEx(sis.available(), "actionBytes");

View File

@@ -29,6 +29,7 @@ import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.types.BasicType;
import com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.flash.types.annotations.SWFType;
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
import com.jpexs.helpers.ByteArrayRange;
@@ -61,6 +62,14 @@ public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
@HideInRawEdit
public ByteArrayRange actionBytes;
@Internal
private String scriptName = "-";
@Override
public String getScriptName() {
return scriptName;
}
/**
* Constructor
*
@@ -71,6 +80,11 @@ public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
actionBytes = ByteArrayRange.EMPTY;
}
@Override
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
/**
* Constructor
*

View File

@@ -91,4 +91,8 @@ public interface ASMSource extends Exportable {
public Tag getSourceTag();
public void setSourceTag(Tag t);
public String getScriptName();
public void setScriptName(String scriptName);
}

View File

@@ -47,6 +47,13 @@ public class BUTTONCONDACTION implements ASMSource, Serializable {
private Tag tag;
private String scriptName = "-";
@Override
public String getScriptName() {
return scriptName;
}
// Constructor for Generic tag editor.
public BUTTONCONDACTION() {
swf = null;
@@ -54,6 +61,11 @@ public class BUTTONCONDACTION implements ASMSource, Serializable {
actionBytes = new ByteArrayRange(SWFInputStream.BYTE_ARRAY_EMPTY);
}
@Override
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
public BUTTONCONDACTION(SWF swf, SWFInputStream sis, Tag tag) throws IOException {
this.swf = swf;
this.tag = tag;

View File

@@ -42,6 +42,13 @@ import java.util.List;
*/
public class CLIPACTIONRECORD implements ASMSource, Serializable {
private String scriptName = "-";
@Override
public String getScriptName() {
return scriptName;
}
public static String keyToString(int key) {
if ((key < CLIPACTIONRECORD.KEYNAMES.length) && (key > 0) && (CLIPACTIONRECORD.KEYNAMES[key] != null)) {
return CLIPACTIONRECORD.KEYNAMES[key];
@@ -100,6 +107,11 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable {
actionBytes = ByteArrayRange.EMPTY;
}
@Override
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
public CLIPACTIONRECORD(SWF swf, SWFInputStream sis, Tag tag) throws IOException {
this.swf = swf;
this.tag = tag;

View File

@@ -37,6 +37,8 @@ public interface GraphSourceItem extends Serializable, Cloneable {
public long getOffset();
public long getLineOffset();
public boolean ignoredLoops();
public List<Integer> getBranches(GraphSource code);

Binary file not shown.

Binary file not shown.

View File

@@ -14,17 +14,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.abc;
package com.jpexs.decompiler.flash.gui;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.debugger.flash.messages.in.InFrame;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.DebuggerHandler;
import com.jpexs.decompiler.flash.gui.DebuggerHandler.VariableChangedListener;
import com.jpexs.decompiler.flash.gui.DebuggerHandler.BreakListener;
import com.jpexs.decompiler.flash.gui.HeaderLabel;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.abc.ABCPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
@@ -55,16 +56,25 @@ public class DebugPanel extends JPanel {
private JTable callStackTable;
private JTable stackTable;
private JTabbedPane varTabs;
private VariableChangedListener listener;
private BreakListener listener;
private JTextArea traceLogTextarea;
private int logLength = 0;
private List<SelectedTab> tabTypes = new ArrayList<>();
private boolean loading = false;
public static enum SelectedTab {
LOG, STACK, SCOPECHAIN, LOCALS, REGISTERS, CALLSTACK
}
public synchronized boolean isLoading() {
return loading;
}
public synchronized void setLoading(boolean loading) {
this.loading = loading;
}
private SelectedTab selectedTab = null;
public DebugPanel() {
@@ -101,11 +111,30 @@ public class DebugPanel extends JPanel {
}
});
Main.getDebugHandler().addVariableChangedListener(listener = new DebuggerHandler.VariableChangedListener() {
Main.getDebugHandler().addBreakListener(listener = new DebuggerHandler.BreakListener() {
@Override
public void variablesChanged() {
refresh();
public void doContinue() {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh();
}
});
}
@Override
public void breakAt(String scriptName, int line) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh();
}
});
}
});
@@ -115,6 +144,9 @@ public class DebugPanel extends JPanel {
@Override
public void stateChanged(ChangeEvent e) {
if (e.getSource() == varTabs) {
if (isLoading()) {
return;
}
synchronized (DebugPanel.this) {
int si = varTabs.getSelectedIndex();
if (si > -1 && si < tabTypes.size()) {
@@ -135,10 +167,10 @@ public class DebugPanel extends JPanel {
@Override
public void run() {
setLoading(true);
synchronized (DebugPanel.this) {
SelectedTab oldSel = selectedTab;
SelectedTab firstVisible = null;
SelectedTab newSel = null;
InFrame f = Main.getDebugHandler().getFrame();
if (f != null) {
debugRegistersTable.setModel(new ABCPanel.VariablesTableModel(f.registers));
@@ -251,23 +283,24 @@ public class DebugPanel extends JPanel {
setVisible(newVisible);
}
if (!tabTypes.isEmpty()) {
if (oldSel != null && tabTypes.contains(oldSel)) {
selectedTab = oldSel;
} else {
selectedTab = tabTypes.get(0);
if (oldSel != null && !tabTypes.contains(oldSel)) {
oldSel = null;
}
varTabs.setSelectedIndex(tabTypes.indexOf(selectedTab));
} else {
selectedTab = null;
}
if (oldSel != null) {
selectedTab = oldSel;
varTabs.setSelectedIndex(tabTypes.indexOf(selectedTab));
}
setLoading(false);
}
}
});
}
public void dispose() {
Main.getDebugHandler().removeVariableChangedListener(listener);
Main.getDebugHandler().removeBreakListener(listener);
}
}

View File

@@ -21,6 +21,7 @@ import com.jpexs.debugger.flash.DebugMessageListener;
import com.jpexs.debugger.flash.Debugger;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.DebuggerConnection;
import com.jpexs.debugger.flash.SWD;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.messages.in.InAskBreakpoints;
import com.jpexs.debugger.flash.messages.in.InBreakAt;
@@ -28,13 +29,19 @@ import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.debugger.flash.messages.in.InBreakReason;
import com.jpexs.debugger.flash.messages.in.InContinue;
import com.jpexs.debugger.flash.messages.in.InFrame;
import com.jpexs.debugger.flash.messages.in.InGetSwd;
import com.jpexs.debugger.flash.messages.in.InGetSwf;
import com.jpexs.debugger.flash.messages.in.InNumScript;
import com.jpexs.debugger.flash.messages.in.InProcessTag;
import com.jpexs.debugger.flash.messages.in.InScript;
import com.jpexs.debugger.flash.messages.in.InSetBreakpoint;
import com.jpexs.debugger.flash.messages.in.InSwfInfo;
import com.jpexs.debugger.flash.messages.in.InTrace;
import com.jpexs.debugger.flash.messages.in.InVersion;
import com.jpexs.debugger.flash.messages.out.OutGetBreakReason;
import com.jpexs.debugger.flash.messages.out.OutGetSwd;
import com.jpexs.debugger.flash.messages.out.OutGetSwf;
import com.jpexs.debugger.flash.messages.out.OutProcessedTag;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.configuration.Configuration;
@@ -43,6 +50,7 @@ import com.jpexs.helpers.CancellableWorker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -50,6 +58,8 @@ import java.util.TreeSet;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
@@ -61,41 +71,178 @@ public class DebuggerHandler implements DebugConnectionListener {
private DebuggerCommands commands = null;
private List<InSwfInfo.SwfInfo> swfs = new ArrayList<>();
private boolean paused = true;
private Map<Integer, ClassPath> modulePaths = new HashMap<>();
private Map<ClassPath, Integer> classToModule = new HashMap<>();
private Map<Integer, String> modulePaths = new HashMap<>();
private Map<String, Integer> classToModule = new HashMap<>();
private Map<String, Set<Integer>> toAddBPointMap = new HashMap<>();
private Map<String, Set<Integer>> confirmedPointMap = new HashMap<>();
private Map<String, Set<Integer>> invalidBreakPointMap = new HashMap<>();
private Map<String, Set<Integer>> toRemoveBPointMap = new HashMap<>();
private int breakIp = -1;
private String breakScriptName = null;
public int getBreakIp() {
return breakIp;
}
public String getBreakScriptName() {
return breakScriptName;
}
public synchronized void removeBreakPoint(String scriptName, int line) {
if (isBreakpointInvalid(scriptName, line)) {
return;
}
if (isBreakpointToAdd(scriptName, line)) {
toAddBPointMap.get(scriptName).remove(line);
if (toAddBPointMap.get(scriptName).isEmpty()) {
toAddBPointMap.remove(scriptName);
}
} else if (isBreakpointConfirmed(scriptName, line)) {
if (!toRemoveBPointMap.containsKey(scriptName)) {
toRemoveBPointMap.put(scriptName, new TreeSet<>());
}
toRemoveBPointMap.get(scriptName).add(line);
}
try {
sendBreakPoints(false);
} catch (IOException ex) {
//ignore
}
}
public synchronized Set<Integer> getBreakPoints(String scriptName) {
Set<Integer> lines = new TreeSet<>();
if (confirmedPointMap.containsKey(scriptName)) {
lines.addAll(confirmedPointMap.get(scriptName));
}
if (toAddBPointMap.containsKey(scriptName)) {
lines.addAll(toAddBPointMap.get(scriptName));
}
return lines;
}
public synchronized void clearBreakPoints() {
for (String scriptName : confirmedPointMap.keySet()) {
if (!toAddBPointMap.containsKey(scriptName)) {
toAddBPointMap.put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(scriptName).addAll(confirmedPointMap.get(scriptName));
}
confirmedPointMap.clear();
invalidBreakPointMap.clear();
}
public synchronized Map<String, Set<Integer>> getAllBreakPoints(boolean validOnly) {
Map<String, Set<Integer>> ret = new HashMap<>();
for (String scriptName : confirmedPointMap.keySet()) {
Set<Integer> lines = new TreeSet<>();
lines.addAll(confirmedPointMap.get(scriptName));
ret.put(scriptName, lines);
}
for (String scriptName : toAddBPointMap.keySet()) {
if (!ret.containsKey(scriptName)) {
ret.put(scriptName, new TreeSet<>());
}
ret.get(scriptName).addAll(toAddBPointMap.get(scriptName));
}
if (!validOnly) {
for (String scriptName : invalidBreakPointMap.keySet()) {
if (!ret.containsKey(scriptName)) {
ret.put(scriptName, new TreeSet<>());
}
ret.get(scriptName).addAll(invalidBreakPointMap.get(scriptName));
}
}
return ret;
}
public boolean addBreakPoint(String scriptName, int line) {
synchronized (this) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "adding bp " + scriptName + ":" + line);
if (isBreakpointToRemove(scriptName, line)) {
toRemoveBPointMap.get(scriptName).remove(line);
if (toRemoveBPointMap.get(scriptName).isEmpty()) {
toRemoveBPointMap.remove(scriptName);
}
}
if (isBreakpointConfirmed(scriptName, line)) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "bp " + scriptName + ":" + line + " already confirmed");
return true;
}
if (isBreakpointInvalid(scriptName, line)) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "bp " + scriptName + ":" + line + " already invalid");
return false;
}
if (!toAddBPointMap.containsKey(scriptName)) {
toAddBPointMap.put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(scriptName).add(line);
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "bp " + scriptName + ":" + line + " added to todo");
}
try {
sendBreakPoints(false);
} catch (IOException ex) {
//ignored
}
return true;
}
public synchronized boolean isBreakpointConfirmed(String scriptName, int line) {
return confirmedPointMap.containsKey(scriptName) && confirmedPointMap.get(scriptName).contains(line);
}
public synchronized boolean isBreakpointToAdd(String scriptName, int line) {
return toAddBPointMap.containsKey(scriptName) && toAddBPointMap.get(scriptName).contains(line);
}
public synchronized boolean isBreakpointToRemove(String scriptName, int line) {
return toRemoveBPointMap.containsKey(scriptName) && toRemoveBPointMap.get(scriptName).contains(line);
}
public synchronized boolean isBreakpointInvalid(String scriptName, int line) {
return invalidBreakPointMap.containsKey(scriptName) && invalidBreakPointMap.get(scriptName).contains(line);
}
private synchronized void markBreakPointInvalid(String scriptName, int line) {
if (!invalidBreakPointMap.containsKey(scriptName)) {
invalidBreakPointMap.put(scriptName, new TreeSet<>());
}
invalidBreakPointMap.get(scriptName).add(line);
}
private InFrame frame;
private InBreakAtExt breakInfo;
private InBreakReason breakReason;
private final List<VariableChangedListener> varListeners = new ArrayList<>();
private final List<BreakListener> breakListeners = new ArrayList<>();
private final List<TraceListener> traceListeners = new ArrayList<>();
private final List<ConnectionListener> clisteners = new ArrayList<>();
public void notSuspended() {
frame = null;
breakInfo = null;
breakReason = null;
for (VariableChangedListener l : varListeners) {
l.variablesChanged();
}
}
public String moduleToString(int file) {
if (!modulePaths.containsKey(file)) {
return "unknown";
}
return modulePaths.get(file).toString();
return modulePaths.get(file);
}
public InBreakAtExt getBreakInfo() {
public synchronized InBreakAtExt getBreakInfo() {
if (!paused) {
return null;
}
return breakInfo;
}
public InBreakReason getBreakReason() {
public synchronized InBreakReason getBreakReason() {
if (!paused) {
return null;
}
return breakReason;
}
@@ -113,14 +260,16 @@ public class DebuggerHandler implements DebugConnectionListener {
}
public static interface VariableChangedListener {
public static interface BreakListener {
public void variablesChanged();
public void breakAt(String scriptName, int line);
public void doContinue();
}
public void addVariableChangedListener(VariableChangedListener l) {
varListeners.add(l);
public void addBreakListener(BreakListener l) {
breakListeners.add(l);
}
public void addTraceListener(TraceListener l) {
@@ -131,8 +280,8 @@ public class DebuggerHandler implements DebugConnectionListener {
traceListeners.remove(l);
}
public void removeVariableChangedListener(VariableChangedListener l) {
varListeners.remove(l);
public void removeBreakListener(BreakListener l) {
breakListeners.remove(l);
}
public void addConnectionListener(ConnectionListener l) {
@@ -143,19 +292,27 @@ public class DebuggerHandler implements DebugConnectionListener {
clisteners.remove(l);
}
public InFrame getFrame() {
public synchronized InFrame getFrame() {
if (!paused) {
return null;
}
return frame;
}
public int moduleIdOf(ScriptPack pack) {
if (classToModule.containsKey(pack.getClassPath())) {
return classToModule.get(pack.getClassPath());
public synchronized int moduleIdOf(String pack) {
if (classToModule.containsKey(pack)) {
return classToModule.get(pack);
}
return -1;
}
public synchronized boolean isPaused() {
return paused;
public boolean isPaused() {
if (!isConnected()) {
return false;
}
synchronized (this) {
return paused;
}
}
public List<InSwfInfo.SwfInfo> getSwfs() {
@@ -174,12 +331,12 @@ public class DebuggerHandler implements DebugConnectionListener {
for (ConnectionListener l : clisteners) {
l.disconnected();
}
for (VariableChangedListener l : varListeners) {
l.variablesChanged();
}
/*for (BreakListener l : breakListeners) {
l.breakAt();
}*/
}
public boolean isConnected() {
public synchronized boolean isConnected() {
return connected;
}
@@ -191,7 +348,7 @@ public class DebuggerHandler implements DebugConnectionListener {
}
private static void enlog(Class<?> cls) {
Level level = Level.FINEST;
Level level = Level.INFO;
Logger mylog = Logger.getLogger(cls.getName());
mylog.setLevel(level);
@@ -201,24 +358,95 @@ public class DebuggerHandler implements DebugConnectionListener {
}
@Override
public void connected(DebuggerConnection con) {
public void failedListen(IOException ex) {
View.execInEventDispatchLater(new Runnable() {
synchronized (DebuggerHandler.this) {
paused = true;
@Override
public void run() {
disconnect();
Main.stopRun();
Main.stopWork();
View.showMessageDialog(Main.getMainFrame().getPanel(), AppStrings.translate("error.debug.listen").replace("%port%", "" + Debugger.DEBUG_PORT));
Main.getMainFrame().getPanel().updateMenu();
}
});
}
@Override
public void connected(DebuggerConnection con) {
clearBreakPoints();
Main.startWork(AppStrings.translate("work.debugging"), null);
synchronized (this) {
paused = false;
}
Main.getMainFrame().getPanel().updateMenu();
//enlog(DebuggerConnection.class);
//enlog(DebuggerCommands.class);
enlog(DebuggerHandler.class);
try {
//rootLog.getHandlers()[0].setLevel(level);
con.getMessage(InVersion.class);
} catch (IOException ex) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.SEVERE, null, ex);
}
commands = new DebuggerCommands(con);
//Respon to InProcessTag with OutProcessedTag
con.addMessageListener(new DebugMessageListener<InProcessTag>() {
@Override
public void message(InProcessTag message) {
try {
con.writeMessage(new OutProcessedTag(con));
} catch (IOException ex) {
//disconnect();
//ignore
}
}
});
Map<Integer, String> moduleNames = new HashMap<>();
try {
int numScript = con.getMessage(InNumScript.class).num;
for (int i = 0; i < numScript; i++) {
InScript sc = con.getMessage(InScript.class);
moduleNames.put(sc.module, sc.name);
}
modulePaths = new HashMap<>();
classToModule = new HashMap<>();
//Pattern patMainFrame = Pattern.compile("^Actions for Scene ([0-9]+): Frame ([0-9]+) of Layer Name .*$");
//Pattern patSymbol = Pattern.compile("^Actions for Symbol ([0-9]+): Frame ([0-9]+) of Layer Name .*$");
//Pattern patAS2 = Pattern.compile("^([^:]+): .*\\.as$");
Pattern patAS3 = Pattern.compile("^(.*);(.*);(.*)\\.as$");
for (int file : moduleNames.keySet()) {
String name = moduleNames.get(file);
String[] parts = name.split(";");
Matcher m;
/*if ((m = patMainFrame.matcher(name)).matches()) {
name = "\\frame_" + m.group(2) + "\\DoAction";
} else if ((m = patSymbol.matcher(name)).matches()) {
name = "\\DefineSprite(" + m.group(1) + ")\\frame_" + m.group(2) + "\\DoAction";
} else if ((m = patAS2.matcher(name)).matches()) {
name = "\\_Packages\\" + m.group(1).replace(".", "\\");
} else*/
if ((m = patAS3.matcher(name)).matches()) {
String clsName = m.group(3);
String pkg = m.group(2).replace("\\", ".");
name = DottedChain.parse(pkg).add(clsName).toString();
}
modulePaths.put(file, name);
classToModule.put(name, file);
}
//con.getMessage(InSetBreakpoint.class);
commands = new DebuggerCommands(con);
commands.stopWarning();
commands.setStopOnFault();
commands.setEnumerateOverride();
@@ -227,43 +455,56 @@ public class DebuggerHandler implements DebugConnectionListener {
commands.setSwfLoadNotify();
commands.setGetterTimeout(1500);
commands.setSetterTimeout(5000);
commands.squelch(true);
swfs = commands.getSwfInfo(1);
Map<Integer, String> moduleNames = new HashMap<>();
modulePaths = new HashMap<>();
classToModule = new HashMap<>();
int numScript = con.getMessage(InNumScript.class).num;
for (int i = 0; i < numScript; i++) {
InScript sc = con.getMessage(InScript.class);
moduleNames.put(sc.module, sc.name);
con.wideLines = commands.getOption("wide_line_player", "false").equals("true");
if (con.wideLines) {
commands.setOption("wide_line_debugger", "on");
}
commands.squelch(true);
for (int mname : moduleNames.keySet()) {
String name = moduleNames.get(mname);
String[] parts = name.split(";");
swfs = commands.getSwfInfo(1);
con.sendMessage(new OutGetSwf(con, 0), InGetSwf.class);
InGetSwd iswd = con.sendMessage(new OutGetSwd(con, 0), InGetSwd.class);
if (parts.length == 3) {
String clsName = parts[2].replace(".as", "");
String pkg = parts[1].replace("/", "\\").replace("\\", ".");
ClassPath cp = new ClassPath(DottedChain.parse(pkg), clsName);
modulePaths.put(mname, cp);
classToModule.put(cp, mname);
boolean isAS3 = (Main.getMainFrame().getPanel().getCurrentSwf().isAS3());
InSetBreakpoint isb = con.getMessage(InSetBreakpoint.class);
synchronized (this) {
for (int i = 0; i < isb.files.size(); i++) {
String sname = moduleNames.get(isb.files.get(i));
if (!confirmedPointMap.containsKey(sname)) {
confirmedPointMap.put(sname, new TreeSet<>());
}
if (toAddBPointMap.containsKey(sname)) {
toAddBPointMap.get(sname).remove(isb.lines.get(i));
if (toAddBPointMap.get(sname).isEmpty()) {
toAddBPointMap.remove(sname);
}
}
confirmedPointMap.get(sname).add(isb.lines.get(i));
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} submitted successfully", new Object[]{sname, isb.lines.get(i)});
}
}
con.getMessage(InSetBreakpoint.class);
con.getMessage(InAskBreakpoints.class);
con.addMessageListener(new DebugMessageListener<InContinue>() {
synchronized (this) {
connected = true;
}
con.addMessageListener(new DebugMessageListener<InAskBreakpoints>() {
@Override
public void message(InAskBreakpoints message) {
}
});
con.addMessageListener(new DebugMessageListener<InContinue>() {
@Override
public void message(InContinue msg) {
synchronized (DebuggerHandler.this) {
paused = false;
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "continued");
}
for (BreakListener bl : breakListeners) {
bl.doContinue();
}
Main.getMainFrame().getPanel().updateMenu();
}
});
con.addMessageListener(new DebugMessageListener<InBreakAt>() {
@@ -272,89 +513,122 @@ public class DebuggerHandler implements DebugConnectionListener {
public void message(InBreakAt message) {
synchronized (DebuggerHandler.this) {
paused = true;
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "paused");
}
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
String newBreakScriptName = "unknown";
if (modulePaths.containsKey(message.file)) {
//Logger.getLogger(DebuggerCommands.class.getName()).log(Level.SEVERE, "Invalid file: " + message.file);
newBreakScriptName = modulePaths.get(message.file);
}
Main.getMainFrame().getPanel().updateMenu();
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "break at {0}:{1}", new Object[]{moduleNames.get(message.file), message.line});
if (!modulePaths.containsKey(message.file)) {
try {
breakInfo = con.getMessage(InBreakAtExt.class);
breakReason = con.sendMessage(new OutGetBreakReason(con), InBreakReason.class);
final String[] reasonNames = new String[]{"unknown", "breakpoint", "watch", "fault", "stopRequest", "step", "halt", "scriptLoaded"};
String reason = breakReason.reason < reasonNames.length ? reasonNames[breakReason.reason] : reasonNames[0];
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "break at {0}:{1}, reason: {2}", new Object[]{newBreakScriptName, message.line, reason});
sendBreakPoints(false);
synchronized (DebuggerHandler.this) {
breakScriptName = newBreakScriptName;
breakIp = message.line;
}
if (breakReason.reason == InBreakReason.REASON_SCRIPT_LOADED) {
if (!Configuration.debugHalt.get()) {
commands.sendContinue();
return;
}
ClassPath cls = modulePaths.get(message.file);
Main.startWork(AppStrings.translate("work.breakat") + cls + ":" + message.line, null);
try {
breakInfo = con.getMessage(InBreakAtExt.class);
breakReason = con.sendMessage(new OutGetBreakReason(con), InBreakReason.class);
frame = commands.getFrame(0);
for (VariableChangedListener l : varListeners) {
l.variablesChanged();
}
} catch (IOException ex) {
//ignore
}
Main.breakAt(cls, message.line);
Main.startWork(AppStrings.translate("work.halted"), null);
} else {
Main.startWork(AppStrings.translate("work.breakat") + newBreakScriptName + ":" + message.line + " " + AppStrings.translate("debug.break.reason." + reason), null);
}
frame = commands.getFrame(0);
for (BreakListener l : breakListeners) {
l.breakAt(newBreakScriptName, message.line);
}
} catch (IOException ex) {
//ignore
}
);
//dc.sendContinue();
}
});
//commands.sendContinue();
List<ScriptPack> packs = Main.getMainFrame().getPanel().getCurrentSwf().getAS3Packs();
for (ScriptPack sp : packs) {
ClassPath cp = sp.getClassPath();
if (classToModule.containsKey(cp)) {
int file = classToModule.get(cp);
Set<Integer> bpts = new TreeSet<>(Main.getPackBreakPoints(sp));
for (int line : bpts) {
if (!commands.addBreakPoint(file, line)) {
Main.markBreakPointInvalid(sp, line);
}
}
}
}
Main.getMainFrame()
.getPanel().refreshBreakPoints();
connected = true;
for (ConnectionListener l : clisteners) {
l.connected();
}
if (Configuration.debugHalt.get()) {
Main.startWork(AppStrings.translate("work.halted"), null);
} else {
con.addMessageListener(new DebugMessageListener<InTrace>() {
@Override
public void message(InTrace tr) {
for (TraceListener l : traceListeners) {
l.trace(tr.text);
}
}
});
if (!isAS3) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINER, "End of connect - sending continue");
commands.sendContinue();
}
new CancellableWorker() {
@Override
protected Object doInBackground() throws Exception {
try {
while (isConnected()) {
InTrace tr = con.getMessage(InTrace.class);
for (TraceListener l : traceListeners) {
l.trace(tr.text);
}
}
} catch (IOException ex) {
//ignore
}
return null;
}
}.execute();
} catch (IOException ex) {
connected = false;
synchronized (this) {
connected = false;
}
}
}
private void sendBreakPoints(boolean force) throws IOException {
if (!force && !isPaused()) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINEST, "not sending bps, not paused");
return;
}
synchronized (this) {
for (String scriptName : toRemoveBPointMap.keySet()) {
int file = moduleIdOf(scriptName);
if (file > -1) {
for (int line : toRemoveBPointMap.get(scriptName)) {
if (isBreakpointConfirmed(scriptName, line)) {
commands.removeBreakPoint(file, line);
confirmedPointMap.get(scriptName).remove(line);
if (confirmedPointMap.get(scriptName).isEmpty()) {
confirmedPointMap.remove(scriptName);
}
}
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} removed", new Object[]{scriptName, line});
}
}
}
toRemoveBPointMap.clear();
for (String scriptName : toAddBPointMap.keySet()) {
int file = moduleIdOf(scriptName);
if (file > -1) {
for (int line : toAddBPointMap.get(scriptName)) {
if (commands.addBreakPoint(file, line)) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} submitted successfully", new Object[]{scriptName, line});
if (!confirmedPointMap.containsKey(scriptName)) {
confirmedPointMap.put(scriptName, new TreeSet<>());
}
confirmedPointMap.get(scriptName).add(line);
} else {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} unable to submit", new Object[]{scriptName, line});
markBreakPointInvalid(scriptName, line);
}
}
}
}
toAddBPointMap.clear();
}
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINEST, "sending bps finished");
}
}

View File

@@ -21,6 +21,7 @@ import com.jpexs.debugger.flash.DebugMessageListener;
import com.jpexs.debugger.flash.Debugger;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.DebuggerConnection;
import com.jpexs.debugger.flash.SWD;
import com.jpexs.debugger.flash.messages.in.InAskBreakpoints;
import com.jpexs.debugger.flash.messages.in.InBreakAt;
import com.jpexs.debugger.flash.messages.in.InNumScript;
@@ -81,6 +82,7 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.Proxy;
@@ -159,117 +161,285 @@ public class Main {
private static DebuggerHandler debugHandler = null;
private static Map<ScriptPack, Set<Integer>> breakPointMap = new WeakHashMap<>();
private static Map<ScriptPack, Set<Integer>> invalidBreakPointMap = new WeakHashMap<>();
private static int ip = 0;
private static ClassPath ipClass = null;
//private static int ip = 0;
//private static String ipClass = null;
private static Process runProcess;
private static boolean runProcessDebug;
public static void debuggerNotSuspended() {
getDebugHandler().notSuspended();
private static boolean inited = false;
private static File runTempFile;
public static void freeRun() {
synchronized (Main.class) {
if (runTempFile != null) {
runTempFile.delete();
runTempFile = null;
}
runProcess = null;
}
mainFrame.getPanel().clearDebuggerColors();
ip = 0;
ipClass = null;
}
public static void clearBreakPoints(ScriptPack pack) {
if (breakPointMap.containsKey(pack)) {
breakPointMap.remove(pack);
if (runProcessDebug) {
Main.getDebugHandler().disconnect();
}
}
public static boolean isDebugging() {
return mainFrame.getMenu().isDebugRunning();
public static synchronized boolean isDebugPaused() {
return runProcess != null && runProcessDebug && getDebugHandler().isPaused();
}
public static int getIp(ScriptPack pack) {
return ip;
public static synchronized boolean isDebugRunning() {
return runProcess != null && runProcessDebug;
}
public static ClassPath getIpClass() {
return ipClass;
public static synchronized boolean isDebugConnected() {
return getDebugHandler().isConnected();
}
public static void breakAt(ClassPath clsName, int ip) {
Main.ip = ip;
Main.ipClass = clsName;
mainFrame.getPanel().gotoClassLine(getMainFrame().getPanel().getCurrentSwf(), clsName.toString(), ip);
//Main.getMainFrame().getPanel().debuggerBreakAt(Main.getMainFrame().getPanel().getCurrentSwf(), cls, message.line);
public static synchronized boolean isRunning() {
return runProcess != null && !runProcessDebug;
}
public static boolean isBreakPointValid(ScriptPack pack, int line) {
if (!invalidBreakPointMap.containsKey(pack)) {
return true;
public static void runPlayer(String title, final String exePath, String file, String flashVars) {
if (flashVars != null && !flashVars.isEmpty()) {
file += "?" + flashVars;
}
return !invalidBreakPointMap.get(pack).contains(line);
}
public static void markBreakPointInvalid(ScriptPack pack, int line) {
if (!invalidBreakPointMap.containsKey(pack)) {
invalidBreakPointMap.put(pack, new TreeSet<>());
if (!new File(file).exists()) {
return;
}
invalidBreakPointMap.get(pack).add(line);
}
public static void addBreakPoint(ScriptPack pack, int line) {
if (!breakPointMap.containsKey(pack)) {
breakPointMap.put(pack, new TreeSet<>());
}
breakPointMap.get(pack).add(line);
if (debugHandler.isConnected()) {
int file = debugHandler.moduleIdOf(pack);
if (file > -1) {
final String ffile = file;
CancellableWorker runWorker = new CancellableWorker() {
@Override
protected Object doInBackground() throws Exception {
Process proc;
try {
if (!debugHandler.getCommands().addBreakPoint(file, line)) {
markBreakPointInvalid(pack, line);
proc = Runtime.getRuntime().exec("\"" + exePath + "\" \"file://" + ffile + "\"");
} catch (IOException ex) {
Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
boolean isDebug;
synchronized (Main.class) {
runProcess = proc;
isDebug = runProcessDebug;
}
if (isDebug) {
mainFrame.getMenu().hilightPath("/debugging");
}
mainFrame.getMenu().updateComponents();
try {
if (proc != null) {
proc.waitFor();
}
} catch (InterruptedException ex) {
if (proc != null) {
try {
proc.destroy();
} catch (Exception ex2) {
//ignore
}
}
} catch (IOException ex) {
debugHandler.disconnect();
//ignore
}
freeRun();
mainFrame.getMenu().updateComponents();
return null;
}
@Override
protected void done() {
Main.stopWork();
}
@Override
public void workerCancelled() {
Main.stopWork();
synchronized (Main.class) {
if (runProcess != null) {
try {
runProcess.destroy();
} catch (Exception ex) {
}
}
}
freeRun();
mainFrame.getMenu().updateComponents();
}
};
mainFrame.getMenu().updateComponents();
Main.startWork(title + "...", runWorker);
runWorker.execute();
}
public static void stopRun() {
synchronized (Main.class) {
if (runProcess != null) {
runProcess.destroy();
}
}
freeRun();
stopDebugger();
mainFrame.getMenu().updateComponents();
}
public static void run(SWF swf) {
String flashVars = "";//key=val&key2=val2
String playerLocation = Configuration.playerLocation.get();
if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
View.showMessageDialog(null, AppStrings.translate("message.playerpath.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
advancedSettings("paths");
return;
}
if (swf == null) {
return;
}
File tempFile;
try {
tempFile = File.createTempFile("ffdec_run_", ".swf");
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tempFile))) {
swf.saveTo(fos);
}
} catch (IOException ex) {
return;
}
if (tempFile != null) {
synchronized (Main.class) {
runTempFile = tempFile;
runProcessDebug = false;
}
runPlayer(AppStrings.translate("work.running"), playerLocation, tempFile.getAbsolutePath(), flashVars);
}
}
public static void removeBreakPoint(ScriptPack pack, int line) {
if (breakPointMap.containsKey(pack)) {
Set<Integer> lines = breakPointMap.get(pack);
if (lines != null) {
lines.remove(line);
}
public static void runDebug(SWF swf) {
String flashVars = "";//key=val&key2=val2
String playerLocation = Configuration.playerDebugLocation.get();
if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
View.showMessageDialog(null, AppStrings.translate("message.playerpath.debug.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
Main.advancedSettings("paths");
return;
}
if (debugHandler.isConnected()) {
int file = debugHandler.moduleIdOf(pack);
if (file > -1) {
try {
debugHandler.getCommands().removeBreakPoint(file, line);
} catch (IOException ex) {
debugHandler.disconnect();
//ignore
if (swf == null) {
return;
}
File tempFile = null;
try {
tempFile = File.createTempFile("ffdec_debug_", ".swf");
} catch (Exception ex) {
}
if (tempFile != null) {
final File fTempFile = tempFile;
CancellableWorker instrumentWorker = new CancellableWorker() {
@Override
protected Object doInBackground() throws Exception {
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fTempFile))) {
swf.saveTo(fos);
}
//Inject Loader
SWF instrSWF = null;
try (FileInputStream fis = new FileInputStream(fTempFile)) {
instrSWF = new SWF(fis, false, false);
} catch (InterruptedException ex) {
Logger.getLogger(MainFrameMenu.class
.getName()).log(Level.SEVERE, null, ex);
}
if (instrSWF != null) {
if (instrSWF.isAS3()) {
instrSWF.enableDebugging(true, new File("."));
} else {
instrSWF.enableDebugging(false, new File("."));
File swdFile = new File(fTempFile.getAbsolutePath().replace(".swf", ".swd"));
instrSWF.generateSwdFile(swdFile, getPackBreakPoints(true));
}
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fTempFile))) {
instrSWF.saveTo(fos);
}
}
return null;
}
}
@Override
public void workerCancelled() {
Main.stopWork();
}
@Override
protected void done() {
synchronized (Main.class) {
runTempFile = fTempFile;
runProcessDebug = true;
}
Main.stopWork();
Main.startDebugger();
runPlayer(AppStrings.translate("work.debugging.wait"), playerLocation, fTempFile.getAbsolutePath(), flashVars);
}
};
Main.startWork(AppStrings.translate("work.debugging.instrumenting"), instrumentWorker);
instrumentWorker.execute();
}
}
public static boolean toggleBreakPoint(ScriptPack pack, int line) {
if (!breakPointMap.containsKey(pack)) {
addBreakPoint(pack, line);
return true;
}
if (breakPointMap.get(pack).contains(line)) {
removeBreakPoint(pack, line);
/* public static void debuggerNotSuspended() {
}*/
public static boolean isDebugging() {
return isDebugRunning();
}
public synchronized static int getIp(Object pack) {
return getDebugHandler().getBreakIp();
}
public synchronized static String getIpClass() {
return getDebugHandler().getBreakScriptName();
}
public static synchronized boolean isBreakPointValid(String scriptName, int line) {
return !getDebugHandler().isBreakpointInvalid(scriptName, line);
}
public synchronized static void addBreakPoint(String scriptName, int line) {
getDebugHandler().addBreakPoint(scriptName, line);
}
public synchronized static void removeBreakPoint(String scriptName, int line) {
getDebugHandler().removeBreakPoint(scriptName, line);
}
public synchronized static boolean toggleBreakPoint(String scriptName, int line) {
if (getDebugHandler().isBreakpointToAdd(scriptName, line) || getDebugHandler().isBreakpointConfirmed(scriptName, line)) {
getDebugHandler().removeBreakPoint(scriptName, line);
return false;
} else {
addBreakPoint(pack, line);
getDebugHandler().addBreakPoint(scriptName, line);
return true;
}
}
public static Set<Integer> getPackBreakPoints(ScriptPack pack) {
if (!breakPointMap.containsKey(pack)) {
return new HashSet<>();
}
return breakPointMap.get(pack);
public synchronized static Map<String, Set<Integer>> getPackBreakPoints(boolean validOnly) {
return getDebugHandler().getAllBreakPoints(validOnly);
}
public synchronized static Set<Integer> getScriptBreakPoints(String pack) {
return getDebugHandler().getBreakPoints(pack);
}
public static DebuggerHandler getDebugHandler() {
@@ -319,6 +489,14 @@ public class Main {
}
}
public synchronized static boolean isInited() {
return inited;
}
public synchronized static void setSessionLoaded(boolean v) {
inited = v;
}
public static boolean isWorking() {
return working;
}
@@ -1151,26 +1329,51 @@ public class Main {
*/
flashDebugger = new Debugger();
debugHandler = new DebuggerHandler();
debugHandler.addBreakListener(new DebuggerHandler.BreakListener() {
@Override
public void doContinue() {
mainFrame.getPanel().clearDebuggerColors();
}
@Override
public void breakAt(String scriptName, int line) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
mainFrame.getPanel().gotoClassLine(getMainFrame().getPanel().getCurrentSwf(), scriptName, line);
}
});
}
});
debugHandler.addConnectionListener(new DebuggerHandler.ConnectionListener() {
@Override
public void connected() {
Main.mainFrame.getMenu().updateComponents();
}
@Override
public void disconnected() {
ip = 0;
ipClass = null;
}
});
flashDebugger.addConnectionListener(debugHandler);
flashDebugger.start();
} catch (IOException ex) {
//ignore
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "eeex", ex);
}
}
public static void startDebugger() {
flashDebugger.startDebugger();
}
public static void stopDebugger() {
flashDebugger.stopDebugger();
}
public static void showModeFrame() {
ensureMainFrame();
mainFrame.setVisible(true);
@@ -1371,6 +1574,7 @@ public class Main {
* @throws IOException On error
*/
public static void main(String[] args) throws IOException {
setSessionLoaded(false);
clearTemp();
try {
@@ -1400,6 +1604,7 @@ public class Main {
}
});
} else {
setSessionLoaded(true);
String[] filesToOpen = CommandLineArgumentParser.parseArguments(args);
if (filesToOpen != null && filesToOpen.length > 0) {
View.execInEventDispatch(() -> {
@@ -1447,9 +1652,16 @@ public class Main {
if (sourceInfos.length > 0) {
openFile(sourceInfos, () -> {
mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get());
setSessionLoaded(true);
});
} else {
setSessionLoaded(true);
}
} else {
setSessionLoaded(true);
}
} else {
setSessionLoaded(true);
}
}

View File

@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.gui;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.messages.out.OutStepContinue;
import com.jpexs.decompiler.flash.ApplicationInfo;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFBundle;
@@ -661,10 +662,11 @@ public abstract class MainFrameMenu implements MenuBuilder {
public void updateComponents(SWF swf) {
this.swf = swf;
boolean isRunning = isRunning();
boolean isDebugRunning = isDebugRunning();
boolean isRunning = Main.isRunning();
boolean isDebugRunning = Main.isDebugRunning();
boolean isDebugPaused = Main.isDebugPaused();
boolean isRunningOrDebugging = isRunning || isDebugRunning;
boolean isDebugPaused = isDebugPaused();
boolean swfSelected = swf != null;
boolean isWorking = Main.isWorking();
@@ -725,7 +727,7 @@ public abstract class MainFrameMenu implements MenuBuilder {
setMenuEnabled("/help/about", !isWorking);
setMenuEnabled("/file/start/run", swfSelected && !isRunningOrDebugging);
setMenuEnabled("/file/start/debug", hasAbc && !isRunningOrDebugging);
setMenuEnabled("/file/start/debug", !isRunningOrDebugging);
setMenuEnabled("/file/start/stop", isRunningOrDebugging);
setMenuEnabled("/debugging/debug/stop", isRunningOrDebugging); //same as previous
@@ -1098,231 +1100,22 @@ public abstract class MainFrameMenu implements MenuBuilder {
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.removeKeyEventDispatcher(keyEventDispatcher);
if (runProcess != null) {
try {
runProcess.destroy();
} catch (Exception ex) {
}
}
}
private Process runProcess;
private boolean runProcessDebug;
private File runTempFile;
public synchronized boolean isDebugPaused() {
return runProcess != null && runProcessDebug && Main.getDebugHandler().isPaused();
}
public synchronized boolean isDebugRunning() {
return runProcess != null && runProcessDebug;
}
public synchronized boolean isRunning() {
return runProcess != null && !runProcessDebug;
}
private synchronized void freeRun() {
if (runTempFile != null) {
runTempFile.delete();
runTempFile = null;
}
runProcess = null;
mainFrame.getPanel().clearDebuggerColors();
if (runProcessDebug) {
Main.getDebugHandler().disconnect();
}
}
private void runPlayer(String title, final String exePath, String file, String flashVars) {
if (flashVars != null && !flashVars.isEmpty()) {
file += "?" + flashVars;
}
if (!new File(file).exists()) {
return;
}
final String ffile = file;
CancellableWorker runWorker = new CancellableWorker() {
@Override
protected Object doInBackground() throws Exception {
Process proc;
try {
proc = Runtime.getRuntime().exec("\"" + exePath + "\" \"file://" + ffile + "\"");
} catch (IOException ex) {
Logger.getLogger(MainFrameMenu.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
synchronized (this) {
runProcess = proc;
}
if (runProcessDebug) {
hilightPath("/debugging");
}
updateComponents();
try {
if (proc != null) {
proc.waitFor();
}
} catch (InterruptedException ex) {
if (proc != null) {
try {
proc.destroy();
} catch (Exception ex2) {
//ignore
}
}
}
freeRun();
updateComponents();
return null;
}
@Override
protected void done() {
Main.stopWork();
}
@Override
public void workerCancelled() {
Main.stopWork();
synchronized (MainFrameMenu.this) {
if (runProcess != null) {
try {
runProcess.destroy();
} catch (Exception ex) {
}
}
}
freeRun();
updateComponents();
}
};
updateComponents();
Main.startWork(title + "...", runWorker);
runWorker.execute();
Main.stopRun();
}
public boolean runActionPerformed(ActionEvent evt) {
String flashVars = "";//key=val&key2=val2
String playerLocation = Configuration.playerLocation.get();
if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
View.showMessageDialog(null, AppStrings.translate("message.playerpath.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
Main.advancedSettings("paths");
return true;
}
if (swf == null) {
return true;
}
File tempFile;
try {
tempFile = File.createTempFile("ffdec_run_", ".swf");
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(tempFile))) {
swf.saveTo(fos);
}
} catch (IOException ex) {
return true;
}
if (tempFile != null) {
synchronized (this) {
runTempFile = tempFile;
runProcessDebug = false;
}
runPlayer(AppStrings.translate("work.running"), playerLocation, tempFile.getAbsolutePath(), flashVars);
}
Main.run(swf);
return true;
}
public boolean debugActionPerformed(ActionEvent evt) {
String flashVars = "";//key=val&key2=val2
String playerLocation = Configuration.playerDebugLocation.get();
if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
View.showMessageDialog(null, AppStrings.translate("message.playerpath.debug.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
Main.advancedSettings("paths");
return true;
}
if (swf == null) {
return true;
}
File tempFile = null;
try {
tempFile = File.createTempFile("ffdec_debug_", ".swf");
} catch (Exception ex) {
}
if (tempFile != null) {
final File fTempFile = tempFile;
CancellableWorker instrumentWorker = new CancellableWorker() {
@Override
protected Object doInBackground() throws Exception {
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fTempFile))) {
swf.saveTo(fos);
}
//Inject Loader
SWF instrSWF = null;
try (FileInputStream fis = new FileInputStream(fTempFile)) {
instrSWF = new SWF(fis, false, false);
} catch (InterruptedException ex) {
Logger.getLogger(MainFrameMenu.class
.getName()).log(Level.SEVERE, null, ex);
}
if (instrSWF != null) {
instrSWF.enableDebugging(true, new File("."));
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fTempFile))) {
instrSWF.saveTo(fos);
}
}
return null;
}
@Override
public void workerCancelled() {
Main.stopWork();
}
@Override
protected void done() {
synchronized (MainFrameMenu.this) {
runTempFile = fTempFile;
runProcessDebug = true;
}
Main.stopWork();
runPlayer(AppStrings.translate("work.debugging"), playerLocation, fTempFile.getAbsolutePath(), flashVars);
}
};
Main.startWork(AppStrings.translate("work.debugging.instrumenting"), instrumentWorker);
instrumentWorker.execute();
}
Main.runDebug(swf);
return true;
}
public boolean stopActionPerformed(ActionEvent evt) {
synchronized (this) {
if (runProcess != null) {
runProcess.destroy();
}
}
freeRun();
updateComponents();
Main.stopRun();
return true;
}
@@ -1339,7 +1132,6 @@ public abstract class MainFrameMenu implements MenuBuilder {
}
public boolean stepOverActionPerformed(ActionEvent evt) {
Main.debuggerNotSuspended();
try {
@@ -1356,8 +1148,6 @@ public abstract class MainFrameMenu implements MenuBuilder {
}
public boolean stepIntoActionPerformed(ActionEvent evt) {
Main.debuggerNotSuspended();
try {
DebuggerCommands cmd = Main.getDebugHandler().getCommands();
mainFrame.getPanel().clearDebuggerColors();
@@ -1373,8 +1163,6 @@ public abstract class MainFrameMenu implements MenuBuilder {
}
public boolean stepOutActionPerformed(ActionEvent evt) {
Main.debuggerNotSuspended();
try {
DebuggerCommands cmd = Main.getDebugHandler().getCommands();
mainFrame.getPanel().clearDebuggerColors();
@@ -1389,10 +1177,9 @@ public abstract class MainFrameMenu implements MenuBuilder {
}
public boolean continueActionPerformed(ActionEvent evt) {
Main.debuggerNotSuspended();
try {
DebuggerCommands cmd = Main.getDebugHandler().getCommands();
mainFrame.getPanel().clearDebuggerColors();
Main.startWork(AppStrings.translate("work.debugging") + "...", null);
cmd.sendContinue();
} catch (IOException ex) {

View File

@@ -539,18 +539,22 @@ public class MainFrameRibbonMenu extends MainFrameMenu {
throw new IllegalArgumentException("Menu not found: " + path);
}
Object o = menuItems.get(path);
if (o instanceof JRibbonBand) {
((JRibbonBand) o).setEnabled(enabled);
} else if (o instanceof AbstractCommandButton) {
((AbstractCommandButton) o).setEnabled(enabled);
} else if (o instanceof RibbonApplicationMenuEntryPrimary) {
((RibbonApplicationMenuEntryPrimary) o).setEnabled(enabled);
} else if (o instanceof RibbonApplicationMenuEntryFooter) {
((RibbonApplicationMenuEntryFooter) o).setEnabled(enabled);
} else if (o instanceof JComponent) {
((JComponent) o).setEnabled(enabled);
} else {
throw new IllegalArgumentException("Cannot set enabled to: " + path);
try {
if (o instanceof JRibbonBand) {
((JRibbonBand) o).setEnabled(enabled);
} else if (o instanceof AbstractCommandButton) {
((AbstractCommandButton) o).setEnabled(enabled);
} else if (o instanceof RibbonApplicationMenuEntryPrimary) {
((RibbonApplicationMenuEntryPrimary) o).setEnabled(enabled);
} else if (o instanceof RibbonApplicationMenuEntryFooter) {
((RibbonApplicationMenuEntryFooter) o).setEnabled(enabled);
} else if (o instanceof JComponent) {
((JComponent) o).setEnabled(enabled);
} else {
throw new IllegalArgumentException("Cannot set enabled to: " + path);
}
} catch (Exception ex) {
//some substance issues, ignore
}
}
@@ -594,7 +598,11 @@ public class MainFrameRibbonMenu extends MainFrameMenu {
@Override
public void run() {
ribbon.setVisible(rg, val);
try {
ribbon.setVisible(rg, val);
} catch (Exception ex) {
}
}
});

View File

@@ -142,6 +142,7 @@ import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.sound.SoundFormat;
import com.jpexs.decompiler.flash.xfl.FLAVersion;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Path;
@@ -320,6 +321,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
private static final Logger logger = Logger.getLogger(MainPanel.class.getName());
private Map<String, ASMSource> asms = new HashMap<>();
public void setPercent(int percent) {
progressBar.setValue(percent);
progressBar.setVisible(true);
@@ -816,6 +819,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
mainFrame.setTitle(ApplicationInfo.applicationVerName + (Configuration.displayFileName.get() ? " - " + swf.getFileTitle() : ""));
List<ABCContainerTag> abcList = swf.getAbcList();
asms = swf.getASMs(true);
boolean hasAbc = !abcList.isEmpty();
@@ -1533,9 +1537,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
public void gotoClassLine(SWF swf, String cls, int line) {
gotoClass(swf, cls);
gotoScriptName(swf, cls);
if (abcPanel != null) {
abcPanel.decompiledTextArea.gotoLine(line);
} else if (actionPanel != null) {
actionPanel.decompiledEditor.gotoLine(line);
}
refreshBreakPoints();
@@ -1561,15 +1567,21 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}*/
public void gotoClass(SWF swf, String cls) {
public void gotoScriptName(SWF swf, String scriptName) {
if (swf == null) {
return;
}
List<ABCContainerTag> abcList = swf.getAbcList();
if (!abcList.isEmpty()) {
ABCPanel abcPanel = getABCPanel();
abcPanel.setAbc(abcList.get(0).getABC());
abcPanel.hilightScript(swf, cls);
if (swf.isAS3()) {
List<ABCContainerTag> abcList = swf.getAbcList();
if (!abcList.isEmpty()) {
ABCPanel abcPanel = getABCPanel();
abcPanel.setAbc(abcList.get(0).getABC());
abcPanel.hilightScript(swf, scriptName);
}
} else {
if (actionPanel != null && asms.containsKey(scriptName)) {
actionPanel.setSource(asms.get(scriptName), true);
}
}
}
@@ -1583,8 +1595,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
List<ABCContainerTag> abcList = swf.getAbcList();
if (!abcList.isEmpty()) {
ABCPanel abcPanel = getABCPanel();
abcPanel.setAbc(abcList.get(0).getABC());
abcPanel.hilightScript(swf, documentClass);
for (ABCContainerTag c : abcList) {
if (c.getABC().findClassByName(documentClass) > -1) {
abcPanel.setAbc(c.getABC());
abcPanel.hilightScript(swf, documentClass);
break;
}
}
}
}
}
@@ -2823,6 +2840,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
if (abcPanel != null) {
abcPanel.decompiledTextArea.removeColorMarkerOnAllLines(DecompiledEditorPane.FG_IP_COLOR, DecompiledEditorPane.BG_IP_COLOR, DecompiledEditorPane.PRIORITY_IP);
}
if (actionPanel != null) {
actionPanel.decompiledEditor.removeColorMarkerOnAllLines(DecompiledEditorPane.FG_IP_COLOR, DecompiledEditorPane.BG_IP_COLOR, DecompiledEditorPane.PRIORITY_IP);
}
}
private void stopFlashPlayer() {
@@ -3050,7 +3070,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
setSourceWorker.cancel(true);
setSourceWorker = null;
}
if (!Main.isWorking() || Main.isDebugging()) {
if (!Main.isInited() || !Main.isWorking() || Main.isDebugging()) {
CancellableWorker worker = new CancellableWorker() {
@Override

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.decompiler.flash.gui.DebugPanel;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.debugger.flash.messages.in.InBreakReason;

View File

@@ -38,6 +38,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.editor.DebuggableEditorPane;
import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightData;
@@ -59,7 +60,7 @@ import jsyntaxpane.Token;
import jsyntaxpane.TokenType;
import jsyntaxpane.components.BreakPointListener;
public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretListener, BreakPointListener {
public class DecompiledEditorPane extends DebuggableEditorPane implements CaretListener {
private List<Highlighting> highlights = new ArrayList<>();
@@ -91,34 +92,6 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
private final List<Runnable> scriptListeners = new ArrayList<>();
public static final Color BG_BREAKPOINT_COLOR = new Color(0xfc, 0x9d, 0x9f);
public static final Color FG_BREAKPOINT_COLOR = null;
public static final int PRIORITY_BREAKPOINT = 20;
public static final Color BG_IP_COLOR = new Color(0xbd, 0xe6, 0xaa);
public static final Color FG_IP_COLOR = null;
public static final int PRIORITY_IP = 0;
public static final Color BG_INVALID_BREAKPOINT_COLOR = new Color(0xdc, 0xdc, 0xd8);
public static final Color FG_INVALID_BREAKPOINT_COLOR = null;
public static final int PRIORITY_INVALID_BREAKPOINT = 10;
@Override
public void toggled(int line) {
boolean on = Main.toggleBreakPoint(script, line);
removeColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
if (on) {
if (Main.isBreakPointValid(script, line)) {
addColorMarker(line, FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
} else {
addColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
}
} else {
removeColorMarker(line, FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
removeColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
}
}
public void addScriptListener(Runnable l) {
scriptListeners.add(l);
}
@@ -676,14 +649,16 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
if (!force && this.script == scriptLeaf) {
return;
}
abcPanel.scriptNameLabel.setText(scriptLeaf.getClassPath().toString());
String sn = scriptLeaf.getClassPath().toString();
setScriptName(sn);
abcPanel.scriptNameLabel.setText(sn);
int scriptIndex = scriptLeaf.scriptIndex;
ScriptInfo script = null;
ScriptInfo nscript = null;
ABC abc = scriptLeaf.abc;
if (scriptIndex > -1) {
script = abc.script_info.get(scriptIndex);
nscript = abc.script_info.get(scriptIndex);
}
if (script == null) {
if (nscript == null) {
highlights = new ArrayList<>();
specialHighlights = new ArrayList<>();
traitHighlights = new ArrayList<>();
@@ -738,36 +713,9 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
return script == null ? null : script.abc;
}
public void refreshMarkers() {
removeColorMarkerOnAllLines(FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
removeColorMarkerOnAllLines(FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
removeColorMarkerOnAllLines(FG_IP_COLOR, BG_IP_COLOR, PRIORITY_IP);
if (script == null) {
return;
}
Set<Integer> bkptLines = Main.getPackBreakPoints(script);
for (int line : bkptLines) {
if (Main.isBreakPointValid(script, line)) {
addColorMarker(line, FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
} else {
addColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
}
}
int ip = Main.getIp(script);
ClassPath ipPath = Main.getIpClass();
if (ip > 0 && ipPath != null && ipPath.equals(script.getClassPath())) {
addColorMarker(ip, FG_IP_COLOR, BG_IP_COLOR, PRIORITY_IP);
}
}
@Override
public void setText(String t) {
super.setText(t);
setCaretPosition(0);
refreshMarkers();
}
}

View File

@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui.action;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionGraph;
import com.jpexs.decompiler.flash.action.ActionList;
@@ -34,6 +35,7 @@ import com.jpexs.decompiler.flash.action.swf4.ConstantIndex;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.DebuggerHandler;
import com.jpexs.decompiler.flash.gui.GraphDialog;
import com.jpexs.decompiler.flash.gui.HeaderLabel;
import com.jpexs.decompiler.flash.gui.Main;
@@ -42,8 +44,19 @@ import com.jpexs.decompiler.flash.gui.SearchListener;
import com.jpexs.decompiler.flash.gui.SearchPanel;
import com.jpexs.decompiler.flash.gui.TagEditorPanel;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.DebugPanel;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.BG_BREAKPOINT_COLOR;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.BG_INVALID_BREAKPOINT_COLOR;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.BG_IP_COLOR;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.FG_BREAKPOINT_COLOR;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.FG_INVALID_BREAKPOINT_COLOR;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.FG_IP_COLOR;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.PRIORITY_BREAKPOINT;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.PRIORITY_INVALID_BREAKPOINT;
import static com.jpexs.decompiler.flash.gui.abc.DecompiledEditorPane.PRIORITY_IP;
import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane;
import com.jpexs.decompiler.flash.gui.controls.NoneSelectedButtonGroup;
import com.jpexs.decompiler.flash.gui.editor.DebuggableEditorPane;
import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane;
import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel;
import com.jpexs.decompiler.flash.helpers.HighlightedText;
@@ -66,6 +79,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -96,7 +110,7 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
public LineMarkedEditorPane editor;
public LineMarkedEditorPane decompiledEditor;
public DebuggableEditorPane decompiledEditor;
public JPersistentSplitPane splitPane;
@@ -170,6 +184,26 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
srcConstants = null;
}
/*public void refreshMarkers() {
decompiledEditor.removeColorMarkerOnAllLines(FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
decompiledEditor.removeColorMarkerOnAllLines(FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
decompiledEditor.removeColorMarkerOnAllLines(FG_IP_COLOR, BG_IP_COLOR, PRIORITY_IP);
Set<Integer> bkptLines = Main.getScriptBreakPoints(sc);
for (int line : bkptLines) {
if (Main.isBreakPointValid(lastASM, line)) {
decompiledEditor.addColorMarker(line, FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
} else {
decompiledEditor.addColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
}
}
int ip = Main.getIp(lastASM);
String ipPath = Main.getIpClass();
if (ip > 0 && ipPath != null && lastASM.getSwf().getASMs(false).get(ipPath) == lastASM) {
decompiledEditor.addColorMarker(ip, FG_IP_COLOR, BG_IP_COLOR, PRIORITY_IP);
}
}*/
public String getStringUnderCursor() {
int pos = decompiledEditor.getCaretPosition();
@@ -206,7 +240,7 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
selIns = ins;
break;
}
if (ins.getOffset() > h.getProperties().offset) {
if (ins.getOffset() > h.getProperties().offset && lastIns != null) {
inspos = (int) (h.getProperties().offset - lastIns.getAddress());
selIns = lastIns;
break;
@@ -274,9 +308,10 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
return null;
}
private void setDecompiledText(final String text) {
private void setDecompiledText(final String scriptName, final String text) {
View.execInEventDispatch(() -> {
ignoreCarret = true;
decompiledEditor.setScriptName(scriptName);
decompiledEditor.setText(text);
ignoreCarret = false;
});
@@ -415,12 +450,13 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
@Override
protected Void doInBackground() throws Exception {
setEditorText("; " + AppStrings.translate("work.disassembling") + "...", "text/flasm");
if (Configuration.decompile.get()) {
setDecompiledText("// " + AppStrings.translate("work.waitingfordissasembly") + "...");
setDecompiledText("-", "// " + AppStrings.translate("work.waitingfordissasembly") + "...");
} else {
lastDecompiled = Helper.getDecompilationSkippedComment();
setDecompiledText(lastDecompiled);
setDecompiledText(asm.getScriptName(), lastDecompiled);
}
DisassemblyListener listener = getDisassemblyListener();
asm.addDisassemblyListener(listener);
@@ -433,7 +469,7 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
srcConstants = null;
setHex(getExportMode());
if (Configuration.decompile.get()) {
setDecompiledText("// " + AppStrings.translate("work.decompiling") + "...");
setDecompiledText("-", "// " + AppStrings.translate("work.decompiling") + "...");
if (!useCache) {
SWF.uncache(asm);
}
@@ -442,10 +478,11 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
decompiledHilights = sc.hilights;
lastDecompiled = sc.text;
lastASM = asm;
setDecompiledText(lastDecompiled);
setDecompiledText(lastASM.getScriptName(), lastDecompiled);
}
setEditMode(false);
setDecompiledEditMode(false);
return null;
}
@@ -453,21 +490,25 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
protected void done() {
View.execInEventDispatch(() -> {
setSourceWorker = null;
Main.stopWork();
if (!Main.isDebugging()) {
Main.stopWork();
}
try {
get();
} catch (CancellationException ex) {
setEditorText("; " + AppStrings.translate("work.canceled"), "text/flasm");
} catch (Exception ex) {
setDecompiledText("// " + AppStrings.translate("decompilationError") + ": " + ex);
setDecompiledText("-", "// " + AppStrings.translate("decompilationError") + ": " + ex);
}
});
}
};
worker.execute();
setSourceWorker = worker;
Main.startWork(AppStrings.translate("work.decompiling") + "...", worker);
if (!Main.isDebugging()) {
Main.startWork(AppStrings.translate("work.decompiling") + "...", worker);
}
}
public void hilightOffset(long offset) {
@@ -477,7 +518,7 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
this.mainPanel = mainPanel;
editor = new LineMarkedEditorPane();
editor.setEditable(false);
decompiledEditor = new LineMarkedEditorPane();
decompiledEditor = new DebuggableEditorPane();
decompiledEditor.setEditable(false);
searchPanel = new SearchPanel<>(new FlowLayout(), this);
@@ -570,15 +611,37 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
saveDecompiledButton.setVisible(false);
cancelDecompiledButton.setVisible(false);
JPanel decPanel = new JPanel(new BorderLayout());
decPanel.add(new JScrollPane(decompiledEditor), BorderLayout.CENTER);
//decPanel.add(searchPanel, BorderLayout.NORTH);
JPanel panA = new JPanel(new BorderLayout());
JPanel panA = new JPanel();
panA.setLayout(new BorderLayout());
panA.add(decPanel, BorderLayout.CENTER);
panA.add(decLabel, BorderLayout.NORTH);
DebugPanel debugPanel = new DebugPanel();
panA.add(new JPersistentSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(decompiledEditor), debugPanel, Configuration.guiActionVarsSplitPaneDividerLocationPercent), BorderLayout.CENTER);
panA.add(decButtonsPan, BorderLayout.SOUTH);
//decPanel.add(searchPanel, BorderLayout.NORTH);
Main.getDebugHandler().addConnectionListener(new DebuggerHandler.ConnectionListener() {
@Override
public void connected() {
decButtonsPan.setVisible(false);
}
@Override
public void disconnected() {
decButtonsPan.setVisible(true);
}
});
//new JSplitPane(JSplitPane.VERTICAL_SPLIT, decompiledEditor, debugPanel)
//decPanel.add(decButtonsPan, BorderLayout.SOUTH);
//JPanel panBot = new JPanel(new BorderLayout());
//panBot.add(decButtonsPan, BorderLayout.NORTH);
//panBot.add(debugPanel, BorderLayout.CENTER);
//panA.add(decButtonsPan, BorderLayout.SOUTH);
debugPanel.setVisible(false);
decLabel.setHorizontalAlignment(SwingConstants.CENTER);
//decLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
@@ -678,63 +741,66 @@ public class ActionPanel extends JPanel implements SearchListener<ActionSearchRe
}
public void setEditMode(boolean val) {
if (val) {
if (hexOnlyButton.isSelected()) {
setHex(ScriptExportMode.HEX);
} else if (constantsViewButton.isSelected()) {
setHex(ScriptExportMode.CONSTANTS);
} else {
setHex(ScriptExportMode.PCODE);
View.execInEventDispatch(() -> {
if (val) {
if (hexOnlyButton.isSelected()) {
setHex(ScriptExportMode.HEX);
} else if (constantsViewButton.isSelected()) {
setHex(ScriptExportMode.CONSTANTS);
} else {
setHex(ScriptExportMode.PCODE);
}
}
}
editor.setEditable(val);
saveButton.setVisible(val);
saveButton.setEnabled(false);
editButton.setVisible(!val);
cancelButton.setVisible(val);
editor.setEditable(val);
saveButton.setVisible(val);
saveButton.setEnabled(false);
editButton.setVisible(!val);
cancelButton.setVisible(val);
editor.getCaret().setVisible(true);
asmLabel.setIcon(val ? View.getIcon("editing16") : null); // this line is not working
topButtonsPan.setVisible(!val);
editMode = val;
editor.requestFocusInWindow();
editor.getCaret().setVisible(true);
asmLabel.setIcon(val ? View.getIcon("editing16") : null); // this line is not working
topButtonsPan.setVisible(!val);
editMode = val;
editor.requestFocusInWindow();
});
}
public void setDecompiledEditMode(boolean val) {
if (lastASM == null) {
return;
}
int lastLine = decompiledEditor.getLine();
int prefLines = lastASM.getPrefixLineCount();
if (val) {
String newText = lastASM.removePrefixAndSuffix(lastDecompiled);
setDecompiledText(newText);
if (lastLine > -1) {
if (lastLine - prefLines >= 0) {
decompiledEditor.gotoLine(lastLine - prefLines + 1);
View.execInEventDispatch(() -> {
int lastLine = decompiledEditor.getLine();
int prefLines = lastASM.getPrefixLineCount();
if (val) {
String newText = lastASM.removePrefixAndSuffix(lastDecompiled);
setDecompiledText(lastASM.getScriptName(), newText);
if (lastLine > -1) {
if (lastLine - prefLines >= 0) {
decompiledEditor.gotoLine(lastLine - prefLines + 1);
}
}
} else {
String newText = lastDecompiled;
setDecompiledText(lastASM.getScriptName(), newText);
if (lastLine > -1) {
decompiledEditor.gotoLine(lastLine + prefLines + 1);
}
}
} else {
String newText = lastDecompiled;
setDecompiledText(newText);
if (lastLine > -1) {
decompiledEditor.gotoLine(lastLine + prefLines + 1);
}
}
decompiledEditor.setEditable(val);
saveDecompiledButton.setVisible(val);
saveDecompiledButton.setEnabled(false);
editDecompiledButton.setVisible(!val);
experimentalLabel.setVisible(!val);
cancelDecompiledButton.setVisible(val);
decompiledEditor.setEditable(val);
saveDecompiledButton.setVisible(val);
saveDecompiledButton.setEnabled(false);
editDecompiledButton.setVisible(!val);
experimentalLabel.setVisible(!val);
cancelDecompiledButton.setVisible(val);
decompiledEditor.getCaret().setVisible(true);
decLabel.setIcon(val ? View.getIcon("editing16") : null);
editDecompiledMode = val;
decompiledEditor.requestFocusInWindow();
decompiledEditor.getCaret().setVisible(true);
decLabel.setIcon(val ? View.getIcon("editing16") : null);
editDecompiledMode = val;
decompiledEditor.requestFocusInWindow();
});
}
private void graphButtonActionPerformed(ActionEvent evt) {

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2015 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.editor;
import com.jpexs.decompiler.flash.gui.Main;
import java.awt.Color;
import java.util.Set;
import jsyntaxpane.components.BreakPointListener;
/**
*
* @author JPEXS
*/
public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakPointListener {
public static final Color BG_BREAKPOINT_COLOR = new Color(0xfc, 0x9d, 0x9f);
public static final Color FG_BREAKPOINT_COLOR = null;
public static final int PRIORITY_BREAKPOINT = 20;
public static final Color BG_IP_COLOR = new Color(0xbd, 0xe6, 0xaa);
public static final Color FG_IP_COLOR = null;
public static final int PRIORITY_IP = 0;
public static final Color BG_INVALID_BREAKPOINT_COLOR = new Color(0xdc, 0xdc, 0xd8);
public static final Color FG_INVALID_BREAKPOINT_COLOR = null;
public static final int PRIORITY_INVALID_BREAKPOINT = 10;
protected String scriptName = null;
public synchronized void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
@Override
public synchronized void toggled(int line) {
if (scriptName == null) {
return;
}
boolean on = Main.toggleBreakPoint(scriptName, line);
removeColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
if (on) {
if (Main.isBreakPointValid(scriptName, line)) {
addColorMarker(line, FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
} else {
addColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
}
} else {
removeColorMarker(line, FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
removeColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
}
}
public synchronized void refreshMarkers() {
removeColorMarkerOnAllLines(FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
removeColorMarkerOnAllLines(FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
removeColorMarkerOnAllLines(FG_IP_COLOR, BG_IP_COLOR, PRIORITY_IP);
if (scriptName == null) {
return;
}
Set<Integer> bkptLines = Main.getScriptBreakPoints(scriptName);
for (int line : bkptLines) {
if (Main.isBreakPointValid(scriptName, line)) {
addColorMarker(line, FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
} else {
addColorMarker(line, FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
}
}
int ip = Main.getIp(scriptName);
String ipPath = Main.getIpClass();
if (ip > 0 && ipPath != null && ipPath.equals(scriptName)) {
addColorMarker(ip, FG_IP_COLOR, BG_IP_COLOR, PRIORITY_IP);
}
}
@Override
public void setText(String t) {
super.setText(t);
refreshMarkers();
}
public String getScriptName() {
return scriptName;
}
}

View File

@@ -678,4 +678,17 @@ work.breakat = Breat at\u0020
work.halted = Debugging started, execution halted. Add breakpoints and click Continue (F5) to resume running.
debuglog.header = Log
debuglog.button.clear = Clear
debuglog.button.clear = Clear
work.debugging.wait = Waiting for Flash debug projector to connect
error.debug.listen = Cannot listen on port %port%. There might be other flash debugger running.
debug.break.reason.unknown = (Unknown)
debug.break.reason.breakpoint = (Breakpoint)
debug.break.reason.watch = (Watch)
debug.break.reason.fault = (Fault)
debug.break.reason.stopRequest = (Stop request)
debug.break.reason.step = (Step)
debug.break.reason.halt = (Halt)
debug.break.reason.scriptLoaded = (Script loaded)

View File

@@ -84,6 +84,7 @@ import java.util.Random;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.testng.annotations.Test;
/**
*